Conversation
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (2)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the 📝 WalkthroughWalkthroughReplaces PrimeVue InputNumber with a custom locale-aware text input plus decrement/increment buttons (drag/keyboard/formatting/clamping), adds exported evaluateInput() for parsing numeric expressions, updates NumberWidget to use it, adapts tests and a browser fixture for new test-id selectors, and changes popover trigger to click. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Widget as WidgetInputNumberInput
participant Eval as evaluateInput()
participant LiteGraph as NumberWidget
User->>Widget: type text / drag / click +/- / press keys
Widget->>Eval: evaluateInput(inputString)
Eval-->>Widget: numeric value or undefined
Widget->>Widget: clamp/apply step & precision, format value
Widget->>LiteGraph: emit/update value
LiteGraph-->>Widget: propagate new prop value
Widget-->>User: render formatted value and update buttons/state
Possibly related PRs
Suggested reviewers
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. Comment |
🎨 Storybook Build Status✅ Build completed successfully! ⏰ Completed at: 01/13/2026, 11:03:26 PM UTC 🔗 Links🎉 Your Storybook is ready for review! |
🎭 Playwright Tests: ✅ PassedResults: 506 passed, 0 failed, 0 flaky, 8 skipped (Total: 514) 📊 Browser Reports
|
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 3.32 MB (baseline 3.32 MB) • 🟢 -4.67 kBMain entry bundles and manifests
Status: 3 added / 3 removed Graph Workspace — 1.04 MB (baseline 1.04 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 6.63 kB (baseline 6.63 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 1 added / 1 removed Panels & Settings — 372 kB (baseline 372 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 6 added / 6 removed UI Components — 206 kB (baseline 200 kB) • 🔴 +5.52 kBReusable component library chunks
Status: 8 added / 8 removed Data & Services — 12.5 kB (baseline 12.5 kB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 2 added / 2 removed Utilities & Hooks — 1.41 kB (baseline 1.41 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 1 added / 1 removed Vendor & Third-Party — 9.19 MB (baseline 9.19 MB) • ⚪ 0 BExternal libraries and shared vendor chunks
Other — 5.25 MB (baseline 5.25 MB) • ⚪ 0 BBundles that do not match a named category
Status: 16 added / 16 removed |
|
Updating Playwright Expectations |
1e3e129 to
7e9c6ee
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (1)
86-90: Returning0as default stepValue disables keyboard and button controls.When
stepValueis0, expressions likemodelValue + stepValueandmodelValue += stepValuehave no effect. The comment says "unrestricted stepping" but this actually prevents all stepping via buttons and arrow keys.Consider returning
1as a sensible default:🐛 Proposed fix
// Default to 'any' for unrestricted stepping - return 0 + return 1
🤖 Fix all issues with AI agents
In @src/lib/litegraph/src/utils/widget.ts:
- Around line 12-25: The evaluateInput function uses eval (arbitrary code
execution), has a faulty regex (missing anchors) and reassigns the parameter
while its comment refers to the wrong name; replace eval with a safe math
expression evaluator (add a lightweight dependency such as mathjs or a small
expression-parser) and parse only numeric/arithmetic tokens, update the
validation regex to anchor both ends (e.g. allow optional decimals and
whitespace-only arithmetic characters), stop reassigning the input parameter
(assign the parser result to a new variable like parsedValue), and update the
comment to reference the input parameter; ensure errors from the parser are
caught and result in undefined rather than executing code.
In
@src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue:
- Around line 126-131: The falsy check in handleMouseUp prevents assigning 0
because "if (!newValue)" treats 0 as false; change the guard to explicitly check
for undefined or null (e.g., newValue == null or newValue === undefined) so that
a numeric 0 is accepted, then assign modelValue.value = newValue and clear
dragValue.value as before.
- Around line 158-165: The input uses formattedValue (a localized string) for
aria-valuenow, which must be a numeric value; create or use an existing numeric
value (e.g., numericValue or parsedNumber derived from the underlying numeric
prop/state) and bind that to aria-valuenow (e.g.,
:aria-valuenow="numericValue"), keep :value="formattedValue" for display, and
ensure aria-valuemin/aria-valuemax use numeric types (filteredProps.min/max) or
are cast to numbers and omitted if NaN so assistive tech receives proper numeric
ARIA attributes.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (21)
browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-overlapped-after-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-overlapped-before-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-widget-overlapped-after-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-widget-overlapped-before-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/bypass.spec.ts-snapshots/vue-node-bypassed-state-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/mute.spec.ts-snapshots/vue-node-muted-state-chromium-linux.pngis excluded by!**/*.png
📒 Files selected for processing (6)
browser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
🧰 Additional context used
📓 Path-based instructions (13)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/widgets/NumberWidget.ts
src/lib/litegraph/**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (src/lib/litegraph/CLAUDE.md)
src/lib/litegraph/**/*.{js,ts,jsx,tsx}: Run ESLint instead of manually figuring out whitespace fixes or other trivial style concerns using thepnpm lint:fixcommand
Take advantage ofTypedArraysubarraywhen appropriate
Thesizeandposproperties ofRectangleshare the same array buffer (subarray); they may be used to set the rectangle's size and position
Prefer single lineifsyntax over adding curly braces, when the statement has a very concise expression and concise, single line statement
Do not replace&&=or||=with=when there is no reason to do so. If you do find a reason to remove either&&=or||=, leave a comment explaining why the removal occurred
When writing methods, prefer returning idiomatic JavaScriptundefinedovernull
Files:
src/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/lib/litegraph/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/lib/litegraph/CLAUDE.md)
Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Files:
src/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
src/**/*.vue: Use Vue 3 Single File Components (SFCs) with Composition API only
Use<script setup lang="ts">for component logic in Vue SFCs
Avoid<style>blocks in Vue components - use Tailwind 4 styling instead
Use vue-i18n for all string literals in Vue components - place translation entries insrc/locales/en/main.json
Use Tailwind utility classes instead ofdark:variant - use semantic values fromstyle.csstheme (e.g.,bg-node-component-surface)
Usecn()utility from@/utils/tailwindUtilfor merging Tailwind class names instead of:class="[]"or hardcoding
Never use!importantor!Tailwind prefix - fix interfering classes instead
Use Tailwind fraction utilities instead of arbitrary percentage values (e.g.,w-4/5instead ofw-[80%])
Use TypeScript Vue 3.5 style default prop declaration with reactive props destructuring - avoidwithDefaultsor runtime props
PreferdefineModelover separately defining a prop and emit for v-model bindings
Define slots via template usage, not viadefineSlots
Use same-name shorthand for slot prop bindings (e.g.,:isExpandedinstead of:is-expanded="isExpanded")
Do not import Vue macros unnecessarily
Avoid new usage of PrimeVue components
Use Tailwind's plurals system via i18n instead of hardcoding ...
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
🧠 Learnings (45)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with Select
📚 Learning: 2025-12-09T03:39:54.501Z
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.
Applied to files:
src/lib/litegraph/src/utils/widget.tsbrowser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-13T11:03:11.264Z
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.
Applied to files:
src/lib/litegraph/src/utils/widget.tsbrowser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-17T00:40:09.635Z
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).
Applied to files:
src/lib/litegraph/src/utils/widget.tsbrowser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-30T22:22:33.836Z
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().
Applied to files:
src/lib/litegraph/src/utils/widget.tsbrowser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-11T12:25:15.470Z
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.
Applied to files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuebrowser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuebrowser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with Select
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-08T02:26:18.357Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7893
File: src/components/button/IconGroup.vue:5-6
Timestamp: 2026-01-08T02:26:18.357Z
Learning: In components that use the cn utility from '@/utils/tailwindUtil' with tailwind-merge, rely on the behavior that conflicting Tailwind classes are resolved by keeping the last one. For example, cn('base-classes bg-default', propClass) will have any conflicting background class from propClass override bg-default. This additive pattern is intentional and aligns with the shadcn-ui convention; ensure you document or review expectations accordingly in Vue components.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T03:55:51.755Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:51.755Z
Learning: In Vue components under src/renderer/extensions/vueNodes (e.g., ImagePreview.vue and LGraphNode.vue), implement image gallery keyboard navigation so that it responds to the node's focus state rather than requiring focus inside the image preview wrapper. Achieve this by wiring keyEvent handling at the node focus level and injecting or propagating key events (arrow keys) to the gallery when the node is focused/selected. This improves accessibility and aligns navigation with node-level focus behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use vue-i18n for ALL UI strings
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InlineMessage component with Message
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Use VueUse function for useI18n in composition API for string literals
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests dependent on non-behavioral features like utility classes or styles
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-22T21:36:46.909Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts:189-194
Timestamp: 2025-12-22T21:36:46.909Z
Learning: In the Comfy-Org/ComfyUI_frontend repository test files: Do not stub primitive UI components or customized primitive components (e.g., Button). Instead, import and register the real components in test setup. This ensures tests accurately reflect production behavior and component API usage.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Don't Mock What You Don't Own
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Do not write change detector tests - avoid tests that only assert default values
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Avoid new usage of PrimeVue components
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Chips component with AutoComplete with multiple enabled
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Use `ref` for reactive state, `computed()` for derived values, and `watch`/`watchEffect` for side effects in Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Avoid using `ref` with `watch` if a `computed` would suffice - minimize refs and derived state
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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 : Implement computed properties with computed()
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧬 Code graph analysis (1)
src/lib/litegraph/src/widgets/NumberWidget.ts (1)
src/lib/litegraph/src/utils/widget.ts (1)
evaluateInput(12-25)
🪛 Biome (2.1.2)
src/lib/litegraph/src/utils/widget.ts
[error] 17-17: eval() exposes to security risks and performance issues.
See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().
(lint/security/noGlobalEval)
🔇 Additional comments (14)
browser_tests/fixtures/VueNodeHelpers.ts (1)
162-163: LGTM - Button mapping updated for new DOM structure.The swap correctly reflects the new custom numeric input component's button order (decrement first, increment last).
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue (1)
53-53: LGTM - Event handler change addresses cursor placement issue.The switch from
pointerdowntoclickaligns with the PR's intent to avoid forced focus without proper cursor positioning. The.stop.preventmodifiers appropriately prevent event propagation.src/lib/litegraph/src/widgets/NumberWidget.ts (1)
71-72: Correct usage ofevaluateInput, but fix the underlying security issue.The conditional check and value-setting logic here is correct. However, this depends on
evaluateInputfromsrc/lib/litegraph/src/utils/widget.ts, which has a critical security vulnerability (usingeval()). Ensure that security issue is addressed.Based on the critical
eval()security issue flagged insrc/lib/litegraph/src/utils/widget.ts.src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts (4)
9-12: LGTM - i18n setup for locale-aware input testing.The i18n plugin configuration correctly supports the new locale-aware formatting in the custom numeric input component.
40-40: LGTM - Correct inputmode for numeric input.Using
inputmode="decimal"is the appropriate HTML5 attribute for numeric inputs that accept decimal values, providing the correct mobile keyboard.
137-160: LGTM - Tests correctly verify button rendering behavior.Counting button elements directly is the appropriate testing approach for the custom numeric input implementation, replacing the previous PrimeVue
showButtonsprop checks. The tests properly validate:
- Buttons shown for safe integer values
- Buttons hidden for unsafe large integers (beyond
Number.MAX_SAFE_INTEGER)
181-194: LGTM - Comprehensive coverage for floating-point precision edge cases.The tests appropriately validate button visibility for both safe and unsafe floating-point values, ensuring the component handles precision limits correctly.
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (7)
1-14: LGTM!Good migration away from PrimeVue InputNumber. Imports are well-organized and follow Vue 3 Composition API guidelines with proper i18n integration.
16-29: LGTM!Good use of Vue 3.5 style props,
defineModel, and locale-aware number formatting viaIntl.NumberFormat. The computed correctly shows drag preview during scrubbing.
31-41: LGTM!The input parsing with
evaluateInput, clamping logic, and fallback toformattedValueon invalid input is well implemented.
143-157: LGTM!Good use of
cn()for class merging, propertabindex="-1"on buttons to maintain focus on the input, and appropriate conditional disabling with visual feedback via opacity.
171-189: LGTM!Comprehensive keyboard navigation (arrows, page up/down, enter) with proper clamping, and good pointer event handling including
pointercancelfor robustness on touch devices.
192-200: LGTM!Increment button is correctly implemented with consistent styling and proper disabled state handling.
97-104: LGTM!Good handling of edge cases for extremely large numbers and helpful tooltip explaining why buttons are disabled. This provides good UX for users encountering JavaScript precision limits.
Also applies to: 133-138
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
Show resolved
Hide resolved
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (1)
149-154: Internationalize the tooltip string.This hardcoded English string should use vue-i18n for localization. As per coding guidelines, all user-facing strings must use vue-i18n.
Suggested fix
Add the translation key to
src/locales/en/main.json:{ "widget.number.precisionLimitTooltip": "Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)" }Then update the computed:
+const { t, locale } = useI18n() + const buttonTooltip = computed(() => { if (buttonsDisabled.value) { - return 'Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)' + return t('widget.number.precisionLimitTooltip') } return null })
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧰 Additional context used
📓 Path-based instructions (11)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/lib/litegraph/src/utils/widget.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/lib/litegraph/**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (src/lib/litegraph/CLAUDE.md)
src/lib/litegraph/**/*.{js,ts,jsx,tsx}: Run ESLint instead of manually figuring out whitespace fixes or other trivial style concerns using thepnpm lint:fixcommand
Take advantage ofTypedArraysubarraywhen appropriate
Thesizeandposproperties ofRectangleshare the same array buffer (subarray); they may be used to set the rectangle's size and position
Prefer single lineifsyntax over adding curly braces, when the statement has a very concise expression and concise, single line statement
Do not replace&&=or||=with=when there is no reason to do so. If you do find a reason to remove either&&=or||=, leave a comment explaining why the removal occurred
When writing methods, prefer returning idiomatic JavaScriptundefinedovernull
Files:
src/lib/litegraph/src/utils/widget.ts
src/lib/litegraph/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/lib/litegraph/CLAUDE.md)
Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Files:
src/lib/litegraph/src/utils/widget.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/lib/litegraph/src/utils/widget.ts
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
src/**/*.vue: Use Vue 3 Single File Components (SFCs) with Composition API only
Use<script setup lang="ts">for component logic in Vue SFCs
Avoid<style>blocks in Vue components - use Tailwind 4 styling instead
Use vue-i18n for all string literals in Vue components - place translation entries insrc/locales/en/main.json
Use Tailwind utility classes instead ofdark:variant - use semantic values fromstyle.csstheme (e.g.,bg-node-component-surface)
Usecn()utility from@/utils/tailwindUtilfor merging Tailwind class names instead of:class="[]"or hardcoding
Never use!importantor!Tailwind prefix - fix interfering classes instead
Use Tailwind fraction utilities instead of arbitrary percentage values (e.g.,w-4/5instead ofw-[80%])
Use TypeScript Vue 3.5 style default prop declaration with reactive props destructuring - avoidwithDefaultsor runtime props
PreferdefineModelover separately defining a prop and emit for v-model bindings
Define slots via template usage, not viadefineSlots
Use same-name shorthand for slot prop bindings (e.g.,:isExpandedinstead of:is-expanded="isExpanded")
Do not import Vue macros unnecessarily
Avoid new usage of PrimeVue components
Use Tailwind's plurals system via i18n instead of hardcoding ...
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧠 Learnings (27)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with Select
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Applied to files:
src/lib/litegraph/src/utils/widget.ts
📚 Learning: 2025-12-09T03:39:54.501Z
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.
Applied to files:
src/lib/litegraph/src/utils/widget.ts
📚 Learning: 2025-12-13T11:03:11.264Z
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.
Applied to files:
src/lib/litegraph/src/utils/widget.ts
📚 Learning: 2025-12-17T00:40:09.635Z
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).
Applied to files:
src/lib/litegraph/src/utils/widget.ts
📚 Learning: 2025-12-30T22:22:33.836Z
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().
Applied to files:
src/lib/litegraph/src/utils/widget.ts
📚 Learning: 2025-12-11T12:25:15.470Z
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.
Applied to files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-12T17:39:27.738Z
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.
Applied to files:
src/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Avoid new usage of PrimeVue components
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Use `ref` for reactive state, `computed()` for derived values, and `watch`/`watchEffect` for side effects in Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Avoid using `ref` with `watch` if a `computed` would suffice - minimize refs and derived state
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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 : Implement computed properties with computed()
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Use VueUse function for useI18n in composition API for string literals
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-08T02:26:18.357Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7893
File: src/components/button/IconGroup.vue:5-6
Timestamp: 2026-01-08T02:26:18.357Z
Learning: In components that use the cn utility from '@/utils/tailwindUtil' with tailwind-merge, rely on the behavior that conflicting Tailwind classes are resolved by keeping the last one. For example, cn('base-classes bg-default', propClass) will have any conflicting background class from propClass override bg-default. This additive pattern is intentional and aligns with the shadcn-ui convention; ensure you document or review expectations accordingly in Vue components.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T03:55:51.755Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:51.755Z
Learning: In Vue components under src/renderer/extensions/vueNodes (e.g., ImagePreview.vue and LGraphNode.vue), implement image gallery keyboard navigation so that it responds to the node's focus state rather than requiring focus inside the image preview wrapper. Achieve this by wiring keyEvent handling at the node focus level and injecting or propagating key events (arrow keys) to the gallery when the node is focused/selected. This improves accessibility and aligns navigation with node-level focus behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🪛 Biome (2.1.2)
src/lib/litegraph/src/utils/widget.ts
[error] 17-17: eval() exposes to security risks and performance issues.
See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().
(lint/security/noGlobalEval)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: deploy-and-comment
- GitHub Check: setup
- GitHub Check: test
- GitHub Check: collect
- GitHub Check: lint-and-format
🔇 Additional comments (5)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (5)
21-35: Nice locale-aware separator detection.The approach of using
Intl.NumberFormatto derive decimal and group separators ensures consistency between formatting and parsing across different locales.
122-147: Drag-to-adjust implementation looks solid.The pointer capture approach ensures reliable drag behavior across element boundaries. The accumulation pattern with
dragDeltacorrectly handles sub-step movements before applying stepped changes.Note: The PR description mentions the known issue where scrubbing can cause text highlighting. This is an acceptable tradeoff given the complexity of preventing it without breaking cursor placement on click.
189-200: Keyboard navigation follows spinbutton conventions.The arrow key and page key handlers correctly implement the standard spinbutton pattern with single-step and 10-step increments, with proper clamping to bounds.
47-57: Value parsing with clamping is correct.The
updateValuefunction properly integrates withevaluateInput, applies min/max constraints, and gracefully reverts to the formatted value on invalid input.
157-218: Good migration away from PrimeVue InputNumber.The custom implementation properly handles locale formatting, accessibility via spinbutton role and ARIA attributes, and keyboard/pointer interactions. This aligns with the guideline to avoid new PrimeVue usage. Based on learnings about replacing PrimeVue components.
0f55dee to
133e592
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts (1)
53-63: Consider simulating user interaction instead of directly emitting.The test emits
update:modelValuedirectly on the component VM rather than simulating a user input action. This tests that the event propagates correctly but doesn't verify the component's input handling behavior.Consider triggering an actual input change to test the full flow:
const input = wrapper.find('input') await input.setValue('20') await input.trigger('blur') // or appropriate eventHowever, if the intent is specifically to test v-model binding propagation, the current approach is acceptable.
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (1)
149-154: Internationalize the tooltip string.The hardcoded English string should use
vue-i18nper coding guidelines. All user-facing strings need to be added tosrc/locales/en/main.json.🌐 Suggested fix
+const { t, locale } = useI18n() + const buttonTooltip = computed(() => { if (buttonsDisabled.value) { - return 'Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)' + return t('widget.numberInput.precisionLimitTooltip') } return null })Add to
src/locales/en/main.json:{ "widget": { "numberInput": { "precisionLimitTooltip": "Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)" } } }
🤖 Fix all issues with AI agents
In @src/lib/litegraph/src/utils/widget.ts:
- Around line 12-25: Update the incorrect comment in evaluateInput to reference
the actual parameter name: change "// Check if v is a valid equation or a
number" to "// Check if input is a valid equation or a number"; leave the
existing guarded eval usage and regex as-is but ensure the comment matches the
parameter name `input`.
In
@src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue:
- Around line 165-173: The decrement/increment icon-only buttons (using cn,
sharedButtonClass, classes 'pi pi-minus'/'pi pi-plus' and manipulating
modelValue with stepValue, conditioned by
buttonsDisabled/canDecrement/canIncrement) lack aria-labels; add aria-label
attributes set via the i18n keys t('widget.numberInput.decrement') and
t('widget.numberInput.increment') to both the decrement button (the one with
@click="modelValue -= stepValue" and canDecrement) and the corresponding
increment button (lines 208–216), keeping existing :disabled, tabindex, and
class bindings intact so screen readers get meaningful labels without altering
behavior.
- Around line 122-147: The code uses a plain mutable variable dragDelta which
breaks consistency with the component's reactive state; replace let dragDelta =
0 with a ref (e.g., const dragDelta = ref<number>(0)) and update all usages in
handleMouseDown, handleMouseMove and handleMouseUp to use dragDelta.value,
including resetting it to 0 when done; additionally replace the bitwise
truncation ((dragDelta / 10) | 0) with Math.trunc((dragDelta.value / 10)) to
avoid 32-bit overflow and improve clarity while keeping the same truncation
behavior.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
browser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
🧰 Additional context used
📓 Path-based instructions (13)
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
src/**/*.vue: Use Vue 3 Single File Components (SFCs) with Composition API only
Use<script setup lang="ts">for component logic in Vue SFCs
Avoid<style>blocks in Vue components - use Tailwind 4 styling instead
Use vue-i18n for all string literals in Vue components - place translation entries insrc/locales/en/main.json
Use Tailwind utility classes instead ofdark:variant - use semantic values fromstyle.csstheme (e.g.,bg-node-component-surface)
Usecn()utility from@/utils/tailwindUtilfor merging Tailwind class names instead of:class="[]"or hardcoding
Never use!importantor!Tailwind prefix - fix interfering classes instead
Use Tailwind fraction utilities instead of arbitrary percentage values (e.g.,w-4/5instead ofw-[80%])
Use TypeScript Vue 3.5 style default prop declaration with reactive props destructuring - avoidwithDefaultsor runtime props
PreferdefineModelover separately defining a prop and emit for v-model bindings
Define slots via template usage, not viadefineSlots
Use same-name shorthand for slot prop bindings (e.g.,:isExpandedinstead of:is-expanded="isExpanded")
Do not import Vue macros unnecessarily
Avoid new usage of PrimeVue components
Use Tailwind's plurals system via i18n instead of hardcoding ...
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
src/lib/litegraph/**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (src/lib/litegraph/CLAUDE.md)
src/lib/litegraph/**/*.{js,ts,jsx,tsx}: Run ESLint instead of manually figuring out whitespace fixes or other trivial style concerns using thepnpm lint:fixcommand
Take advantage ofTypedArraysubarraywhen appropriate
Thesizeandposproperties ofRectangleshare the same array buffer (subarray); they may be used to set the rectangle's size and position
Prefer single lineifsyntax over adding curly braces, when the statement has a very concise expression and concise, single line statement
Do not replace&&=or||=with=when there is no reason to do so. If you do find a reason to remove either&&=or||=, leave a comment explaining why the removal occurred
When writing methods, prefer returning idiomatic JavaScriptundefinedovernull
Files:
src/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
src/lib/litegraph/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/lib/litegraph/CLAUDE.md)
Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Files:
src/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
🧠 Learnings (43)
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuebrowser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with Select
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-08T02:26:18.357Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7893
File: src/components/button/IconGroup.vue:5-6
Timestamp: 2026-01-08T02:26:18.357Z
Learning: In components that use the cn utility from '@/utils/tailwindUtil' with tailwind-merge, rely on the behavior that conflicting Tailwind classes are resolved by keeping the last one. For example, cn('base-classes bg-default', propClass) will have any conflicting background class from propClass override bg-default. This additive pattern is intentional and aligns with the shadcn-ui convention; ensure you document or review expectations accordingly in Vue components.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T03:55:51.755Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:51.755Z
Learning: In Vue components under src/renderer/extensions/vueNodes (e.g., ImagePreview.vue and LGraphNode.vue), implement image gallery keyboard navigation so that it responds to the node's focus state rather than requiring focus inside the image preview wrapper. Achieve this by wiring keyEvent handling at the node focus level and injecting or propagating key events (arrow keys) to the gallery when the node is focused/selected. This improves accessibility and aligns navigation with node-level focus behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T12:25:15.470Z
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.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuebrowser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-12T17:39:27.738Z
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.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use vue-i18n for ALL UI strings
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests dependent on non-behavioral features like utility classes or styles
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InlineMessage component with Message
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Use VueUse function for useI18n in composition API for string literals
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-22T21:36:46.909Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts:189-194
Timestamp: 2025-12-22T21:36:46.909Z
Learning: In the Comfy-Org/ComfyUI_frontend repository test files: Do not stub primitive UI components or customized primitive components (e.g., Button). Instead, import and register the real components in test setup. This ensures tests accurately reflect production behavior and component API usage.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Don't Mock What You Don't Own
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
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.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tsbrowser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-13T11:03:11.264Z
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.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tsbrowser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-17T00:40:09.635Z
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).
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tsbrowser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-30T22:22:33.836Z
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().
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tsbrowser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Avoid new usage of PrimeVue components
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Use `ref` for reactive state, `computed()` for derived values, and `watch`/`watchEffect` for side effects in Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Avoid using `ref` with `watch` if a `computed` would suffice - minimize refs and derived state
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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 : Implement computed properties with computed()
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Use `<script setup lang="ts">` for component logic in Vue SFCs
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧬 Code graph analysis (1)
src/lib/litegraph/src/widgets/NumberWidget.ts (1)
src/lib/litegraph/src/utils/widget.ts (1)
evaluateInput(12-25)
🪛 Biome (2.1.2)
src/lib/litegraph/src/utils/widget.ts
[error] 17-17: eval() exposes to security risks and performance issues.
See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().
(lint/security/noGlobalEval)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: deploy-and-comment
- GitHub Check: setup
- GitHub Check: lint-and-format
- GitHub Check: test
- GitHub Check: setup
- GitHub Check: collect
🔇 Additional comments (12)
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue (1)
53-53: LGTM - Better event binding for accessibility.Switching from
pointerdowntoclickis the correct choice for button activation. This properly supports keyboard interaction and follows standard button activation semantics.browser_tests/fixtures/VueNodeHelpers.ts (1)
159-165: LGTM - Fixture correctly aligned with new button order.The locator assignments now match the expected DOM order where the decrement button appears first (left) and increment button appears last (right), which is the standard layout for numeric steppers:
[-] [input] [+].src/lib/litegraph/src/widgets/NumberWidget.ts (1)
71-72: LGTM - Clean refactor using extracted utility.The inline parsing logic is now consolidated into
evaluateInput, improving maintainability and ensuring consistent behavior across the codebase. Theundefinedcheck correctly guards against invalid input.src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts (2)
1-43: LGTM - Test setup properly migrated.The test file correctly:
- Uses
vue-i18nwith composition API mode (legacy: false)- Updates input selector to
inputmode="decimal"matching the new component- Registers i18n as a global plugin
- Switches from component prop assertions to behavioral button count checks
This aligns well with the guideline to test behavioral features rather than implementation details.
129-195: LGTM - Precision handling tests cover important edge cases.Good coverage of:
- Safe integer boundaries (
Number.MAX_SAFE_INTEGER)- Unsafe large integers that could lose precision
- Float handling for both safe and unsafe ranges
The button visibility tests appropriately verify user-facing behavior rather than internal state.
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (7)
1-14: LGTM!Imports are well-organized with proper separation of type imports. Uses
<script setup lang="ts">as required by coding guidelines.
16-19: LGTM!Props definition follows Vue 3.5 style guidelines, and i18n is properly configured for locale access.
21-35: LGTM!The locale-aware separator detection using
Intl.NumberFormatis a robust approach. TheunformatValuefunction correctly normalizes input before parsing.
37-57: LGTM!Good use of
defineModelfor v-model binding and proper input validation with clamping to min/max bounds.
59-69: LGTM!Proper use of
computed()for derived state. The button enablement logic correctly accounts for both value bounds and disabled state.
71-120: LGTM!Well-documented computed properties with proper edge case handling. The
stepValuecalculation correctly handles the various configuration options (step2, large custom steps, precision-based).
174-206: LGTM!The input element has proper accessibility attributes (
role="spinbutton",aria-valuenow,aria-valuemin,aria-valuemax). The keyboard navigation implementation with arrow keys and page keys follows the spinbutton pattern correctly. Pointer events for drag functionality are well-integrated.
| const dragValue = ref<number | undefined>() | ||
| let dragDelta = 0 | ||
| function handleMouseDown(e: PointerEvent) { | ||
| if (props.widget.options?.disabled) return | ||
| const { target } = e | ||
| if (!(target instanceof HTMLElement)) return | ||
| target.setPointerCapture(e.pointerId) | ||
| dragValue.value = modelValue.value | ||
| dragDelta = 0 | ||
| } | ||
| function handleMouseMove(e: PointerEvent) { | ||
| if (dragValue.value === undefined) return | ||
| dragDelta += e.movementX | ||
| const unclippedValue = | ||
| modelValue.value + ((dragDelta / 10) | 0) * stepValue.value | ||
| dragValue.value = Math.min( | ||
| filteredProps.value.max, | ||
| Math.max(filteredProps.value.min, unclippedValue) | ||
| ) | ||
| } | ||
| function handleMouseUp() { | ||
| const newValue = dragValue.value | ||
| if (newValue === undefined) return | ||
| modelValue.value = newValue | ||
| dragValue.value = undefined | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider using ref for drag state consistency.
The dragDelta variable uses a plain let which is mutable state outside Vue's reactivity system. While this works because dragDelta doesn't need to trigger re-renders, using a ref would be more consistent with the codebase patterns and coding guidelines that prefer ref for state management.
♻️ Suggested refactor
const dragValue = ref<number | undefined>()
-let dragDelta = 0
+const dragDelta = ref(0)
function handleMouseDown(e: PointerEvent) {
if (props.widget.options?.disabled) return
const { target } = e
if (!(target instanceof HTMLElement)) return
target.setPointerCapture(e.pointerId)
dragValue.value = modelValue.value
- dragDelta = 0
+ dragDelta.value = 0
}
function handleMouseMove(e: PointerEvent) {
if (dragValue.value === undefined) return
- dragDelta += e.movementX
+ dragDelta.value += e.movementX
const unclippedValue =
- modelValue.value + ((dragDelta / 10) | 0) * stepValue.value
+ modelValue.value + Math.trunc(dragDelta.value / 10) * stepValue.value
dragValue.value = Math.min(
filteredProps.value.max,
Math.max(filteredProps.value.min, unclippedValue)
)
}Note: Also replaced | 0 with Math.trunc() for clarity and to avoid potential 32-bit integer overflow with extremely large drag movements.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const dragValue = ref<number | undefined>() | |
| let dragDelta = 0 | |
| function handleMouseDown(e: PointerEvent) { | |
| if (props.widget.options?.disabled) return | |
| const { target } = e | |
| if (!(target instanceof HTMLElement)) return | |
| target.setPointerCapture(e.pointerId) | |
| dragValue.value = modelValue.value | |
| dragDelta = 0 | |
| } | |
| function handleMouseMove(e: PointerEvent) { | |
| if (dragValue.value === undefined) return | |
| dragDelta += e.movementX | |
| const unclippedValue = | |
| modelValue.value + ((dragDelta / 10) | 0) * stepValue.value | |
| dragValue.value = Math.min( | |
| filteredProps.value.max, | |
| Math.max(filteredProps.value.min, unclippedValue) | |
| ) | |
| } | |
| function handleMouseUp() { | |
| const newValue = dragValue.value | |
| if (newValue === undefined) return | |
| modelValue.value = newValue | |
| dragValue.value = undefined | |
| } | |
| const dragValue = ref<number | undefined>() | |
| const dragDelta = ref(0) | |
| function handleMouseDown(e: PointerEvent) { | |
| if (props.widget.options?.disabled) return | |
| const { target } = e | |
| if (!(target instanceof HTMLElement)) return | |
| target.setPointerCapture(e.pointerId) | |
| dragValue.value = modelValue.value | |
| dragDelta.value = 0 | |
| } | |
| function handleMouseMove(e: PointerEvent) { | |
| if (dragValue.value === undefined) return | |
| dragDelta.value += e.movementX | |
| const unclippedValue = | |
| modelValue.value + Math.trunc(dragDelta.value / 10) * stepValue.value | |
| dragValue.value = Math.min( | |
| filteredProps.value.max, | |
| Math.max(filteredProps.value.min, unclippedValue) | |
| ) | |
| } | |
| function handleMouseUp() { | |
| const newValue = dragValue.value | |
| if (newValue === undefined) return | |
| modelValue.value = newValue | |
| dragValue.value = undefined | |
| } |
🤖 Prompt for AI Agents
In
@src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
around lines 122 - 147, The code uses a plain mutable variable dragDelta which
breaks consistency with the component's reactive state; replace let dragDelta =
0 with a ref (e.g., const dragDelta = ref<number>(0)) and update all usages in
handleMouseDown, handleMouseMove and handleMouseUp to use dragDelta.value,
including resetting it to 0 when done; additionally replace the bitwise
truncation ((dragDelta / 10) | 0) with Math.trunc((dragDelta.value / 10)) to
avoid 32-bit overflow and improve clarity while keeping the same truncation
behavior.
| decrementButton: widget.locator('button').first(), | ||
| incrementButton: widget.locator('button').last() |
There was a problem hiding this comment.
Nit: Is there an a11y attribute we can use to target them?
There was a problem hiding this comment.
I did some poking (since needing to update this fixture every time I touch number widgets is annoying) and I don't think so. We explicitly do not apply aria descriptors to the buttons since the input field is the point of control. Feels great for keyboard usage: Can tab to and modify control widgets with just keyboard now which feels great.
Might be worth adding test ids?
| if (/^[\d\s.()*+/-]+$/.test(input)) { | ||
| // Solve the equation if possible | ||
| try { | ||
| input = eval(input) |
There was a problem hiding this comment.
Have we explored any of the libraries that do this? Maybe this one?
There was a problem hiding this comment.
We did some testing with expr-eval, but decided to move that to a future PR.
Math.js looks like a btter option.
There was a problem hiding this comment.
@coderabbitai Open an issue to replace the evals with a library, possibly Math.js
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Create a GitHub issue to track replacing eval with a math library
gh issue create \
--repo Comfy-Org/ComfyUI_frontend \
--title "Replace eval() with math expression library (e.g., Math.js)" \
--body "## Description
The current implementation of mathematical expression evaluation in number widgets uses \`eval()\` to parse and evaluate user input expressions. This should be replaced with a dedicated math expression library for better security and functionality.
## Context
- Current implementation: \`evaluateInput()\` function in \`src/lib/litegraph/src/utils/widget.ts\`
- Previous testing was done with [expr-eval](https://github.com/silentmatt/expr-eval)
- [Math.js](https://mathjs.org/docs/reference/functions/evaluate.html) is suggested as a potentially better option
## Related
- PR: https://github.com/Comfy-Org/ComfyUI_frontend/pull/7759
- Comment: https://github.com/Comfy-Org/ComfyUI_frontend/pull/7759#discussion_r2687812989
- Requested by: @DrJKL" \
--assignee DrJKL
Length of output: 57
@DrJKL I've created issue #8032 to track replacing the eval() usage with a math expression library like Math.js. The issue has been assigned to you and includes references back to this PR and comment thread.
🧬 Code Graph Analysis Results
src/lib/litegraph/src/utils/widget.ts
Filename: src/lib/litegraph/src/utils/widget.ts Lines: 1-25import type { IWidgetOptions } from '@/lib/litegraph/src/types/widgets'
/**
- The step value for numeric widgets.
- Use {@link IWidgetOptions.step2} if available, otherwise fallback to
- {@link IWidgetOptions.step} which is scaled up by 10x in the legacy frontend logic.
*/
export function getWidgetStep(options: IWidgetOptions): number {
return options.step2 || (options.step || 10) * 0.1
}
export function evaluateInput(input: string): number | undefined {
// Check if v is a valid equation or a number
if (/^[\d\s.()*+/-]+$/.test(input)) {
// Solve the equation if possible
try {
input = eval(input)
} catch {
// Ignore eval errors
}
}
const newValue = Number(input)
if (isNaN(newValue)) return undefined
return newValue
}
#isValidConnection(input: INodeInputSlot, forceUpdate?: boolean) {
// Only allow connections where the configs match
const output = this.outputs?.[0]
const config2 = (input.widget?.[GET_CONFIG] as () => InputSpec)?.()
if (!config2) return false
return !!mergeIfValid.call(
this,
output,
config2,
forceUpdate,
this.recreateWidget
)
}
🧠 Learnings used
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
| }>() | ||
| const { locale } = useI18n() | ||
|
|
||
| const decimalSeparator = computed(() => |
There was a problem hiding this comment.
Instead of doing this ourselves, can we use the number formatter? https://vue-i18n.intlify.dev/guide/essentials/number.html
There was a problem hiding this comment.
Strangely n() breaks with Infinity and -Infinity. Do you have a preference between hardcoding these cases, removing the tests, or reverting to Intl.NumberFormat?
There was a problem hiding this comment.
I do have a preference. It ended up being wrong. You've already fixed it 😁
| const dragValue = ref<number | undefined>() | ||
| let dragDelta = 0 | ||
| function handleMouseDown(e: PointerEvent) { | ||
| if (props.widget.options?.disabled) return | ||
| const { target } = e | ||
| if (!(target instanceof HTMLElement)) return | ||
| target.setPointerCapture(e.pointerId) | ||
| dragValue.value = modelValue.value | ||
| dragDelta = 0 | ||
| } | ||
| function handleMouseMove(e: PointerEvent) { | ||
| if (dragValue.value === undefined) return | ||
| dragDelta += e.movementX | ||
| const unclippedValue = | ||
| modelValue.value + ((dragDelta / 10) | 0) * stepValue.value | ||
| dragValue.value = Math.min( | ||
| filteredProps.value.max, | ||
| Math.max(filteredProps.value.min, unclippedValue) | ||
| ) | ||
| } | ||
| function handleMouseUp() { | ||
| const newValue = dragValue.value | ||
| if (newValue === undefined) return | ||
| modelValue.value = newValue | ||
| dragValue.value = undefined | ||
| } |
There was a problem hiding this comment.
Nit: This feels like it could be extracted. Is there an existing composable we could use for this?
There was a problem hiding this comment.
With the recent change, maybe just a Component?
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (2)
115-118: DefaultstepValueof 0 breaks increment/decrement functionality.When precision is undefined and no step options are provided,
stepValuereturns 0. This causes the +/- buttons and keyboard Up/Down handlers to add/subtract 0, effectively doing nothing. The comment mentions "unrestricted stepping" but returning 0 prevents any stepping.Proposed fix
// Default to 'any' for unrestricted stepping - return 0 + return 1Alternatively, if "any" stepping means the input accepts any value but shouldn't have step buttons, consider hiding the buttons when stepValue would be 0.
168-173: Hardcoded string should use vue-i18n.The tooltip text is hardcoded in English. Per coding guidelines, all user-facing strings should use vue-i18n.
Proposed fix
Add to
src/locales/en/main.json:"widgetInputNumber": { "precisionLimitTooltip": "Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)" }Then update the computed:
+const { t, locale } = useI18n() + const buttonTooltip = computed(() => { if (buttonsDisabled.value) { - return 'Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)' + return t('widgetInputNumber.precisionLimitTooltip') } return null })
🤖 Fix all issues with AI agents
In
@src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue:
- Around line 160-165: The code uses inputField.value?.setSelectionRange(0, -1)
which is incorrect because setSelectionRange's end index must be an absolute
position; change the selection logic to select the entire input by using the
input element's select() method or by calling setSelectionRange(0,
inputField.value.value.length) after focusing; update the block handling
dragDelta/value to call inputField.value.select() (or compute length) so the
full text is actually selected when textEdit is enabled.
- Around line 215-232: Keyboard handlers directly mutate modelValue without
respecting widget.options?.disabled; update each
@keydown.up/down.page-up/page-down handler to first check that
widget.options?.disabled is falsy before changing modelValue (or refactor into
methods on the component like onKeyUp/onKeyDown/onPageUp/onPageDown that perform
the disabled check and then adjust modelValue using stepValue clamped to
filteredProps.max/min). Ensure all four handlers reference the same guard
(widget.options?.disabled) so disabled widgets cannot be changed via keyboard.
- Around line 178-184: FilteredProps currently spreads min/max onto the wrapper
div via v-bind="filteredProps"; remove min and max from filteredProps before
binding to the container and instead pass them explicitly to the actual <input>
element (the number input inside this component that already sets
aria-valuemin/aria-valuemax) so min/max are valid HTML attributes on the input
and not on the div; update the code that constructs/returns filteredProps (or
apply a small local copy/filter before binding) and add :min="filteredProps.min"
and :max="filteredProps.max" (or equivalent) to the input element while ensuring
the wrapper continues to receive the other filtered props.
- Around line 185-193: The decrement and increment <button> elements in the
WidgetInputNumberInput.vue template (the ones with :class="cn(sharedButtonClass,
'pi pi-minus', !canDecrement && 'opacity-60')" and the corresponding plus button
that updates modelValue by +/- stepValue) lack an explicit type and will default
to submit inside forms; add type="button" to both buttons to prevent unintended
form submission while preserving their existing :class, :disabled, tabindex and
@click handlers.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (22)
browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-overlapped-after-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-overlapped-before-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-widget-overlapped-after-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-widget-overlapped-before-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/bypass.spec.ts-snapshots/vue-node-bypassed-state-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/mute.spec.ts-snapshots/vue-node-muted-state-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.pngis excluded by!**/*.png
📒 Files selected for processing (1)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧰 Additional context used
📓 Path-based instructions (7)
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
src/**/*.vue: Use Vue 3 Single File Components (SFCs) with Composition API only
Use<script setup lang="ts">for component logic in Vue SFCs
Avoid<style>blocks in Vue components - use Tailwind 4 styling instead
Use vue-i18n for all string literals in Vue components - place translation entries insrc/locales/en/main.json
Use Tailwind utility classes instead ofdark:variant - use semantic values fromstyle.csstheme (e.g.,bg-node-component-surface)
Usecn()utility from@/utils/tailwindUtilfor merging Tailwind class names instead of:class="[]"or hardcoding
Never use!importantor!Tailwind prefix - fix interfering classes instead
Use Tailwind fraction utilities instead of arbitrary percentage values (e.g.,w-4/5instead ofw-[80%])
Use TypeScript Vue 3.5 style default prop declaration with reactive props destructuring - avoidwithDefaultsor runtime props
PreferdefineModelover separately defining a prop and emit for v-model bindings
Define slots via template usage, not viadefineSlots
Use same-name shorthand for slot prop bindings (e.g.,:isExpandedinstead of:is-expanded="isExpanded")
Do not import Vue macros unnecessarily
Avoid new usage of PrimeVue components
Use Tailwind's plurals system via i18n instead of hardcoding ...
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧠 Learnings (26)
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InlineMessage component with Message
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Chips component with AutoComplete with multiple enabled
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Avoid new usage of PrimeVue components
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with Select
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Avoid using `ref` with `watch` if a `computed` would suffice - minimize refs and derived state
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Use Tailwind's plurals system via i18n instead of hardcoding pluralization in templates
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-05T20:35:28.330Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/locales/en/main.json:2257-2272
Timestamp: 2025-12-05T20:35:28.330Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, vue-i18n pluralization uses a two-parameter pattern: `t('key', { count: value })` where the `count` property in the interpolation object automatically triggers plural selection from pipe-separated locale strings (e.g., "no items | 1 item | {count} items"). This is the correct pattern used throughout the codebase, as validated by Playwright tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Use `<script setup lang="ts">` for component logic in Vue SFCs
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-08T02:26:18.357Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7893
File: src/components/button/IconGroup.vue:5-6
Timestamp: 2026-01-08T02:26:18.357Z
Learning: In components that use the cn utility from '@/utils/tailwindUtil' with tailwind-merge, rely on the behavior that conflicting Tailwind classes are resolved by keeping the last one. For example, cn('base-classes bg-default', propClass) will have any conflicting background class from propClass override bg-default. This additive pattern is intentional and aligns with the shadcn-ui convention; ensure you document or review expectations accordingly in Vue components.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T03:55:51.755Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:51.755Z
Learning: In Vue components under src/renderer/extensions/vueNodes (e.g., ImagePreview.vue and LGraphNode.vue), implement image gallery keyboard navigation so that it responds to the node's focus state rather than requiring focus inside the image preview wrapper. Achieve this by wiring keyEvent handling at the node focus level and injecting or propagating key events (arrow keys) to the gallery when the node is focused/selected. This improves accessibility and aligns navigation with node-level focus behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T12:25:15.470Z
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.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-12T17:39:27.738Z
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.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: test
- GitHub Check: setup
- GitHub Check: lint-and-format
- GitHub Check: collect
- GitHub Check: playwright-tests-chromium-sharded (5, 8)
- GitHub Check: playwright-tests-chromium-sharded (3, 8)
- GitHub Check: playwright-tests-chromium-sharded (7, 8)
- GitHub Check: playwright-tests-chromium-sharded (4, 8)
🔇 Additional comments (2)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (2)
31-45: Locale-aware formatting implementation looks solid.The computed properties for
decimalSeparatorandgroupSeparatorcorrectly extract locale-specific characters usingIntl.NumberFormat. TheunformatValuefunction properly reverses this for parsing, andformattedValuecorrectly displays the current or dragged value with appropriate locale formatting.Also applies to: 49-55
136-153: Drag-to-change implementation is well structured.The pointer capture pattern ensures smooth dragging even when the cursor leaves the element. The bitwise
| 0truncation for step calculation and clamping within min/max bounds are correctly implemented.
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
Show resolved
Hide resolved
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
Show resolved
Hide resolved
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In
@src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue:
- Around line 32-38: The locale-based separator extraction using
decimalSeparator and groupSeparator is fragile; update the computed values and
unformatValue to provide safe fallbacks and handle edge cases: if n(1.1) or
n(11111) yields empty or identical separators, default decimalSeparator to '.'
and groupSeparator to ',' (or detect a non-digit character fallback), and ensure
unformatValue only calls replaceAll when the separator is non-empty and
different from the other (avoid replacing the decimal with group or vice versa);
reference the computed values decimalSeparator and groupSeparator and the
unformatValue function to implement these guard clauses and fallbacks.
- Around line 161-165: The call inputField.value?.setSelectionRange(0, -1) is
invalid because the second argument must be a non-negative integer; replace it
so the full text is selected properly — either call inputField.value?.select()
or call inputField.value?.setSelectionRange(0, inputField.value.value.length)
(use the HTMLElement refs inputField and its value property), keeping the
focus/textEdit logic unchanged.
- Around line 186-195: The decrement/increment button click handlers directly
mutate modelValue by ±stepValue which can overshoot min/max; replace the inline
arithmetic in both button blocks (the one shown and the other at lines ~243-252)
to call the existing updateValueBy function with -stepValue for decrement and
+stepValue for increment so the change is applied via updateValueBy (which
handles clamping and emits correctly); update the v-if buttons that reference
canDecrement/canIncrement to keep behavior identical but delegate all value
changes to updateValueBy.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
browser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧰 Additional context used
📓 Path-based instructions (7)
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
src/**/*.vue: Use Vue 3 Single File Components (SFCs) with Composition API only
Use<script setup lang="ts">for component logic in Vue SFCs
Avoid<style>blocks in Vue components - use Tailwind 4 styling instead
Use vue-i18n for all string literals in Vue components - place translation entries insrc/locales/en/main.json
Use Tailwind utility classes instead ofdark:variant - use semantic values fromstyle.csstheme (e.g.,bg-node-component-surface)
Usecn()utility from@/utils/tailwindUtilfor merging Tailwind class names instead of:class="[]"or hardcoding
Never use!importantor!Tailwind prefix - fix interfering classes instead
Use Tailwind fraction utilities instead of arbitrary percentage values (e.g.,w-4/5instead ofw-[80%])
Use TypeScript Vue 3.5 style default prop declaration with reactive props destructuring - avoidwithDefaultsor runtime props
PreferdefineModelover separately defining a prop and emit for v-model bindings
Define slots via template usage, not viadefineSlots
Use same-name shorthand for slot prop bindings (e.g.,:isExpandedinstead of:is-expanded="isExpanded")
Do not import Vue macros unnecessarily
Avoid new usage of PrimeVue components
Use Tailwind's plurals system via i18n instead of hardcoding ...
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧠 Learnings (33)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuebrowser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InlineMessage component with Message
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Chips component with AutoComplete with multiple enabled
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with Select
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Avoid new usage of PrimeVue components
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Avoid using `ref` with `watch` if a `computed` would suffice - minimize refs and derived state
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Use Tailwind's plurals system via i18n instead of hardcoding pluralization in templates
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-05T20:35:28.330Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/locales/en/main.json:2257-2272
Timestamp: 2025-12-05T20:35:28.330Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, vue-i18n pluralization uses a two-parameter pattern: `t('key', { count: value })` where the `count` property in the interpolation object automatically triggers plural selection from pipe-separated locale strings (e.g., "no items | 1 item | {count} items"). This is the correct pattern used throughout the codebase, as validated by Playwright tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T03:55:51.755Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:51.755Z
Learning: In Vue components under src/renderer/extensions/vueNodes (e.g., ImagePreview.vue and LGraphNode.vue), implement image gallery keyboard navigation so that it responds to the node's focus state rather than requiring focus inside the image preview wrapper. Achieve this by wiring keyEvent handling at the node focus level and injecting or propagating key events (arrow keys) to the gallery when the node is focused/selected. This improves accessibility and aligns navigation with node-level focus behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Use `<script setup lang="ts">` for component logic in Vue SFCs
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-08T02:26:18.357Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7893
File: src/components/button/IconGroup.vue:5-6
Timestamp: 2026-01-08T02:26:18.357Z
Learning: In components that use the cn utility from '@/utils/tailwindUtil' with tailwind-merge, rely on the behavior that conflicting Tailwind classes are resolved by keeping the last one. For example, cn('base-classes bg-default', propClass) will have any conflicting background class from propClass override bg-default. This additive pattern is intentional and aligns with the shadcn-ui convention; ensure you document or review expectations accordingly in Vue components.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T12:25:15.470Z
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.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuebrowser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-12T17:39:27.738Z
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.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Prefer specific selectors in browser tests
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-10T03:09:19.636Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:19.636Z
Learning: For test files in the Comfy-Org/ComfyUI_frontend repository: When writing tests, prefer selecting elements by accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests verify actual user-facing behavior and accessibility compliance.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-18T21:15:54.349Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:54.349Z
Learning: For Vue components in Comfy-Org/ComfyUI_frontend: Do not suggest adding aria-label to buttons that already have visible text content (e.g., <span> elements with labels). The visible text automatically provides the accessible name. aria-label should only be used for elements without visible labels, such as icon-only buttons.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-09T03:39:54.501Z
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.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-13T11:03:11.264Z
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.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-17T00:40:09.635Z
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).
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-30T22:22:33.836Z
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().
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: deploy-and-comment
- GitHub Check: lint-and-format
- GitHub Check: setup
- GitHub Check: collect
- GitHub Check: test
🔇 Additional comments (2)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (1)
177-254: Clean implementation of the custom number input.The component correctly implements:
- Accessible spinbutton role with proper ARIA attributes
- Keyboard navigation (Up/Down/PageUp/PageDown)
- Drag-to-scrub functionality with pointer capture
- Locale-aware formatting via i18n
- Integration with
evaluateInputfor math expressionsThe migration away from PrimeVue aligns with the coding guidelines to avoid new PrimeVue usage. Based on learnings.
browser_tests/fixtures/VueNodeHelpers.ts (1)
159-165: Good use ofdata-testidselectors for test reliability.Switching from DOM position-based selection (
first()/nth(1)) to explicitdata-testidattributes makes tests more resilient to template structure changes and aligns with the new component implementation. Based on learnings.
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
Show resolved
Hide resolved
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
Show resolved
Hide resolved
aria-label="Decrease", aria-roledescription="Number field", and aria-label="Increase" were skipped as linting requires localization, but these do not appear to have been before. I lean towards the caution of "no aria is better than wrong aria" here.
This removes the ability to highlight the text value
Preventing mouseDown prevents focus at location of mouse click. This feels awful and has been reverted. Minor naming tweaks Remove unused style
9c56db6 to
ca1d0c4
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts (1)
53-63: Consider testing actual input interaction instead of programmatic emit.The test now emits directly via
wrapper.vm.$emit()rather than simulating user input interaction. While this validates that the component's emit wiring works, it doesn't test the actual input → emit flow.♻️ Alternative approach to test actual input behavior
it('emits update:modelValue when value changes', async () => { const widget = createMockWidget(10, 'int') const wrapper = mountComponent(widget, 10) const input = wrapper.get<HTMLInputElement>('input[inputmode="decimal"]') await input.setValue('20') await input.trigger('blur') // or 'change' depending on component behavior const emitted = wrapper.emitted('update:modelValue') expect(emitted).toBeDefined() expect(emitted![0]).toContain(20) })src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (1)
172-177: User-facing tooltip string should use i18n.The tooltip message is hardcoded in English. Per coding guidelines, all user-facing strings should use vue-i18n.
♻️ Proposed fix
Add to
src/locales/en/main.json:"widget.numberInput.precisionLimitTooltip": "Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)"Then update the component:
-const { n } = useI18n() +const { n, t } = useI18n()const buttonTooltip = computed(() => { if (buttonsDisabled.value) { - return 'Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)' + return t('widget.numberInput.precisionLimitTooltip') } return null })
🤖 Fix all issues with AI agents
In @src/lib/litegraph/src/utils/widget.ts:
- Around line 12-25: In evaluateInput, update the inline documentation to
explain the security rationale for using eval: state that the allowlist regex
/^[\d\s.()*+/-]+$/ restricts input to digits, whitespace and arithmetic
operators (preventing identifier/property access and injection) and therefore is
intentionally used here to evaluate arithmetic expressions; also fix the
misleading comment that refers to "v" to use the actual parameter name "input".
Additionally, add a TODO note on the evaluateInput function referencing
NumberWidget to plan replacing eval with a safer evaluator (e.g., a small math
expression parser or vetted library) as a long‑term improvement.
In
@src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue:
- Around line 164-168: The current selection call uses the non-standard
setSelectionRange(0, -1) which can fail; update the logic in the block that
checks dragDelta.value === 0 (where textEdit.value is set and inputField is
focused) to call the standard inputField.value?.select() after focusing the
element instead of setSelectionRange, ensuring the element is focused first so
select() will work across browsers.
- Line 197: The decrement/increment button click handlers currently mutate
modelValue directly (e.g., @click="modelValue -= stepValue") while keyboard
handlers call updateValueBy(...) which applies clamping/bounds; change both
button handlers to call updateValueBy(-stepValue) and updateValueBy(+stepValue)
(or updateValueBy(stepValue) as appropriate) so clicks go through the same
bounded update path as keyboard events, referencing the existing updateValueBy
function and modelValue prop.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (20)
browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-overlapped-after-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-overlapped-before-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-widget-overlapped-after-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/bringToFront.spec.ts-snapshots/bring-to-front-widget-overlapped-before-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/bypass.spec.ts-snapshots/vue-node-bypassed-state-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.pngis excluded by!**/*.pngbrowser_tests/tests/vueNodes/nodeStates/mute.spec.ts-snapshots/vue-node-muted-state-chromium-linux.pngis excluded by!**/*.png
📒 Files selected for processing (6)
browser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/utils/widget.tssrc/lib/litegraph/src/widgets/NumberWidget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
🧰 Additional context used
📓 Path-based instructions (13)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/lib/litegraph/**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (src/lib/litegraph/CLAUDE.md)
src/lib/litegraph/**/*.{js,ts,jsx,tsx}: Run ESLint instead of manually figuring out whitespace fixes or other trivial style concerns using thepnpm lint:fixcommand
Take advantage ofTypedArraysubarraywhen appropriate
Thesizeandposproperties ofRectangleshare the same array buffer (subarray); they may be used to set the rectangle's size and position
Prefer single lineifsyntax over adding curly braces, when the statement has a very concise expression and concise, single line statement
Do not replace&&=or||=with=when there is no reason to do so. If you do find a reason to remove either&&=or||=, leave a comment explaining why the removal occurred
When writing methods, prefer returning idiomatic JavaScriptundefinedovernull
Files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.ts
src/lib/litegraph/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/lib/litegraph/CLAUDE.md)
Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
src/**/*.vue: Use Vue 3 Single File Components (SFCs) with Composition API only
Use<script setup lang="ts">for component logic in Vue SFCs
Avoid<style>blocks in Vue components - use Tailwind 4 styling instead
Use vue-i18n for all string literals in Vue components - place translation entries insrc/locales/en/main.json
Use Tailwind utility classes instead ofdark:variant - use semantic values fromstyle.csstheme (e.g.,bg-node-component-surface)
Usecn()utility from@/utils/tailwindUtilfor merging Tailwind class names instead of:class="[]"or hardcoding
Never use!importantor!Tailwind prefix - fix interfering classes instead
Use Tailwind fraction utilities instead of arbitrary percentage values (e.g.,w-4/5instead ofw-[80%])
Use TypeScript Vue 3.5 style default prop declaration with reactive props destructuring - avoidwithDefaultsor runtime props
PreferdefineModelover separately defining a prop and emit for v-model bindings
Define slots via template usage, not viadefineSlots
Use same-name shorthand for slot prop bindings (e.g.,:isExpandedinstead of:is-expanded="isExpanded")
Do not import Vue macros unnecessarily
Avoid new usage of PrimeVue components
Use Tailwind's plurals system via i18n instead of hardcoding ...
Files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧠 Learnings (51)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Prefer specific selectors in browser tests
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Applied to files:
browser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Applied to files:
browser_tests/fixtures/VueNodeHelpers.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-10T03:09:19.636Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:19.636Z
Learning: For test files in the Comfy-Org/ComfyUI_frontend repository: When writing tests, prefer selecting elements by accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests verify actual user-facing behavior and accessibility compliance.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-18T21:15:54.349Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:54.349Z
Learning: For Vue components in Comfy-Org/ComfyUI_frontend: Do not suggest adding aria-label to buttons that already have visible text content (e.g., <span> elements with labels). The visible text automatically provides the accessible name. aria-label should only be used for elements without visible labels, such as icon-only buttons.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.ts
📚 Learning: 2025-12-09T03:39:54.501Z
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.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
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.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-17T00:40:09.635Z
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).
Applied to files:
browser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-30T22:22:33.836Z
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().
Applied to files:
browser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
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.
Applied to files:
browser_tests/fixtures/VueNodeHelpers.tssrc/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-12T17:39:27.738Z
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.
Applied to files:
src/lib/litegraph/src/widgets/NumberWidget.tssrc/lib/litegraph/src/utils/widget.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Applied to files:
src/lib/litegraph/src/utils/widget.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests dependent on non-behavioral features like utility classes or styles
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Do not write change detector tests - avoid tests that only assert default values
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.tssrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Write tests for all changes, especially bug fixes to catch future regressions
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-22T21:36:46.909Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts:189-194
Timestamp: 2025-12-22T21:36:46.909Z
Learning: In the Comfy-Org/ComfyUI_frontend repository test files: Do not stub primitive UI components or customized primitive components (e.g., Button). Instead, import and register the real components in test setup. This ensures tests accurately reflect production behavior and component API usage.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Don't Mock What You Don't Own
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with Select
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Prefer emit/event-name for state changes over other communication patterns
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-08T02:26:18.357Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7893
File: src/components/button/IconGroup.vue:5-6
Timestamp: 2026-01-08T02:26:18.357Z
Learning: In components that use the cn utility from '@/utils/tailwindUtil' with tailwind-merge, rely on the behavior that conflicting Tailwind classes are resolved by keeping the last one. For example, cn('base-classes bg-default', propClass) will have any conflicting background class from propClass override bg-default. This additive pattern is intentional and aligns with the shadcn-ui convention; ensure you document or review expectations accordingly in Vue components.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-11T03:55:51.755Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:51.755Z
Learning: In Vue components under src/renderer/extensions/vueNodes (e.g., ImagePreview.vue and LGraphNode.vue), implement image gallery keyboard navigation so that it responds to the node's focus state rather than requiring focus inside the image preview wrapper. Achieve this by wiring keyEvent handling at the node focus level and injecting or propagating key events (arrow keys) to the gallery when the node is focused/selected. This improves accessibility and aligns navigation with node-level focus behavior.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vuesrc/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InlineMessage component with Message
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Chips component with AutoComplete with multiple enabled
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Avoid new usage of PrimeVue components
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.{ts,vue} : Avoid using `ref` with `watch` if a `computed` would suffice - minimize refs and derived state
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Use Tailwind's plurals system via i18n instead of hardcoding pluralization in templates
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-12-05T20:35:28.330Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/locales/en/main.json:2257-2272
Timestamp: 2025-12-05T20:35:28.330Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, vue-i18n pluralization uses a two-parameter pattern: `t('key', { count: value })` where the `count` property in the interpolation object automatically triggers plural selection from pipe-separated locale strings (e.g., "no items | 1 item | {count} items"). This is the correct pattern used throughout the codebase, as validated by Playwright tests.
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2026-01-10T00:24:17.695Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.695Z
Learning: Applies to src/**/*.vue : Use `<script setup lang="ts">` for component logic in Vue SFCs
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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
Applied to files:
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧬 Code graph analysis (1)
src/lib/litegraph/src/widgets/NumberWidget.ts (1)
src/lib/litegraph/src/utils/widget.ts (1)
evaluateInput(12-25)
🪛 Biome (2.1.2)
src/lib/litegraph/src/utils/widget.ts
[error] 17-17: eval() exposes to security risks and performance issues.
See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().
(lint/security/noGlobalEval)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: setup
- GitHub Check: test
- GitHub Check: lint-and-format
- GitHub Check: collect
🔇 Additional comments (8)
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue (1)
53-53: LGTM!The change from
@pointerdownto@click.stop.preventis appropriate for popover toggling. Usingclickprovides better UX semantics for this interaction, and the.stop.preventmodifiers correctly prevent event bubbling and default behavior.src/lib/litegraph/src/widgets/NumberWidget.ts (1)
71-72: LGTM!Good refactor extracting the expression evaluation logic into a reusable utility. The undefined check correctly handles parse failures without changing widget state.
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.test.ts (3)
9-12: LGTM!Correct i18n setup for Vue 3 Composition API with
legacy: false. The locale setting aligns with the test expectations.
39-42: LGTM!The selector change to
input[inputmode="decimal"]appropriately targets the native input element in the refactored component.
133-145: LGTM!The button count assertions (
wrapper.findAll('button').length) appropriately test the behavioral outcome (buttons visible/hidden) without depending on implementation details of the button components.browser_tests/fixtures/VueNodeHelpers.ts (1)
159-165: Good migration from positional selectors to explicit test-id based selectors. This improves test stability and makes the selectors resilient to DOM structure changes. The correspondingWidgetInputNumberInput.vuecomponent includes the requireddata-testid="decrement"anddata-testid="increment"attributes, confirming this fixture update aligns with the component implementation. Follows best practices for specific, stable selectors in browser tests.src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (2)
53-65: LGTM!The value update logic correctly handles parsing mathematical expressions, clamps values to bounds, and gracefully falls back to the previous formatted value on invalid input.
200-225: LGTM!The input element implements the ARIA spinbutton pattern correctly with proper attributes (
aria-valuenow,aria-valuemin,aria-valuemax), appropriateinputmodefor mobile, and comprehensive keyboard navigation support.
| export function evaluateInput(input: string): number | undefined { | ||
| // Check if v is a valid equation or a number | ||
| if (/^[\d\s.()*+/-]+$/.test(input)) { | ||
| // Solve the equation if possible | ||
| try { | ||
| input = eval(input) | ||
| } catch { | ||
| // Ignore eval errors | ||
| } | ||
| } | ||
| const newValue = Number(input) | ||
| if (isNaN(newValue)) return undefined | ||
| return newValue | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider documenting the security rationale or using a safer alternative to eval.
The regex allowlist on line 14 restricts input to digits, whitespace, and arithmetic operators, which mitigates common injection vectors. However, eval remains a security-sensitive pattern that static analysis tools will continue to flag.
Since this centralizes existing behavior from NumberWidget, the risk profile is unchanged. Consider either:
- Adding a comment explaining why the regex makes this safe for arithmetic expressions
- Long-term: replacing
evalwith a simple expression parser (e.g., Function constructor with the same regex guard, or a lightweight math expression library)
Also, minor nit: the comment on line 13 references v but the parameter is named input.
📝 Suggested comment addition
export function evaluateInput(input: string): number | undefined {
- // Check if v is a valid equation or a number
+ // SECURITY: Regex allowlist restricts input to digits, whitespace, decimal points,
+ // parentheses, and arithmetic operators (+-*/). This prevents variable access,
+ // function calls, and other code execution vectors.
if (/^[\d\s.()*+/-]+$/.test(input)) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function evaluateInput(input: string): number | undefined { | |
| // Check if v is a valid equation or a number | |
| if (/^[\d\s.()*+/-]+$/.test(input)) { | |
| // Solve the equation if possible | |
| try { | |
| input = eval(input) | |
| } catch { | |
| // Ignore eval errors | |
| } | |
| } | |
| const newValue = Number(input) | |
| if (isNaN(newValue)) return undefined | |
| return newValue | |
| } | |
| export function evaluateInput(input: string): number | undefined { | |
| // SECURITY: Regex allowlist restricts input to digits, whitespace, decimal points, | |
| // parentheses, and arithmetic operators (+-*/). This prevents variable access, | |
| // function calls, and other code execution vectors. | |
| if (/^[\d\s.()*+/-]+$/.test(input)) { | |
| // Solve the equation if possible | |
| try { | |
| input = eval(input) | |
| } catch { | |
| // Ignore eval errors | |
| } | |
| } | |
| const newValue = Number(input) | |
| if (isNaN(newValue)) return undefined | |
| return newValue | |
| } |
🧰 Tools
🪛 Biome (2.1.2)
[error] 17-17: eval() exposes to security risks and performance issues.
See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().
(lint/security/noGlobalEval)
🤖 Prompt for AI Agents
In @src/lib/litegraph/src/utils/widget.ts around lines 12 - 25, In
evaluateInput, update the inline documentation to explain the security rationale
for using eval: state that the allowlist regex /^[\d\s.()*+/-]+$/ restricts
input to digits, whitespace and arithmetic operators (preventing
identifier/property access and injection) and therefore is intentionally used
here to evaluate arithmetic expressions; also fix the misleading comment that
refers to "v" to use the actual parameter name "input". Additionally, add a TODO
note on the evaluateInput function referencing NumberWidget to plan replacing
eval with a safer evaluator (e.g., a small math expression parser or vetted
library) as a long‑term improvement.
There was a problem hiding this comment.
See the issue opened related to this.
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for recently opened issues that might be related to this PR or eval security
gh issue list --repo Comfy-Org/ComfyUI_frontend --limit 20 --state open --json number,title,url,createdAt,author | jq -r '.[] | "\(.number): \(.title) (created: \(.createdAt), author: \(.author.login))\n URL: \(.url)"'
# Also search for issues mentioning eval or this PR number
gh issue list --repo Comfy-Org/ComfyUI_frontend --search "eval" --limit 10 --state open --json number,title,url,body | jq -r '.[] | "\(.number): \(.title)\n URL: \(.url)\n Body preview: \(.body[:200])"'
# Search for issues mentioning PR 7759
gh issue list --repo Comfy-Org/ComfyUI_frontend --search "7759" --limit 10 --state open --json number,title,url,body | jq -r '.[] | "\(.number): \(.title)\n URL: \(.url)\n Body preview: \(.body[:200])"'
Length of output: 4428
@DrJKL Thanks for opening #8032 to track the eval replacement! That's the right approach—this PR centralizes the existing behavior without changing the security profile, and the issue ensures we can tackle the safer math expression parser as a follow-up improvement.
🧬 Code Graph Analysis Results
src/extensions/core/widgetInputs.ts:355-368
#isValidConnection(input: INodeInputSlot, forceUpdate?: boolean) {
// Only allow connections where the configs match
const output = this.outputs?.[0]
const config2 = (input.widget?.[GET_CONFIG] as () => InputSpec)?.()
if (!config2) return false
return !!mergeIfValid.call(
this,
output,
config2,
forceUpdate,
this.recreateWidget
)
}
🧠 Learnings used
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
| if (dragDelta.value === 0) { | ||
| textEdit.value = true | ||
| inputField.value?.focus() | ||
| inputField.value?.setSelectionRange(0, -1) | ||
| } |
There was a problem hiding this comment.
Non-standard setSelectionRange usage may fail to select text in some browsers.
The setSelectionRange(0, -1) call uses -1 as the end index, which is not spec-compliant. Per the HTMLInputElement specification, both arguments should be non-negative integers. This may not select all text as intended across browsers.
🐛 Proposed fix
if (dragDelta.value === 0) {
textEdit.value = true
inputField.value?.focus()
- inputField.value?.setSelectionRange(0, -1)
+ inputField.value?.select()
}Using select() is the standard, cross-browser way to select all text in an input field.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (dragDelta.value === 0) { | |
| textEdit.value = true | |
| inputField.value?.focus() | |
| inputField.value?.setSelectionRange(0, -1) | |
| } | |
| if (dragDelta.value === 0) { | |
| textEdit.value = true | |
| inputField.value?.focus() | |
| inputField.value?.select() | |
| } |
🤖 Prompt for AI Agents
In
@src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
around lines 164 - 168, The current selection call uses the non-standard
setSelectionRange(0, -1) which can fail; update the logic in the block that
checks dragDelta.value === 0 (where textEdit.value is set and inputField is
focused) to call the standard inputField.value?.select() after focusing the
element instead of setSelectionRange, ensuring the element is focused first so
select() will work across browsers.
There was a problem hiding this comment.
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
MDN setSelectionRange negative index -1
💡 Result:
MDN does not document using -1 with setSelectionRange. The docs state selectionStart/selectionEnd are 0‑based, non‑negative indices (indices > length are treated as the end of the value) and make no mention of negative values. Use an explicit clamp in your code (Math.max(0, i)) before calling setSelectionRange. [1][2]
Sources:
- setSelectionRange (MDN). [1]
- selectionStart / selectionEnd (MDN) — value is a non‑negative number. [2]
@DrJKL Thank you for linking to the documentation! The MDN docs confirm that setSelectionRange expects non-negative integers for both parameters. Using -1 is non-standard—negative indices are not documented, and the behavior is undefined.
The original suggestion to use inputField.value?.select() remains the correct, cross-browser approach for selecting all text in the input field.
🧠 Learnings used
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels
| " | ||
| :disabled="!canDecrement" | ||
| tabindex="-1" | ||
| @click="modelValue -= stepValue" |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider using updateValueBy for consistency with keyboard handlers.
The button click handlers directly modify modelValue without clamping, while keyboard handlers (lines 220-223) use updateValueBy() which includes bounds checking. For consistency and defensive coding:
♻️ Proposed fix
<button
v-if="!buttonsDisabled"
data-testid="decrement"
:class="
cn(sharedButtonClass, 'pi pi-minus', !canDecrement && 'opacity-60')
"
:disabled="!canDecrement"
tabindex="-1"
- @click="modelValue -= stepValue"
+ @click="updateValueBy(-stepValue)"
/>And similarly for the increment button:
<button
v-if="!buttonsDisabled"
data-testid="increment"
:class="
cn(sharedButtonClass, 'pi pi-plus', !canIncrement && 'opacity-60')
"
:disabled="!canIncrement"
tabindex="-1"
- @click="modelValue += stepValue"
+ @click="updateValueBy(stepValue)"
/>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @click="modelValue -= stepValue" | |
| <button | |
| v-if="!buttonsDisabled" | |
| data-testid="decrement" | |
| :class=" | |
| cn(sharedButtonClass, 'pi pi-minus', !canDecrement && 'opacity-60') | |
| " | |
| :disabled="!canDecrement" | |
| tabindex="-1" | |
| @click="updateValueBy(-stepValue)" | |
| /> | |
| <button | |
| v-if="!buttonsDisabled" | |
| data-testid="increment" | |
| :class=" | |
| cn(sharedButtonClass, 'pi pi-plus', !canIncrement && 'opacity-60') | |
| " | |
| :disabled="!canIncrement" | |
| tabindex="-1" | |
| @click="updateValueBy(stepValue)" | |
| /> |
🤖 Prompt for AI Agents
In
@src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
at line 197, The decrement/increment button click handlers currently mutate
modelValue directly (e.g., @click="modelValue -= stepValue") while keyboard
handlers call updateValueBy(...) which applies clamping/bounds; change both
button handlers to call updateValueBy(-stepValue) and updateValueBy(+stepValue)
(or updateValueBy(stepValue) as appropriate) so clicks go through the same
bounded update path as keyboard events, referencing the existing updateValueBy
function and modelValue prop.
|
Nice, thanks for moving the floating text off the widget as it coveed up the field in litegraph. Here's a thought: if you want people to migrate to nodes 2.0 sooner, just make litegraph a worse experience in many little ways like that. |

Adds support for entering math inside number widgets in vue mode

Migrates components to simple html elements (div and button) by borrowing styling from the (reverted) reka-ui migration in #6985. The existing (evil) litegraph eval code is extracted as a utility function and reused.
This PR means we're entirely writing our own NumberField.
Also adds support for scrubbing widgets like in litegraph

Known Issue
Scrubbing causes text to be highlighted,starting a scrub from highlighted text will instead drag the text.(Obligatory: It won't do you a bit of good to review math)
┆Issue is synchronized with this Notion page by Unito