Skip to content

feat: add CurveEditor component#8860

Merged
christian-byrne merged 4 commits intomainfrom
feat/curve-editor
Feb 24, 2026
Merged

feat: add CurveEditor component#8860
christian-byrne merged 4 commits intomainfrom
feat/curve-editor

Conversation

@jtydhr88
Copy link
Collaborator

@jtydhr88 jtydhr88 commented Feb 14, 2026

Summary

Prerequisite for upcoming native color correction nodes (ColorCurves).

Reusable curve editor with monotone cubic Hermite interpolation, drag-to-add/move/delete control points, and SVG-based rendering.
Includes CurvePoint type, LUT generation utility, and useCurveEditor composable for interaction logic.

Screenshots (if applicable)

2026-02-13.20-26-52.mp4

┆Issue is synchronized with this Notion page by Unito

@jtydhr88 jtydhr88 requested a review from a team as a code owner February 14, 2026 01:48
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Feb 14, 2026
@github-actions
Copy link

github-actions bot commented Feb 14, 2026

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 02/24/2026, 03:46:41 AM UTC

Links

@github-actions
Copy link

github-actions bot commented Feb 14, 2026

🎭 Playwright: ✅ 555 passed, 0 failed · 1 flaky

📊 Browser Reports
  • chromium: View Report (✅ 542 / ❌ 0 / ⚠️ 1 / ⏭️ 10)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 10 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 14, 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

Adds an interactive SVG curve editor: new CurveEditor component and useCurveEditor composable, interpolation/histogram/LUT utilities with tests, Vue widget wrapper and registry integration, LiteGraph types/widget plumbing, and schema support for curve inputs.

Changes

Cohort / File(s) Summary
Curve editor component & composable
src/components/curve/CurveEditor.vue, src/composables/useCurveEditor.ts
New Vue SFC and composable implementing interactive SVG curve editing with pointer handlers for add/drag/delete; exposes computed curvePath, handleSvgPointerDown, and startDrag, and binds v-model to CurvePoint[].
Curve utilities & tests
src/components/curve/curveUtils.ts, src/components/curve/curveUtils.test.ts
Added monotone cubic interpolator, histogram→SVG path, and LUT generator; tests cover interpolation behavior, LUT output/clamping, and histogram path normalization.
Component tests
src/components/curve/CurveEditor.test.ts
New test suite for CurveEditor: rendering of SVG/path/circles, histogram path presence, path shape checks, x-range assertions, and deletion via right-click while enforcing ≥2 points.
Widget UI integration
src/components/curve/WidgetCurve.vue, src/renderer/extensions/vueNodes/widgets/composables/useCurveWidget.ts
Vue wrapper component and composable to create/configure a 'curve' widget on LiteGraph nodes; provides defaults and runtime validation of widget type.
LiteGraph types & widget plumbing
src/lib/litegraph/src/types/widgets.ts, src/lib/litegraph/src/widgets/CurveWidget.ts, src/lib/litegraph/src/widgets/widgetMap.ts
Added CurvePoint type and ICurveWidget interface, implemented CurveWidget class, and extended factory/map to instantiate 'curve' widgets.
Widget registry & scripts
src/renderer/extensions/vueNodes/widgets/registry/widgetRegistry.ts, src/scripts/widgets.ts
Registered async WidgetCurve component in widget registry, marked 'curve' as expandable, and exposed CURVE in ComfyWidgets via transformer wrapper.
Schema / node defs
src/schemas/nodeDef/nodeDefSchemaV2.ts
Added internal zCurvePoint and zCurveInputSpec, extended input spec union, and exported CurveInputSpec type.

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant CurveComp as CurveEditor.vue
  participant Composable as useCurveEditor
  participant Model as Parent Model (v-model)

  rect rgba(200,200,255,0.5)
  User->>CurveComp: pointerdown / pointermove / pointerup
  end

  CurveComp->>Composable: handleSvgPointerDown / startDrag
  Composable->>Composable: compute svgCoords, update dragIndex, modify points (immutable)
  Composable->>Model: emit updated modelValue (new array)
  Model-->>CurveComp: reactive modelValue update
  CurveComp->>CurveComp: recompute curvePath and rerender SVG
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

"I hopped along the bezier trail,
adding points with a twitchy tail,
bins and curves in tidy rows,
I nudged each knot where the river flows,
and left a tiny carrot-shaped glow. 🐇"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add CurveEditor component' accurately describes the main addition: a new interactive curve editor component with supporting utilities and types.
Description check ✅ Passed The description covers the purpose, key features (monotone interpolation, drag interactions, SVG rendering), and includes a video demo. However, it omits the 'Changes' section from the template with specific 'What' and 'Breaking' details.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/curve-editor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link

github-actions bot commented Feb 14, 2026

📦 Bundle: 4.39 MB gzip 🔴 +2.92 kB

Details

Summary

  • Raw size: 20.6 MB baseline 20.6 MB — 🔴 +10.5 kB
  • Gzip: 4.39 MB baseline 4.39 MB — 🔴 +2.92 kB
  • Brotli: 3.39 MB baseline 3.39 MB — 🔴 +2.71 kB
  • Bundles: 225 current • 224 baseline • 190 added / 189 removed

Category Glance
Other 🔴 +9.35 kB (7.63 MB) · Data & Services 🔴 +1.17 kB (2.54 MB) · Vendor & Third-Party ⚪ 0 B (8.84 MB) · Graph Workspace ⚪ 0 B (968 kB) · Panels & Settings ⚪ 0 B (436 kB) · Views & Navigation ⚪ 0 B (68.8 kB) · + 5 more

App Entry Points — 17.9 kB (baseline 17.9 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-CQC79e1z.js (new) 17.9 kB 🔴 +17.9 kB 🔴 +6.33 kB 🔴 +5.5 kB
assets/index-rkSbQXQd.js (removed) 17.9 kB 🟢 -17.9 kB 🟢 -6.34 kB 🟢 -5.51 kB

Status: 1 added / 1 removed

Graph Workspace — 968 kB (baseline 968 kB) • ⚪ 0 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-Ba3-EZyU.js (new) 968 kB 🔴 +968 kB 🔴 +208 kB 🔴 +158 kB
assets/GraphView-CKMC6OPn.js (removed) 968 kB 🟢 -968 kB 🟢 -208 kB 🟢 -158 kB

Status: 1 added / 1 removed

Views & Navigation — 68.8 kB (baseline 68.8 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-BuTYmMuw.js (removed) 15.5 kB 🟢 -15.5 kB 🟢 -3.31 kB 🟢 -2.83 kB
assets/CloudSurveyView-CwTrMLro.js (new) 15.5 kB 🔴 +15.5 kB 🔴 +3.31 kB 🔴 +2.82 kB
assets/CloudLoginView--C5KyZcg.js (new) 10 kB 🔴 +10 kB 🔴 +2.93 kB 🔴 +2.57 kB
assets/CloudLoginView-DnCV1FaY.js (removed) 10 kB 🟢 -10 kB 🟢 -2.92 kB 🟢 -2.57 kB
assets/UserCheckView-DhwuwhX-.js (new) 8.41 kB 🔴 +8.41 kB 🔴 +2.23 kB 🔴 +1.94 kB
assets/UserCheckView-Dphb1pbi.js (removed) 8.41 kB 🟢 -8.41 kB 🟢 -2.23 kB 🟢 -1.93 kB
assets/CloudSignupView-C5OX2G6A.js (removed) 7.41 kB 🟢 -7.41 kB 🟢 -2.32 kB 🟢 -2.03 kB
assets/CloudSignupView-rXb6JVab.js (new) 7.41 kB 🔴 +7.41 kB 🔴 +2.32 kB 🔴 +2.04 kB
assets/CloudLayoutView-CwZS-ukY.js (new) 6.43 kB 🔴 +6.43 kB 🔴 +2.1 kB 🔴 +1.82 kB
assets/CloudLayoutView-DuU5_zAP.js (removed) 6.43 kB 🟢 -6.43 kB 🟢 -2.1 kB 🟢 -1.82 kB
assets/CloudForgotPasswordView-BIAWcIlQ.js (removed) 5.56 kB 🟢 -5.56 kB 🟢 -1.93 kB 🟢 -1.72 kB
assets/CloudForgotPasswordView-Cb6HSlW_.js (new) 5.56 kB 🔴 +5.56 kB 🔴 +1.93 kB 🔴 +1.7 kB
assets/CloudAuthTimeoutView-exxe7rly.js (new) 4.91 kB 🔴 +4.91 kB 🔴 +1.76 kB 🔴 +1.54 kB
assets/CloudAuthTimeoutView-krpR0MTj.js (removed) 4.91 kB 🟢 -4.91 kB 🟢 -1.77 kB 🟢 -1.55 kB
assets/CloudSubscriptionRedirectView-CeNSZ3r1.js (removed) 4.71 kB 🟢 -4.71 kB 🟢 -1.78 kB 🟢 -1.57 kB
assets/CloudSubscriptionRedirectView-wa4gxmwJ.js (new) 4.71 kB 🔴 +4.71 kB 🔴 +1.78 kB 🔴 +1.58 kB
assets/UserSelectView-BURgsp_a.js (new) 4.5 kB 🔴 +4.5 kB 🔴 +1.63 kB 🔴 +1.46 kB
assets/UserSelectView-Ds_xQ5o6.js (removed) 4.5 kB 🟢 -4.5 kB 🟢 -1.64 kB 🟢 -1.47 kB
assets/CloudSorryContactSupportView-B44yD6kN.js (removed) 1.02 kB 🟢 -1.02 kB 🟢 -541 B 🟢 -463 B
assets/CloudSorryContactSupportView-CY9LHUzS.js (new) 1.02 kB 🔴 +1.02 kB 🔴 +541 B 🔴 +463 B
assets/layout-B9Qr_k9X.js (new) 296 B 🔴 +296 B 🔴 +224 B 🔴 +189 B
assets/layout-Cr8hM5-r.js (removed) 296 B 🟢 -296 B 🟢 -224 B 🟢 -189 B

Status: 11 added / 11 removed

Panels & Settings — 436 kB (baseline 436 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/settings-BNn9zn5v.js (new) 38.5 kB 🔴 +38.5 kB 🔴 +9.34 kB 🔴 +7.7 kB
assets/settings-DLqeCT09.js (removed) 38.5 kB 🟢 -38.5 kB 🟢 -9.34 kB 🟢 -7.7 kB
assets/settings-BOcWl0Qp.js (removed) 34.2 kB 🟢 -34.2 kB 🟢 -8.33 kB 🟢 -7.04 kB
assets/settings-CRqB5n8m.js (new) 34.2 kB 🔴 +34.2 kB 🔴 +8.34 kB 🔴 +7.04 kB
assets/settings-Cs_NVkbc.js (new) 32.4 kB 🔴 +32.4 kB 🔴 +8.15 kB 🔴 +6.7 kB
assets/settings-IRk9rDbu.js (removed) 32.4 kB 🟢 -32.4 kB 🟢 -8.15 kB 🟢 -6.63 kB
assets/settings-BAN61mfQ.js (new) 30.5 kB 🔴 +30.5 kB 🔴 +8.45 kB 🔴 +7.09 kB
assets/settings-BodhSOuG.js (removed) 30.5 kB 🟢 -30.5 kB 🟢 -8.45 kB 🟢 -7.09 kB
assets/settings-B2VYgS-a.js (new) 29.9 kB 🔴 +29.9 kB 🔴 +8.1 kB 🔴 +7.07 kB
assets/settings-DP-OgTXN.js (removed) 29.9 kB 🟢 -29.9 kB 🟢 -8.1 kB 🟢 -7.07 kB
assets/settings-axAeoUrZ.js (new) 28.8 kB 🔴 +28.8 kB 🔴 +7.79 kB 🔴 +6.64 kB
assets/settings-DRIXyZ_Z.js (removed) 28.8 kB 🟢 -28.8 kB 🟢 -7.79 kB 🟢 -6.64 kB
assets/settings-AqJa7Oe1.js (removed) 28.7 kB 🟢 -28.7 kB 🟢 -8 kB 🟢 -7.02 kB
assets/settings-CIIZ9BHS.js (new) 28.7 kB 🔴 +28.7 kB 🔴 +8 kB 🔴 +7.02 kB
assets/settings-3cK4vYSX.js (removed) 27.9 kB 🟢 -27.9 kB 🟢 -7.71 kB 🟢 -6.7 kB
assets/settings-CYbBf6ct.js (new) 27.9 kB 🔴 +27.9 kB 🔴 +7.71 kB 🔴 +6.7 kB
assets/settings-CCD8qxmc.js (removed) 27.8 kB 🟢 -27.8 kB 🟢 -8.12 kB 🟢 -6.77 kB
assets/settings-FzjdIfFm.js (new) 27.8 kB 🔴 +27.8 kB 🔴 +8.12 kB 🔴 +6.77 kB
assets/settings-DLodCRRz.js (removed) 24.5 kB 🟢 -24.5 kB 🟢 -7.91 kB 🟢 -6.35 kB
assets/settings-DW8FtJHC.js (new) 24.5 kB 🔴 +24.5 kB 🔴 +7.91 kB 🔴 +6.36 kB
assets/settings-CVDNuOXV.js (removed) 23.9 kB 🟢 -23.9 kB 🟢 -7.67 kB 🟢 -5.96 kB
assets/settings-DhTbqRj2.js (new) 23.9 kB 🔴 +23.9 kB 🔴 +7.67 kB 🔴 +5.96 kB
assets/SecretsPanel-BaupA8iP.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.3 kB 🔴 +4.66 kB
assets/SecretsPanel-DFlu3hLT.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -5.3 kB 🟢 -4.66 kB
assets/LegacyCreditsPanel-9Vi0FDjg.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +5.56 kB 🔴 +4.9 kB
assets/LegacyCreditsPanel-DDzLPtY6.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.57 kB 🟢 -4.9 kB
assets/SubscriptionPanel-C998pxAV.js (new) 18.6 kB 🔴 +18.6 kB 🔴 +4.73 kB 🔴 +4.16 kB
assets/SubscriptionPanel-Sq2Npn4C.js (removed) 18.6 kB 🟢 -18.6 kB 🟢 -4.73 kB 🟢 -4.17 kB
assets/KeybindingPanel-BVh3ONs7.js (new) 12.3 kB 🔴 +12.3 kB 🔴 +3.57 kB 🔴 +3.17 kB
assets/KeybindingPanel-CEm3k6py.js (removed) 12.3 kB 🟢 -12.3 kB 🟢 -3.57 kB 🟢 -3.17 kB
assets/AboutPanel-C-kmqvfL.js (removed) 9.79 kB 🟢 -9.79 kB 🟢 -2.73 kB 🟢 -2.45 kB
assets/AboutPanel-CyWOHXoZ.js (new) 9.79 kB 🔴 +9.79 kB 🔴 +2.73 kB 🔴 +2.45 kB
assets/ExtensionPanel-DpLKikcS.js (removed) 9.38 kB 🟢 -9.38 kB 🟢 -2.65 kB 🟢 -2.35 kB
assets/ExtensionPanel-tCKqJpor.js (new) 9.38 kB 🔴 +9.38 kB 🔴 +2.65 kB 🔴 +2.35 kB
assets/ServerConfigPanel-CoGE80P1.js (removed) 6.44 kB 🟢 -6.44 kB 🟢 -2.13 kB 🟢 -1.92 kB
assets/ServerConfigPanel-DIcMaFlJ.js (new) 6.44 kB 🔴 +6.44 kB 🔴 +2.12 kB 🔴 +1.9 kB
assets/UserPanel-Bmd4Zx86.js (new) 6.16 kB 🔴 +6.16 kB 🔴 +1.99 kB 🔴 +1.74 kB
assets/UserPanel-CJwe7-nR.js (removed) 6.16 kB 🟢 -6.16 kB 🟢 -1.99 kB 🟢 -1.75 kB
assets/cloudRemoteConfig-D7iFltgi.js (removed) 1.44 kB 🟢 -1.44 kB 🟢 -706 B 🟢 -613 B
assets/cloudRemoteConfig-DOc6ysvO.js (new) 1.44 kB 🔴 +1.44 kB 🔴 +701 B 🔴 +614 B
assets/refreshRemoteConfig-Bu6somS6.js (new) 1.14 kB 🔴 +1.14 kB 🔴 +517 B 🔴 +461 B
assets/refreshRemoteConfig-Bui8pHDm.js (removed) 1.14 kB 🟢 -1.14 kB 🟢 -518 B 🟢 -468 B
assets/config-QxkqTZy6.js (removed) 996 B 🟢 -996 B 🟢 -542 B 🟢 -471 B
assets/config-Tm3IpjoS.js (new) 996 B 🔴 +996 B 🔴 +540 B 🔴 +474 B

Status: 22 added / 22 removed

User & Accounts — 16 kB (baseline 16 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/PasswordFields-BBjRUT_F.js (new) 4.51 kB 🔴 +4.51 kB 🔴 +1.35 kB 🔴 +1.2 kB
assets/PasswordFields-CVWWQ8UT.js (removed) 4.51 kB 🟢 -4.51 kB 🟢 -1.36 kB 🟢 -1.2 kB
assets/auth-Dc9K9tYI.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.18 kB 🔴 +991 B
assets/auth-DxW6C33-.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.18 kB 🟢 -990 B
assets/SignUpForm-C_MQQGqJ.js (new) 3.01 kB 🔴 +3.01 kB 🔴 +1.23 kB 🔴 +1.09 kB
assets/SignUpForm-LqTXFeVS.js (removed) 3.01 kB 🟢 -3.01 kB 🟢 -1.23 kB 🟢 -1.1 kB
assets/UpdatePasswordContent-BX1jmKQJ.js (removed) 2.37 kB 🟢 -2.37 kB 🟢 -1.07 kB 🟢 -943 B
assets/UpdatePasswordContent-C1cWKfw3.js (new) 2.37 kB 🔴 +2.37 kB 🔴 +1.07 kB 🔴 +939 B
assets/WorkspaceProfilePic-Cv4HUNOU.js (removed) 1.57 kB 🟢 -1.57 kB 🟢 -821 B 🟢 -707 B
assets/WorkspaceProfilePic-DLDXZ3rv.js (new) 1.57 kB 🔴 +1.57 kB 🔴 +822 B 🔴 +730 B
assets/firebaseAuthStore-C5hULQ9G.js (removed) 788 B 🟢 -788 B 🟢 -388 B 🟢 -343 B
assets/firebaseAuthStore-D4lOiPfT.js (new) 788 B 🔴 +788 B 🔴 +382 B 🔴 +344 B
assets/auth--W5Ybmb3.js (removed) 357 B 🟢 -357 B 🟢 -222 B 🟢 -191 B
assets/auth-DOsTQ-D4.js (new) 357 B 🔴 +357 B 🔴 +224 B 🔴 +217 B

Status: 7 added / 7 removed

Editors & Dialogs — 736 B (baseline 736 B) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useSubscriptionDialog-BQn_td7K.js (removed) 736 B 🟢 -736 B 🟢 -382 B 🟢 -329 B
assets/useSubscriptionDialog-DShB2vei.js (new) 736 B 🔴 +736 B 🔴 +374 B 🔴 +327 B

Status: 1 added / 1 removed

UI Components — 46.9 kB (baseline 46.9 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useTerminalTabs-BDVUJCpC.js (new) 9.84 kB 🔴 +9.84 kB 🔴 +3.4 kB 🔴 +3 kB
assets/useTerminalTabs-G4kYCJbx.js (removed) 9.84 kB 🟢 -9.84 kB 🟢 -3.4 kB 🟢 -2.99 kB
assets/ComfyQueueButton-C46WFt_M.js (new) 8.02 kB 🔴 +8.02 kB 🔴 +2.48 kB 🔴 +2.22 kB
assets/ComfyQueueButton-CzUHBN_H.js (removed) 8.02 kB 🟢 -8.02 kB 🟢 -2.49 kB 🟢 -2.22 kB
assets/TopbarBadge-CNZvjjLw.js (removed) 7.45 kB 🟢 -7.45 kB 🟢 -1.81 kB 🟢 -1.6 kB
assets/TopbarBadge-CyPIKWZI.js (new) 7.45 kB 🔴 +7.45 kB 🔴 +1.82 kB 🔴 +1.6 kB
assets/FormSearchInput-BNeIXugj.js (new) 3.73 kB 🔴 +3.73 kB 🔴 +1.54 kB 🔴 +1.35 kB
assets/FormSearchInput-DA66ft_f.js (removed) 3.73 kB 🟢 -3.73 kB 🟢 -1.54 kB 🟢 -1.35 kB
assets/SubscribeButton-CDkdei6t.js (new) 2.35 kB 🔴 +2.35 kB 🔴 +1.02 kB 🔴 +888 B
assets/SubscribeButton-CWIIZ5QB.js (removed) 2.35 kB 🟢 -2.35 kB 🟢 -1.02 kB 🟢 -890 B
assets/WidgetButton-CJqDWz7I.js (removed) 1.84 kB 🟢 -1.84 kB 🟢 -878 B 🟢 -794 B
assets/WidgetButton-DIN5zdNw.js (new) 1.84 kB 🔴 +1.84 kB 🔴 +876 B 🔴 +790 B
assets/cloudFeedbackTopbarButton-CRol2dwv.js (removed) 1.59 kB 🟢 -1.59 kB 🟢 -855 B 🟢 -763 B
assets/cloudFeedbackTopbarButton-DKVrdsMx.js (new) 1.59 kB 🔴 +1.59 kB 🔴 +849 B 🔴 +768 B
assets/CloudBadge-B8O5mK9a.js (removed) 1.24 kB 🟢 -1.24 kB 🟢 -608 B 🟢 -525 B
assets/CloudBadge-D6-MQNih.js (new) 1.24 kB 🔴 +1.24 kB 🔴 +609 B 🔴 +525 B
assets/UserAvatar-BRD5QYeZ.js (removed) 1.17 kB 🟢 -1.17 kB 🟢 -616 B 🟢 -525 B
assets/UserAvatar-DB8MvHaC.js (new) 1.17 kB 🔴 +1.17 kB 🔴 +615 B 🔴 +526 B
assets/ComfyQueueButton-CD12l3CD.js (removed) 793 B 🟢 -793 B 🟢 -397 B 🟢 -352 B
assets/ComfyQueueButton-CFILuhQj.js (new) 793 B 🔴 +793 B 🔴 +391 B 🔴 +354 B
assets/Button-_rljyWPY.js 2.98 kB 2.98 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ScrubableNumberInput-CVilsRHA.js 5.94 kB 5.94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 10 added / 10 removed

Data & Services — 2.54 MB (baseline 2.54 MB) • 🔴 +1.17 kB

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-BMrfIxUH.js (new) 1.73 MB 🔴 +1.73 MB 🔴 +390 kB 🔴 +294 kB
assets/dialogService-QXqqcPUs.js (removed) 1.73 MB 🟢 -1.73 MB 🟢 -389 kB 🟢 -294 kB
assets/api-krOwRRgF.js (new) 675 kB 🔴 +675 kB 🔴 +153 kB 🔴 +121 kB
assets/api-CA0HzTNi.js (removed) 675 kB 🟢 -675 kB 🟢 -153 kB 🟢 -121 kB
assets/load3dService-DZVqKoaT.js (new) 91 kB 🔴 +91 kB 🔴 +19.1 kB 🔴 +16.4 kB
assets/load3dService-Pb2kfEmB.js (removed) 91 kB 🟢 -91 kB 🟢 -19.1 kB 🟢 -16.4 kB
assets/extensionStore-k758ROsX.js (new) 12.7 kB 🔴 +12.7 kB 🔴 +4.42 kB 🔴 +3.88 kB
assets/extensionStore-QUtqybe3.js (removed) 12.7 kB 🟢 -12.7 kB 🟢 -4.42 kB 🟢 -3.88 kB
assets/releaseStore-BVtIX5fC.js (removed) 7.96 kB 🟢 -7.96 kB 🟢 -2.22 kB 🟢 -1.95 kB
assets/releaseStore-DMjTtHcd.js (new) 7.96 kB 🔴 +7.96 kB 🔴 +2.22 kB 🔴 +1.95 kB
assets/keybindingService-l_EW9tOU.js (removed) 6.52 kB 🟢 -6.52 kB 🟢 -1.71 kB 🟢 -1.48 kB
assets/keybindingService-w0qOKUff.js (new) 6.52 kB 🔴 +6.52 kB 🔴 +1.71 kB 🔴 +1.48 kB
assets/serverConfigStore-DEs1_NHN.js (removed) 2.32 kB 🟢 -2.32 kB 🟢 -791 B 🟢 -689 B
assets/serverConfigStore-y5yc8Qaf.js (new) 2.32 kB 🔴 +2.32 kB 🔴 +790 B 🔴 +692 B
assets/bootstrapStore-CPsEekB0.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +872 B 🔴 +792 B
assets/bootstrapStore-CyGuFHJC.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -874 B 🟢 -794 B
assets/userStore-BdklhS-t.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +718 B 🔴 +634 B
assets/userStore-CCWgSB0T.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -721 B 🟢 -634 B
assets/audioService-4rD9u_0f.js (new) 1.73 kB 🔴 +1.73 kB 🔴 +848 B 🔴 +723 B
assets/audioService-Ds20JWox.js (removed) 1.73 kB 🟢 -1.73 kB 🟢 -849 B 🟢 -728 B
assets/releaseStore-Couc4-m8.js (removed) 760 B 🟢 -760 B 🟢 -388 B 🟢 -341 B
assets/releaseStore-KRdYqebz.js (new) 760 B 🔴 +760 B 🔴 +381 B 🔴 +342 B
assets/settingStore-CmZ87mP6.js (removed) 744 B 🟢 -744 B 🟢 -390 B 🟢 -342 B
assets/settingStore-SMoqIVGZ.js (new) 744 B 🔴 +744 B 🔴 +382 B 🔴 +342 B
assets/workflowDraftStore-Cfc5yuGh.js (new) 736 B 🔴 +736 B 🔴 +374 B 🔴 +332 B
assets/workflowDraftStore-qlSZYxP9.js (removed) 736 B 🟢 -736 B 🟢 -382 B 🟢 -334 B
assets/dialogService-BpDbL2zh.js (removed) 725 B 🟢 -725 B 🟢 -374 B 🟢 -327 B
assets/dialogService-DqeI9ugX.js (new) 725 B 🔴 +725 B 🔴 +366 B 🔴 +326 B

Status: 14 added / 14 removed

Utilities & Hooks — 58.3 kB (baseline 58.3 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useLoad3d-BX0-NULu.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.63 kB 🔴 +3.2 kB
assets/useLoad3d-DRpAjvBE.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.63 kB 🟢 -3.2 kB
assets/useLoad3dViewer-7OcBlAQb.js (removed) 14.1 kB 🟢 -14.1 kB 🟢 -3.15 kB 🟢 -2.79 kB
assets/useLoad3dViewer-Dj1Sc-Fw.js (new) 14.1 kB 🔴 +14.1 kB 🔴 +3.15 kB 🔴 +2.79 kB
assets/useFeatureFlags-BRNo3Kug.js (removed) 4.14 kB 🟢 -4.14 kB 🟢 -1.24 kB 🟢 -1.06 kB
assets/useFeatureFlags-sIWOxaQ6.js (new) 4.14 kB 🔴 +4.14 kB 🔴 +1.24 kB 🔴 +1.06 kB
assets/useWorkspaceUI-CEK8vxNf.js (removed) 3 kB 🟢 -3 kB 🟢 -824 B 🟢 -702 B
assets/useWorkspaceUI-zk_jeVcv.js (new) 3 kB 🔴 +3 kB 🔴 +822 B 🔴 +703 B
assets/useSubscriptionCredits-CyYZ4VL1.js (new) 2.75 kB 🔴 +2.75 kB 🔴 +1.04 kB 🔴 +899 B
assets/useSubscriptionCredits-WuDB061C.js (removed) 2.75 kB 🟢 -2.75 kB 🟢 -1.04 kB 🟢 -898 B
assets/subscriptionCheckoutUtil-BCZT4eti.js (removed) 2.53 kB 🟢 -2.53 kB 🟢 -1.06 kB 🟢 -949 B
assets/subscriptionCheckoutUtil-C_65FpCP.js (new) 2.53 kB 🔴 +2.53 kB 🔴 +1.06 kB 🔴 +924 B
assets/useExternalLink-C002nTPZ.js (removed) 1.66 kB 🟢 -1.66 kB 🟢 -771 B 🟢 -678 B
assets/useExternalLink-DxJ7sjn9.js (new) 1.66 kB 🔴 +1.66 kB 🔴 +769 B 🔴 +675 B
assets/useErrorHandling-BIlugy88.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -628 B 🟢 -535 B
assets/useErrorHandling-D5Ef6RTc.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +627 B 🔴 +532 B
assets/useWorkspaceSwitch-Cepor02u.js (new) 1.25 kB 🔴 +1.25 kB 🔴 +544 B 🔴 +482 B
assets/useWorkspaceSwitch-DffOeHcQ.js (removed) 1.25 kB 🟢 -1.25 kB 🟢 -545 B 🟢 -477 B
assets/useLoad3d-DVPaaeRM.js (new) 859 B 🔴 +859 B 🔴 +424 B 🔴 +382 B
assets/useLoad3d-kr8XPBoN.js (removed) 859 B 🟢 -859 B 🟢 -428 B 🟢 -380 B
assets/audioUtils-CWyAgqYk.js (removed) 858 B 🟢 -858 B 🟢 -502 B 🟢 -402 B
assets/audioUtils-fCfdW1bg.js (new) 858 B 🔴 +858 B 🔴 +500 B 🔴 +424 B
assets/useLoad3dViewer-BB8905oi.js (removed) 838 B 🟢 -838 B 🟢 -413 B 🟢 -368 B
assets/useLoad3dViewer-DoyGZh6n.js (new) 838 B 🔴 +838 B 🔴 +409 B 🔴 +371 B
assets/useCurrentUser-DftcB_Lt.js (new) 722 B 🔴 +722 B 🔴 +369 B 🔴 +326 B
assets/useCurrentUser-Q9jsNtWG.js (removed) 722 B 🟢 -722 B 🟢 -377 B 🟢 -328 B
assets/_plugin-vue_export-helper-c0As6Sx3.js 315 B 315 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/colorUtil-C2D2Hl5T.js 7 kB 7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/envUtil-Clzmwvt4.js 466 B 466 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/markdownRendererUtil-Cddas8Zl.js 1.56 kB 1.56 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SkeletonUtils-BputJAFn.js 133 B 133 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 13 added / 13 removed

Vendor & Third-Party — 8.84 MB (baseline 8.84 MB) • ⚪ 0 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-xterm-DK6Ygydn.js (new) 374 kB 🔴 +374 kB 🔴 +75.5 kB 🔴 +61 kB
assets/vendor-xterm-vkxZGffR.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-chart-BxkFiWzp.js 399 kB 399 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-DNX73mqE.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-other-Cj6OpvOm.js 1.52 MB 1.52 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-DCruF9hs.js 1.73 MB 1.73 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-reka-ui-DVmi2O2Z.js 388 kB 388 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-sentry-SQwstEKc.js 182 kB 182 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-LBLOE6BD.js 1.8 MB 1.8 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-BnYkbQDM.js 634 kB 634 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-core-DtiQ1dr9.js 311 kB 311 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vueuse-D2jVNnmE.js 113 kB 113 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: 1 added / 1 removed

Other — 7.63 MB (baseline 7.62 MB) • 🔴 +9.35 kB

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/i18n-BaYAy13-.js (new) 521 kB 🔴 +521 kB 🔴 +100 kB 🔴 +78.1 kB
assets/i18n-CPASsDRs.js (removed) 521 kB 🟢 -521 kB 🟢 -100 kB 🟢 -78.1 kB
assets/nodeDefs-B7VKtnlU.js (new) 480 kB 🔴 +480 kB 🔴 +73 kB 🔴 +50.3 kB
assets/nodeDefs-BTBSP0IQ.js (removed) 480 kB 🟢 -480 kB 🟢 -73 kB 🟢 -50.2 kB
assets/nodeDefs-BILRZez4.js (new) 441 kB 🔴 +441 kB 🔴 +68.1 kB 🔴 +48 kB
assets/nodeDefs-C76rbmLh.js (removed) 441 kB 🟢 -441 kB 🟢 -68.1 kB 🟢 -48 kB
assets/nodeDefs-cZHjSfze.js (new) 440 kB 🔴 +440 kB 🔴 +65.8 kB 🔴 +46.3 kB
assets/nodeDefs-xiPSrG6S.js (removed) 440 kB 🟢 -440 kB 🟢 -65.8 kB 🟢 -46.3 kB
assets/nodeDefs-C-Tw-7I_.js (removed) 407 kB 🟢 -407 kB 🟢 -66.2 kB 🟢 -46.3 kB
assets/nodeDefs-C-ZPYULw.js (new) 407 kB 🔴 +407 kB 🔴 +66.2 kB 🔴 +46.3 kB
assets/nodeDefs-C9hYV0K4.js (new) 395 kB 🔴 +395 kB 🔴 +64.7 kB 🔴 +45.9 kB
assets/nodeDefs-CxxD1ymF.js (removed) 395 kB 🟢 -395 kB 🟢 -64.7 kB 🟢 -45.9 kB
assets/nodeDefs-catDPeFD.js (new) 392 kB 🔴 +392 kB 🔴 +63.4 kB 🔴 +46.4 kB
assets/nodeDefs-DciNsuYe.js (removed) 392 kB 🟢 -392 kB 🟢 -63.4 kB 🟢 -46.4 kB
assets/nodeDefs-5rcOJVex.js (removed) 391 kB 🟢 -391 kB 🟢 -64.8 kB 🟢 -47.1 kB
assets/nodeDefs-Dx0_qWUI.js (new) 391 kB 🔴 +391 kB 🔴 +64.8 kB 🔴 +47 kB
assets/nodeDefs-BHUUV2kN.js (new) 388 kB 🔴 +388 kB 🔴 +62 kB 🔴 +45.3 kB
assets/nodeDefs-nGdg-hIO.js (removed) 388 kB 🟢 -388 kB 🟢 -62 kB 🟢 -45.3 kB
assets/nodeDefs-A9Dx-vsT.js (new) 383 kB 🔴 +383 kB 🔴 +61 kB 🔴 +44.7 kB
assets/nodeDefs-BZEpP7w6.js (removed) 383 kB 🟢 -383 kB 🟢 -61 kB 🟢 -44.7 kB
assets/nodeDefs-2U4KtUml.js (removed) 360 kB 🟢 -360 kB 🟢 -63.6 kB 🟢 -44.5 kB
assets/nodeDefs-CQNTrpgx.js (new) 360 kB 🔴 +360 kB 🔴 +63.6 kB 🔴 +44.4 kB
assets/nodeDefs-CSlfLU5b.js (new) 356 kB 🔴 +356 kB 🔴 +62.4 kB 🔴 +43.3 kB
assets/nodeDefs-G7wcMpUD.js (removed) 356 kB 🟢 -356 kB 🟢 -62.4 kB 🟢 -43.3 kB
assets/main-CMBzVhV2.js (new) 196 kB 🔴 +196 kB 🔴 +51.4 kB 🔴 +40.9 kB
assets/main-CTgQOf6T.js (removed) 196 kB 🟢 -196 kB 🟢 -51.4 kB 🟢 -40.9 kB
assets/main-CTuvj7wJ.js (new) 176 kB 🔴 +176 kB 🔴 +46.4 kB 🔴 +37.7 kB
assets/main-CxmFjxCA.js (removed) 176 kB 🟢 -176 kB 🟢 -46.4 kB 🟢 -37.7 kB
assets/main-CD9yNL_V.js (new) 170 kB 🔴 +170 kB 🔴 +46.4 kB 🔴 +37.3 kB
assets/main-D-U7Lzb5.js (removed) 170 kB 🟢 -170 kB 🟢 -46.4 kB 🟢 -37.3 kB
assets/main-B5U6cVPC.js (new) 162 kB 🔴 +162 kB 🔴 +46.1 kB 🔴 +37 kB
assets/main-D_siPGTl.js (removed) 162 kB 🟢 -162 kB 🟢 -46.1 kB 🟢 -37 kB
assets/main-BH99zfen.js (removed) 148 kB 🟢 -148 kB 🟢 -44.7 kB 🟢 -37.7 kB
assets/main-DbJvfVKg.js (new) 148 kB 🔴 +148 kB 🔴 +44.7 kB 🔴 +37.7 kB
assets/main-BgWDQhKn.js (removed) 145 kB 🟢 -145 kB 🟢 -44.1 kB 🟢 -35.9 kB
assets/main-CG5d4IKS.js (new) 145 kB 🔴 +145 kB 🔴 +44.1 kB 🔴 +35.9 kB
assets/main-B38pKNvo.js (new) 143 kB 🔴 +143 kB 🔴 +43.7 kB 🔴 +36.6 kB
assets/main-Cl0TDHs-.js (removed) 143 kB 🟢 -143 kB 🟢 -43.7 kB 🟢 -36.6 kB
assets/main-Dm-TeEId.js (new) 141 kB 🔴 +141 kB 🔴 +43.9 kB 🔴 +37.1 kB
assets/main-DN0hguJt.js (removed) 141 kB 🟢 -141 kB 🟢 -43.9 kB 🟢 -37.1 kB
assets/main-CTIe-PdP.js (removed) 140 kB 🟢 -140 kB 🟢 -43.3 kB 🟢 -36.6 kB
assets/main-FGkc3Cku.js (new) 140 kB 🔴 +140 kB 🔴 +43.3 kB 🔴 +36.6 kB
assets/main-D5d-6dvh.js (new) 124 kB 🔴 +124 kB 🔴 +42.5 kB 🔴 +34.1 kB
assets/main-DzJxAN6l.js (removed) 124 kB 🟢 -124 kB 🟢 -42.5 kB 🟢 -34.1 kB
assets/main-BueLatZg.js (new) 123 kB 🔴 +123 kB 🔴 +42.6 kB 🔴 +33.9 kB
assets/main-d6c2x81N.js (removed) 123 kB 🟢 -123 kB 🟢 -42.6 kB 🟢 -34 kB
assets/core-Co72TRqk.js (removed) 73 kB 🟢 -73 kB 🟢 -18.8 kB 🟢 -16.2 kB
assets/core-Q25xeu9r.js (new) 73 kB 🔴 +73 kB 🔴 +18.8 kB 🔴 +16.1 kB
assets/groupNode-BcKH3Eis.js (removed) 71.8 kB 🟢 -71.8 kB 🟢 -17.7 kB 🟢 -15.5 kB
assets/groupNode-Gi0CX_X-.js (new) 71.8 kB 🔴 +71.8 kB 🔴 +17.7 kB 🔴 +15.5 kB
assets/WidgetSelect-fVqiPVUZ.js (new) 58.1 kB 🔴 +58.1 kB 🔴 +12.4 kB 🔴 +10.7 kB
assets/WidgetSelect-o8zu2l2m.js (removed) 58.1 kB 🟢 -58.1 kB 🟢 -12.4 kB 🟢 -10.7 kB
assets/SubscriptionRequiredDialogContentWorkspace-CTKPVj4f.js (removed) 45.8 kB 🟢 -45.8 kB 🟢 -8.56 kB 🟢 -7.4 kB
assets/SubscriptionRequiredDialogContentWorkspace-gd8BXOnK.js (new) 45.8 kB 🔴 +45.8 kB 🔴 +8.55 kB 🔴 +7.42 kB
assets/Load3DControls-BPGQkBhc.js (removed) 30.9 kB 🟢 -30.9 kB 🟢 -5.34 kB 🟢 -4.64 kB
assets/Load3DControls-kJA1aQBM.js (new) 30.9 kB 🔴 +30.9 kB 🔴 +5.34 kB 🔴 +4.66 kB
assets/WorkspacePanelContent-B3wXM34U.js (removed) 29.3 kB 🟢 -29.3 kB 🟢 -6.14 kB 🟢 -5.39 kB
assets/WorkspacePanelContent-DCoqNeru.js (new) 29.3 kB 🔴 +29.3 kB 🔴 +6.14 kB 🔴 +5.38 kB
assets/SubscriptionRequiredDialogContent-DRNdJnm3.js (removed) 26.2 kB 🟢 -26.2 kB 🟢 -6.56 kB 🟢 -5.77 kB
assets/SubscriptionRequiredDialogContent-us7mJkEE.js (new) 26.2 kB 🔴 +26.2 kB 🔴 +6.56 kB 🔴 +5.78 kB
assets/Load3dViewerContent-6Vd_dHSJ.js (new) 23 kB 🔴 +23 kB 🔴 +5.18 kB 🔴 +4.5 kB
assets/Load3dViewerContent-CdqmWdq8.js (removed) 23 kB 🟢 -23 kB 🟢 -5.18 kB 🟢 -4.5 kB
assets/WidgetImageCrop-DJMeWBlQ.js (new) 22.1 kB 🔴 +22.1 kB 🔴 +5.5 kB 🔴 +4.85 kB
assets/WidgetImageCrop-P_vCIS3x.js (removed) 22.1 kB 🟢 -22.1 kB 🟢 -5.5 kB 🟢 -4.84 kB
assets/SubscriptionPanelContentWorkspace-BTFY42CX.js (new) 21.6 kB 🔴 +21.6 kB 🔴 +5.02 kB 🔴 +4.42 kB
assets/SubscriptionPanelContentWorkspace-DULkHOge.js (removed) 21.6 kB 🟢 -21.6 kB 🟢 -5.02 kB 🟢 -4.43 kB
assets/CurrentUserPopoverWorkspace-BB2tJS9-.js (removed) 19.8 kB 🟢 -19.8 kB 🟢 -4.86 kB 🟢 -4.33 kB
assets/CurrentUserPopoverWorkspace-kRofelUU.js (new) 19.8 kB 🔴 +19.8 kB 🔴 +4.85 kB 🔴 +4.33 kB
assets/SignInContent-6y9S-Ajh.js (removed) 18.9 kB 🟢 -18.9 kB 🟢 -4.79 kB 🟢 -4.18 kB
assets/SignInContent-BIcMcZy-.js (new) 18.9 kB 🔴 +18.9 kB 🔴 +4.79 kB 🔴 +4.19 kB
assets/commands-C0NcxRH3.js (removed) 18.8 kB 🟢 -18.8 kB 🟢 -4.02 kB 🟢 -3.12 kB
assets/commands-ClFTZZY8.js (new) 18.8 kB 🔴 +18.8 kB 🔴 +4.02 kB 🔴 +3.13 kB
assets/WidgetInputNumber-D3pLdXEO.js (removed) 18.7 kB 🟢 -18.7 kB 🟢 -4.75 kB 🟢 -4.21 kB
assets/WidgetInputNumber-DSM8gnzn.js (new) 18.7 kB 🔴 +18.7 kB 🔴 +4.75 kB 🔴 +4.22 kB
assets/commands-C2xuXGb5.js (removed) 17.5 kB 🟢 -17.5 kB 🟢 -3.7 kB 🟢 -2.89 kB
assets/commands-CNvwc2P-.js (new) 17.5 kB 🔴 +17.5 kB 🔴 +3.7 kB 🔴 +2.89 kB
assets/commands-eBbhcNBX.js (new) 17.5 kB 🔴 +17.5 kB 🔴 +3.75 kB 🔴 +2.99 kB
assets/commands-wq2Y-YKn.js (removed) 17.5 kB 🟢 -17.5 kB 🟢 -3.75 kB 🟢 -2.99 kB
assets/WidgetRecordAudio-C1MFxXww.js (new) 17.3 kB 🔴 +17.3 kB 🔴 +4.94 kB 🔴 +4.42 kB
assets/WidgetRecordAudio-DMF1u1cS.js (removed) 17.3 kB 🟢 -17.3 kB 🟢 -4.94 kB 🟢 -4.44 kB
assets/commands-BIWmUVEc.js (removed) 16.9 kB 🟢 -16.9 kB 🟢 -3.8 kB 🟢 -3 kB
assets/commands-Boqbp4FE.js (new) 16.9 kB 🔴 +16.9 kB 🔴 +3.8 kB 🔴 +3 kB
assets/commands-Bdca9E4N.js (new) 16.7 kB 🔴 +16.7 kB 🔴 +3.54 kB 🔴 +2.94 kB
assets/commands-DMwP8S5e.js (removed) 16.7 kB 🟢 -16.7 kB 🟢 -3.54 kB 🟢 -2.94 kB
assets/Load3D-7OM6qEEv.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -4.03 kB 🟢 -3.51 kB
assets/Load3D-DY9ZpNBQ.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +4.03 kB 🔴 +3.52 kB
assets/commands-CsOV8HcO.js (new) 16.1 kB 🔴 +16.1 kB 🔴 +3.53 kB 🔴 +2.89 kB
assets/commands-OO-8nFm9.js (removed) 16.1 kB 🟢 -16.1 kB 🟢 -3.53 kB 🟢 -2.89 kB
assets/commands-CmiKIQwc.js (removed) 16.1 kB 🟢 -16.1 kB 🟢 -3.43 kB 🟢 -2.79 kB
assets/commands-CnE4PBoq.js (new) 16.1 kB 🔴 +16.1 kB 🔴 +3.43 kB 🔴 +2.8 kB
assets/commands-BOt38VCw.js (removed) 16.1 kB 🟢 -16.1 kB 🟢 -3.38 kB 🟢 -2.79 kB
assets/commands-DPVHiFlP.js (new) 16.1 kB 🔴 +16.1 kB 🔴 +3.38 kB 🔴 +2.78 kB
assets/commands-DwBt3HhT.js (removed) 15.9 kB 🟢 -15.9 kB 🟢 -3.66 kB 🟢 -2.86 kB
assets/commands-oGOH5erQ.js (new) 15.9 kB 🔴 +15.9 kB 🔴 +3.66 kB 🔴 +2.86 kB
assets/commands-DBggpNhX.js (new) 15.2 kB 🔴 +15.2 kB 🔴 +3.58 kB 🔴 +2.73 kB
assets/commands-n_2KJWcD.js (removed) 15.2 kB 🟢 -15.2 kB 🟢 -3.58 kB 🟢 -2.73 kB
assets/commands-DC4TJj5_.js (new) 15.1 kB 🔴 +15.1 kB 🔴 +3.55 kB 🔴 +2.65 kB
assets/commands-JX559A2n.js (removed) 15.1 kB 🟢 -15.1 kB 🟢 -3.55 kB 🟢 -2.65 kB
assets/load3d-CaqWg7-f.js (new) 14.7 kB 🔴 +14.7 kB 🔴 +4.19 kB 🔴 +3.63 kB
assets/load3d-DKc5l6BN.js (removed) 14.7 kB 🟢 -14.7 kB 🟢 -4.19 kB 🟢 -3.63 kB
assets/AudioPreviewPlayer-Cm-zOfSP.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -3.19 kB 🟢 -2.85 kB
assets/AudioPreviewPlayer-DJQzu51X.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +3.19 kB 🔴 +2.85 kB
assets/changeTracker-BHUbWVaY.js (new) 9.38 kB 🔴 +9.38 kB 🔴 +2.89 kB 🔴 +2.54 kB
assets/changeTracker-C7h6BQIr.js (removed) 9.38 kB 🟢 -9.38 kB 🟢 -2.89 kB 🟢 -2.55 kB
assets/WidgetCurve-CNAR8Elf.js (new) 9.35 kB 🔴 +9.35 kB 🔴 +3.01 kB 🔴 +2.72 kB
assets/nodeTemplates-2ala7asJ.js (new) 9.29 kB 🔴 +9.29 kB 🔴 +3.25 kB 🔴 +2.86 kB
assets/nodeTemplates-DDZFbN1u.js (removed) 9.29 kB 🟢 -9.29 kB 🟢 -3.26 kB 🟢 -2.86 kB
assets/InviteMemberDialogContent-B5OIVjiI.js (removed) 7.38 kB 🟢 -7.38 kB 🟢 -2.29 kB 🟢 -2 kB
assets/InviteMemberDialogContent-VQ7C5Uw2.js (new) 7.38 kB 🔴 +7.38 kB 🔴 +2.29 kB 🔴 +2 kB
assets/WidgetToggleSwitch-BUaI5lT4.js (new) 6.8 kB 🔴 +6.8 kB 🔴 +2.19 kB 🔴 +1.94 kB
assets/WidgetToggleSwitch-C1n8cLaU.js (removed) 6.8 kB 🟢 -6.8 kB 🟢 -2.19 kB 🟢 -1.94 kB
assets/Load3DConfiguration-BgQ87KTR.js (removed) 6.27 kB 🟢 -6.27 kB 🟢 -1.92 kB 🟢 -1.68 kB
assets/Load3DConfiguration-BnYciDQD.js (new) 6.27 kB 🔴 +6.27 kB 🔴 +1.91 kB 🔴 +1.68 kB
assets/CreateWorkspaceDialogContent-DKUOgah2.js (removed) 5.53 kB 🟢 -5.53 kB 🟢 -1.99 kB 🟢 -1.73 kB
assets/CreateWorkspaceDialogContent-OpX3ievY.js (new) 5.53 kB 🔴 +5.53 kB 🔴 +1.99 kB 🔴 +1.73 kB
assets/onboardingCloudRoutes-Be6cWUif.js (new) 5.41 kB 🔴 +5.41 kB 🔴 +1.84 kB 🔴 +1.61 kB
assets/onboardingCloudRoutes-DEDCh2R9.js (removed) 5.41 kB 🟢 -5.41 kB 🟢 -1.83 kB 🟢 -1.6 kB
assets/EditWorkspaceDialogContent-CiC7duss.js (new) 5.33 kB 🔴 +5.33 kB 🔴 +1.94 kB 🔴 +1.69 kB
assets/EditWorkspaceDialogContent-Zn60uH0Y.js (removed) 5.33 kB 🟢 -5.33 kB 🟢 -1.95 kB 🟢 -1.7 kB
assets/ValueControlPopover-CGJlnOhN.js (removed) 4.92 kB 🟢 -4.92 kB 🟢 -1.76 kB 🟢 -1.57 kB
assets/ValueControlPopover-DkWNSAzN.js (new) 4.92 kB 🔴 +4.92 kB 🔴 +1.76 kB 🔴 +1.57 kB
assets/Preview3d-CjdE2IPj.js (removed) 4.81 kB 🟢 -4.81 kB 🟢 -1.57 kB 🟢 -1.36 kB
assets/Preview3d-oi-XniMU.js (new) 4.81 kB 🔴 +4.81 kB 🔴 +1.56 kB 🔴 +1.36 kB
assets/CancelSubscriptionDialogContent-_mDXF9JV.js (removed) 4.79 kB 🟢 -4.79 kB 🟢 -1.79 kB 🟢 -1.55 kB
assets/CancelSubscriptionDialogContent-vl_rPtHk.js (new) 4.79 kB 🔴 +4.79 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/AnimationControls-B4iSARcq.js (new) 4.61 kB 🔴 +4.61 kB 🔴 +1.6 kB 🔴 +1.4 kB
assets/AnimationControls-DjijCZ7o.js (removed) 4.61 kB 🟢 -4.61 kB 🟢 -1.6 kB 🟢 -1.41 kB
assets/DeleteWorkspaceDialogContent-DogjOrf-.js (new) 4.23 kB 🔴 +4.23 kB 🔴 +1.63 kB 🔴 +1.42 kB
assets/DeleteWorkspaceDialogContent-DZ6MIGxE.js (removed) 4.23 kB 🟢 -4.23 kB 🟢 -1.63 kB 🟢 -1.42 kB
assets/WidgetWithControl-DSQZsudp.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.77 kB 🔴 +1.59 kB
assets/WidgetWithControl-UjfcsH0R.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.77 kB 🟢 -1.61 kB
assets/LeaveWorkspaceDialogContent-CuGyvAGO.js (new) 4.06 kB 🔴 +4.06 kB 🔴 +1.58 kB 🔴 +1.37 kB
assets/LeaveWorkspaceDialogContent-HOR9L3kt.js (removed) 4.06 kB 🟢 -4.06 kB 🟢 -1.58 kB 🟢 -1.37 kB
assets/RemoveMemberDialogContent-DnSLNHvm.js (new) 4.04 kB 🔴 +4.04 kB 🔴 +1.52 kB 🔴 +1.33 kB
assets/RemoveMemberDialogContent-Do537ZBk.js (removed) 4.04 kB 🟢 -4.04 kB 🟢 -1.53 kB 🟢 -1.32 kB
assets/WidgetTextarea-D8GUT4SH.js (removed) 3.96 kB 🟢 -3.96 kB 🟢 -1.49 kB 🟢 -1.31 kB
assets/WidgetTextarea-Q-qdfbqq.js (new) 3.96 kB 🔴 +3.96 kB 🔴 +1.49 kB 🔴 +1.3 kB
assets/RevokeInviteDialogContent-CJ2pJCKI.js (new) 3.95 kB 🔴 +3.95 kB 🔴 +1.54 kB 🔴 +1.35 kB
assets/RevokeInviteDialogContent-MHbF8nD3.js (removed) 3.95 kB 🟢 -3.95 kB 🟢 -1.54 kB 🟢 -1.35 kB
assets/InviteMemberUpsellDialogContent-D5ohi94-.js (new) 3.82 kB 🔴 +3.82 kB 🔴 +1.4 kB 🔴 +1.23 kB
assets/InviteMemberUpsellDialogContent-Yf9mTrxy.js (removed) 3.82 kB 🟢 -3.82 kB 🟢 -1.4 kB 🟢 -1.23 kB
assets/WidgetGalleria-D6GhU3q2.js (removed) 3.61 kB 🟢 -3.61 kB 🟢 -1.39 kB 🟢 -1.25 kB
assets/WidgetGalleria-uOqACd0E.js (new) 3.61 kB 🔴 +3.61 kB 🔴 +1.39 kB 🔴 +1.25 kB
assets/Slider-C6m7fecr.js (new) 3.52 kB 🔴 +3.52 kB 🔴 +1.36 kB 🔴 +1.18 kB
assets/Slider-Cv2r2AJm.js (removed) 3.52 kB 🟢 -3.52 kB 🟢 -1.36 kB 🟢 -1.18 kB
assets/saveMesh-BM8gv4UU.js (new) 3.38 kB 🔴 +3.38 kB 🔴 +1.45 kB 🔴 +1.29 kB
assets/saveMesh-C7kD7UnF.js (removed) 3.38 kB 🟢 -3.38 kB 🟢 -1.46 kB 🟢 -1.29 kB
assets/cloudSessionCookie-Bz0rivoM.js (new) 3.1 kB 🔴 +3.1 kB 🔴 +1.08 kB 🔴 +952 B
assets/cloudSessionCookie-Cwp3oqkz.js (removed) 3.1 kB 🟢 -3.1 kB 🟢 -1.09 kB 🟢 -941 B
assets/WidgetImageCompare-CNzAJjYU.js (new) 3.1 kB 🔴 +3.1 kB 🔴 +1.15 kB 🔴 +1.02 kB
assets/WidgetImageCompare-DqrezrkI.js (removed) 3.1 kB 🟢 -3.1 kB 🟢 -1.15 kB 🟢 -1.02 kB
assets/WidgetMarkdown-BLTsLNPD.js (removed) 2.93 kB 🟢 -2.93 kB 🟢 -1.23 kB 🟢 -1.08 kB
assets/WidgetMarkdown-CVdw9hX2.js (new) 2.93 kB 🔴 +2.93 kB 🔴 +1.23 kB 🔴 +1.07 kB
assets/GlobalToast-BF1bBMZO.js (new) 2.91 kB 🔴 +2.91 kB 🔴 +1.21 kB 🔴 +1.03 kB
assets/GlobalToast-C2qTHCvN.js (removed) 2.91 kB 🟢 -2.91 kB 🟢 -1.21 kB 🟢 -1.03 kB
assets/WidgetColorPicker-C2UPaFjl.js (removed) 2.9 kB 🟢 -2.9 kB 🟢 -1.23 kB 🟢 -1.1 kB
assets/WidgetColorPicker-Dc4t8Faf.js (new) 2.9 kB 🔴 +2.9 kB 🔴 +1.23 kB 🔴 +1.1 kB
assets/MediaVideoTop-BO2aZavV.js (removed) 2.77 kB 🟢 -2.77 kB 🟢 -1.13 kB 🟢 -999 B
assets/MediaVideoTop-pufIlXJs.js (new) 2.77 kB 🔴 +2.77 kB 🔴 +1.13 kB 🔴 +1 kB
assets/ApiNodesSignInContent-CqtWKhoS.js (new) 2.69 kB 🔴 +2.69 kB 🔴 +1.05 kB 🔴 +919 B
assets/ApiNodesSignInContent-CuPvGXL1.js (removed) 2.69 kB 🟢 -2.69 kB 🟢 -1.05 kB 🟢 -920 B
assets/WidgetChart-CgT9e03M.js (removed) 2.21 kB 🟢 -2.21 kB 🟢 -951 B 🟢 -821 B
assets/WidgetChart-D4dGOl3j.js (new) 2.21 kB 🔴 +2.21 kB 🔴 +950 B 🔴 +821 B
assets/SubscribeToRun-CeCGlS8v.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +1.01 kB 🔴 +881 B
assets/SubscribeToRun-DPLqZfb6.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -1.01 kB 🟢 -867 B
assets/WidgetLayoutField-DJYJrhiu.js (removed) 1.98 kB 🟢 -1.98 kB 🟢 -891 B 🟢 -778 B
assets/WidgetLayoutField-DNiJ_Scb.js (new) 1.98 kB 🔴 +1.98 kB 🔴 +891 B 🔴 +778 B
assets/WidgetInputText-DHQ3B5q-.js (removed) 1.86 kB 🟢 -1.86 kB 🟢 -872 B 🟢 -782 B
assets/WidgetInputText-DjlHlRoz.js (new) 1.86 kB 🔴 +1.86 kB 🔴 +871 B 🔴 +789 B
assets/Media3DTop-CouvCIvd.js (new) 1.82 kB 🔴 +1.82 kB 🔴 +895 B 🔴 +764 B
assets/Media3DTop-CpdNXNf1.js (removed) 1.82 kB 🟢 -1.82 kB 🟢 -896 B 🟢 -764 B
assets/BaseViewTemplate-C7TdQsa4.js (new) 1.78 kB 🔴 +1.78 kB 🔴 +922 B 🔴 +832 B
assets/BaseViewTemplate-SpFD1rBU.js (removed) 1.78 kB 🟢 -1.78 kB 🟢 -924 B 🟢 -810 B
assets/MediaImageTop-CsrUK1I8.js (new) 1.75 kB 🔴 +1.75 kB 🔴 +878 B 🔴 +750 B
assets/MediaImageTop-vhWMCCeS.js (removed) 1.75 kB 🟢 -1.75 kB 🟢 -878 B 🟢 -751 B
assets/CloudRunButtonWrapper-D9rymLjn.js (new) 1.68 kB 🔴 +1.68 kB 🔴 +780 B 🔴 +716 B
assets/CloudRunButtonWrapper-DDwnHzaP.js (removed) 1.68 kB 🟢 -1.68 kB 🟢 -788 B 🟢 -712 B
assets/signInSchema-Bd1Doi2f.js (removed) 1.53 kB 🟢 -1.53 kB 🟢 -562 B 🟢 -518 B
assets/signInSchema-Bqr0xvWO.js (new) 1.53 kB 🔴 +1.53 kB 🔴 +562 B 🔴 +516 B
assets/MediaAudioTop-CJNtJ1Vf.js (new) 1.43 kB 🔴 +1.43 kB 🔴 +763 B 🔴 +632 B
assets/MediaAudioTop-qYtfOhNn.js (removed) 1.43 kB 🟢 -1.43 kB 🟢 -763 B 🟢 -632 B
assets/cloudBadges-BkchT9M4.js (removed) 1.37 kB 🟢 -1.37 kB 🟢 -701 B 🟢 -606 B
assets/cloudBadges-TnTwwPnx.js (new) 1.37 kB 🔴 +1.37 kB 🔴 +697 B 🔴 +613 B
assets/cloudSubscription-4eFnYbey.js (new) 1.33 kB 🔴 +1.33 kB 🔴 +651 B 🔴 +568 B
assets/cloudSubscription-Ckj8aogW.js (removed) 1.33 kB 🟢 -1.33 kB 🟢 -657 B 🟢 -567 B
assets/widgetPropFilter-C9FcIgiN.js (new) 1.1 kB 🔴 +1.1 kB 🔴 +509 B 🔴 +431 B
assets/widgetPropFilter-Cd0O5LPR.js (removed) 1.1 kB 🟢 -1.1 kB 🟢 -510 B 🟢 -431 B
assets/Load3D-CtTvNg6w.js (new) 1.07 kB 🔴 +1.07 kB 🔴 +500 B 🔴 +443 B
assets/Load3D-DYYWqNur.js (removed) 1.07 kB 🟢 -1.07 kB 🟢 -500 B 🟢 -443 B
assets/MediaOtherTop-BWV5s4M2.js (removed) 1.02 kB 🟢 -1.02 kB 🟢 -569 B 🟢 -474 B
assets/MediaOtherTop-DT9GM-Zv.js (new) 1.02 kB 🔴 +1.02 kB 🔴 +569 B 🔴 +470 B
assets/MediaTextTop-BcCnQHMJ.js (removed) 1.01 kB 🟢 -1.01 kB 🟢 -564 B 🟢 -475 B
assets/MediaTextTop-vLt-EA1h.js (new) 1.01 kB 🔴 +1.01 kB 🔴 +562 B 🔴 +476 B
assets/nightlyBadges-q-JOxlbB.js (new) 1 kB 🔴 +1 kB 🔴 +529 B 🔴 +476 B
assets/nightlyBadges-XWZFRXDf.js (removed) 1 kB 🟢 -1 kB 🟢 -532 B 🟢 -471 B
assets/Load3dViewerContent-CjuKUB8s.js (new) 993 B 🔴 +993 B 🔴 +469 B 🔴 +415 B
assets/Load3dViewerContent-D3SvpXsq.js (removed) 993 B 🟢 -993 B 🟢 -470 B 🟢 -414 B
assets/SubscriptionPanelContentWorkspace-Bhk8pwZA.js (new) 930 B 🔴 +930 B 🔴 +437 B 🔴 +383 B
assets/SubscriptionPanelContentWorkspace-sxoTlIcu.js (removed) 930 B 🟢 -930 B 🟢 -440 B 🟢 -381 B
assets/ComfyOrgHeader-hCSVqQLq.js (new) 910 B 🔴 +910 B 🔴 +498 B 🔴 +427 B
assets/ComfyOrgHeader-vsmXNmmw.js (removed) 910 B 🟢 -910 B 🟢 -495 B 🟢 -426 B
assets/graphHasMissingNodes--QxthI8H.js (new) 761 B 🔴 +761 B 🔴 +373 B 🔴 +326 B
assets/graphHasMissingNodes-CBdZzex6.js (removed) 761 B 🟢 -761 B 🟢 -374 B 🟢 -328 B
assets/changeTracker-bGRi6xqS.js (removed) 757 B 🟢 -757 B 🟢 -388 B 🟢 -335 B
assets/changeTracker-Cvc1YriG.js (new) 757 B 🔴 +757 B 🔴 +380 B 🔴 +338 B
assets/WidgetLegacy-C58uXn9n.js (removed) 745 B 🟢 -745 B 🟢 -388 B 🟢 -336 B
assets/WidgetLegacy-yJ0DyfMZ.js (new) 745 B 🔴 +745 B 🔴 +380 B 🔴 +337 B
assets/previousFullPath-Bpf5sR83.js (new) 665 B 🔴 +665 B 🔴 +368 B 🔴 +335 B
assets/previousFullPath-DeIFnh1k.js (removed) 665 B 🟢 -665 B 🟢 -367 B 🟢 -306 B
assets/constants-BIWjk1ar.js (removed) 579 B 🟢 -579 B 🟢 -256 B 🟢 -231 B
assets/constants-htt0vt7m.js (new) 579 B 🔴 +579 B 🔴 +257 B 🔴 +212 B
assets/WidgetInputNumber-BgeFes29.js (new) 469 B 🔴 +469 B 🔴 +262 B 🔴 +231 B
assets/WidgetInputNumber-DFiNm5ju.js (removed) 469 B 🟢 -469 B 🟢 -261 B 🟢 -229 B
assets/i18n-BSCphJtf.js (removed) 199 B 🟢 -199 B 🟢 -159 B 🟢 -137 B
assets/i18n-C1oMxlHA.js (new) 199 B 🔴 +199 B 🔴 +160 B 🔴 +139 B
assets/comfy-logo-single-D9MrYETV.js (new) 198 B 🔴 +198 B 🔴 +162 B 🔴 +126 B
assets/comfy-logo-single-DhnNuB-i.js (removed) 198 B 🟢 -198 B 🟢 -160 B 🟢 -132 B
assets/auto-BTnZwrs2.js 1.7 kB 1.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/OBJLoader2WorkerModule-DTMpvldF.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Popover-BRmRgwNy.js 3.65 kB 3.65 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/SelectValue-D-D55K_n.js 8.94 kB 8.94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/src-PwE2kea4.js 251 B 251 B ⚪ 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/VideoPlayOverlay-CMR8YZxL.js 1.35 kB 1.35 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widget-NeEr3XWN.js 586 B 586 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-3ihy3W8s.js 283 B 283 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-B1dc4Mvs.js 3.19 kB 3.19 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetTypes-DjwSopYV.js 393 B 393 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 109 added / 108 removed

@jtydhr88
Copy link
Collaborator Author

i don't think the failing tests caused by my changes, another two have the same failure tests

Copy link
Contributor

@christian-byrne christian-byrne left a comment

Choose a reason for hiding this comment

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

Looking good

@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Feb 22, 2026
@jtydhr88 jtydhr88 changed the title feat: add CurveEditor component and d3-shape dependency feat: add CurveEditor component Feb 22, 2026
@jtydhr88 jtydhr88 assigned christian-byrne and unassigned jtydhr88 Feb 22, 2026
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 (4)
src/components/curve/CurveEditor.test.ts (2)

18-18: Use the imported component reference in describe() instead of a string literal

CurveEditor is already imported at line 6, so the describe suite can reference it directly.

♻️ Proposed fix
-describe('CurveEditor', () => {
+describe(CurveEditor, () => {

Based on learnings: "follow the vitest/prefer-describe-function-title rule by using describe(ComponentOrFunction, ...) instead of a string literal description when naming test suites."

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

In `@src/components/curve/CurveEditor.test.ts` at line 18, The test suite
currently uses a string literal in describe; update the suite to pass the
imported component reference instead by replacing the string with the
CurveEditor symbol (i.e., use describe(CurveEditor, ...) so the describe call
references the imported CurveEditor component), ensuring imports at top
(CurveEditor) remain unchanged and tests inside the suite keep their existing
names and behavior.

8-16: extraProps parameter lacks type safety — use Partial<ComponentProps<typeof CurveEditor>>

The implicit {} type on extraProps accepts anything, losing the benefit of TypeScript validation for prop names and types. Per the repo convention, test mount helpers should type extra props against the component's actual prop types.

♻️ Proposed fix
+import type { ComponentProps } from 'vue-component-type-helpers'
+
-function mountEditor(points: CurvePoint[], extraProps = {}) {
+function mountEditor(
+  points: CurvePoint[],
+  extraProps: Partial<ComponentProps<typeof CurveEditor>> = {}
+) {
   return mount(CurveEditor, {
     props: { modelValue: points, ...extraProps }
   })
 }

-function getCurvePath(wrapper: ReturnType<typeof mount>) {
+function getCurvePath(wrapper: ReturnType<typeof mountEditor>) {

Based on learnings: "for test helpers like mountComponent, type the props parameter as Partial<ComponentProps<typeof Component>>."

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

In `@src/components/curve/CurveEditor.test.ts` around lines 8 - 16, The
mountEditor helper currently types extraProps as an untyped {}, losing TS prop
checks; update the signature of mountEditor to type extraProps as
Partial<ComponentProps<typeof CurveEditor>> and add the necessary import for
ComponentProps from 'vue' (or the appropriate typings source) so passing props
is type-checked against CurveEditor; keep the rest of the logic (props: {
modelValue: points, ...extraProps }) unchanged and leave getCurvePath as-is.
src/components/curve/CurveEditor.vue (1)

62-72: Use a stable key instead of array index for deletable control points

:key="i" means Vue identifies each circle by its position in the array. When a middle point is deleted, all subsequent circles get recycled with shifted indices, which can cause incorrect pointer-capture state or stale composable state in startDrag. A point's [x, y] tuple uniquely identifies it in practice.

♻️ Proposed fix
-    :key="i"
+    :key="`${point[0]},${point[1]}`"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/curve/CurveEditor.vue` around lines 62 - 72, The circles
currently use the array index as the key which causes recycled DOM elements and
stale pointer state when points are removed; change the key to a stable
identifier derived from the point value (e.g. a string based on the point tuple)
so Vue tracks each control point by its coordinates instead of position in
modelValue; update the v-for key expression where the circle is rendered and
ensure handlers like startDrag(i, $event) still receive the correct index (you
can compute the index from modelValue when handling events if you switch the key
to a point-based string).
src/components/curve/curveUtils.test.ts (1)

11-11: Use function references instead of string literals in describe()

Per the vitest/prefer-describe-function-title rule enforced in this repo, test suites should be named by passing the tested function/component directly rather than a string.

♻️ Proposed fix
-describe('createMonotoneInterpolator', () => {
+describe(createMonotoneInterpolator, () => {
-describe('curvesToLUT', () => {
+describe(curvesToLUT, () => {
-describe('histogramToPath', () => {
+describe(histogramToPath, () => {

Based on learnings: "In test files under src/**/*.test.ts, follow the vitest/prefer-describe-function-title rule by using describe(ComponentOrFunction, ...) instead of a string literal description when naming test suites."

Also applies to: 76-76, 109-109

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

In `@src/components/curve/curveUtils.test.ts` at line 11, Replace string literal
titles in the test suites with direct function references: change
describe('createMonotoneInterpolator', ...) to
describe(createMonotoneInterpolator, ...) in
src/components/curve/curveUtils.test.ts and do the same for the other describe
blocks in this file that currently use string literals (the ones flagged by the
rule). Ensure the imported/defined symbol createMonotoneInterpolator is in scope
for the describe call and update any other test-suite names in this file to pass
the function/ component reference instead of a string.
🤖 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/components/curve/CurveEditor.vue`:
- Line 68: The control point circles currently use a hardcoded stroke="white"
which breaks theming; change the circle stroke to use the component's theming or
prop (e.g., use stroke="currentColor" or bind to the existing curveColor prop
with a fallback to a semantic CSS variable) so the stroke follows light/dark
themes and the component's color conventions (update the circle element in
CurveEditor.vue to reference curveColor or currentColor instead of the literal
"white").

In `@src/components/curve/curveUtils.ts`:
- Around line 95-111: The histogramToPath function assumes a 256-bin histogram
causing NaNs for other lengths; update it to validate and enforce the 256-bin
contract (or handle variable-length histograms consistently): inside
histogramToPath check histogram.length and either return '' or throw if
histogram.length !== 256 (or, if supporting variable lengths, compute n =
histogram.length, use percentileIndex = Math.floor((n - 1) * 0.995) to find max
from sorted, guard against undefined max, set step = 1 / (n - 1) and loop for
(let i = 0; i < n; i++) using histogram[i] safely); ensure all references to
255/256 are replaced by n-1/n as needed and preserve the early-return when max
is 0 to avoid NaNs.
- Around line 87-91: The docblock describing "Generate a 256-entry lookup table
from curve control points" is placed above histogramToPath instead of above
curvesToLUT; move that comment block so it directly precedes the curvesToLUT
function declaration (and remove or replace any incorrect docblock above
histogramToPath), ensuring curvesToLUT has the proper description and
histogramToPath has its own appropriate docblock if needed; reference the
functions curvesToLUT and histogramToPath to locate and reattach the docblock.

---

Nitpick comments:
In `@src/components/curve/CurveEditor.test.ts`:
- Line 18: The test suite currently uses a string literal in describe; update
the suite to pass the imported component reference instead by replacing the
string with the CurveEditor symbol (i.e., use describe(CurveEditor, ...) so the
describe call references the imported CurveEditor component), ensuring imports
at top (CurveEditor) remain unchanged and tests inside the suite keep their
existing names and behavior.
- Around line 8-16: The mountEditor helper currently types extraProps as an
untyped {}, losing TS prop checks; update the signature of mountEditor to type
extraProps as Partial<ComponentProps<typeof CurveEditor>> and add the necessary
import for ComponentProps from 'vue' (or the appropriate typings source) so
passing props is type-checked against CurveEditor; keep the rest of the logic
(props: { modelValue: points, ...extraProps }) unchanged and leave getCurvePath
as-is.

In `@src/components/curve/CurveEditor.vue`:
- Around line 62-72: The circles currently use the array index as the key which
causes recycled DOM elements and stale pointer state when points are removed;
change the key to a stable identifier derived from the point value (e.g. a
string based on the point tuple) so Vue tracks each control point by its
coordinates instead of position in modelValue; update the v-for key expression
where the circle is rendered and ensure handlers like startDrag(i, $event) still
receive the correct index (you can compute the index from modelValue when
handling events if you switch the key to a point-based string).

In `@src/components/curve/curveUtils.test.ts`:
- Line 11: Replace string literal titles in the test suites with direct function
references: change describe('createMonotoneInterpolator', ...) to
describe(createMonotoneInterpolator, ...) in
src/components/curve/curveUtils.test.ts and do the same for the other describe
blocks in this file that currently use string literals (the ones flagged by the
rule). Ensure the imported/defined symbol createMonotoneInterpolator is in scope
for the describe call and update any other test-suite names in this file to pass
the function/ component reference instead of a string.

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: 5

🧹 Nitpick comments (4)
src/schemas/nodeDef/nodeDefSchemaV2.ts (1)

129-136: Consider exporting CurveInputSpec type and isCurveInputSpec guard for consistency.

Every other concrete input spec in this file has both an exported TypeScript type (ColorInputSpec, BoundingBoxInputSpec, ChartInputSpec, etc.) and for some an exported is*InputSpec guard. zCurveInputSpec is the only one added without them, which breaks the pattern and leaves callers unable to narrow an InputSpec to CurveInputSpec without re-declaring the shape.

💡 Suggested additions (at the bottom of the file)
+export type CurveInputSpec = z.infer<typeof zCurveInputSpec>
+
+export const isCurveInputSpec = (
+  inputSpec: InputSpec
+): inputSpec is CurveInputSpec => {
+  return inputSpec.type === 'CURVE'
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/schemas/nodeDef/nodeDefSchemaV2.ts` around lines 129 - 136, Export a
TypeScript type alias and a type guard for the curve spec to match the file's
pattern: add an exported type named CurveInputSpec that infers the shape from
zCurveInputSpec and export a boolean type guard isCurveInputSpec (or similar)
that narrows InputSpec to CurveInputSpec using zCurveInputSpec.safeParse or
instance checks. Reference zCurveInputSpec when creating the type alias and when
implementing the guard so callers can import CurveInputSpec and call
isCurveInputSpec(...) to narrow an InputSpec to the CURVE variant.
src/components/curve/CurveEditor.test.ts (1)

67-76: expect(d).toContain('L') is tightly coupled to the path command format.

This assertion passes today because the curve generator samples points and emits L (lineto) commands. If the rendering is ever changed to use d3-shape's smooth-curve generators (which emit C cubic-bezier commands), this assertion—and the split(/[ML]/) x-range parsing on lines 84–89—will silently produce wrong results or fail. Consider documenting the assumption, or testing the rendered shape semantically (e.g., checking that the curve path exists and is non-empty) rather than encoding the SVG command syntax.

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

In `@src/components/curve/CurveEditor.test.ts` around lines 67 - 76, The test
"generates path starting with M and containing L segments" is tightly coupled to
SVG command letters — instead of asserting expect(d).toContain('L'), use a
semantic check: locate the path via getCurvePath(wrapper) and assert it's
present and non-empty (d is a non-empty string and not just "M"), or better call
the DOM SVG path API (e.g., element.getTotalLength()) and assert the length is >
0 to prove a rendered curve exists; update the test around mountEditor /
getCurvePath to remove the 'L' assertion and replace it with the
non-empty/totalLength check.
src/composables/useCurveEditor.ts (1)

126-130: Consider useEventListener from VueUse for drag listener cleanup.

The three listeners added in startDrag are manually removed in endDrag and guarded via cleanupDrag + onBeforeUnmount. VueUse's useEventListener with a reactive/conditional target can consolidate cleanup automatically and aligns with the VueUse-first composable guideline.

Based on learnings: "Applies to **/composables/**/*.ts: Leverage VueUse functions for performance-enhancing composables."

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

In `@src/composables/useCurveEditor.ts` around lines 126 - 130, Replace the manual
add/remove listener pattern in startDrag/endDrag by using VueUse's
useEventListener for the svg target so cleanup is automatic: locate startDrag,
endDrag and the cleanupDrag handling in useCurveEditor.ts and swap
svg.addEventListener('pointermove', onMove)/('pointerup',
endDrag)/('lostpointercapture', endDrag) and the cleanupDrag assignment with
useEventListener calls (reactive/conditional target bound to svg) for
'pointermove', 'pointerup' and 'lostpointercapture'; remove the manual
removeEventListener calls and the cleanupDrag/onBeforeUnmount guard so VueUse
handles teardown.
src/renderer/extensions/vueNodes/widgets/composables/useCurveWidget.ts (1)

9-9: Use a function declaration instead of a function expression.

♻️ Proposed fix
-export const useCurveWidget = (): ComfyWidgetConstructorV2 => {
-  return (node: LGraphNode, inputSpec: InputSpecV2): ICurveWidget => {
+export function useCurveWidget(): ComfyWidgetConstructorV2 {
+  return function (node: LGraphNode, inputSpec: InputSpecV2): ICurveWidget {

As per coding guidelines: "Do not use function expressions if it's possible to use function declarations instead."

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

In `@src/renderer/extensions/vueNodes/widgets/composables/useCurveWidget.ts` at
line 9, The exported function is currently declared as a function expression
named useCurveWidget; change it to a function declaration to follow the
guideline—replace "export const useCurveWidget = (): ComfyWidgetConstructorV2 =>
{ ... }" with "export function useCurveWidget(): ComfyWidgetConstructorV2 { ...
}", keeping the same return type and body and preserving the exported symbol so
callers of useCurveWidget are unaffected.
🤖 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/components/curve/CurveEditor.test.ts`:
- Line 18: The test suite is using a string literal; change
describe('CurveEditor', ...) to use the actual component reference
describe(CurveEditor, ...) so it satisfies
vitest/prefer-describe-function-title; ensure the CurveEditor symbol is imported
or referenced in the test file (e.g., the existing CurveEditor import or export
used by tests) so the identifier is in scope before updating the describe call.

In `@src/components/curve/CurveEditor.vue`:
- Around line 84-87: The default prop curveColor in CurveEditor.vue is set to
'white' which disappears on light backgrounds; update the defineProps default
for curveColor from 'white' to 'currentColor' (or a semantic CSS variable like
'--foreground') so the histogram fill, curve stroke and control circle fills
inherit the host foreground; ensure the components and bindings that reference
curveColor (the histogram, the curve path, and control circle rendering logic)
keep using that prop so they automatically pick up the inherited color.

In `@src/components/curve/WidgetCurve.vue`:
- Around line 2-4: The div wrapping CurveEditor uses a non-existent class
"widget-expands"; update the wrapper in WidgetCurve.vue (the div containing
<CurveEditor v-model="modelValue" />) to use Tailwind utility classes instead —
for parity with WidgetImageCrop.vue replace "widget-expands" with the equivalent
utilities such as "relative flex h-full w-full flex-col" (add "gap-1" if spacing
is needed) and remove any custom class references so only Tailwind classes are
used.

In `@src/composables/useCurveEditor.ts`:
- Around line 70-86: handleSvgPointerDown currently adds a new point then calls
startDrag(newIndex, e), but if e.ctrlKey is true startDrag will immediately
delete that new point; to avoid the spurious add/remove, add an early-exit guard
in handleSvgPointerDown to return if e.ctrlKey is set (after checking e.button
=== 0) so you only proceed to create a new point when ctrl is not pressed;
update the logic in handleSvgPointerDown (which uses svgCoords,
findNearestPoint, modelValue and startDrag) to check e.ctrlKey before creating
and assigning newPoints.

In `@src/renderer/extensions/vueNodes/widgets/composables/useCurveWidget.ts`:
- Around line 12-16: The current defaultValue assignment unsafely asserts
inputSpec as { default?: CurvePoint[] } — replace that with proper type
narrowing: use the provided isCurveInputSpec(inputSpec) type guard to narrow
InputSpec to the CURVE case before reading inputSpec.default, or if you prefer a
local assertion, read (inputSpec.default as CurvePoint[] | undefined) and
fallback to [[0,0],[1,1]]; update the defaultValue initialization in
useCurveWidget.ts (the defaultValue constant) to perform the narrowing via
isCurveInputSpec or the narrower assertion so you no longer cast the whole
inputSpec object.

---

Duplicate comments:
In `@src/components/curve/CurveEditor.vue`:
- Around line 61-72: The circle elements in CurveEditor.vue hardcode
stroke="white", breaking theming; change the SVG circles to use a themed stroke
value instead (e.g., bind :stroke to a reactive/prop/computed like strokeColor
or to a CSS variable) and provide that value via the existing theming (use
curveColor fallback or a new prop/computed). Update the <circle> that references
modelValue and startDrag to use :stroke="strokeColor" (or
:stroke="getStrokeColor()") and add the corresponding prop/computed (and
default) so the component respects app/theme colors rather than the literal
"white".

---

Nitpick comments:
In `@src/components/curve/CurveEditor.test.ts`:
- Around line 67-76: The test "generates path starting with M and containing L
segments" is tightly coupled to SVG command letters — instead of asserting
expect(d).toContain('L'), use a semantic check: locate the path via
getCurvePath(wrapper) and assert it's present and non-empty (d is a non-empty
string and not just "M"), or better call the DOM SVG path API (e.g.,
element.getTotalLength()) and assert the length is > 0 to prove a rendered curve
exists; update the test around mountEditor / getCurvePath to remove the 'L'
assertion and replace it with the non-empty/totalLength check.

In `@src/composables/useCurveEditor.ts`:
- Around line 126-130: Replace the manual add/remove listener pattern in
startDrag/endDrag by using VueUse's useEventListener for the svg target so
cleanup is automatic: locate startDrag, endDrag and the cleanupDrag handling in
useCurveEditor.ts and swap svg.addEventListener('pointermove',
onMove)/('pointerup', endDrag)/('lostpointercapture', endDrag) and the
cleanupDrag assignment with useEventListener calls (reactive/conditional target
bound to svg) for 'pointermove', 'pointerup' and 'lostpointercapture'; remove
the manual removeEventListener calls and the cleanupDrag/onBeforeUnmount guard
so VueUse handles teardown.

In `@src/renderer/extensions/vueNodes/widgets/composables/useCurveWidget.ts`:
- Line 9: The exported function is currently declared as a function expression
named useCurveWidget; change it to a function declaration to follow the
guideline—replace "export const useCurveWidget = (): ComfyWidgetConstructorV2 =>
{ ... }" with "export function useCurveWidget(): ComfyWidgetConstructorV2 { ...
}", keeping the same return type and body and preserving the exported symbol so
callers of useCurveWidget are unaffected.

In `@src/schemas/nodeDef/nodeDefSchemaV2.ts`:
- Around line 129-136: Export a TypeScript type alias and a type guard for the
curve spec to match the file's pattern: add an exported type named
CurveInputSpec that infers the shape from zCurveInputSpec and export a boolean
type guard isCurveInputSpec (or similar) that narrows InputSpec to
CurveInputSpec using zCurveInputSpec.safeParse or instance checks. Reference
zCurveInputSpec when creating the type alias and when implementing the guard so
callers can import CurveInputSpec and call isCurveInputSpec(...) to narrow an
InputSpec to the CURVE variant.

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/schemas/nodeDef/nodeDefSchemaV2.ts (1)

203-203: Consider adding an isCurveInputSpec type guard for consistency.

The file provides narrowing guards for several other exported specs (e.g. isChartInputSpec). The CurveWidget downstream will likely need to narrow InputSpec → CurveInputSpec; a guard here would make that ergonomic and consistent with the existing pattern.

✨ Suggested addition
 export type CurveInputSpec = z.infer<typeof zCurveInputSpec>

Append after the existing isChartInputSpec guard:

+export function isCurveInputSpec(
+  inputSpec: InputSpec
+): inputSpec is CurveInputSpec {
+  return inputSpec.type === 'CURVE'
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/schemas/nodeDef/nodeDefSchemaV2.ts` at line 203, Add an exported type
guard named isCurveInputSpec to mirror the existing pattern (e.g.,
isChartInputSpec): implement isCurveInputSpec(spec: unknown): spec is
CurveInputSpec by using zCurveInputSpec.safeParse(spec).success (or equivalent
zod validation) to narrow the InputSpec to CurveInputSpec, and export it so
downstream consumers like CurveWidget can reliably narrow InputSpec →
CurveInputSpec.
🤖 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/schemas/nodeDef/nodeDefSchemaV2.ts`:
- Line 203: Add an exported type guard named isCurveInputSpec to mirror the
existing pattern (e.g., isChartInputSpec): implement isCurveInputSpec(spec:
unknown): spec is CurveInputSpec by using
zCurveInputSpec.safeParse(spec).success (or equivalent zod validation) to narrow
the InputSpec to CurveInputSpec, and export it so downstream consumers like
CurveWidget can reliably narrow InputSpec → CurveInputSpec.

Copy link
Contributor

@christian-byrne christian-byrne left a comment

Choose a reason for hiding this comment

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

LGTM!

@christian-byrne christian-byrne merged commit e333ad4 into main Feb 24, 2026
30 checks passed
@christian-byrne christian-byrne deleted the feat/curve-editor branch February 24, 2026 05:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants