Skip to content

fix: migrate DOM widgets to ComponentWidgetImpl and add element value bridge#9230

Open
christian-byrne wants to merge 4 commits intomainfrom
fix/dom-widget-value-ownership
Open

fix: migrate DOM widgets to ComponentWidgetImpl and add element value bridge#9230
christian-byrne wants to merge 4 commits intomainfrom
fix/dom-widget-value-ownership

Conversation

@christian-byrne
Copy link
Contributor

@christian-byrne christian-byrne commented Feb 26, 2026

Summary

Migrate internal DOM widgets (textarea, markdown) from raw DOM element creation via addDOMWidget to ComponentWidgetImpl, and add an element value bridge for extension compatibility.

Changes

  • What:
    • New useDomValueBridge composable — a Vue customRef bridged to a DOM element .value via Object.defineProperty interception + input event listener. Wired into addDOMWidget so extension widgets that write widget.inputEl.value = "x" (bypassing widget.value) sync to the store.
    • useStringWidget rewritten to use ComponentWidgetImpl + WidgetTextarea.vue instead of creating an orphaned raw <textarea> via addDOMWidget. Removes ~92 lines of manual DOM setup, event listeners, and store sync code.
    • useMarkdownWidget rewritten to use ComponentWidgetImpl + WidgetMarkdown.vue instead of Tiptap editor + raw DOM. Removes all Tiptap dependencies from the project.
    • WidgetTextarea.vue gains spellcheck setting support and data-testid.
  • Dependencies: Removed 9 Tiptap packages (@tiptap/core, @tiptap/extension-link, @tiptap/extension-table, @tiptap/extension-table-cell, @tiptap/extension-table-header, @tiptap/extension-table-row, @tiptap/pm, @tiptap/starter-kit, tiptap-markdown)
  • No feature loss from Tiptap removal: The old useMarkdownWidget.ts created a Tiptap editor with editable: false — it was only used as a markdown-to-HTML renderer, not as a WYSIWYG editor. Editing was done via a raw <textarea> appended alongside it. WidgetMarkdown.vue (which predates this PR) already replaces that same pattern using marked with GFM support for rendering + a <textarea> for editing. Table rendering is preserved via marked's gfm: true option, and link rendering is handled by the custom marked renderer in markdownRendererUtil.ts.

Review Focus

  • The two-strategy architecture: Store OWNS values for internal widgets (ComponentWidgetImpl — pure Vue reactivity). Store DELEGATES values for extension widgets (DOMWidgetImpl — best-effort sync via the element value bridge).
  • useDomValueBridge intercepts both programmatic writes (element.value = "x") and user input events. It chains through any existing Object.defineProperty on the element (e.g. from extensions).
  • Widget type preserved: customtext for textarea, MARKDOWN for markdown — ensures registry mappings and extension compatibility.
  • Audio widget migration (AUDIO_UI) intentionally deferred — the <audio> element is the API surface (.src, .classList, playback methods), not just a rendering detail.

Fixes #9194

┆Issue is synchronized with this Notion page by Unito

@christian-byrne christian-byrne requested a review from a team as a code owner February 26, 2026 02:59
@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Feb 26, 2026
@github-actions
Copy link

github-actions bot commented Feb 26, 2026

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 03/04/2026, 10:43:21 PM UTC

Links

@github-actions
Copy link

github-actions bot commented Feb 26, 2026

🎭 Playwright: ❌ 335 passed, 108 failed · 4 flaky

❌ Failed Tests

📊 Browser Reports

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Removed TipTap packages; replaced TipTap-based markdown and raw DOM textarea flows with component-backed widgets; added useDomValueBridge to synchronize input/textarea element values with Vue reactivity and integrated its lifecycle into domWidget to start/stop bridges and propagate updates to widget.store.

Changes

Cohort / File(s) Summary
Dependency Removal
package.json, pnpm-workspace.yaml
Removed TipTap-related dependencies and catalog entries (@tiptap/*, tiptap-markdown).
DOM Value Bridge (impl & tests)
src/composables/element/useDomValueBridge.ts, src/composables/element/useDomValueBridge.test.ts
Added useDomValueBridge that returns a Ref<string> synchronized with an input/textarea, delegates to existing descriptors when present, overrides descriptor to notify Vue when needed, listens for input events, and restores descriptor on disposal; comprehensive tests added.
domWidget lifecycle integration
src/scripts/domWidget.ts
Wired effectScope-based bridge lifecycle: start bridge for input/textarea on add, watch bridged value to update widget.value, and stop/restore on widget removal.
Multiline/string widget refactor
src/renderer/extensions/vueNodes/widgets/composables/useStringWidget.ts
Replaced raw DOM <textarea> construction with ComponentWidgetImpl usage (WidgetTextarea), removed manual DOM listeners and direct DOM value management, and initialize widget value via component path.
Markdown widget refactor
src/renderer/extensions/vueNodes/widgets/composables/useMarkdownWidget.ts
Removed TipTap editor lifecycle and in-DOM editing logic; now registers a Markdown component widget (ComponentWidgetImpl / WidgetMarkdown.vue) via shared widget API and initializes value through widget path.
WidgetTextarea component & tests
src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue, src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.test.ts
Added data-testid="dom-widget-textarea", comfy-multiline-input class, and :spellcheck binding wired to settings store; tests updated to include Pinia testing plugin in mount globals.

Sequence Diagram(s)

sequenceDiagram
  participant DOM as DOM Element
  participant Bridge as useDomValueBridge
  participant Store as Widget Store / domWidget
  participant Vue as Widget Vue Component

  rect rgba(200,220,255,0.5)
  DOM ->> Bridge: read initial value / inspect descriptor
  Bridge ->> Store: initialize widget.value (delegate or snapshot)
  end

  rect rgba(200,255,200,0.5)
  DOM -->> Bridge: user input event
  Bridge ->> Store: update widget.value (watch)
  Store ->> Vue: reactive update (store -> v-model)
  Vue ->> Store: user edits via update:modelValue
  end

  rect rgba(255,220,200,0.5)
  Store ->> Bridge: widget removal -> stop effectScope
  Bridge -->> DOM: restore original descriptor / remove listener
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nudged the bridge where inputs sleep and sigh,

Snipped TipTap threads and watched the widgets fly,
Components sing, descriptors hushed and mended,
Values hold steady, and the sync’s defended.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately and specifically describes the main changes: migrating DOM widgets to ComponentWidgetImpl and adding an element value bridge.
Description check ✅ Passed The PR description comprehensively covers all template sections with clear detail on what changed, dependencies removed, and rationale for architectural decisions.
Linked Issues check ✅ Passed The PR successfully implements the recommended approach from #9194: adding useDomValueBridge delegation for extension widgets while migrating internal widgets to ComponentWidgetImpl, addressing the architectural mismatch.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the objectives: DOM widget migration, element value bridge implementation, dependency removal, and test additions. Audio widget migration is explicitly deferred as noted.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/dom-widget-value-ownership

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 26, 2026

📦 Bundle: 4.28 MB gzip 🟢 -212 kB

Details

Summary

  • Raw size: 20.2 MB baseline 21.1 MB — 🟢 -845 kB
  • Gzip: 4.28 MB baseline 4.49 MB — 🟢 -212 kB
  • Brotli: 3.29 MB baseline 3.46 MB — 🟢 -172 kB
  • Bundles: 225 current • 227 baseline • 208 added / 210 removed

Category Glance
Vendor & Third-Party 🟢 -845 kB (8.01 MB) · Data & Services 🔴 +1.64 kB (2.73 MB) · Utilities & Hooks 🟢 -1.47 kB (54.1 kB) · Other 🟢 -1.21 kB (7.91 MB) · Views & Navigation 🔴 +501 B (72.6 kB) · Panels & Settings 🔴 +188 B (436 kB) · + 5 more

App Entry Points — 17.7 kB (baseline 17.7 kB) • 🟢 -12 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-dGTlnQol.js (removed) 17.7 kB 🟢 -17.7 kB 🟢 -6.26 kB 🟢 -5.42 kB
assets/index-Dm1sOuyp.js (new) 17.7 kB 🔴 +17.7 kB 🔴 +6.24 kB 🔴 +5.42 kB

Status: 1 added / 1 removed

Graph Workspace — 912 kB (baseline 912 kB) • 🟢 -55 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-1Zo-e7q4.js (removed) 912 kB 🟢 -912 kB 🟢 -194 kB 🟢 -147 kB
assets/GraphView-BMFFVT-b.js (new) 912 kB 🔴 +912 kB 🔴 +194 kB 🔴 +147 kB

Status: 1 added / 1 removed

Views & Navigation — 72.6 kB (baseline 72.1 kB) • 🔴 +501 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-Bx_SSqvp.js (new) 15.5 kB 🔴 +15.5 kB 🔴 +3.32 kB 🔴 +2.81 kB
assets/CloudSurveyView-Loy-Li_d.js (removed) 15.5 kB 🟢 -15.5 kB 🟢 -3.32 kB 🟢 -2.82 kB
assets/CloudLoginView-BzA3E3mV.js (new) 11.5 kB 🔴 +11.5 kB 🔴 +3.21 kB 🔴 +2.83 kB
assets/CloudLoginView-AkDc2ah6.js (removed) 11.4 kB 🟢 -11.4 kB 🟢 -3.19 kB 🟢 -2.81 kB
assets/CloudSignupView-B70dJtrG.js (new) 9.4 kB 🔴 +9.4 kB 🔴 +2.71 kB 🔴 +2.37 kB
assets/CloudSignupView-CNL3pdC-.js (removed) 9.37 kB 🟢 -9.37 kB 🟢 -2.69 kB 🟢 -2.36 kB
assets/UserCheckView-4L9PrZcj.js (removed) 8.41 kB 🟢 -8.41 kB 🟢 -2.23 kB 🟢 -1.93 kB
assets/UserCheckView-ulFTVkPS.js (new) 8.41 kB 🔴 +8.41 kB 🔴 +2.23 kB 🔴 +1.93 kB
assets/CloudLayoutView-D-pRTcHA.js (new) 6.46 kB 🔴 +6.46 kB 🔴 +2.12 kB 🔴 +1.84 kB
assets/CloudLayoutView-C0okXIyZ.js (removed) 6.43 kB 🟢 -6.43 kB 🟢 -2.1 kB 🟢 -1.83 kB
assets/CloudForgotPasswordView-9QhEE65P.js (new) 5.58 kB 🔴 +5.58 kB 🔴 +1.95 kB 🔴 +1.71 kB
assets/CloudForgotPasswordView-CuGMBoQn.js (removed) 5.56 kB 🟢 -5.56 kB 🟢 -1.93 kB 🟢 -1.7 kB
assets/CloudAuthTimeoutView-32fKXO6o.js (new) 4.94 kB 🔴 +4.94 kB 🔴 +1.79 kB 🔴 +1.56 kB
assets/CloudAuthTimeoutView-CvRdAY1w.js (removed) 4.91 kB 🟢 -4.91 kB 🟢 -1.77 kB 🟢 -1.55 kB
assets/CloudSubscriptionRedirectView-It4mzrIR.js (new) 4.78 kB 🔴 +4.78 kB 🔴 +1.8 kB 🔴 +1.59 kB
assets/CloudSubscriptionRedirectView-Jj_k1EKq.js (removed) 4.75 kB 🟢 -4.75 kB 🟢 -1.79 kB 🟢 -1.58 kB
assets/UserSelectView-CDEF6z41.js (removed) 4.5 kB 🟢 -4.5 kB 🟢 -1.64 kB 🟢 -1.46 kB
assets/UserSelectView-CHA8UlpD.js (new) 4.5 kB 🔴 +4.5 kB 🔴 +1.64 kB 🔴 +1.47 kB
assets/CloudSorryContactSupportView-kf2atGXo.js (new) 1.02 kB 🔴 +1.02 kB 🔴 +537 B 🔴 +470 B
assets/CloudSorryContactSupportView-oBJgqwAb.js (removed) 1.02 kB 🟢 -1.02 kB 🟢 -539 B 🟢 -470 B
assets/layout-U_v0Ycaz.js (new) 629 B 🔴 +629 B 🔴 +361 B 🔴 +319 B
assets/layout-C7HwWHX2.js (removed) 296 B 🟢 -296 B 🟢 -225 B 🟢 -188 B

Status: 11 added / 11 removed

Panels & Settings — 436 kB (baseline 436 kB) • 🔴 +188 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/settings-CBEvSL1z.js (removed) 38.5 kB 🟢 -38.5 kB 🟢 -9.34 kB 🟢 -7.7 kB
assets/settings-CiXfim_M.js (new) 38.5 kB 🔴 +38.5 kB 🔴 +9.34 kB 🔴 +7.7 kB
assets/settings-Bwt_U2hc.js (new) 34.2 kB 🔴 +34.2 kB 🔴 +8.33 kB 🔴 +7.01 kB
assets/settings-GRFn4guL.js (removed) 34.2 kB 🟢 -34.2 kB 🟢 -8.33 kB 🟢 -7.04 kB
assets/settings-71sPPmDw.js (new) 32.4 kB 🔴 +32.4 kB 🔴 +8.15 kB 🔴 +6.63 kB
assets/settings-DXxgnCSn.js (removed) 32.4 kB 🟢 -32.4 kB 🟢 -8.15 kB 🟢 -6.7 kB
assets/settings-CFCCJ6bh.js (new) 30.5 kB 🔴 +30.5 kB 🔴 +8.45 kB 🔴 +7.09 kB
assets/settings-CNcb_4nC.js (removed) 30.5 kB 🟢 -30.5 kB 🟢 -8.45 kB 🟢 -7.09 kB
assets/settings-B5oF6TeI.js (removed) 29.9 kB 🟢 -29.9 kB 🟢 -8.1 kB 🟢 -7.07 kB
assets/settings-BntF-aiB.js (new) 29.9 kB 🔴 +29.9 kB 🔴 +8.1 kB 🔴 +7.07 kB
assets/settings-B4se7HWo.js (new) 28.8 kB 🔴 +28.8 kB 🔴 +7.79 kB 🔴 +6.66 kB
assets/settings-mgwKIVQ2.js (removed) 28.8 kB 🟢 -28.8 kB 🟢 -7.79 kB 🟢 -6.64 kB
assets/settings-LhJVbur1.js (new) 28.7 kB 🔴 +28.7 kB 🔴 +8 kB 🔴 +7.01 kB
assets/settings-s83B801I.js (removed) 28.7 kB 🟢 -28.7 kB 🟢 -8 kB 🟢 -7.02 kB
assets/settings-DKOsOORk.js (new) 27.9 kB 🔴 +27.9 kB 🔴 +7.71 kB 🔴 +6.69 kB
assets/settings-Dw-QS6Nb.js (removed) 27.9 kB 🟢 -27.9 kB 🟢 -7.71 kB 🟢 -6.69 kB
assets/settings-BsTYoQcE.js (new) 27.8 kB 🔴 +27.8 kB 🔴 +8.12 kB 🔴 +6.77 kB
assets/settings-CGx1t8IZ.js (removed) 27.8 kB 🟢 -27.8 kB 🟢 -8.12 kB 🟢 -6.77 kB
assets/settings-BnWq3fMI.js (new) 24.5 kB 🔴 +24.5 kB 🔴 +7.91 kB 🔴 +6.35 kB
assets/settings-BVYOg4dh.js (removed) 24.5 kB 🟢 -24.5 kB 🟢 -7.9 kB 🟢 -6.36 kB
assets/settings-B7IP4XTb.js (new) 23.9 kB 🔴 +23.9 kB 🔴 +7.67 kB 🔴 +5.97 kB
assets/settings-Cx1dZM6H.js (removed) 23.9 kB 🟢 -23.9 kB 🟢 -7.67 kB 🟢 -5.97 kB
assets/SecretsPanel-DE7Kcuwr.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -5.3 kB 🟢 -4.65 kB
assets/SecretsPanel-DSqspX1n.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.3 kB 🔴 +4.65 kB
assets/LegacyCreditsPanel-DJ5XYcn-.js (new) 20.7 kB 🔴 +20.7 kB 🔴 +5.58 kB 🔴 +4.92 kB
assets/LegacyCreditsPanel-Dz5-w2H7.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.56 kB 🟢 -4.88 kB
assets/SubscriptionPanel-CEjYFGET.js (new) 18.6 kB 🔴 +18.6 kB 🔴 +4.72 kB 🔴 +4.16 kB
assets/SubscriptionPanel-CHBEAARf.js (removed) 18.6 kB 🟢 -18.6 kB 🟢 -4.72 kB 🟢 -4.15 kB
assets/KeybindingPanel-Cp4_dlUV.js (new) 12.3 kB 🔴 +12.3 kB 🔴 +3.53 kB 🔴 +3.13 kB
assets/KeybindingPanel-Di1MUJYl.js (removed) 12.3 kB 🟢 -12.3 kB 🟢 -3.51 kB 🟢 -3.11 kB
assets/AboutPanel-BEAAua0v.js (removed) 9.79 kB 🟢 -9.79 kB 🟢 -2.73 kB 🟢 -2.45 kB
assets/AboutPanel-Dvz1MI_6.js (new) 9.79 kB 🔴 +9.79 kB 🔴 +2.73 kB 🔴 +2.47 kB
assets/ExtensionPanel-DEi8mZOJ.js (new) 9.4 kB 🔴 +9.4 kB 🔴 +2.66 kB 🔴 +2.37 kB
assets/ExtensionPanel-DM9k55eK.js (removed) 9.38 kB 🟢 -9.38 kB 🟢 -2.65 kB 🟢 -2.35 kB
assets/ServerConfigPanel-Cq1fPgoD.js (new) 6.47 kB 🔴 +6.47 kB 🔴 +2.14 kB 🔴 +1.92 kB
assets/ServerConfigPanel-BzVxkAhc.js (removed) 6.44 kB 🟢 -6.44 kB 🟢 -2.12 kB 🟢 -1.91 kB
assets/UserPanel-6UASeYHm.js (new) 6.19 kB 🔴 +6.19 kB 🔴 +2.01 kB 🔴 +1.75 kB
assets/UserPanel-Ch0qyKYO.js (removed) 6.16 kB 🟢 -6.16 kB 🟢 -1.99 kB 🟢 -1.75 kB
assets/cloudRemoteConfig-BJOoaSPq.js (new) 1.47 kB 🔴 +1.47 kB 🔴 +719 B 🔴 +625 B
assets/cloudRemoteConfig-CG9hFvo6.js (removed) 1.44 kB 🟢 -1.44 kB 🟢 -699 B 🟢 -611 B
assets/refreshRemoteConfig-DpuIfkfr.js (removed) 1.14 kB 🟢 -1.14 kB 🟢 -516 B 🟢 -468 B
assets/refreshRemoteConfig-nNxm7c1F.js (new) 1.14 kB 🔴 +1.14 kB 🔴 +520 B 🔴 +456 B
assets/config-CGn5JFmU.js (removed) 996 B 🟢 -996 B 🟢 -541 B 🟢 -447 B
assets/config-CH_cdA2N.js (new) 996 B 🔴 +996 B 🔴 +541 B 🔴 +446 B

Status: 22 added / 22 removed

User & Accounts — 16.1 kB (baseline 16 kB) • 🔴 +56 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/PasswordFields-CSQ0uUu4.js (new) 4.51 kB 🔴 +4.51 kB 🔴 +1.35 kB 🔴 +1.2 kB
assets/PasswordFields-D2N9Ml9Z.js (removed) 4.51 kB 🟢 -4.51 kB 🟢 -1.35 kB 🟢 -1.19 kB
assets/auth-B5L3BScZ.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.18 kB 🔴 +988 B
assets/auth-WnXC7j-W.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.18 kB 🟢 -990 B
assets/SignUpForm-BkMwmT4l.js (removed) 3.01 kB 🟢 -3.01 kB 🟢 -1.23 kB 🟢 -1.09 kB
assets/SignUpForm-DBYt7XPn.js (new) 3.01 kB 🔴 +3.01 kB 🔴 +1.23 kB 🔴 +1.1 kB
assets/UpdatePasswordContent-BLoLtnls.js (new) 2.4 kB 🔴 +2.4 kB 🔴 +1.08 kB 🔴 +957 B
assets/UpdatePasswordContent-DNbu7USP.js (removed) 2.37 kB 🟢 -2.37 kB 🟢 -1.07 kB 🟢 -947 B
assets/WorkspaceProfilePic-CtN65k-t.js (new) 1.57 kB 🔴 +1.57 kB 🔴 +821 B 🔴 +744 B
assets/WorkspaceProfilePic-D9lCv5xq.js (removed) 1.57 kB 🟢 -1.57 kB 🟢 -821 B 🟢 -739 B
assets/firebaseAuthStore-j-djC-x5.js (new) 816 B 🔴 +816 B 🔴 +402 B 🔴 +353 B
assets/firebaseAuthStore-gsIPO2tj.js (removed) 788 B 🟢 -788 B 🟢 -382 B 🟢 -344 B
assets/auth-C6DUy746.js (new) 357 B 🔴 +357 B 🔴 +226 B 🔴 +194 B
assets/auth-DSsp18is.js (removed) 357 B 🟢 -357 B 🟢 -224 B 🟢 -190 B

Status: 7 added / 7 removed

Editors & Dialogs — 764 B (baseline 736 B) • 🔴 +28 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useSubscriptionDialog-GAy7ZNSj.js (new) 764 B 🔴 +764 B 🔴 +391 B 🔴 +333 B
assets/useSubscriptionDialog-DVZX5B0Y.js (removed) 736 B 🟢 -736 B 🟢 -373 B 🟢 -323 B

Status: 1 added / 1 removed

UI Components — 47.1 kB (baseline 47 kB) • 🔴 +84 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useTerminalTabs-BgVifm-m.js (new) 9.87 kB 🔴 +9.87 kB 🔴 +3.42 kB 🔴 +3 kB
assets/useTerminalTabs-B4mFByU1.js (removed) 9.84 kB 🟢 -9.84 kB 🟢 -3.39 kB 🟢 -3 kB
assets/ComfyQueueButton-GBUzkCnu.js (new) 8.02 kB 🔴 +8.02 kB 🔴 +2.49 kB 🔴 +2.23 kB
assets/ComfyQueueButton-QVT6OFsa.js (removed) 8.02 kB 🟢 -8.02 kB 🟢 -2.49 kB 🟢 -2.22 kB
assets/TopbarBadge-BpSw2jyq.js (removed) 7.44 kB 🟢 -7.44 kB 🟢 -1.81 kB 🟢 -1.6 kB
assets/TopbarBadge-mGv6Ww5q.js (new) 7.44 kB 🔴 +7.44 kB 🔴 +1.81 kB 🔴 +1.6 kB
assets/ScrubableNumberInput-_Rw93HFG.js (removed) 5.95 kB 🟢 -5.95 kB 🟢 -2.07 kB 🟢 -1.83 kB
assets/ScrubableNumberInput-YCcH-cvH.js (new) 5.95 kB 🔴 +5.95 kB 🔴 +2.06 kB 🔴 +1.83 kB
assets/FormSearchInput-BJeGeP_m.js (removed) 3.73 kB 🟢 -3.73 kB 🟢 -1.54 kB 🟢 -1.36 kB
assets/FormSearchInput-DCIIcwo8.js (new) 3.73 kB 🔴 +3.73 kB 🔴 +1.54 kB 🔴 +1.36 kB
assets/Button-B_0-Na0g.js (new) 3.08 kB 🔴 +3.08 kB 🔴 +1.24 kB 🔴 +1.1 kB
assets/Button-Dw6K3LMw.js (removed) 3.08 kB 🟢 -3.08 kB 🟢 -1.25 kB 🟢 -1.1 kB
assets/SubscribeButton-CLbsB-ko.js (removed) 2.34 kB 🟢 -2.34 kB 🟢 -1.01 kB 🟢 -881 B
assets/SubscribeButton-DydjSySw.js (new) 2.34 kB 🔴 +2.34 kB 🔴 +1.01 kB 🔴 +881 B
assets/WidgetButton-DN5DqC83.js (new) 1.84 kB 🔴 +1.84 kB 🔴 +874 B 🔴 +765 B
assets/WidgetButton-DQ_BOv-g.js (removed) 1.84 kB 🟢 -1.84 kB 🟢 -876 B 🟢 -765 B
assets/cloudFeedbackTopbarButton-CXKgkYr_.js (new) 1.62 kB 🔴 +1.62 kB 🔴 +865 B 🔴 +763 B
assets/cloudFeedbackTopbarButton-wirWAuvS.js (removed) 1.59 kB 🟢 -1.59 kB 🟢 -848 B 🟢 -754 B
assets/UserAvatar-4quz6WWI.js (removed) 1.17 kB 🟢 -1.17 kB 🟢 -621 B 🟢 -528 B
assets/UserAvatar-CfcAx3sc.js (new) 1.17 kB 🔴 +1.17 kB 🔴 +618 B 🔴 +527 B
assets/CloudBadge-6CtUsQEQ.js (new) 1.16 kB 🔴 +1.16 kB 🔴 +580 B 🔴 +505 B
assets/CloudBadge-y8d0lfIa.js (removed) 1.16 kB 🟢 -1.16 kB 🟢 -578 B 🟢 -506 B
assets/ComfyQueueButton-IrQfxJbH.js (new) 821 B 🔴 +821 B 🔴 +405 B 🔴 +357 B
assets/ComfyQueueButton-BirDIRaF.js (removed) 793 B 🟢 -793 B 🟢 -389 B 🟢 -349 B

Status: 12 added / 12 removed

Data & Services — 2.73 MB (baseline 2.73 MB) • 🔴 +1.64 kB

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-B1p9gOSr.js (new) 1.91 MB 🔴 +1.91 MB 🔴 +429 kB 🔴 +321 kB
assets/dialogService-DCuSFno-.js (removed) 1.91 MB 🟢 -1.91 MB 🟢 -429 kB 🟢 -321 kB
assets/api-DgoBagOU.js (removed) 689 kB 🟢 -689 kB 🟢 -155 kB 🟢 -124 kB
assets/api-BGt84Xp2.js (new) 689 kB 🔴 +689 kB 🔴 +155 kB 🔴 +124 kB
assets/load3dService-DVhKhIek.js (removed) 91 kB 🟢 -91 kB 🟢 -19.1 kB 🟢 -16.4 kB
assets/load3dService-CB0188XL.js (new) 91 kB 🔴 +91 kB 🔴 +19.1 kB 🔴 +16.4 kB
assets/extensionStore-BHKdD2s7.js (new) 13 kB 🔴 +13 kB 🔴 +4.42 kB 🔴 +3.91 kB
assets/extensionStore-BKpFb9pP.js (removed) 13 kB 🟢 -13 kB 🟢 -4.42 kB 🟢 -3.9 kB
assets/releaseStore-CvcN_hyN.js (new) 7.96 kB 🔴 +7.96 kB 🔴 +2.22 kB 🔴 +1.95 kB
assets/releaseStore-YoqqFwKr.js (removed) 7.96 kB 🟢 -7.96 kB 🟢 -2.22 kB 🟢 -1.95 kB
assets/keybindingService-CEOEI7VO.js (removed) 6.52 kB 🟢 -6.52 kB 🟢 -1.7 kB 🟢 -1.48 kB
assets/keybindingService-DNEYy8iC.js (new) 6.52 kB 🔴 +6.52 kB 🔴 +1.71 kB 🔴 +1.47 kB
assets/serverConfigStore-CjFLR4Tj.js (removed) 2.32 kB 🟢 -2.32 kB 🟢 -790 B 🟢 -693 B
assets/serverConfigStore-gMFb9Bxl.js (new) 2.32 kB 🔴 +2.32 kB 🔴 +790 B 🔴 +691 B
assets/bootstrapStore-AbyrVRPs.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -873 B 🟢 -792 B
assets/bootstrapStore-BfDDS4Vv.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +873 B 🔴 +794 B
assets/userStore-CrJcGO0W.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +722 B 🔴 +676 B
assets/userStore-DtMfd3Bf.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -717 B 🟢 -670 B
assets/audioService-DpL7yxiM.js (removed) 1.73 kB 🟢 -1.73 kB 🟢 -849 B 🟢 -726 B
assets/audioService-omrpw8Az.js (new) 1.73 kB 🔴 +1.73 kB 🔴 +849 B 🔴 +724 B
assets/releaseStore-DA9fkBvL.js (new) 788 B 🔴 +788 B 🔴 +398 B 🔴 +342 B
assets/settingStore-Dbq8pCTR.js (new) 772 B 🔴 +772 B 🔴 +400 B 🔴 +348 B
assets/workflowDraftStore-D0HCJkt1.js (new) 764 B 🔴 +764 B 🔴 +390 B 🔴 +339 B
assets/releaseStore-D2YbBiHt.js (removed) 760 B 🟢 -760 B 🟢 -377 B 🟢 -341 B
assets/dialogService-BeMEr71N.js (new) 753 B 🔴 +753 B 🔴 +383 B 🔴 +332 B
assets/settingStore-E5siUYtY.js (removed) 744 B 🟢 -744 B 🟢 -382 B 🟢 -341 B
assets/workflowDraftStore-DDsJ_otr.js (removed) 736 B 🟢 -736 B 🟢 -370 B 🟢 -335 B
assets/dialogService-BEID2e91.js (removed) 725 B 🟢 -725 B 🟢 -362 B 🟢 -322 B

Status: 14 added / 14 removed

Utilities & Hooks — 54.1 kB (baseline 55.5 kB) • 🟢 -1.47 kB

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useLoad3d-DncgaiTq.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.63 kB 🔴 +3.22 kB
assets/useLoad3d-UTyQCnJm.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.63 kB 🟢 -3.2 kB
assets/useLoad3dViewer-DA69_a5R.js (new) 14.1 kB 🔴 +14.1 kB 🔴 +3.15 kB 🔴 +2.8 kB
assets/useLoad3dViewer-SlOVEF_Z.js (removed) 14.1 kB 🟢 -14.1 kB 🟢 -3.15 kB 🟢 -2.8 kB
assets/colorUtil-BdnFBncR.js (removed) 7 kB 🟢 -7 kB 🟢 -2.14 kB 🟢 -1.9 kB
assets/colorUtil-Buh3KifE.js (new) 7 kB 🔴 +7 kB 🔴 +2.14 kB 🔴 +1.91 kB
assets/useFeatureFlags-DehCeTq7.js (new) 4.14 kB 🔴 +4.14 kB 🔴 +1.24 kB 🔴 +1.06 kB
assets/useFeatureFlags-DoumKB1J.js (removed) 4.14 kB 🟢 -4.14 kB 🟢 -1.23 kB 🟢 -1.06 kB
assets/useWorkspaceUI-gVWEZw1w.js (removed) 3 kB 🟢 -3 kB 🟢 -821 B 🟢 -703 B
assets/useWorkspaceUI-RQfwIoE_.js (new) 3 kB 🔴 +3 kB 🔴 +822 B 🔴 +708 B
assets/subscriptionCheckoutUtil-CE8-2BAL.js (new) 2.53 kB 🔴 +2.53 kB 🔴 +1.06 kB 🔴 +934 B
assets/subscriptionCheckoutUtil-D9gBJGPF.js (removed) 2.53 kB 🟢 -2.53 kB 🟢 -1.06 kB 🟢 -957 B
assets/useExternalLink-B9aoMT4L.js (new) 1.66 kB 🔴 +1.66 kB 🔴 +772 B 🔴 +679 B
assets/useExternalLink-Cbx5Gxws.js (removed) 1.66 kB 🟢 -1.66 kB 🟢 -771 B 🟢 -684 B
assets/markdownRendererUtil-BwTAJqBg.js (removed) 1.56 kB 🟢 -1.56 kB 🟢 -815 B 🟢 -697 B
assets/useErrorHandling-B4-gqEH-.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +629 B 🔴 +534 B
assets/useErrorHandling-CI6s3w32.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -630 B 🟢 -535 B
assets/useWorkspaceSwitch-DGlLDafV.js (new) 1.25 kB 🔴 +1.25 kB 🔴 +542 B 🔴 +487 B
assets/useWorkspaceSwitch-U5vLQ0F4.js (removed) 1.25 kB 🟢 -1.25 kB 🟢 -542 B 🟢 -487 B
assets/useLoad3d-UvpJlBS0.js (new) 887 B 🔴 +887 B 🔴 +439 B 🔴 +390 B
assets/useLoad3dViewer-a45Viq3w.js (new) 866 B 🔴 +866 B 🔴 +426 B 🔴 +377 B
assets/useLoad3d-DEHuVQpQ.js (removed) 859 B 🟢 -859 B 🟢 -420 B 🟢 -374 B
assets/audioUtils-V0Q10ICB.js (removed) 858 B 🟢 -858 B 🟢 -498 B 🟢 -416 B
assets/audioUtils-v8N9vjXQ.js (new) 858 B 🔴 +858 B 🔴 +501 B 🔴 +406 B
assets/useLoad3dViewer-N6ut2-Cd.js (removed) 838 B 🟢 -838 B 🟢 -405 B 🟢 -365 B
assets/useCurrentUser-Dg_Cnsws.js (new) 750 B 🔴 +750 B 🔴 +386 B 🔴 +332 B
assets/useCurrentUser-D11v51_u.js (removed) 722 B 🟢 -722 B 🟢 -366 B 🟢 -325 B
assets/SkeletonUtils-BputJAFn.js (removed) 133 B 🟢 -133 B 🟢 -114 B 🟢 -108 B
assets/SkeletonUtils-udjgEG1T.js (new) 133 B 🔴 +133 B 🔴 +114 B 🔴 +110 B
assets/_plugin-vue_export-helper-ralzwvFM.js 315 B 315 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/envUtil-Clzmwvt4.js 466 B 466 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 14 added / 15 removed

Vendor & Third-Party — 8.01 MB (baseline 8.86 MB) • 🟢 -845 kB

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-three-fZJTFMbU.js (new) 1.8 MB 🔴 +1.8 MB 🔴 +385 kB 🔴 +280 kB
assets/vendor-three-LBLOE6BD.js (removed) 1.8 MB 🟢 -1.8 MB 🟢 -385 kB 🟢 -280 kB
assets/vendor-primevue-BleJN4K0.js (removed) 1.73 MB 🟢 -1.73 MB 🟢 -312 kB 🟢 -190 kB
assets/vendor-primevue-BSUCC47U.js (new) 1.73 MB 🔴 +1.73 MB 🔴 +312 kB 🔴 +190 kB
assets/vendor-other-5I_5Qfg0.js (removed) 1.52 MB 🟢 -1.52 MB 🟢 -320 kB 🟢 -254 kB
assets/vendor-other-DWzaT72d.js (new) 1.31 MB 🔴 +1.31 MB 🔴 +256 kB 🔴 +203 kB
assets/vendor-tiptap-z9_RK3Ae.js (removed) 634 kB 🟢 -634 kB 🟢 -149 kB 🟢 -120 kB
assets/vendor-chart-BxkFiWzp.js (removed) 399 kB 🟢 -399 kB 🟢 -95.7 kB 🟢 -79.5 kB
assets/vendor-chart-D1OJsayB.js (new) 399 kB 🔴 +399 kB 🔴 +95.7 kB 🔴 +79.5 kB
assets/vendor-xterm-CWHPCody.js (new) 374 kB 🔴 +374 kB 🔴 +75.5 kB 🔴 +61 kB
assets/vendor-xterm-MKpa1ZAW.js (removed) 374 kB 🟢 -374 kB 🟢 -75.5 kB 🟢 -61 kB
assets/vendor-axios-Cp6hch1I.js 70.7 kB 70.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-firebase-BvMr43CG.js 836 kB 836 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-i18n-DccD0mxo.js 133 kB 133 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-markdown-D5S6AC80.js 103 kB 103 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-reka-ui-C-tDe-KL.js 399 kB 399 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-sentry-SQwstEKc.js 182 kB 182 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-core-CmHHRvL9.js 311 kB 311 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vueuse-cYXYo6hi.js 121 kB 121 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-yjs-CP_4YO8u.js 143 kB 143 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-zod-DcCUUPIi.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 6 removed

Other — 7.91 MB (baseline 7.91 MB) • 🟢 -1.21 kB

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/i18n-D-R48JYg.js (new) 535 kB 🔴 +535 kB 🔴 +103 kB 🔴 +80.6 kB
assets/i18n-DWSIB0xb.js (removed) 535 kB 🟢 -535 kB 🟢 -103 kB 🟢 -80.6 kB
assets/nodeDefs-BRir5eKv.js (new) 491 kB 🔴 +491 kB 🔴 +74.8 kB 🔴 +51.5 kB
assets/nodeDefs-EIvY3SXE.js (removed) 491 kB 🟢 -491 kB 🟢 -74.8 kB 🟢 -51.5 kB
assets/nodeDefs-Bcl39Lvm.js (new) 451 kB 🔴 +451 kB 🔴 +69.9 kB 🔴 +49.4 kB
assets/nodeDefs-BRiV_JqD.js (removed) 451 kB 🟢 -451 kB 🟢 -69.9 kB 🟢 -49.4 kB
assets/nodeDefs-Dh_P7hgI.js (new) 450 kB 🔴 +450 kB 🔴 +67.5 kB 🔴 +47.5 kB
assets/nodeDefs-WGHIzLau.js (removed) 450 kB 🟢 -450 kB 🟢 -67.5 kB 🟢 -47.5 kB
assets/nodeDefs-LLg_Oz68.js (new) 416 kB 🔴 +416 kB 🔴 +68 kB 🔴 +47.4 kB
assets/nodeDefs-TppPBr5S.js (removed) 416 kB 🟢 -416 kB 🟢 -68 kB 🟢 -47.5 kB
assets/nodeDefs-9jedFKUy.js (new) 404 kB 🔴 +404 kB 🔴 +66.4 kB 🔴 +47.1 kB
assets/nodeDefs-BRNi4BQJ.js (removed) 404 kB 🟢 -404 kB 🟢 -66.4 kB 🟢 -47.1 kB
assets/nodeDefs-BYxgBGHq.js (removed) 400 kB 🟢 -400 kB 🟢 -65 kB 🟢 -47.6 kB
assets/nodeDefs-DtagOBeq.js (new) 400 kB 🔴 +400 kB 🔴 +65 kB 🔴 +47.6 kB
assets/nodeDefs-BEjht2Qw.js (new) 399 kB 🔴 +399 kB 🔴 +66.5 kB 🔴 +48.2 kB
assets/nodeDefs-DY1M9TFM.js (removed) 399 kB 🟢 -399 kB 🟢 -66.5 kB 🟢 -48.2 kB
assets/nodeDefs-CRJ1lnRc.js (removed) 396 kB 🟢 -396 kB 🟢 -63.6 kB 🟢 -46.5 kB
assets/nodeDefs-GYHTPda6.js (new) 396 kB 🔴 +396 kB 🔴 +63.6 kB 🔴 +46.4 kB
assets/nodeDefs-DareRcew.js (new) 391 kB 🔴 +391 kB 🔴 +62.6 kB 🔴 +45.7 kB
assets/nodeDefs-Dp7_2zi-.js (removed) 391 kB 🟢 -391 kB 🟢 -62.6 kB 🟢 -45.8 kB
assets/nodeDefs-Czw9YrJ_.js (removed) 368 kB 🟢 -368 kB 🟢 -65.1 kB 🟢 -45.6 kB
assets/nodeDefs-XOU4GspB.js (new) 368 kB 🔴 +368 kB 🔴 +65.1 kB 🔴 +45.6 kB
assets/nodeDefs-BnufKPki.js (new) 364 kB 🔴 +364 kB 🔴 +64.2 kB 🔴 +44.5 kB
assets/nodeDefs-CYplVYdX.js (removed) 364 kB 🟢 -364 kB 🟢 -64.2 kB 🟢 -44.5 kB
assets/main-BwvjM7NS.js (removed) 210 kB 🟢 -210 kB 🟢 -54.6 kB 🟢 -43.3 kB
assets/main-pJSWgiS7.js (new) 210 kB 🔴 +210 kB 🔴 +54.6 kB 🔴 +43.3 kB
assets/main-Bpn2Hd-v.js (removed) 188 kB 🟢 -188 kB 🟢 -49.4 kB 🟢 -39.9 kB
assets/main-Bq-taiiP.js (new) 188 kB 🔴 +188 kB 🔴 +49.4 kB 🔴 +39.9 kB
assets/main-C2qCKfdm.js (removed) 181 kB 🟢 -181 kB 🟢 -49.2 kB 🟢 -39.4 kB
assets/main-CBzZ_b_M.js (new) 181 kB 🔴 +181 kB 🔴 +49.2 kB 🔴 +39.4 kB
assets/main-BfwPzKFt.js (removed) 173 kB 🟢 -173 kB 🟢 -48.9 kB 🟢 -39.1 kB
assets/main-BtQAgBzg.js (new) 173 kB 🔴 +173 kB 🔴 +48.9 kB 🔴 +39.1 kB
assets/main-BEMY9ugQ.js (removed) 158 kB 🟢 -158 kB 🟢 -47.5 kB 🟢 -39.9 kB
assets/main-BpjG3IBH.js (new) 158 kB 🔴 +158 kB 🔴 +47.5 kB 🔴 +39.9 kB
assets/main-B7Q8IAH-.js (new) 155 kB 🔴 +155 kB 🔴 +46.9 kB 🔴 +38 kB
assets/main-BSlofMTK.js (removed) 155 kB 🟢 -155 kB 🟢 -46.9 kB 🟢 -38 kB
assets/main-Cu-O7-UJ.js (removed) 153 kB 🟢 -153 kB 🟢 -46.4 kB 🟢 -38.7 kB
assets/main-iDPSIS74.js (new) 153 kB 🔴 +153 kB 🔴 +46.4 kB 🔴 +38.7 kB
assets/main-BvcTMsV_.js (new) 150 kB 🔴 +150 kB 🔴 +46.6 kB 🔴 +39.3 kB
assets/main-BzFhiL9M.js (removed) 150 kB 🟢 -150 kB 🟢 -46.6 kB 🟢 -39.3 kB
assets/main-Bii6Trku.js (removed) 150 kB 🟢 -150 kB 🟢 -46 kB 🟢 -38.7 kB
assets/main-BYJXr60l.js (new) 150 kB 🔴 +150 kB 🔴 +46 kB 🔴 +38.7 kB
assets/main-D_rzH3JH.js (removed) 133 kB 🟢 -133 kB 🟢 -45.2 kB 🟢 -36.1 kB
assets/main-DAtpIdWX.js (new) 133 kB 🔴 +133 kB 🔴 +45.2 kB 🔴 +36.1 kB
assets/main-DG7BURfj.js (new) 132 kB 🔴 +132 kB 🔴 +45.2 kB 🔴 +35.9 kB
assets/main-DWCBhr37.js (removed) 132 kB 🟢 -132 kB 🟢 -45.2 kB 🟢 -36 kB
assets/core-CTxeUmk5.js (new) 73.7 kB 🔴 +73.7 kB 🔴 +19 kB 🔴 +16.2 kB
assets/core-DgtVfG5I.js (removed) 73.6 kB 🟢 -73.6 kB 🟢 -19 kB 🟢 -16.2 kB
assets/groupNode-BzmuBrUa.js (new) 71.8 kB 🔴 +71.8 kB 🔴 +17.7 kB 🔴 +15.6 kB
assets/groupNode-D2ttUXG0.js (removed) 71.8 kB 🟢 -71.8 kB 🟢 -17.7 kB 🟢 -15.6 kB
assets/WidgetSelect-i1wAsB_T.js (removed) 58.3 kB 🟢 -58.3 kB 🟢 -12.4 kB 🟢 -10.7 kB
assets/WidgetSelect-DZ8_gvkq.js (new) 58.2 kB 🔴 +58.2 kB 🔴 +12.4 kB 🔴 +10.7 kB
assets/SubscriptionRequiredDialogContentWorkspace-Cv14c_Oz.js (new) 46.4 kB 🔴 +46.4 kB 🔴 +8.66 kB 🔴 +7.52 kB
assets/SubscriptionRequiredDialogContentWorkspace-DfGLDm9T.js (removed) 46.3 kB 🟢 -46.3 kB 🟢 -8.65 kB 🟢 -7.48 kB
assets/WidgetPainter-CgSTbzQC.js (new) 32.6 kB 🔴 +32.6 kB 🔴 +7.97 kB 🔴 +7.06 kB
assets/WidgetPainter-DIZFFh8f.js (removed) 32.5 kB 🟢 -32.5 kB 🟢 -7.95 kB 🟢 -7.04 kB
assets/Load3DControls-BPJvdh3K.js (removed) 30.9 kB 🟢 -30.9 kB 🟢 -5.34 kB 🟢 -4.65 kB
assets/Load3DControls-CKyxeJ3X.js (new) 30.9 kB 🔴 +30.9 kB 🔴 +5.34 kB 🔴 +4.65 kB
assets/WorkspacePanelContent-DejJS8ZR.js (new) 29.3 kB 🔴 +29.3 kB 🔴 +6.16 kB 🔴 +5.39 kB
assets/WorkspacePanelContent-B_iPIe6M.js (removed) 29.3 kB 🟢 -29.3 kB 🟢 -6.14 kB 🟢 -5.41 kB
assets/SubscriptionRequiredDialogContent-DPf5Ddig.js (new) 25.7 kB 🔴 +25.7 kB 🔴 +6.58 kB 🔴 +5.78 kB
assets/SubscriptionRequiredDialogContent-CmlGURO0.js (removed) 25.7 kB 🟢 -25.7 kB 🟢 -6.57 kB 🟢 -5.77 kB
assets/Load3dViewerContent-aTEaj4dT.js (new) 23 kB 🔴 +23 kB 🔴 +5.18 kB 🔴 +4.5 kB
assets/Load3dViewerContent-Ca1aK0iD.js (removed) 23 kB 🟢 -23 kB 🟢 -5.18 kB 🟢 -4.49 kB
assets/WidgetImageCrop-Ce66_Tw_.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +5.52 kB 🔴 +4.86 kB
assets/WidgetImageCrop-DlLKmzSv.js (removed) 22.1 kB 🟢 -22.1 kB 🟢 -5.51 kB 🟢 -4.84 kB
assets/SubscriptionPanelContentWorkspace-BvcwFJ-X.js (new) 22 kB 🔴 +22 kB 🔴 +5.11 kB 🔴 +4.5 kB
assets/SubscriptionPanelContentWorkspace-DpVAh8gx.js (removed) 22 kB 🟢 -22 kB 🟢 -5.11 kB 🟢 -4.5 kB
assets/CurrentUserPopoverWorkspace-CO9oDvzg.js (new) 20.5 kB 🔴 +20.5 kB 🔴 +4.95 kB 🔴 +4.41 kB
assets/CurrentUserPopoverWorkspace-fJFjmcdR.js (removed) 20.4 kB 🟢 -20.4 kB 🟢 -4.93 kB 🟢 -4.4 kB
assets/commands-BFgRi4P3.js (removed) 19 kB 🟢 -19 kB 🟢 -4.05 kB 🟢 -3.14 kB
assets/commands-BMLsYxKd.js (new) 19 kB 🔴 +19 kB 🔴 +4.05 kB 🔴 +3.14 kB
assets/SignInContent-DdKTdTs4.js (new) 18.9 kB 🔴 +18.9 kB 🔴 +4.77 kB 🔴 +4.17 kB
assets/SignInContent-nqRXbvj7.js (removed) 18.9 kB 🟢 -18.9 kB 🟢 -4.76 kB 🟢 -4.17 kB
assets/WidgetInputNumber-DJd7qhfM.js (removed) 18.8 kB 🟢 -18.8 kB 🟢 -4.8 kB 🟢 -4.27 kB
assets/WidgetInputNumber-R2wjSOxi.js (new) 18.8 kB 🔴 +18.8 kB 🔴 +4.8 kB 🔴 +4.27 kB
assets/commands-BUxt8PgP.js (removed) 17.7 kB 🟢 -17.7 kB 🟢 -3.73 kB 🟢 -2.9 kB
assets/commands-DZFUlDVf.js (new) 17.7 kB 🔴 +17.7 kB 🔴 +3.73 kB 🔴 +2.9 kB
assets/commands-Bfucg9mP.js (new) 17.7 kB 🔴 +17.7 kB 🔴 +3.8 kB 🔴 +2.98 kB
assets/commands-CaYVZOZt.js (removed) 17.7 kB 🟢 -17.7 kB 🟢 -3.8 kB 🟢 -2.99 kB
assets/WidgetRecordAudio-EY8A6Zgj.js (new) 17.4 kB 🔴 +17.4 kB 🔴 +5.01 kB 🔴 +4.48 kB
assets/WidgetRecordAudio-DGGLrQL-.js (removed) 17.4 kB 🟢 -17.4 kB 🟢 -4.99 kB 🟢 -4.45 kB
assets/commands-BWxUDagn.js (removed) 17.1 kB 🟢 -17.1 kB 🟢 -3.83 kB 🟢 -3.02 kB
assets/commands-CCml88sK.js (new) 17.1 kB 🔴 +17.1 kB 🔴 +3.83 kB 🔴 +3.02 kB
assets/commands-DstS1-8g.js (new) 16.9 kB 🔴 +16.9 kB 🔴 +3.56 kB 🔴 +2.97 kB
assets/commands-DU-y2_NM.js (removed) 16.9 kB 🟢 -16.9 kB 🟢 -3.56 kB 🟢 -2.97 kB
assets/commands-BEB4P0rH.js (new) 16.3 kB 🔴 +16.3 kB 🔴 +3.56 kB 🔴 +2.95 kB
assets/commands-BEYCqLzR.js (removed) 16.3 kB 🟢 -16.3 kB 🟢 -3.56 kB 🟢 -2.95 kB
assets/commands-CTQPlIVl.js (removed) 16.3 kB 🟢 -16.3 kB 🟢 -3.45 kB 🟢 -2.79 kB
assets/commands-CXLXD2h2.js (new) 16.3 kB 🔴 +16.3 kB 🔴 +3.45 kB 🔴 +2.79 kB
assets/commands-DbC3OFpW.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +3.41 kB 🔴 +2.85 kB
assets/commands-Ji49gKfP.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -3.42 kB 🟢 -2.85 kB
assets/Load3D-4YdvkcKN.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +4.02 kB 🔴 +3.51 kB
assets/Load3D-BZPQ0_k2.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -4.03 kB 🟢 -3.51 kB
assets/commands-BbyDu2gv.js (new) 16.1 kB 🔴 +16.1 kB 🔴 +3.69 kB 🔴 +2.87 kB
assets/commands-DBek0Hch.js (removed) 16.1 kB 🟢 -16.1 kB 🟢 -3.69 kB 🟢 -2.87 kB
assets/commands-CAkQMSj_.js (new) 15.4 kB 🔴 +15.4 kB 🔴 +3.61 kB 🔴 +2.72 kB
assets/commands-g_-oH-q2.js (removed) 15.4 kB 🟢 -15.4 kB 🟢 -3.61 kB 🟢 -2.73 kB
assets/commands-CQAp--Ck.js (removed) 15.2 kB 🟢 -15.2 kB 🟢 -3.57 kB 🟢 -2.66 kB
assets/commands-DSqCRthz.js (new) 15.2 kB 🔴 +15.2 kB 🔴 +3.57 kB 🔴 +2.67 kB
assets/load3d-D4louSZE.js (new) 14.8 kB 🔴 +14.8 kB 🔴 +4.21 kB 🔴 +3.64 kB
assets/load3d-dWo-n-dG.js (removed) 14.7 kB 🟢 -14.7 kB 🟢 -4.19 kB 🟢 -3.63 kB
assets/AudioPreviewPlayer-BWQfJs9w.js (new) 11 kB 🔴 +11 kB 🔴 +3.25 kB 🔴 +2.92 kB
assets/AudioPreviewPlayer-BmTPwZQ2.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -3.23 kB 🟢 -2.88 kB
assets/changeTracker-_KvaA4tV.js (new) 9.43 kB 🔴 +9.43 kB 🔴 +2.9 kB 🔴 +2.55 kB
assets/changeTracker-DBdD528B.js (removed) 9.43 kB 🟢 -9.43 kB 🟢 -2.9 kB 🟢 -2.55 kB
assets/WidgetCurve-CcAQLD_P.js (new) 9.36 kB 🔴 +9.36 kB 🔴 +3 kB 🔴 +2.71 kB
assets/WidgetCurve-D_JEKVtF.js (removed) 9.36 kB 🟢 -9.36 kB 🟢 -3 kB 🟢 -2.71 kB
assets/nodeTemplates-BRtVleMO.js (new) 9.32 kB 🔴 +9.32 kB 🔴 +3.27 kB 🔴 +2.87 kB
assets/nodeTemplates-DtS5tOP8.js (removed) 9.29 kB 🟢 -9.29 kB 🟢 -3.25 kB 🟢 -2.85 kB
assets/SelectValue-C7rPyMBI.js (new) 8.94 kB 🔴 +8.94 kB 🔴 +2.27 kB 🔴 +2 kB
assets/SelectValue-mHgijvCJ.js (removed) 8.94 kB 🟢 -8.94 kB 🟢 -2.27 kB 🟢 -2 kB
assets/InviteMemberDialogContent-DOSH2N8G.js (new) 7.41 kB 🔴 +7.41 kB 🔴 +2.31 kB 🔴 +2 kB
assets/InviteMemberDialogContent-B33xWBFO.js (removed) 7.38 kB 🟢 -7.38 kB 🟢 -2.29 kB 🟢 -1.99 kB
assets/WidgetImageCompare-C6hTlaKi.js (removed) 7 kB 🟢 -7 kB 🟢 -2.07 kB 🟢 -1.81 kB
assets/WidgetImageCompare-chQlQ6fX.js (new) 7 kB 🔴 +7 kB 🔴 +2.07 kB 🔴 +1.81 kB
assets/WidgetToggleSwitch-BBrQMwt0.js (removed) 6.8 kB 🟢 -6.8 kB 🟢 -2.19 kB 🟢 -1.94 kB
assets/WidgetToggleSwitch-BGCf6s5t.js (new) 6.76 kB 🔴 +6.76 kB 🔴 +2.18 kB 🔴 +1.92 kB
assets/Load3DConfiguration-BOTAhhxX.js (removed) 6.27 kB 🟢 -6.27 kB 🟢 -1.91 kB 🟢 -1.67 kB
assets/Load3DConfiguration-BPgVo5H2.js (new) 6.27 kB 🔴 +6.27 kB 🔴 +1.91 kB 🔴 +1.68 kB
assets/CreateWorkspaceDialogContent-BqxovG0q.js (new) 5.55 kB 🔴 +5.55 kB 🔴 +2.01 kB 🔴 +1.75 kB
assets/CreateWorkspaceDialogContent-BCj1nskF.js (removed) 5.53 kB 🟢 -5.53 kB 🟢 -1.99 kB 🟢 -1.73 kB
assets/FreeTierDialogContent-Cq9-7oqu.js (new) 5.42 kB 🔴 +5.42 kB 🔴 +1.91 kB 🔴 +1.69 kB
assets/onboardingCloudRoutes-BxiFVv_W.js (removed) 5.41 kB 🟢 -5.41 kB 🟢 -1.84 kB 🟢 -1.61 kB
assets/onboardingCloudRoutes-Co7C5RoW.js (new) 5.4 kB 🔴 +5.4 kB 🔴 +1.83 kB 🔴 +1.6 kB
assets/FreeTierDialogContent-CY5GfwAp.js (removed) 5.39 kB 🟢 -5.39 kB 🟢 -1.89 kB 🟢 -1.67 kB
assets/EditWorkspaceDialogContent-CzhWTkrM.js (new) 5.36 kB 🔴 +5.36 kB 🔴 +1.96 kB 🔴 +1.71 kB
assets/EditWorkspaceDialogContent-COwaEHtW.js (removed) 5.33 kB 🟢 -5.33 kB 🟢 -1.94 kB 🟢 -1.69 kB
assets/ValueControlPopover-CpCSbjJa.js (new) 4.95 kB 🔴 +4.95 kB 🔴 +1.78 kB 🔴 +1.59 kB
assets/ValueControlPopover-A4kKtAzT.js (removed) 4.92 kB 🟢 -4.92 kB 🟢 -1.76 kB 🟢 -1.58 kB
assets/Preview3d-Do0vbNSw.js (new) 4.88 kB 🔴 +4.88 kB 🔴 +1.61 kB 🔴 +1.4 kB
assets/Preview3d-CD6qLSXO.js (removed) 4.85 kB 🟢 -4.85 kB 🟢 -1.59 kB 🟢 -1.4 kB
assets/CancelSubscriptionDialogContent-Cb6NHKIT.js (new) 4.82 kB 🔴 +4.82 kB 🔴 +1.8 kB 🔴 +1.58 kB
assets/CancelSubscriptionDialogContent-D18dQ8Q0.js (removed) 4.79 kB 🟢 -4.79 kB 🟢 -1.78 kB 🟢 -1.56 kB
assets/AnimationControls-CLBE0-3G.js (new) 4.61 kB 🔴 +4.61 kB 🔴 +1.6 kB 🔴 +1.41 kB
assets/AnimationControls-rvj0ANn9.js (removed) 4.61 kB 🟢 -4.61 kB 🟢 -1.6 kB 🟢 -1.41 kB
assets/DeleteWorkspaceDialogContent-CcYvby7j.js (new) 4.26 kB 🔴 +4.26 kB 🔴 +1.65 kB 🔴 +1.43 kB
assets/WidgetMarkdown-B2Um-cw_.js (new) 4.23 kB 🔴 +4.23 kB 🔴 +1.82 kB 🔴 +1.58 kB
assets/DeleteWorkspaceDialogContent-B2EKEvw-.js (removed) 4.23 kB 🟢 -4.23 kB 🟢 -1.63 kB 🟢 -1.42 kB
assets/WidgetWithControl-DMMELLbl.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.77 kB 🟢 -1.59 kB
assets/WidgetWithControl-LWWrGyCE.js (new) 4.09 kB 🔴 +4.09 kB 🔴 +1.77 kB 🔴 +1.61 kB
assets/LeaveWorkspaceDialogContent-Di-YhJzs.js (new) 4.09 kB 🔴 +4.09 kB 🔴 +1.59 kB 🔴 +1.39 kB
assets/RemoveMemberDialogContent-CmaCIlCQ.js (new) 4.07 kB 🔴 +4.07 kB 🔴 +1.54 kB 🔴 +1.34 kB
assets/LeaveWorkspaceDialogContent-Vntdi4w0.js (removed) 4.06 kB 🟢 -4.06 kB 🟢 -1.57 kB 🟢 -1.37 kB
assets/RemoveMemberDialogContent-DKrqXuk8.js (removed) 4.04 kB 🟢 -4.04 kB 🟢 -1.52 kB 🟢 -1.33 kB
assets/RevokeInviteDialogContent-G76N0bIk.js (new) 3.98 kB 🔴 +3.98 kB 🔴 +1.56 kB 🔴 +1.37 kB
assets/WidgetTextarea-D4ckclZT.js (removed) 3.96 kB 🟢 -3.96 kB 🟢 -1.49 kB 🟢 -1.3 kB
assets/RevokeInviteDialogContent-Y50DBdXb.js (removed) 3.95 kB 🟢 -3.95 kB 🟢 -1.54 kB 🟢 -1.36 kB
assets/InviteMemberUpsellDialogContent-Bg4vFSpe.js (new) 3.85 kB 🔴 +3.85 kB 🔴 +1.42 kB 🔴 +1.24 kB
assets/InviteMemberUpsellDialogContent-CYSAk0cG.js (removed) 3.82 kB 🟢 -3.82 kB 🟢 -1.4 kB 🟢 -1.23 kB
assets/tierBenefits-BYfB1IRp.js (new) 3.66 kB 🔴 +3.66 kB 🔴 +1.3 kB 🔴 +1.15 kB
assets/tierBenefits-CpepENSZ.js (removed) 3.66 kB 🟢 -3.66 kB 🟢 -1.3 kB 🟢 -1.15 kB
assets/Popover-CiXBGsU8.js (removed) 3.65 kB 🟢 -3.65 kB 🟢 -1.44 kB 🟢 -1.27 kB
assets/Popover-Co6Uv-6a.js (new) 3.65 kB 🔴 +3.65 kB 🔴 +1.44 kB 🔴 +1.27 kB
assets/WidgetGalleria-BHbklsS7.js (removed) 3.61 kB 🟢 -3.61 kB 🟢 -1.39 kB 🟢 -1.25 kB
assets/WidgetGalleria-CIaHSZ3e.js (new) 3.61 kB 🔴 +3.61 kB 🔴 +1.39 kB 🔴 +1.25 kB
assets/Slider-BQpkVGjT.js (new) 3.52 kB 🔴 +3.52 kB 🔴 +1.36 kB 🔴 +1.19 kB
assets/Slider-CQRjYlXR.js (removed) 3.52 kB 🟢 -3.52 kB 🟢 -1.36 kB 🟢 -1.22 kB
assets/saveMesh-dXaNtMeu.js (new) 3.41 kB 🔴 +3.41 kB 🔴 +1.47 kB 🔴 +1.32 kB
assets/saveMesh-CCvlHpQX.js (removed) 3.38 kB 🟢 -3.38 kB 🟢 -1.45 kB 🟢 -1.29 kB
assets/WidgetBoundingBox-aM9dgT_H.js (removed) 3.19 kB 🟢 -3.19 kB 🟢 -895 B 🟢 -779 B
assets/WidgetBoundingBox-Djv2HTYe.js (new) 3.19 kB 🔴 +3.19 kB 🔴 +895 B 🔴 +778 B
assets/cloudSessionCookie-Du68wwOw.js (new) 3.13 kB 🔴 +3.13 kB 🔴 +1.1 kB 🔴 +959 B
assets/cloudSessionCookie-ByacqpEf.js (removed) 3.1 kB 🟢 -3.1 kB 🟢 -1.08 kB 🟢 -977 B
assets/WidgetMarkdown-CFetMknf.js (removed) 2.93 kB 🟢 -2.93 kB 🟢 -1.23 kB 🟢 -1.08 kB
assets/GlobalToast-B6GXBXmK.js (removed) 2.91 kB 🟢 -2.91 kB 🟢 -1.21 kB 🟢 -1.03 kB
assets/GlobalToast-mhTYcUMD.js (new) 2.91 kB 🔴 +2.91 kB 🔴 +1.21 kB 🔴 +1.07 kB
assets/WidgetColorPicker-ckOPhgJO.js (new) 2.9 kB 🔴 +2.9 kB 🔴 +1.23 kB 🔴 +1.1 kB
assets/WidgetColorPicker-DfzN4kvf.js (removed) 2.9 kB 🟢 -2.9 kB 🟢 -1.23 kB 🟢 -1.11 kB
assets/MediaVideoTop-C5eK56v1.js (removed) 2.77 kB 🟢 -2.77 kB 🟢 -1.13 kB 🟢 -1.01 kB
assets/MediaVideoTop-Dm6nc4g7.js (new) 2.77 kB 🔴 +2.77 kB 🔴 +1.13 kB 🔴 +1.01 kB
assets/ApiNodesSignInContent-CV6ueEHE.js (removed) 2.69 kB 🟢 -2.69 kB 🟢 -1.05 kB 🟢 -957 B
assets/ApiNodesSignInContent-DVG6cRCQ.js (new) 2.69 kB 🔴 +2.69 kB 🔴 +1.05 kB 🔴 +953 B
assets/WidgetChart-BF6Uqf9O.js (removed) 2.21 kB 🟢 -2.21 kB 🟢 -954 B 🟢 -824 B
assets/WidgetChart-DaL3Dp9F.js (new) 2.21 kB 🔴 +2.21 kB 🔴 +953 B 🔴 +825 B
assets/SubscribeToRun-BTqGcxdn.js (removed) 2.06 kB 🟢 -2.06 kB 🟢 -949 B 🟢 -830 B
assets/SubscribeToRun-CqfzHzpo.js (new) 2.06 kB 🔴 +2.06 kB 🔴 +947 B 🔴 +848 B
assets/SubscriptionBenefits-CC52XK_P.js (removed) 2.01 kB 🟢 -2.01 kB 🟢 -702 B 🟢 -600 B
assets/SubscriptionBenefits-D1DueXTw.js (new) 2.01 kB 🔴 +2.01 kB 🔴 +701 B 🔴 +599 B
assets/WidgetLayoutField-CIhDMEfL.js (removed) 1.98 kB 🟢 -1.98 kB 🟢 -892 B 🟢 -792 B
assets/WidgetLayoutField-B67WUo8X.js (new) 1.98 kB 🔴 +1.98 kB 🔴 +890 B 🔴 +795 B
assets/WidgetInputText-CwLynoNC.js (removed) 1.86 kB 🟢 -1.86 kB 🟢 -874 B 🟢 -796 B
assets/WidgetInputText-Dpl6n9rz.js (new) 1.86 kB 🔴 +1.86 kB 🔴 +872 B 🔴 +791 B
assets/Media3DTop-B8kwOZX2.js (new) 1.82 kB 🔴 +1.82 kB 🔴 +901 B 🔴 +770 B
assets/Media3DTop-DjGAidD-.js (removed) 1.82 kB 🟢 -1.82 kB 🟢 -898 B 🟢 -768 B
assets/BaseViewTemplate-BNRU5hKJ.js (removed) 1.78 kB 🟢 -1.78 kB 🟢 -924 B 🟢 -804 B
assets/BaseViewTemplate-Ca2CiJVB.js (new) 1.78 kB 🔴 +1.78 kB 🔴 +924 B 🔴 +804 B
assets/MediaImageTop-B7hI8C6m.js (new) 1.75 kB 🔴 +1.75 kB 🔴 +880 B 🔴 +749 B
assets/MediaImageTop-CCi6hDYh.js (removed) 1.75 kB 🟢 -1.75 kB 🟢 -879 B 🟢 -753 B
assets/CloudRunButtonWrapper-CKdVhCZk.js (new) 1.7 kB 🔴 +1.7 kB 🔴 +803 B 🔴 +716 B
assets/auto-BTnZwrs2.js (removed) 1.7 kB 🟢 -1.7 kB 🟢 -619 B 🟢 -549 B
assets/auto-Mr7ZnDOO.js (new) 1.7 kB 🔴 +1.7 kB 🔴 +619 B 🔴 +562 B
assets/CloudRunButtonWrapper-ipIVWIIX.js (removed) 1.68 kB 🟢 -1.68 kB 🟢 -781 B 🟢 -713 B
assets/signInSchema-CTd1qZoR.js (new) 1.53 kB 🔴 +1.53 kB 🔴 +563 B 🔴 +516 B
assets/signInSchema-D4M-Ad2-.js (removed) 1.53 kB 🟢 -1.53 kB 🟢 -562 B 🟢 -525 B
assets/MediaAudioTop-CXjvquTX.js (removed) 1.43 kB 🟢 -1.43 kB 🟢 -765 B 🟢 -638 B
assets/MediaAudioTop-DDTuINa7.js (new) 1.43 kB 🔴 +1.43 kB 🔴 +764 B 🔴 +638 B
assets/cloudBadges-CzFa-rJU.js (new) 1.39 kB 🔴 +1.39 kB 🔴 +717 B 🔴 +623 B
assets/previousFullPath-BPijTOEX.js (new) 1.39 kB 🔴 +1.39 kB 🔴 +650 B 🔴 +579 B
assets/previousFullPath-fPz-S114.js (removed) 1.39 kB 🟢 -1.39 kB 🟢 -649 B 🟢 -566 B
assets/cloudBadges-DeLGoTtY.js (removed) 1.36 kB 🟢 -1.36 kB 🟢 -703 B 🟢 -613 B
assets/cloudSubscription-Ly2tYa9B.js (new) 1.35 kB 🔴 +1.35 kB 🔴 +670 B 🔴 +578 B
assets/VideoPlayOverlay-Cka4lq1O.js (new) 1.35 kB 🔴 +1.35 kB 🔴 +702 B 🔴 +621 B
assets/VideoPlayOverlay-D_dHFUc0.js (removed) 1.35 kB 🟢 -1.35 kB 🟢 -701 B 🟢 -623 B
assets/cloudSubscription-AcZRxZI1.js (removed) 1.33 kB 🟢 -1.33 kB 🟢 -652 B 🟢 -573 B
assets/widgetPropFilter-CRLfTD3C.js (new) 1.1 kB 🔴 +1.1 kB 🔴 +508 B 🔴 +429 B
assets/widgetPropFilter-DN03zIgB.js (removed) 1.1 kB 🟢 -1.1 kB 🟢 -510 B 🟢 -432 B
assets/Load3D-Bt-7HxuM.js (new) 1.1 kB 🔴 +1.1 kB 🔴 +513 B 🔴 +451 B
assets/Load3D-Boxz-edt.js (removed) 1.07 kB 🟢 -1.07 kB 🟢 -491 B 🟢 -441 B
assets/nightlyBadges-FsvhYX_3.js (new) 1.03 kB 🔴 +1.03 kB 🔴 +545 B 🔴 +488 B
assets/Load3dViewerContent-DPMzdmSR.js (new) 1.02 kB 🔴 +1.02 kB 🔴 +484 B 🔴 +423 B
assets/MediaOtherTop-DdexkKM5.js (new) 1.02 kB 🔴 +1.02 kB 🔴 +568 B 🔴 +473 B
assets/MediaOtherTop-z-FoiFro.js (removed) 1.02 kB 🟢 -1.02 kB 🟢 -566 B 🟢 -473 B
assets/MediaTextTop-BUmyBrmT.js (removed) 1.01 kB 🟢 -1.01 kB 🟢 -563 B 🟢 -477 B
assets/MediaTextTop-DwMYdDEr.js (new) 1.01 kB 🔴 +1.01 kB 🔴 +564 B 🔴 +478 B
assets/nightlyBadges-pbSLuGjg.js (removed) 1 kB 🟢 -1 kB 🟢 -525 B 🟢 -470 B
assets/Load3dViewerContent-DcG15IQm.js (removed) 993 B 🟢 -993 B 🟢 -461 B 🟢 -415 B
assets/SubscriptionPanelContentWorkspace-BdQHUtM0.js (new) 948 B 🔴 +948 B 🔴 +450 B 🔴 +383 B
assets/SubscriptionPanelContentWorkspace-CK8ltaig.js (removed) 920 B 🟢 -920 B 🟢 -434 B 🟢 -377 B
assets/ComfyOrgHeader-BbfHqQlJ.js (removed) 910 B 🟢 -910 B 🟢 -498 B 🟢 -426 B
assets/ComfyOrgHeader-BiqY9Lcy.js (new) 910 B 🔴 +910 B 🔴 +496 B 🔴 +426 B
assets/changeTracker-smOVIYeu.js (new) 785 B 🔴 +785 B 🔴 +397 B 🔴 +341 B
assets/WidgetTextarea-CJQ6Y2wU.js (new) 777 B 🔴 +777 B 🔴 +396 B 🔴 +340 B
assets/WidgetLegacy-BLxWr4oO.js (new) 772 B 🔴 +772 B 🔴 +396 B 🔴 +363 B
assets/graphHasMissingNodes-Cm8D6zIs.js (new) 761 B 🔴 +761 B 🔴 +374 B 🔴 +315 B
assets/graphHasMissingNodes-CvTgpJS2.js (removed) 761 B 🟢 -761 B 🟢 -373 B 🟢 -323 B
assets/changeTracker-BOL6A97M.js (removed) 757 B 🟢 -757 B 🟢 -379 B 🟢 -333 B
assets/WidgetLegacy-BsF8ULRE.js (removed) 744 B 🟢 -744 B 🟢 -381 B 🟢 -335 B
assets/constants-Cl4K4L4H.js (new) 579 B 🔴 +579 B 🔴 +257 B 🔴 +232 B
assets/constants-htt0vt7m.js (removed) 579 B 🟢 -579 B 🟢 -257 B 🟢 -212 B
assets/widgetTypes-DYLaC2lj.js (removed) 393 B 🟢 -393 B 🟢 -257 B 🟢 -243 B
assets/WidgetBoundingBox-BwuHEI4p.js (new) 283 B 🔴 +283 B 🔴 +182 B 🔴 +162 B
assets/WidgetBoundingBox-BYsbWVeN.js (removed) 283 B 🟢 -283 B 🟢 -186 B 🟢 -162 B
assets/src-0j89C3u5.js (new) 251 B 🔴 +251 B 🔴 +213 B 🔴 +183 B
assets/src-DqM23qfs.js (removed) 251 B 🟢 -251 B 🟢 -211 B 🟢 -197 B
assets/WidgetMarkdown-CSoah_x9.js (new) 202 B 🔴 +202 B 🔴 +142 B 🔴 +126 B
assets/i18n-BSY-PFQs.js (removed) 199 B 🟢 -199 B 🟢 -162 B 🟢 -140 B
assets/i18n-ch294GXZ.js (new) 199 B 🔴 +199 B 🔴 +162 B 🔴 +140 B
assets/comfy-logo-single-C9H6LVPO.js (new) 198 B 🔴 +198 B 🔴 +163 B 🔴 +127 B
assets/comfy-logo-single-D9MrYETV.js (removed) 198 B 🟢 -198 B 🟢 -162 B 🟢 -126 B
assets/OBJLoader2WorkerModule-DTMpvldF.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/rolldown-runtime-DLICfi3-.js 1.97 kB 1.97 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/telemetry-zZf2dHJ2.js 226 B 226 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/types-DT3N7am7.js 204 B 204 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widget-DIRwAHBY.js 3.01 kB 3.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 120 added / 120 removed

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/composables/element/useDomValueBridge.test.ts (1)

72-139: Add a non-configurable descriptor regression test.

Current descriptor-path tests cover chaining/restoration, but not configurable: false. Adding that case would protect against runtime throw regressions in bridge setup.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/composables/element/useDomValueBridge.test.ts` around lines 72 - 139, Add
a new test that ensures useDomValueBridge handles a non-configurable descriptor
without throwing and restores behavior: create a non-configurable property
descriptor on element for 'value' via Object.defineProperty (configurable:
false) with appropriate get/set delegating to HTMLTextAreaElement.prototype's
native descriptor, wrap useDomValueBridge call inside an effectScope().run and
call scope.stop(), then assert no exception occurred, the descriptor remained
non-configurable during the scope (Object.getOwnPropertyDescriptor(element,
'value') is defined), and after scope.stop() the descriptor is still present and
unchanged (verify configurable is false and the custom getter/setter were
preserved or called as expected). Reference useDomValueBridge, effectScope,
Object.defineProperty, and the 'value' property on element in the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/composables/element/useDomValueBridge.ts`:
- Around line 43-53: Before calling Object.defineProperty on element.value, read
the current descriptor with Object.getOwnPropertyDescriptor(element, 'value')
and only perform the override if the descriptor is missing or
descriptor.configurable === true; if it's non-configurable, skip the redefine
and set a flag (e.g., skippedOverride) so callers know no override was
installed. Do the same check in the cleanup/restore logic (where you currently
attempt to restore prevGet/prevSet) and only restore or delete the property if
the original descriptor was configurable (otherwise leave it untouched);
reference the symbols element, prevGet, prevSet, notifyChange and the
cleanup/restore block to locate both places to add the conditional guard.

In `@src/renderer/extensions/vueNodes/widgets/composables/useStringWidget.ts`:
- Line 22: Change the placeholder fallback in useStringWidget.ts to use nullish
coalescing so explicit empty placeholders are preserved: replace the use of
opts.placeholder || name with a nullish check (opts.placeholder ?? name) in the
props object (see the props: { placeholder: ... } expression) so only
null/undefined fall back to name.

In `@src/scripts/domWidget.ts`:
- Around line 430-432: The current useChainCallback call unconditionally calls
bridgeScope.stop() in widget.onRemove which wrongly tears down the bridge during
subgraph moves; change the teardown to only run for genuine deletions (e.g.
check the node/widget destruction/attachment state before calling
bridgeScope.stop) and/or move bridgeScope.stop into a true destroy callback,
while adding a complementary setup re-run when the widget is (re)attached (e.g.,
run the bridge setup from the widget attach/onAdd handler); update the
references around widget.onRemove, useChainCallback, and bridgeScope.stop and
ensure the bridge setup is invoked in the widget attach/onAdd path so
restructured widgets regain synchronization.

---

Nitpick comments:
In `@src/composables/element/useDomValueBridge.test.ts`:
- Around line 72-139: Add a new test that ensures useDomValueBridge handles a
non-configurable descriptor without throwing and restores behavior: create a
non-configurable property descriptor on element for 'value' via
Object.defineProperty (configurable: false) with appropriate get/set delegating
to HTMLTextAreaElement.prototype's native descriptor, wrap useDomValueBridge
call inside an effectScope().run and call scope.stop(), then assert no exception
occurred, the descriptor remained non-configurable during the scope
(Object.getOwnPropertyDescriptor(element, 'value') is defined), and after
scope.stop() the descriptor is still present and unchanged (verify configurable
is false and the custom getter/setter were preserved or called as expected).
Reference useDomValueBridge, effectScope, Object.defineProperty, and the 'value'
property on element in the test.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c957841 and e45c01f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • package.json
  • pnpm-workspace.yaml
  • src/composables/element/useDomValueBridge.test.ts
  • src/composables/element/useDomValueBridge.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.test.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue
  • src/renderer/extensions/vueNodes/widgets/composables/useMarkdownWidget.ts
  • src/renderer/extensions/vueNodes/widgets/composables/useStringWidget.ts
  • src/scripts/domWidget.ts
💤 Files with no reviewable changes (2)
  • pnpm-workspace.yaml
  • package.json

event.preventDefault()
app.canvas.processMouseWheel(event)
})
addWidget(node, widget as BaseDOMWidget<object | string>)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not really a BaseDOMWidget<object | string>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that is what it is — line 28 already has widget as BaseDOMWidget<object | string>. This was pre-existing from the original code.

import { useWidgetValueStore } from '@/stores/widgetValueStore'

const TRACKPAD_DETECTION_THRESHOLD = 50
import WidgetTextarea from '../components/WidgetTextarea.vue'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never finished prohibiting ancestor segments in imports. 🪦

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged — not something to address in this PR but would be a nice lint rule to have.

@github-actions
Copy link

github-actions bot commented Feb 26, 2026

⚡ Performance Report

Metric Baseline PR Δ
canvas-idle: style recalcs 123 122 -1% ⚪
canvas-idle: layouts 0 0 +0% ⚪
canvas-idle: task duration 425ms 389ms -8% ⚪
canvas-mouse-sweep: style recalcs 168 167 -1% ⚪
canvas-mouse-sweep: layouts 12 12 +0% ⚪
canvas-mouse-sweep: task duration 824ms 836ms +1% ⚪
dom-widget-clipping: style recalcs 51 31 -39% 🟢
dom-widget-clipping: layouts 0 0 +0% ⚪
dom-widget-clipping: task duration 456ms 218ms -52% 🟢
subgraph-dom-widget-clipping: style recalcs 74 75 +1% ⚪
subgraph-dom-widget-clipping: layouts 0 0 +0% ⚪
subgraph-dom-widget-clipping: task duration 436ms 435ms -0% ⚪
subgraph-idle: style recalcs 121 121 +0% ⚪
subgraph-idle: layouts 0 0 +0% ⚪
subgraph-idle: task duration 401ms 417ms +4% ⚪
subgraph-mouse-sweep: style recalcs 158 171 +8% ⚪
subgraph-mouse-sweep: layouts 16 16 +0% ⚪
subgraph-mouse-sweep: task duration 796ms 972ms +22% 🔴
Raw data
{
  "timestamp": "2026-03-04T22:45:19.771Z",
  "gitSha": "0f3d653d594ddbaa9be8ee4284fa63e2a7e68133",
  "branch": "fix/dom-widget-value-ownership",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2026.4040000000136,
      "styleRecalcs": 122,
      "styleRecalcDurationMs": 19.678,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 388.601,
      "heapDeltaBytes": -2952832
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1829.7849999999585,
      "styleRecalcs": 167,
      "styleRecalcDurationMs": 48.81,
      "layouts": 12,
      "layoutDurationMs": 3.052,
      "taskDurationMs": 835.831,
      "heapDeltaBytes": -3083808
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 443.1640000000243,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 14.498000000000005,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 217.645,
      "heapDeltaBytes": 2597016
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 620.5949999999802,
      "styleRecalcs": 75,
      "styleRecalcDurationMs": 18.623,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 435.21999999999997,
      "heapDeltaBytes": 15741312
    },
    {
      "name": "subgraph-idle",
      "durationMs": 1999.9239999999645,
      "styleRecalcs": 121,
      "styleRecalcDurationMs": 25.902,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 417.096,
      "heapDeltaBytes": -3141808
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1975.665000000049,
      "styleRecalcs": 171,
      "styleRecalcDurationMs": 54.50400000000001,
      "layouts": 16,
      "layoutDurationMs": 3.7909999999999995,
      "taskDurationMs": 971.9570000000001,
      "heapDeltaBytes": -5032700
    }
  ]
}

function onInput() {
notifyChange?.()
}
element.addEventListener('input', onInput)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about useEventListener?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to useEventListener from @vueuse/core in c060787 — handles cleanup automatically via scope disposal.

if (existingDescriptor) {
Object.defineProperty(element, 'value', existingDescriptor)
} else {
delete (element as unknown as Record<string, unknown>).value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah the cast is unfortunate but necessary — delete only works on index-signature types, and HTMLTextAreaElement does not have one. This restores the element to its prototype descriptor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should come up with a clean API for extension authors so we can add a proper deprecation warning here. How to wire up your custom widget to the widgetValueStore properly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, that deserves its own effort. This PR keeps the existing escape hatch working but a proper public API for extension widget authors would be the right long-term fix.

@coderabbitai Make an Issue to design a clean public API for extension authors to wire custom widgets to the widgetValueStore, replacing the current value-descriptor pattern with a supported integration point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@christian-byrne I'll create that issue for you.


🏁 Script executed:

#!/bin/bash
# Create GitHub issue for designing a clean public API for extension widget integration

gh issue create \
  --title "Design clean public API for extension authors to integrate custom widgets with widgetValueStore" \
  --body "## Context

PR `#9230` introduces \`useDomValueBridge\` to synchronize DOM widget values with the \`widgetValueStore\` by intercepting \`Object.defineProperty\` on element.value and listening for input events. While this approach works as a bridge for extension-created DOM widgets, it relies on internal value-descriptor patterns that are not part of a supported public API.

## Problem

Extension authors currently lack a clean, documented integration point to wire custom widgets to the \`widgetValueStore\`. The current value-descriptor pattern is an implementation detail rather than a stable extension API.

## Proposed Solution

Design and implement a proper public API that:
- Provides a clear, documented way for extension authors to integrate custom widgets with the store
- Replaces the current value-descriptor pattern with a supported integration mechanism
- Maintains backward compatibility where feasible
- Includes documentation and migration guidance

## References

- PR: https://github.com/Comfy-Org/ComfyUI_frontend/pull/9230
- Discussion: https://github.com/Comfy-Org/ComfyUI_frontend/pull/9230#discussion_r2857107802
- Requested by: `@christian-byrne`

## Acceptance Criteria

- [ ] Public API design documented
- [ ] Extension author documentation created
- [ ] Deprecation path defined for current pattern (if applicable)
- [ ] Implementation plan outlined" \
  --assignee christian-byrne

Length of output: 57


@christian-byrne Issue created!

I've opened #9296 to track the design of a clean public API for extension authors to integrate custom widgets with the widgetValueStore. The issue captures the current value-descriptor pattern as a temporary workaround and outlines the need for a proper supported integration point with documentation and migration guidance.


🧠 Learnings used
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 8753
File: src/renderer/extensions/vueNodes/widgets/components/WidgetDOM.vue:17-28
Timestamp: 2026-02-09T03:24:50.064Z
Learning: In this codebase: When destructuring reactive properties from Pinia stores, use `storeToRefs()` to maintain reactivity. Example: `const canvasStore = useCanvasStore(); const { canvas } = storeToRefs(canvasStore)`. Then access with `.value` (e.g., `canvas.value`).

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-23T21:34:45.361Z
Learning: Applies to src/**/*.ts : Use `ref` for reactive state, `computed()` for derived values, and `watch`/`watchEffect` for side effects

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 8594
File: src/lib/litegraph/src/widgets/BaseWidget.ts:146-155
Timestamp: 2026-02-06T09:27:31.576Z
Learning: In the ComfyUI frontend codebase: `LGraphNode.removeWidget()` (and the `widget.onRemove?.()` hook) is called during subgraph conversion operations where widgets are being moved or restructured, not just when they're being permanently deleted. Therefore, widget unregistration from `widgetValueStore` should not be tied to `onRemove`, as this would cause premature state loss during legitimate graph restructuring operations.

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-23T21:34:45.361Z
Learning: Applies to src/**/*.ts : Minimize addition of new refs or other state; if possible to accomplish with just a prop, don't add a `ref`; if possible to use ref/prop directly, don't add a `computed`; if possible to use `computed` for derived values, don't use a `watch`

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).

Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7906
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:545-552
Timestamp: 2026-01-12T17:39:27.738Z
Learning: In Vue/TypeScript files (src/**/*.{ts,tsx,vue}), prefer if/else statements over ternary operators when performing side effects or actions (e.g., mutating state, calling methods with side effects). Ternaries should be reserved for computing and returning values.

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 8248
File: src/platform/assets/schemas/assetSchema.ts:109-118
Timestamp: 2026-01-22T23:44:59.888Z
Learning: Do not export declarations (e.g., schemas, constants, types) unless they are actually used elsewhere in the codebase. Keep the public API surface minimal by exporting only items with concrete usage. This reduces coupling and keeps imports explicit. In src/platform/assets/schemas/assetSchema.ts, ensure only necessary exports are exposed; remove unused exports or switch to non-exported/internal where appropriate.

Learnt from: JemiloII
Repo: Comfy-Org/ComfyUI_frontend PR: 8282
File: src/composables/usePaste.test.ts:372-383
Timestamp: 2026-01-23T21:06:15.240Z
Learning: In paste/clipboard handling code, do not rely on ephemeral DataTransfer data across async boundaries. If an operation awaits async tasks (such as node creation) during a paste, clone the DataTransfer (e.g., using cloneDataTransfer) to persist files and string data before the paste event completes. This ensures clipboard contents remain available for subsequent processing.

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 8722
File: src/composables/maskeditor/useBrushDrawing.ts:5-5
Timestamp: 2026-02-08T03:19:12.009Z
Learning: Treat unresolved import warnings caused by pnpm workspace catalog mappings (pnpm-workspace.yaml) and unplugin-typegpu in vite.config.mts as false positives. Do not flag these in PR reviews; they are expected in sandboxes without node_modules and are not indicative of actual missing dependencies in the TS codebase.

Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 8966
File: src/extensions/core/load3d.ts:427-430
Timestamp: 2026-02-19T02:06:23.468Z
Learning: In TypeScript, you can use typeof SomeClass in type annotation positions (e.g., param: typeof LGraphNode) even when SomeClass is imported with import type. This is a type query that only exists at compile time and is erased in runtime, so it is safe to combine with type-only imports. Apply this pattern to TS files broadly when you need a type that references the shape of a class or constructor function without importing the value at runtime.

Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 8966
File: src/extensions/core/uploadAudio.ts:91-94
Timestamp: 2026-02-19T02:06:38.395Z
Learning: In TypeScript files, you can use a type annotation like 'nodeType: typeof MyClass' even if MyClass is imported via 'import type'. Both the type-only import and 'typeof' operate at the type level and are erased at compile time. This pattern is commonly used for constructor types (e.g., 'nodeType: typeof LGraphNode'). Apply this pattern across TypeScript files in the repository (src/**/*.ts) as appropriate, ensuring the imported symbol is a type-only import when possible for clarity and to avoid runtime imports.

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 8992
File: src/lib/litegraph/src/widgets/GradientSliderWidget.ts:18-18
Timestamp: 2026-02-20T21:08:19.814Z
Learning: When drawing with CanvasRenderingContext2D in TypeScript/JavaScript, wrap the drawing logic with ctx.save() at the start and ctx.restore() at the end to preserve and restore the canvas state. Do not manually destructure and restore individual properties (e.g., fillStyle, strokeStyle); rely on save/restore to manage state changes in a scoped manner. This should be applied to all TS files that perform canvas drawing.

Learnt from: dante01yoon
Repo: Comfy-Org/ComfyUI_frontend PR: 9075
File: src/scripts/api.featureFlags.test.ts:237-268
Timestamp: 2026-02-22T04:27:33.379Z
Learning: In Vite/Vitest, import.meta.env.DEV is true for any mode that is not 'production' (i.e., DEV is the opposite of PROD, and can be true in 'test', 'development', etc.). Do not assume DEV implies only 'development' mode. When reviewing code and tests, treat DEV as a non-production flag and verify environment-specific logic accordingly. Reference: https://vite.dev/guide/env-and-mode#modes

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/scripts/domWidget.ts (1)

2-2: Separate import type from value imports.

Per coding guidelines, use separate import type statements instead of inline type in mixed imports.

♻️ Proposed fix
-import { type Component, effectScope, toRaw, watch } from 'vue'
+import type { Component } from 'vue'
+import { effectScope, toRaw, watch } from 'vue'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/scripts/domWidget.ts` at line 2, Change the mixed import to use a
dedicated type-only import for Component and a separate value import for the
runtime helpers: replace the single line that imports "Component, effectScope,
toRaw, watch" with two statements so Component is imported via "import type {
Component } from 'vue'" and the others via "import { effectScope, toRaw, watch }
from 'vue'"; update the import near the top of domWidget.ts where those symbols
are referenced.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/scripts/domWidget.ts`:
- Line 2: Change the mixed import to use a dedicated type-only import for
Component and a separate value import for the runtime helpers: replace the
single line that imports "Component, effectScope, toRaw, watch" with two
statements so Component is imported via "import type { Component } from 'vue'"
and the others via "import { effectScope, toRaw, watch } from 'vue'"; update the
import near the top of domWidget.ts where those symbols are referenced.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b24e2ba and c060787.

📒 Files selected for processing (4)
  • src/composables/element/useDomValueBridge.test.ts
  • src/composables/element/useDomValueBridge.ts
  • src/renderer/extensions/vueNodes/widgets/composables/useStringWidget.ts
  • src/scripts/domWidget.ts

@christian-byrne christian-byrne added the preview-cpu Creates a preview ephemeral environment for this PR (CPU only) label Feb 28, 2026
christian-byrne and others added 4 commits March 4, 2026 14:31
… bridge

- Add useDomValueBridge composable that bridges DOM element .value to Vue
  reactivity via Object.defineProperty interception + input events
- Wire bridge into addDOMWidget for extension widget compatibility
- Migrate useStringWidget from raw textarea + addDOMWidget to
  ComponentWidgetImpl + WidgetTextarea.vue
- Migrate useMarkdownWidget from Tiptap + addDOMWidget to
  ComponentWidgetImpl + WidgetMarkdown.vue
- Remove all Tiptap dependencies (no longer used anywhere)
- Add spellcheck setting support to WidgetTextarea.vue

Fixes #9194

Amp-Thread-ID: https://ampcode.com/threads/T-019c977f-02f8-701d-b258-95157da8c261
The migration to ComponentWidgetImpl dropped the .comfy-multiline-input
CSS class that e2e tests and GraphCanvas.vue spellcheck logic depend on.

Amp-Thread-ID: https://ampcode.com/threads/T-019c97e6-7c3f-7179-aebe-25a7de8d7405
- Guard non-configurable value descriptors in useDomValueBridge
- Use useEventListener for auto-cleanup input listener
- Use nullish coalescing for placeholder fallback
- Make bridge lifecycle-safe for subgraph restructuring
- Add non-configurable descriptor test

Amp-Thread-ID: https://ampcode.com/threads/T-019c98be-fa4e-77fa-aa8e-74ec9b709624
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/composables/element/useDomValueBridge.ts (1)

49-52: Preserve original descriptor flags when overriding element.value.

The override currently hardcodes enumerable: true, which can change observable element behavior (Object.keys, descriptor introspection). Prefer preserving existing/native enumerability.

♻️ Suggested diff
   if (canOverride) {
+    const enumerable =
+      existingDescriptor?.enumerable ?? nativeDescriptor?.enumerable ?? true
     Object.defineProperty(element, 'value', {
       configurable: true,
-      enumerable: true,
+      enumerable,
       get() {
         return prevGet.call(element)
       },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/composables/element/useDomValueBridge.ts` around lines 49 - 52, The
override for element's 'value' property currently hardcodes enumerable: true;
instead, read the existing property descriptor (via
Object.getOwnPropertyDescriptor on the element or its prototype) and preserve
its flags (enumerable, configurable, and any accessors/writable) when calling
Object.defineProperty for 'value' inside useDomValueBridge; ensure you fall back
to sensible defaults if no descriptor exists so you don't change observable
behavior of methods like Object.keys or descriptor inspection.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/composables/element/useDomValueBridge.ts`:
- Around line 49-52: The override for element's 'value' property currently
hardcodes enumerable: true; instead, read the existing property descriptor (via
Object.getOwnPropertyDescriptor on the element or its prototype) and preserve
its flags (enumerable, configurable, and any accessors/writable) when calling
Object.defineProperty for 'value' inside useDomValueBridge; ensure you fall back
to sensible defaults if no descriptor exists so you don't change observable
behavior of methods like Object.keys or descriptor inspection.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 641d0e58-ed19-4ee3-ab5f-3162c3e6fb13

📥 Commits

Reviewing files that changed from the base of the PR and between c060787 and 50bd1ee.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • package.json
  • pnpm-workspace.yaml
  • src/composables/element/useDomValueBridge.test.ts
  • src/composables/element/useDomValueBridge.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.test.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue
💤 Files with no reviewable changes (2)
  • pnpm-workspace.yaml
  • package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue

@christian-byrne christian-byrne added New Browser Test Expectations New browser test screenshot should be set by github action and removed Update Screenshots labels Mar 5, 2026
@DrJKL DrJKL removed the New Browser Test Expectations New browser test screenshot should be set by github action label Mar 5, 2026
@DrJKL DrJKL added New Browser Test Expectations New browser test screenshot should be set by github action and removed New Browser Test Expectations New browser test screenshot should be set by github action labels Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

New Browser Test Expectations New browser test screenshot should be set by github action preview-cpu Creates a preview ephemeral environment for this PR (CPU only) size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DOM widget values: architectural mismatch between store ownership and DOM delegation

3 participants