Skip to content

feat(Number Field): add startingValue prop for increment/decrement#2628

Open
rikzwarthoff wants to merge 3 commits into
unovue:v2from
rikzwarthoff:v2_numberfield_startingvalue
Open

feat(Number Field): add startingValue prop for increment/decrement#2628
rikzwarthoff wants to merge 3 commits into
unovue:v2from
rikzwarthoff:v2_numberfield_startingvalue

Conversation

@rikzwarthoff
Copy link
Copy Markdown

@rikzwarthoff rikzwarthoff commented May 6, 2026

🔗 Linked issue

(#2627)

❓ Type of change

  • 📖 Documentation (updates to the documentation, readme or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Added new prop 'startingValue' to Number Field
When no value is present and startingValue is given, increment/decrement will fill the startingValue. If startingValue is not present it will fallback to previous behavior, min value or zero.

See the issue for an useful example.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

Summary by CodeRabbit

  • New Features

    • Number fields gain an optional starting value. When empty, the first increment or decrement begins from this configured starting value instead of the minimum or zero.
  • Tests

    • Added test coverage ensuring increment/decrement sequences respect the configured starting value, including clearing and subsequent operations.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

Added an optional startingValue prop to NumberField and used it to initialize increment/decrement when the input is empty/NaN (fallback to min or 0). Added a test verifying behavior with startingValue: 40 and step: 3.

Changes

NumberField Starting Value

Layer / File(s) Summary
Props Definition
packages/core/src/NumberField/NumberFieldRoot.vue
Added optional prop startingValue?: number to NumberFieldRootProps and destructured it in setup.
Initialization Logic
packages/core/src/NumberField/NumberFieldRoot.vue
NaN-handling branch in handleChangingValue now initializes from startingValue.value !== undefined ? clampInputValue(startingValue.value) : min.value ?? 0.
Tests
packages/core/src/NumberField/NumberField.test.ts
New test: verifies that with step: 3 and startingValue: 40, first increment from empty yields 40, next yields 43, and after clearing, decrement yields 40 then 37.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

"i am a rabbit, small and spry,
I hop to fields of numbers high,
When boxes empty block the day,
A starting value shows the way,
Click up or down — I dance, hooray! 🐇"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(Number Field): add startingValue prop for increment/decrement' accurately and concisely summarizes the main change: adding a new startingValue prop to the Number Field component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/core/src/NumberField/NumberField.test.ts (1)

94-108: ⚡ Quick win

Add edge-case coverage for startingValue outside [min, max] bounds.

The new test only covers the happy path (no min/max). A test with startingValue outside the configured range would expose the missing clampInputValue() call flagged above, and document the expected clamping behavior going forward.

✅ Suggested additional test
it('should clamp startingValue to min/max on first increment/decrement', async () => {
  // startingValue below min — first increment should clamp to min
  const { input, increment } = setup({ min: 10, max: 20, step: 3, startingValue: 5 })
  expect(input.value).toBe('')
  await userEvent.click(increment)
  expect(input.value).toBe('10') // clamped to min, snapped to step
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/NumberField/NumberField.test.ts` around lines 94 - 108, Add
a test to cover startingValue outside min/max so startingValue is clamped before
the first increment/decrement: update NumberField.test.ts to add a case using
setup({ min, max, step, startingValue }) (e.g., startingValue < min and
startingValue > max) and assert that after the first userEvent.click(increment)
or click(decrement) the input.value equals the clamped/snapped value; reference
the same setup helper and ensure behavior matches clampInputValue() (i.e.,
snapped to step and bounded by min/max) for both increment and decrement flows.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/NumberField/NumberFieldRoot.vue`:
- Line 124: The NaN-branch assigns startingValue directly to modelValue.value
without enforcing bounds or step alignment; replace that direct assignment by
passing startingValue through the existing clampInputValue() logic (the same
function used elsewhere) before setting modelValue.value so the initial value is
clamped/snapped to [min, max] and step rules; update the assignment at
modelValue.value = startingValue.value ?? min.value ?? 0 to call
clampInputValue(startingValue.value) (or equivalent) and preserve the fallback
to min.value ?? 0 if startingValue is undefined/NaN.

---

Nitpick comments:
In `@packages/core/src/NumberField/NumberField.test.ts`:
- Around line 94-108: Add a test to cover startingValue outside min/max so
startingValue is clamped before the first increment/decrement: update
NumberField.test.ts to add a case using setup({ min, max, step, startingValue })
(e.g., startingValue < min and startingValue > max) and assert that after the
first userEvent.click(increment) or click(decrement) the input.value equals the
clamped/snapped value; reference the same setup helper and ensure behavior
matches clampInputValue() (i.e., snapped to step and bounded by min/max) for
both increment and decrement flows.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dd647a25-99a9-41ca-9f45-50285f34877d

📥 Commits

Reviewing files that changed from the base of the PR and between edbeb93 and a8944c5.

📒 Files selected for processing (2)
  • packages/core/src/NumberField/NumberField.test.ts
  • packages/core/src/NumberField/NumberFieldRoot.vue

Comment thread packages/core/src/NumberField/NumberFieldRoot.vue Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/NumberField/NumberFieldRoot.vue`:
- Around line 123-125: The code clamps the parsed NaN input by calling
clampInputValue(startingValue.value ?? min.value ?? 0), but snapValueToStep
currently treats an undefined lower bound as 0 which causes a startingValue
(e.g., 40 with step 3) to snap down to 39; update clamp behavior so that when
startingValue is explicitly provided and min is undefined you preserve the raw
startingValue (do not call snapValueToStep against an implied 0), i.e., change
the logic around clampInputValue / snapValueToStep invocation to only snap to
step when a concrete lower bound (min) exists or when startingValue is absent,
referencing clampInputValue and snapValueToStep in NumberFieldRoot.vue and the
startingValue/min variables.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4edcc05f-b072-4ffb-8d9c-de579a98b15d

📥 Commits

Reviewing files that changed from the base of the PR and between a8944c5 and da1e58a.

📒 Files selected for processing (1)
  • packages/core/src/NumberField/NumberFieldRoot.vue

Comment thread packages/core/src/NumberField/NumberFieldRoot.vue
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/core/src/NumberField/NumberFieldRoot.vue (1)

123-125: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

clampInputValue snaps startingValue away from the intended value when min is undefined.

clampInputValue delegates to snapValueToStep(val, min, max, step). When min is undefined, snapValueToStep anchors the grid at 0. With the test's own configuration (startingValue: 40, step: 3, no min):

(40 − 0) % 3 = 1  →  snaps down to 39

The first increment will write 39 instead of the expected 40, and subsequent assertions (43, 40, 37) are all offset by −1, so the entire test will fail.

Semantically, startingValue represents an exact starting point, not a point that must align with the step grid. Only min/max clamping should apply here.

🛡️ Proposed fix
-    modelValue.value = startingValue.value !== undefined ? clampInputValue(startingValue.value) : min.value ?? 0
+    modelValue.value = startingValue.value !== undefined ? clamp(startingValue.value, min.value, max.value) : min.value ?? 0

clamp (already imported) enforces [min, max] bounds without snapping to the step grid, preserving the user's exact startingValue. Subsequent increments/decrements from that value will still be step-aligned.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/NumberField/NumberFieldRoot.vue` around lines 123 - 125,
The code uses clampInputValue (which snaps via snapValueToStep) when
initializing modelValue from startingValue causing unwanted step snapping;
instead, preserve the exact startingValue and only enforce min/max bounds using
the existing clamp helper. Replace the clampInputValue call in the isNaN branch
with a clamp of startingValue.value against min and max (use min.value and
max.value or their undefined-aware defaults) so startingValue is not snapped to
the step grid while still respecting bounds; keep all other logic (modelValue,
startingValue, snapValueToStep) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/core/src/NumberField/NumberFieldRoot.vue`:
- Around line 123-125: The code uses clampInputValue (which snaps via
snapValueToStep) when initializing modelValue from startingValue causing
unwanted step snapping; instead, preserve the exact startingValue and only
enforce min/max bounds using the existing clamp helper. Replace the
clampInputValue call in the isNaN branch with a clamp of startingValue.value
against min and max (use min.value and max.value or their undefined-aware
defaults) so startingValue is not snapped to the step grid while still
respecting bounds; keep all other logic (modelValue, startingValue,
snapValueToStep) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8175c21f-13b2-4b92-94e3-05ec7453ea66

📥 Commits

Reviewing files that changed from the base of the PR and between da1e58a and aeec578.

📒 Files selected for processing (1)
  • packages/core/src/NumberField/NumberFieldRoot.vue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants