Commit Graph

36 Commits

Author SHA1 Message Date
Alexander Brown
dd1a1f77d6 fix: stabilize nested subgraph promoted widget resolution (#9282)
## Summary

Fix multiple issues with promoted widget resolution in nested subgraphs,
ensuring correct value propagation, slot matching, and rendering for
deeply nested promoted widgets.

## Changes

- **What**: Stabilize nested subgraph promoted widget resolution chain
- Use deep source keys for promoted widget values in Vue rendering mode
- Resolve effective widget options from the source widget instead of the
promoted view
  - Stabilize slot resolution for nested promoted widgets
  - Preserve combo value rendering for promoted subgraph widgets
- Prevent subgraph definition deletion while other nodes still reference
the same type
  - Clean up unused exported resolution types

## Review Focus

- `resolveConcretePromotedWidget.ts` — new recursive resolution logic
for deeply nested promoted widgets
- `useGraphNodeManager.ts` — option extraction now uses
`effectiveWidget` for promoted widgets
- `SubgraphNode.ts` — unpack no longer force-deletes definitions
referenced by other nodes

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9282-fix-stabilize-nested-subgraph-promoted-widget-resolution-3146d73d365081208a4fe931bb7569cf)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
2026-02-28 13:45:04 -08:00
Christian Byrne
aef299caf8 fix: add GLSLShader to canvas image preview node types (#9198)
## Summary

Add `GLSLShader` to `CANVAS_IMAGE_PREVIEW_NODE_TYPES` so GLSL shader
previews are promoted through subgraph nodes.

## Changes

- Add `'GLSLShader'` to the `CANVAS_IMAGE_PREVIEW_NODE_TYPES` set in
`src/composables/node/useNodeCanvasImagePreview.ts`

## Context

GLSLShader node previews were not showing on parent subgraph nodes
because `CANVAS_IMAGE_PREVIEW_NODE_TYPES` only included `PreviewImage`
and `SaveImage`. The `$$canvas-image-preview` pseudo-widget was never
created for GLSLShader nodes, so the promotion system had nothing to
promote. This degraded the UX of all 12 shipped GLSL blueprint subgraphs
— users couldn't see shader output previews without expanding the
subgraph.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9198-fix-add-GLSLShader-to-canvas-image-preview-node-types-3126d73d3650817dbe9beab4bdeaa414)
by [Unito](https://www.unito.io)
2026-02-26 01:15:24 -08:00
Alexander Brown
c25f9a0e93 feat: synthetic widgets getter for SubgraphNode (proxy-widget-v2) (#8856)
## Summary

Replace the Proxy-based proxy widget system with a store-driven
architecture where `promotionStore` and `widgetValueStore` are the
single sources of truth for subgraph widget promotion and widget values,
and `SubgraphNode.widgets` is a synthetic getter composing lightweight
`PromotedWidgetView` objects from store state.

## Motivation

The subgraph widget promotion system previously scattered state across
multiple unsynchronized layers:

- **Persistence**: `node.properties.proxyWidgets` (tuples on the
LiteGraph node)
- **Runtime**: Proxy-based `proxyWidget.ts` with `Overlay` objects,
`DisconnectedWidget` singleton, and `isProxyWidget` type guards
- **UI**: Each Vue component independently calling `parseProxyWidgets()`
via `customRef` hacks
- **Mutation flags**: Imperative `widget.promoted = true/false` set on
`subgraph-opened` events

This led to 4+ independent parsings of the same data, complex cache
invalidation, and no reactive contract between the promotion state and
the rendering layer. Widget values were similarly owned by LiteGraph
with no Vue-reactive backing.

The core principle driving these changes: **Vue owns truth**. Pinia
stores are the canonical source; LiteGraph objects delegate to stores
via getters/setters; Vue components react to store state directly.

## Changes

### New stores (single sources of truth)

- **`promotionStore`** — Reactive `Map<NodeId, PromotionEntry[]>`
tracking which interior widgets are promoted on which SubgraphNode
instances. Graph-scoped by root graph ID to prevent cross-workflow state
collision. Replaces `properties.proxyWidgets` parsing, `customRef`
hacks, `widget.promoted` mutation, and the `subgraph-opened` event
listener.
- **`widgetValueStore`** — Graph-scoped `Map<WidgetKey, WidgetState>`
that is the canonical owner of widget values. `BaseWidget.value`
delegates to this store via getter/setter when a node ID is assigned.
Eliminates the need for Proxy-based value forwarding.

### Synthetic widgets getter (SubgraphNode)

`SubgraphNode.widgets` is now a getter that reads
`promotionStore.getPromotions(rootGraphId, nodeId)` and returns cached
`PromotedWidgetView` objects. No stubs, no Proxies, no fake widgets
persisted in the array. The setter is a no-op — mutations go through
`promotionStore`.

### PromotedWidgetView

A class behind a `createPromotedWidgetView` factory, implementing the
`PromotedWidgetView` interface. Delegates value/type/options/drawing to
the resolved interior widget and stores. Owns positional state (`y`,
`computedHeight`) for canvas layout. Cached by
`PromotedWidgetViewManager` for object-identity stability across frames.

### DOM widget promotion

Promoted DOM widgets (textarea, image upload, etc.) render on the
SubgraphNode surface via `positionOverride` in `domWidgetStore`.
`DomWidgets.vue` checks for overrides and uses the SubgraphNode's
coordinates instead of the interior node's.

### Promoted previews

New `usePromotedPreviews` composable resolves image/audio/video preview
widgets from promoted entries, enabling SubgraphNodes to display
previews of interior preview nodes.

### Deleted

- `proxyWidget.ts` (257 lines) — Proxy handler, `Overlay`,
`newProxyWidget`, `isProxyWidget`
- `DisconnectedWidget.ts` (39 lines) — Singleton Proxy target
- `useValueTransform.ts` (32 lines) — Replaced by store delegation

### Key architectural changes

- `BaseWidget.value` getter/setter delegates to `widgetValueStore` when
node ID is set
- `LGraph.add()` reordered: `node.graph` assigned before widget
`setNodeId` (enables store registration)
- `LGraph.clear()` cleans up graph-scoped stores to prevent stale
entries across workflow switches
- `promotionStore` and `widgetValueStore` state nested under root graph
UUID for multi-workflow isolation
- `SubgraphNode.serialize()` writes promotions back to
`properties.proxyWidgets` for persistence compatibility
- Legacy `-1` promotion entries resolved and migrated on first load with
dev warning

## Test coverage

- **3,700+ lines of new/updated tests** across 36 test files
- **Unit**: `promotionStore.test.ts`, `widgetValueStore.test.ts`,
`promotedWidgetView.test.ts` (921 lines),
`subgraphNodePromotion.test.ts`, `proxyWidgetUtils.test.ts`,
`DomWidgets.test.ts`, `PromotedWidgetViewManager.test.ts`,
`usePromotedPreviews.test.ts`, `resolvePromotedWidget.test.ts`,
`subgraphPseudoWidgetCache.test.ts`
- **E2E**: `subgraphPromotion.spec.ts` (622 lines) — promote/demote,
manual/auto promotion, paste preservation, seed control augmentation,
image preview promotion; `imagePreview.spec.ts` extended with
multi-promoted-preview coverage
- **Fixtures**: 2 new subgraph workflow fixtures for preview promotion
scenarios

## Review focus

- Graph-scoped store keying (`rootGraphId`) — verify isolation across
workflows/tabs and cleanup on `LGraph.clear()`
- `PromotedWidgetView` positional stability — `_arrangeWidgets` writes
to `y`/`computedHeight` on cached objects; getter returns fresh array
but stable object references
- DOM widget position override lifecycle — overrides set on promote,
cleared on demote/removal/subgraph navigation
- Legacy `-1` entry migration — resolved and written back on first load;
unresolvable entries dropped with dev warning
- Serialization round-trip — `promotionStore` state →
`properties.proxyWidgets` on serialize, hydrated back on configure

## Diff breakdown (excluding lockfile)

- 153 files changed, ~7,500 insertions, ~1,900 deletions (excluding
pnpm-lock.yaml churn)
- ~3,700 lines are tests
- ~300 lines deleted (proxyWidget.ts, DisconnectedWidget.ts,
useValueTransform.ts)

<!-- Fixes #ISSUE_NUMBER -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8856-feat-synthetic-widgets-getter-for-SubgraphNode-proxy-widget-v2-3076d73d365081c7b517f5ec7cb514f3)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-02-23 13:33:41 -08:00
Christian Byrne
c1a569211d fix: skip MatchType recalculation during graph configuration (#9004)
## Summary

Fixes COM-14955: "Bug: Switch node in subgraph causes link disconnection
on export"

## Problem

When a MatchType node (like Switch) inside a subgraph is
configured/restored, `LGraphNode.configure()` calls
`onConnectionsChange` for each input sequentially. The
`withComfyMatchType` callback was running before all links were
restored, seeing incomplete state and incorrectly computing types, which
could cause link disconnection.

## Solution

Add early return when `app.configuringGraph` is true to defer type
recalculation until after all links are restored. This pattern is
already used throughout the codebase:
- `widgetInputs.ts`
- `rerouteNode.ts`
- `customWidgets.ts`

Post-configure recomputation is handled by the existing
`requestAnimationFrame` callback in `applyMatchType`.

## Changes

- `src/core/graph/widgets/dynamicWidgets.ts` - Added 1 line: `if
(app.configuringGraph) return`
- `src/core/graph/widgets/matchTypeConfiguring.test.ts` - New test file
with 3 tests

## Testing

- All existing tests pass
- Added 3 new tests:
  - `skips type recalculation when configuringGraph is true`
  - `performs type recalculation during normal operation`
  - `connects both inputs with same type`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9004-fix-skip-MatchType-recalculation-during-graph-configuration-30d6d73d365081339088ffd8aebba107)
by [Unito](https://www.unito.io)
2026-02-20 19:44:34 -08:00
Christian Byrne
ee0789e153 fix: promoted widget labels show widgetName instead of "nodeId: widgetName" (#9013)
## Summary

Promoted/proxied widgets on subgraph nodes showed generic "nodeId:
widgetName" labels (e.g., "3: seed") in the LiteGraph renderer. Now they
correctly show just the widget name (e.g., "seed").

## Changes

- **What**: Set proxy widget overlay `label` to `widgetName` instead of
`name` (which contains the unique `"nodeId: widgetName"` format). The
overlay `name` still retains the unique format for internal
identification.
- Added 2 tests verifying proxy widget label defaults and user rename
behavior.

## Review Focus

- The one-line fix in `proxyWidget.ts` line 157: `label: widgetName`
instead of `label: name`
- The overlay `name` property is unchanged — only `label` (used for
display) is affected
- No code parses the label string for identification; all lookups use
`_overlay.nodeId` and `_overlay.widgetName` directly

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9013-fix-promoted-widget-labels-show-widgetName-instead-of-nodeId-widgetName-30d6d73d365081ca8d2feb68585fc187)
by [Unito](https://www.unito.io)
2026-02-20 19:14:57 -08:00
Christian Byrne
9dc6203b3d docs: document subgraph limitations with autogrow and matchtype (#8709)
## Summary

Document why autogrow and matchtype don't work inside subgraphs,
covering root cause, symptoms, workarounds, and historical context.

## Changes

- **What**: Add `src/core/graph/subgraph-dynamic-input-limitations.md`
explaining the static-vs-dynamic impedance mismatch between subgraph
slots (fixed type at creation) and matchtype/autogrow (runtime
mutations). Includes Mermaid diagrams, workarounds, and PR history. Link
added to `src/lib/litegraph/AGENTS.md` for discoverability.

## Review Focus

- Accuracy of the technical explanation — @AustinMroz authored
matchtype/autogrow, @webfiltered authored the subgraph system
- Whether the workarounds section is practical and complete
- File placement: colocated at `src/core/graph/` next to both
`subgraph/` and `widgets/dynamicWidgets.ts`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8709-docs-document-subgraph-limitations-with-autogrow-and-matchtype-3006d73d36508134a64ce8c2c49e05f1)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-02-19 21:29:17 -08:00
Alexander Brown
a7c2115166 feat: add WidgetValueStore for centralized widget value management (#8594)
## Summary

Implements Phase 1 of the **Vue-owns-truth** pattern for widget values.
Widget values are now canonical in a Pinia store; `widget.value`
delegates to the store while preserving full backward compatibility.

## Changes

- **New store**: `src/stores/widgetValueStore.ts` - centralized widget
value storage with `get/set/remove/removeNode` API
- **BaseWidget integration**: `widget.value` getter/setter now delegates
to store when widget is associated with a node
- **LGraphNode wiring**: `addCustomWidget()` automatically calls
`widget.setNodeId(this.id)` to wire widgets to their nodes
- **Test fixes**: Added Pinia setup to test files that use widgets

## Why

This foundation enables:
- Vue components to reactively bind to widget values via `computed(() =>
store.get(...))`
- Future Yjs/CRDT backing for real-time collaboration
- Cleaner separation between Vue state and LiteGraph rendering

## Backward Compatibility

| Extension Pattern | Status |
|-------------------|--------|
| `widget.value = x` |  Works unchanged |
| `node.widgets[i].value` |  Works unchanged |
| `widget.callback` |  Still fires |
| `node.onWidgetChanged` |  Still fires |

## Testing

-  4252 unit tests pass
-  Build succeeds

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8594-feat-add-WidgetValueStore-for-centralized-widget-value-management-2fc6d73d36508160886fcb9f3ebd941e)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-02-10 19:37:17 -08:00
Christian Byrne
ffc0bf00ef fix: make SubgraphNode.graph nullable to allow proper cleanup (#8180)
## Summary

Fix `SubgraphNode.graph` property to match `LGraphNode` lifecycle
contract. Previously declared as `override readonly graph` via
constructor parameter promotion, which prevented `LGraph.remove()` from
setting `node.graph = null`.

## Changes

- Remove `readonly` from `SubgraphNode.graph` constructor parameter
- Add `override graph: GraphOrSubgraph | null` as class property  
- Add `NullGraphError` guard in `rootGraph` getter with node ID for
debugging
- Add null guards in `ExecutableNodeDTO.resolveInput` and
`imagePreviewStore.revokeSubgraphPreviews`
- Add test verifying `rootGraph` throws after node removal

## Testing

- Existing subgraph tests pass
- New test confirms `NullGraphError` is thrown when accessing
`rootGraph` on removed node

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-02-03 16:18:48 -08:00
AustinMroz
e2625a4055 Fix paste-with-links breaking autogrow connections (#8442)
The extra `linf` check was made in 878c8c0f39. I'm no longer able to
replicate the cloning bug the check was introduced for.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8442-Fix-paste-with-links-breaking-autogrow-connections-2f76d73d3650817aa99cc3b9e4e6412c)
by [Unito](https://www.unito.io)
2026-01-29 16:25:16 -08:00
AustinMroz
af8433fb3d Support widget specific contextmenu options in vue (#8431)
<img width="614" height="485" alt="image"
src="https://github.com/user-attachments/assets/2a635dec-8bed-4fab-9881-5e6057d482e1"
/>

These options were defined in `litegraphService`. While the existing
code for defining options is reused (to ensure there's no implementation
drift) these extra widget options use the litegraph format for context
menu options and do not belong in `useSelectionMenuOptions`. They have
been moved out of `useLitegraphService` (good), but left in
`litegraphService` (not great)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8431-Support-widget-specific-contextmenu-options-in-vue-2f76d73d3650814fb20fca352dc81e3b)
by [Unito](https://www.unito.io)
2026-01-29 11:38:41 -08:00
AustinMroz
4a5e7c8bcb Further dynamic input fixes (#8026)
- Fix deserialization of matchtype inputs spawned by autogrow.
- Rotate multitype slot indicators to align with design changes.
- Fix several instance of incorrect group matching
- MatchType reactively updates input type in vue
- Support the "hollow circle" optional input indicator in vue
- Custom combo sends index of selection to backend

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8026-Further-dynamic-input-fixes-2e76d73d3650819680fef327a94f4294)
by [Unito](https://www.unito.io)
2026-01-22 00:02:49 -08:00
Rizumu Ayaka
b1b2fd8a4f feat: right side panel favorites, no selection state, and more... (#7812)
Most of the features in this pull request are completed and can be
reviewed and merged.

## TODO

- [x] no selection panel
- [x] group selected panel
- [x] tabs 
  - [x] favorites tab
  - [x] global settings tab
  - [x] nodes tab
- [x] widget actions menu 
  - [x] [Bug]: style bugs
- [x] button zoom to the node on canvas.
- [x] rename widgets on widget actions
  - [ ] [Bug]: the canvas has not been updated after renaming. 
- [x] global settings
  - [ ] setting item: "show advanced parameters"
    - blocked by other things. skip for now.
  - [x] setting item: show toolbox on selection 
  - [x] setting item: nodes 2.0
  - [ ] setting item: "background color"
    - blocked by other things. skip for now.
  - [x] setting item: grid spacing
  - [x] setting item: snap nodes to grid
  - [x] setting item: link shape
  - [x] setting item: show connected links
  - [x] form style reuses the form style of node widgets
- [x] group node cases
  - [x] group node settings
  - [x] show all nodes in group
  - [x] show frame name on nodes when multiple selections are made
  - [x] group multiple selections
- [x] [Bug]: nodes without widgets cannot display the location and their
group
  - [x] [Bug]: labels layout
- [x] favorites
  - [x] the indicator on widgets
  - [x] favorite and unfavorite buttons on widgets
- [x] [Bug]: show node name in favorite widgets + improve labels layout
- [ ] [Bug]: After canceling the like, the like list will not be updated
immediately.
- [x] [Bug]: The favorite function does not work for the project on
Subgraph.
- [x] subgraph
- [x] add the node name from where this parameter comes from when node
is subgraph
  - [x] show and hide directly on Inputs
    - [x] some bugs need to be fixed.
- [x] advanced widgets 
  - [x] button: show advanced inputs
- Clicking button expands the "Advanced Inputs" section on the right
side panel, regardless of whether the panel is open or not
    - [x] [Bug]: style bugs
  - [x] advanced inputs section when node is subgraph
- [x] inputs tab rearranging
  - [x] favorited inputs rearranging
  - [x] subgraph inputs rearranging
- [ ] review and reconstruction to improve complexity and architecture

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7812-feat-right-side-panel-favorites-no-selection-state-and-more-2da6d73d36508134b503d676f9b3d248)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
2026-01-13 20:37:17 -07:00
AustinMroz
dcf0886d89 Dynamic input fixes (#7837)
A couple small dynamic input fixes.
- When removing widgets, call any onRemove methods
  - This is required for DOMWidgets to properly clean themself up.
- Resolve actual current link state when initializing match type
- This is only a partial fix for combing matchtype with autogrow, there
is a separate issue with skipped initialization that will need to be
resolved separately in the future.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7837-Dynamic-input-fixes-2de6d73d365081bdb263ed659e25e6ea)
by [Unito](https://www.unito.io)
2026-01-06 19:45:36 -07:00
Alexander Brown
10feb1fd5b chore: migrate tests from tests-ui/ to colocate with source files (#7811)
## Summary

Migrates all unit tests from `tests-ui/` to colocate with their source
files in `src/`, improving discoverability and maintainability.

## Changes

- **What**: Relocated all unit tests to be adjacent to the code they
test, following the `<source>.test.ts` naming convention
- **Config**: Updated `vitest.config.ts` to remove `tests-ui` include
pattern and `@tests-ui` alias
- **Docs**: Moved testing documentation to `docs/testing/` with updated
paths and patterns

## Review Focus

- Migration patterns documented in
`temp/plans/migrate-tests-ui-to-src.md`
- Tests use `@/` path aliases instead of relative imports
- Shared fixtures placed in `__fixtures__/` directories

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7811-chore-migrate-tests-from-tests-ui-to-colocate-with-source-files-2da6d73d36508147a4cce85365dee614)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-05 16:32:24 -08:00
AustinMroz
f9b58904d9 Ensure widgets always get a single callback (#7579)
The other side of reactivity. Ensure that vue mode always registers a
callback on litegraph nodes and never registers more than one.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7579-Ensure-widgets-always-get-a-single-callback-2cc6d73d365081e2a488c38ae394efc0)
by [Unito](https://www.unito.io)
2025-12-23 15:48:01 -08:00
AustinMroz
3a091277d0 Nesting support for autogrow (#7275)
- Modifies autogrow inputs to be named by key
- Allows autogrow inputs to be added after initialization.
  - Such as when added by another dynamic combo
- Groups dynamic input information under a single comfyDynamic property
which is opaque to Litegraph

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7275-Nesting-support-for-autogrow-2c46d73d36508171893ec43275f5b644)
by [Unito](https://www.unito.io)
2025-12-14 02:29:34 -08:00
AustinMroz
a8f6bea371 Color links as common type (#7211)
Previously the color of a link would simply use the type of the target
slot and fallback to the type of the origin slot. When a connection is
made to a node that accepts the any type ('*'), the link has the green
color of an unknown type.

Instead, when a connection is made, the type of a link is now calculated
as the greatest common type of the source and destination. This means
that connections to reroutes are correctly colored.

| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/a5544730-e69a-4c85-af33-b303bb30ae71"
/>| <img width="360" alt="after"
src="https://github.com/user-attachments/assets/7d7b59fd-1b79-440b-a97d-a1657313c484"
/>|

The code for calculating common types already exists, it has simply been
moved into litegraph and given a more descriptive name.

Resolves #7196

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7211-Color-links-as-common-type-2c16d73d365081188460f6b5973db962)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-12-06 12:00:07 -08:00
Rizumu Ayaka
68274134c8 feat: right side panel (#6952)
<img width="1183" height="809" alt="CleanShot 2025-11-26 at 16 01 15"
src="https://github.com/user-attachments/assets/c14dc5c3-a672-4dcd-917d-14f16310188e"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6952-feat-right-side-panel-2b76d73d36508112b121c283a479f42a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-12-02 22:55:24 -07:00
AustinMroz
49824824e6 Add support for growable inputs (#6830)
![autogrow-optional_00002](https://github.com/user-attachments/assets/79bfe703-23d7-45fb-86ce-88baa9eaf582)

Also fixes connections to widget inputs created by a dynamic combo
breaking on reload.

Performs some refactoring to group the prior dynamic inputs code.

See also, the overarching frontend PR: comfyanonymous/ComfyUI#10832

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6830-Add-support-for-growable-inputs-2b36d73d365081c484ebc251a10aa6dd)
by [Unito](https://www.unito.io)
2025-12-01 21:05:25 -08:00
AustinMroz
bc553f12be Add support for dynamic widgets (#6661)
Adds support for "dynamic combo" widgets where selecting a value on a
combo widget can cause other widgets or inputs to be created.


![dynamic-widgets_00001](https://github.com/user-attachments/assets/c797d008-f335-4d4e-9b2e-6fe4a7187ba7)

Includes a fairly large refactoring in litegraphService to remove
`#private` methods and cleanup some duplication in constructors for
subgraphNodes.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6661-Add-support-for-dynamic-widgets-2a96d73d3650817aa570c7babbaca2f3)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2025-11-20 16:53:59 -07:00
AustinMroz
6491db6f68 Further subgraph improvements (#6466)
- Prune disconnected widgets on config panel open
- Fix breakage of DOMWidgets on double nest
- Fix self clipping of proxied DOMWidget nodes
- Blacklist cloning of promtoed widget prop

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6466-Further-subgraph-improvements-29c6d73d365081c8b63dda068486805c)
by [Unito](https://www.unito.io)
2025-10-30 18:06:10 -07:00
AustinMroz
ca5729a8e7 Add pricing badge when a subgraph contains partner nodes (#6354)
<img width="596" height="213" alt="image"
src="https://github.com/user-attachments/assets/174c5461-f638-42de-b3ad-0e108dee3983"
/>


![api-badge-subgraph_00003](https://github.com/user-attachments/assets/067d0398-47e9-4e97-9e1d-67fac2935e55)


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6354-Add-pricing-badge-when-a-subgraph-contains-partner-nodes-29b6d73d365081c685bec3e9446970eb)
by [Unito](https://www.unito.io)
2025-10-29 20:41:04 -07:00
AustinMroz
6f068c87da Multiple fixes related to copying subgraphs (#6383)
- DOMWidgets have ownership reset after a `subgraphNode.clone()`.
- Fixes Ctrl+C on a subgraphNode with a prompted prompt making the
prompt disappear.
- alt + drag uses the copy/paste pathway that deeply clones subgraphs.
- Fixed dangling references on nodes in subgraphs by updating subgraph
ids before configuration.
- Attempt to recursively resolve disconnected proxyWidgets (Can matter
when subgraphs load out of order).
- Fix Right click -> clone creating linked copies of subgraphs.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6383-Multiple-fixes-related-to-copying-subgraphs-29b6d73d365081819671ced440dde327)
by [Unito](https://www.unito.io)
2025-10-29 18:05:04 -07:00
Alexander Brown
b03cf7e11d Style: Token renaming and style organization (#6337)
## Summary

Align color names and organize style.css some more

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6337-Style-Token-renaming-and-style-organization-29a6d73d365081b69f25ce1298c67fdc)
by [Unito](https://www.unito.io)
2025-10-28 12:13:28 -07:00
AustinMroz
7f5efca00b Respect minimum node size on subgraph conversion (#6241)
Two small changes to improve sizing on subgraphs
- On conversion, automatically promoted widgets can increase the minimum
width of a node. When this occurs, the node is now automatically resized
to respect this new minimum. <img width="434" height="274" alt="image"
src="https://github.com/user-attachments/assets/8b642f12-24bf-439a-a07d-b392b1f406df"
/>

- On nodes with title_badges, titles now have greatly reduced empty
padding before being abbreviated. <img width="314" height="123"
alt="image"
src="https://github.com/user-attachments/assets/4d8fd899-a159-4c0d-b309-04844b6203fc"
/>


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6241-Respect-minimum-node-size-on-subgraph-conversion-2956d73d3650817c867fe42d60afa28b)
by [Unito](https://www.unito.io)
2025-10-24 09:23:41 -07:00
AustinMroz
a0d9cc7e33 Add subgraph management keybinds (#6114)
Adds a new keybind to attempt to toggle the promotion state of the
currently hovered widget

Adds a keybind to open the subgraph configuration panel

Neither of these options are given a default binding.

Cleans up some incorrect version and icon information that was forgotten
about.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6114-Add-subgraph-management-keybinds-28f6d73d365081e6b6f3c78f99afc094)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Benjamin Lu <benceruleanlu@proton.me>
2025-10-17 15:09:37 -07:00
AustinMroz
9bfc9b740d Add additional check when restoring widgets_values (#6054)
Prior to #6014, I had identified and started on #6015 to resolve what I
believed to be a larger class of issues. While the issue I was solving
produced the same error log on the same line, I misunderstood the
circumstances in which the reported issue would occur. As proxyWidgets
do not have their own value, only linked widgets should have their value
restored from `widgets_values`. This PR adds an additional check both
that the property entry is within bounds, and that the property entry is
for a linked widget.

See #6014
A potential additional issue is still being investigated.
- Additional issue seems unrelated to fix here. Will leave issue open,
but recommend merging this as is to not block v1.28.7

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6054-Add-additional-check-when-restoring-widgets_values-28c6d73d365081489d29fc9723132db0)
by [Unito](https://www.unito.io)
2025-10-15 19:37:41 -07:00
AustinMroz
cb40da612b Safer restoration of widgets_values on subgraph nodes (#6015)
Reordering linked widgets requires special attention on load to restore
widgets_values. The method which was merged was optimistic and
insufficient for some rarer edge cases.

Resolves #6014 

Fix was already included in #6009. Backport is not required.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6015-Safer-restoration-of-widgets_values-on-subgraph-nodes-2896d73d3650813a9162e8459e686981)
by [Unito](https://www.unito.io)
2025-10-11 23:09:29 -07:00
AustinMroz
4e08ed64f0 Allow reordering of linked subgraph widgets (#5981)
Widgets which are promoted by linking to a subgraphInput node are now
also displayed in the subgraph configuration window. They can now be
reordered by drag and drop along with proxyWidgets


![linked-reorder](https://github.com/user-attachments/assets/e1b8d590-211a-4d84-9f84-3a5fd5a7aa6c)

Known Issues:
- "Hide All" will incorrectly remove physically linked widgets

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5981-Allow-reordering-of-linked-subgraph-widgets-2866d73d365081d9b27cf4a9c3078007)
by [Unito](https://www.unito.io)
2025-10-09 13:50:15 -07:00
Alexander Brown
b943c0fa75 Lint: Add tailwind linter (#5984)
## Summary

Adds the [tailwind lint
plugin](https://github.com/francoismassart/eslint-plugin-tailwindcss/?tab=readme-ov-file#eslint-plugin-tailwindcss)
and fixes the currently fixable rules ([v4 is still in
beta](https://github.com/francoismassart/eslint-plugin-tailwindcss/?tab=readme-ov-file#about-tailwind-css-4-support)).

## Changes

- **What**: Enforces things like consistent class order, and eventually
can prohibit extra classes that could be utilities instead
- **Dependencies**: The plugin and its types

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5984-Lint-Add-tailwind-linter-2866d73d365081d89db0d998232533bb)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2025-10-08 19:39:14 -07:00
Alexander Brown
874ef3ba0c Lint: Add eslint import plugin (#5955)
## Summary

Adds the linter, turns on the recommended and a few extra rules, fixes
existing violations.

Doesn't prohibit `../../...` imports yet, that'll be it's own PR.

## Changes

- **What**: Consistent and fixable imports
- **Dependencies**: The plugin and parser

## Review Focus

How do you feel about the recommended rules?
What about the extra ones?
[Any
more](https://github.com/un-ts/eslint-plugin-import-x?tab=readme-ov-file#rules)
you'd want to turn on?

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5955-Lint-Add-eslint-import-plugin-2856d73d3650819985c0fb9ca3fa94b0)
by [Unito](https://www.unito.io)
2025-10-07 20:31:00 -07:00
Alexander Brown
e7745eb2be Style: Make components themeable (#5908)
## Summary

Replace color/dark-color pairs in components with design tokens to allow
for easy overriding.
<!-- Also standardizes the icon pattern to simplify the tailwind config.
-->

## Changes

- **What**: Token based colors, for now, mostly.
- **Breaking**: Got approval from Design to collapse some very similar
pairs of colors that seem to have diverged in implementations over time.
Some of the colors might be a little different, but we can tweak them
later.

## Review Focus

Still have quite a few places from which to remove `dark-theme`, but
this at least gets the theming much closer.
Need to decide if I want to keep going in here or cut this and do the
rest in a subsequent PR.

## Screenshots (if applicable)

<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5908-WIP-Make-components-themeable-2816d73d365081ffbc05d189fe71084b)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-10-06 16:27:08 -07:00
AustinMroz
d69c54820f Subgraph widget promotion fixes (#5911)
- Fixes automatic promotion of image previews by ~~more correctly
handling a usage of `requestAnimationFrame` and~~ introducing a means to
perform actions upon successful load of preview.
- When workflows contain an old proxyWidget property in string form,
parse it instead of throwing an error.
- Do not overlay the `label` of promoted widgets. Further consideration
is needed, but this resolves the primary annoyance and prevents
untranslated widget names
See #5914

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5911-Subgraph-widget-promotion-fixes-2826d73d365081838ffeeea4b8d7068c)
by [Unito](https://www.unito.io)
2025-10-06 13:11:14 -07:00
AustinMroz
720de8cc8a Add UI code for configuring subgraphNode widgets (#5826)
The third PR for managing display of widgets on subgraph nodes. This is
the one that actually makes the functionality usable and user visible.

Adds
- A right-side modal for configuring which widgets are promoted,
accessed by right click or selection toolbar
- This menu allows for re-arranging widget order by dragging and
dropping.
- Indicators inside the subgraph for which widgets have been promoted.
- Context menu options for promoting or demoting widget inside of a
subgraph.
<img width="767" height="694" alt="image"
src="https://github.com/user-attachments/assets/4f78645d-7b26-48ba-8c49-78f4807e89e8"
/>
<img width="784" height="435" alt="image"
src="https://github.com/user-attachments/assets/7005c730-a732-481e-befb-57019a8a31a7"
/>


Known issues
- Some preview widgets are not added to a node until a draw operation
occurs. The code does not yet have a way of determining which nodes
should have draw operations forced to facilitate initial widget
creation.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5826-Add-UI-code-for-configuring-subgraphNode-widgets-27c6d73d36508146accbf395e5bcd36a)
by [Unito](https://www.unito.io)
2025-10-02 17:19:47 -07:00
Marcel Petrick
d0e81cdd33 fix(docs): correct typos in comments and strings found during code view (#5880)
Non-functional changes only:
- Fixed minor spelling mistakes in comments
- Corrected typos in user-facing strings
- No variables, logic, or functional code was modified.

Signed-off-by: Marcel Petrick <mail@marcelpetrick.it>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5880-fix-docs-correct-typos-in-comments-and-strings-found-during-code-view-27f6d73d3650815db62af6115991304a)
by [Unito](https://www.unito.io)

---------

Signed-off-by: Marcel Petrick <mail@marcelpetrick.it>
Co-authored-by: Alexander Brown <DrJKL0424@gmail.com>
Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com>
2025-10-01 18:35:38 -07:00
AustinMroz
9678a87846 Subgraph widget promotion - Part 2 (#5617)
Implements proxyWidget support on subgraph nodes.  This registers a
special proxyWidgets property on subgraph nodes which is directly mapped
to the proxyWidgets displayed on the node. Each proxyWidget directly
maps to a real widget inside the subgraph.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5617-Subgraph-widget-promotion-Part-2-2716d73d3650813d8621fefdce6ae518)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2025-09-26 10:24:55 -05:00