feat: add WidgetValueStore for centralized widget value management#8594
feat: add WidgetValueStore for centralized widget value management#8594
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a Pinia-backed WidgetValueStore and migrates widget metadata/value access to it; moves advanced/hidden flags to top-level widget fields; updates BaseWidget to register with the store; introduces global ID deduplication in LGraph; many tests updated to use Pinia and store-backed fixtures. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as Vue Component
participant Store as WidgetValueStore
participant Node as BaseWidget
participant DOM as DOM Widget
UI->>Store: read widgetState(nodeId, widgetName)
Store-->>UI: reactive widgetState (value,label,hidden,advanced,options)
UI->>Node: user interaction -> update handler
Node->>Store: registerWidget(nodeId, widgetName) / set value
Store-->>DOM: propagate reactive changes
DOM-->>UI: UI reflects updated store-backed state
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Comment |
|
Playwright: ✅ 521 passed, 0 failed · 3 flaky 📊 Browser Reports
|
🎨 Storybook Build Status✅ Build completed successfully! ⏰ Completed at: 02/11/2026, 02:23:35 AM UTC 🔗 Links🎉 Your Storybook is ready for review! |
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 22.2 kB (baseline 22.2 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 854 kB (baseline 855 kB) • 🟢 -283 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 68.8 kB (baseline 68.8 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 9 added / 9 removed Panels & Settings — 451 kB (baseline 451 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 11 added / 11 removed User & Accounts — 16 kB (baseline 16 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 5 added / 5 removed Editors & Dialogs — 751 B (baseline 751 B) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 1 added / 1 removed UI Components — 36.6 kB (baseline 36.6 kB) • ⚪ 0 BReusable component library chunks
Status: 5 added / 5 removed Data & Services — 2.13 MB (baseline 2.12 MB) • 🔴 +3.37 kBStores, services, APIs, and repositories
Status: 12 added / 12 removed Utilities & Hooks — 236 kB (baseline 236 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 12 added / 12 removed Vendor & Third-Party — 8.77 MB (baseline 8.77 MB) • ⚪ 0 BExternal libraries and shared vendor chunks
Other — 7.21 MB (baseline 7.21 MB) • 🔴 +406 BBundles that do not match a named category
Status: 54 added / 54 removed |
7d3ae89 to
474b148
Compare
|
Updating Playwright Expectations |
| promoted?: boolean | ||
| tooltip?: string | ||
|
|
||
| private _state: WidgetState |
There was a problem hiding this comment.
There are likely more properties that we'll want to move into the store.
62b9bbd to
f318a7a
Compare
| return String(scopedId).replace(/^(.*:)+/, '') as NodeId | ||
| } | ||
|
|
||
| export interface WidgetState< |
There was a problem hiding this comment.
I'm hoping to be able to remove this and instead compose types soon.
This should also let us eliminate some redundant interfaces floating around in various modules.
Amp-Thread-ID: https://ampcode.com/threads/T-019c2554-9721-705e-82f9-7742306a49cc Co-authored-by: Amp <amp@ampcode.com>
- Add _nodeId field and setNodeId() method - Delegate value getter/setter to store when node ID set - Seed store with current value on setNodeId() call Amp-Thread-ID: https://ampcode.com/threads/T-019c2559-977f-77a2-9633-d8fed5b5a2ad Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019c2567-2a52-7010-a85e-79eb76be24a1 Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019c2570-5dc2-7518-b20b-2b87f14bb2f3 Co-authored-by: Amp <amp@ampcode.com>
…tivity - BaseWidget.value getter/setter now delegates to WidgetValueStore when nodeId is set - Widget registration deferred until node is added to graph (to get valid ID) - LGraph.add() registers widgets with store after assigning node ID - Removed vueTrack pattern from useGraphNodeManager - store provides reactivity - Simplified useReactiveWidgetValue to return widget.value directly This enables reactive widget values across Vue components without custom tracking infrastructure. Extensions continue to work unchanged via the preserved widget.value API. Amp-Thread-ID: https://ampcode.com/threads/T-019c25f1-e920-70bb-afaf-59366bdab667 Co-authored-by: Amp <amp@ampcode.com>
Add WidgetState interface and widgetStates Map alongside existing values Map to support full widget lifecycle management: - WidgetState: nodeId, name, type, value, label, hidden, disabled, advanced, promoted, options, serialize - Registration: registerWidget(), unregisterWidget(), unregisterNode() - Getters: getWidget(), getNodeWidgets(), getVisibleWidgets(), getAdvancedWidgets(), getPromotedWidgets() - Setters: setHidden(), setDisabled(), setAdvanced(), setPromoted(), setLabel() Existing get/set/remove/removeNode API preserved for backward compat. set() now syncs value to WidgetState when widget is registered. Amp-Thread-ID: https://ampcode.com/threads/T-019c2626-df19-75cf-b9c9-11fe9735083d Co-authored-by: Amp <amp@ampcode.com>
- Convert label/hidden/disabled/advanced/promoted to getter/setter pairs - Getters read from store when registered, fallback to internal value - Setters update both internal field and store - Add BaseWidget.test.ts with 7 tests for store integration Amp-Thread-ID: https://ampcode.com/threads/T-019c262b-bed5-714e-bfc8-c4d6949e2fed Co-authored-by: Amp <amp@ampcode.com>
- setNodeId() now calls registerWidget() with all widget metadata - Updated BaseWidget tests with 3 new tests for automatic registration - Fixed IWidgetOptions type to use unknown instead of unknown[] Amp-Thread-ID: https://ampcode.com/threads/T-019c2631-966c-73a0-a399-7fe85bd6d495 Co-authored-by: Amp <amp@ampcode.com>
|
Thoroughly discussed offline. PR has my approval, but will be merged after 1.40.0 |
Amp-Thread-ID: https://ampcode.com/threads/T-019c44dd-e8b5-7610-973b-7bc6e554f6ec Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019c46e0-f3de-7131-bf8d-9fb1da183f38 Co-authored-by: Amp <amp@ampcode.com>
These are input-spec-derived properties set in litegraphService.ts, not widget runtime state. Restored as plain properties on BaseWidget and read from widget.options in the Vue renderer. Amp-Thread-ID: https://ampcode.com/threads/T-019c48e9-f93f-773b-b6b6-d965b479a0be Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019c48e9-f93f-773b-b6b6-d965b479a0be Co-authored-by: Amp <amp@ampcode.com>
Option exercised 🫡 |
…8861) ## Summary Add per-widget and reset-all-parameters functionality to the right side panel, allowing users to quickly revert widget values to their defaults. ## Changes - **What**: Per-widget "Reset to default" option in the WidgetActions overflow menu, plus a "Reset all parameters" button in each SectionWidgets header. Defaults are derived from the InputSpec (explicit default, then type-specific fallbacks: 0 for INT/FLOAT, false for BOOLEAN, empty string for STRING, first option for COMBO). - **Dependencies**: Builds on #8594 (WidgetValueStore) for reactive UI updates after reset. ## Review Focus - `getWidgetDefaultValue` fallback logic in `src/utils/widgetUtil.ts` — are the type-specific defaults appropriate? - Deep equality check (`isEqual`) for disabling the reset button when the value already matches the default. - Event flow: WidgetActions emits `resetToDefault` → WidgetItem forwards → SectionWidgets handles via `writeWidgetValue` (sets value, triggers callback, marks canvas dirty). ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8861-feat-add-reset-to-default-for-widget-parameters-in-right-side-panel-3076d73d365081d1aa08d5b965a16cf4) by [Unito](https://www.unito.io) Co-authored-by: Terry Jia <terryjia88@gmail.com>
…9759) ## Summary Restores `widget.inputEl` assignment on STRING multiline widgets that was removed in commit a7c2115 (PR #8594) when it was renamed to `widget.element`. Custom nodes (e.g. comfyui-custom-scripts) rely on `widget.inputEl` to call `addEventListener` or set `readOnly`. - Fixes Comfy-Org/ComfyUI#12893 ## Test plan - Verify custom nodes that access `widget.inputEl` on STRING widgets work correctly - Verify `widget.element` still works as before Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…9759) ## Summary Restores `widget.inputEl` assignment on STRING multiline widgets that was removed in commit a7c2115 (PR #8594) when it was renamed to `widget.element`. Custom nodes (e.g. comfyui-custom-scripts) rely on `widget.inputEl` to call `addEventListener` or set `readOnly`. - Fixes Comfy-Org/ComfyUI#12893 ## Test plan - Verify custom nodes that access `widget.inputEl` on STRING widgets work correctly - Verify `widget.element` still works as before Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…9759) ## Summary Restores `widget.inputEl` assignment on STRING multiline widgets that was removed in commit a7c2115 (PR #8594) when it was renamed to `widget.element`. Custom nodes (e.g. comfyui-custom-scripts) rely on `widget.inputEl` to call `addEventListener` or set `readOnly`. - Fixes Comfy-Org/ComfyUI#12893 ## Test plan - Verify custom nodes that access `widget.inputEl` on STRING widgets work correctly - Verify `widget.element` still works as before Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Implements Phase 1 of the Vue-owns-truth pattern for widget values. Widget values are now canonical in a Pinia store;
widget.valuedelegates to the store while preserving full backward compatibility.Changes
src/stores/widgetValueStore.ts- centralized widget value storage withget/set/remove/removeNodeAPIwidget.valuegetter/setter now delegates to store when widget is associated with a nodeaddCustomWidget()automatically callswidget.setNodeId(this.id)to wire widgets to their nodesWhy
This foundation enables:
computed(() => store.get(...))Backward Compatibility
widget.value = xnode.widgets[i].valuewidget.callbacknode.onWidgetChangedTesting
┆Issue is synchronized with this Notion page by Unito