NumberField
The NumberField family provides a headless numeric control with pointer scrubbing, mixed values, keyboard stepping, safe arithmetic expressions, units, trailing actions, and binding-aware state.
Interactive anatomy
Try +10, *2, 50%, or 12*8+4
Mixed
Disabled
Bound
Anatomy
NumberFieldRoot— renderless state and interaction ownerNumberFieldLeading— leading label or iconNumberFieldValue— non-editing valueNumberFieldInput— editing input with spinbutton semanticsNumberFieldUnit— unit textNumberFieldTrailing— trailing action areaNumberFieldMenu— field menu area
Root slot
The default slot receives modelValue, displayValue, draftValue, placeholder, all state booleans, state, actions, and attrs. Bind attrs to the focusable outer element. It contains the canonical spinbutton ARIA contract, keyboard/focus handlers, and data-editing, data-scrubbing, data-mixed, data-disabled, and data-bound attributes.
Expressions and keyboard
Committed input accepts absolute arithmetic such as 12*8+4, relative operations such as +10, -4, *2, and /3, and percentages such as 50% when max is finite. The parser only accepts numbers, parentheses, and + - * /; it never evaluates JavaScript.
Arrow keys step by step. Shift multiplies the step by 10 and Alt multiplies it by 0.1. Enter commits and Escape restores the interaction-start value.
Example
<script setup lang="ts">
import { ref } from 'vue'
import {
NumberFieldInput,
NumberFieldLeading,
NumberFieldRoot,
NumberFieldUnit,
NumberFieldValue
} from '@open-pencil/vue'
const width = ref(120)
</script>
<template>
<NumberFieldRoot
v-slot="{ attrs, editing, actions }"
v-model="width"
:min="0"
:max="1000"
aria-label="Width"
>
<div v-bind="attrs" @pointerdown="!editing && actions.startScrub($event)">
<NumberFieldLeading>W</NumberFieldLeading>
<NumberFieldInput />
<NumberFieldValue />
<NumberFieldUnit>px</NumberFieldUnit>
</div>
</NumberFieldRoot>
</template>Generated API reference
The following tables are extracted from the Vue source and its JSDoc during the documentation build.
NumberFieldRoot
Generated from packages/vue/src/primitives/NumberField/NumberFieldRoot.vue
Props
| Prop | Default | Type |
|---|---|---|
modelValue*Current numeric value or the mixed-value sentinel. | — | number | symbol |
minMinimum allowed value. | -Infinity | number | undefined |
maxMaximum allowed value and percentage-expression basis. | Infinity | number | undefined |
stepPointer-scrub and Arrow-key increment. | 1 | number | undefined |
sensitivityMultiplier applied to pointer-scrub movement. | 1 | number | undefined |
placeholderText shown when modelValue is mixed. | "Mixed" | string | undefined |
ariaLabelAccessible name for the spinbutton. | — | string | undefined |
disabledPrevents editing, scrubbing, and keyboard stepping. | — | boolean | undefined |
boundMarks the value as controlled by an external binding. | — | boolean | undefined |
editPolicyMutation policy used when the value is bound. | "editable" | NumberFieldEditPolicy | undefined |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | [value: number] | |
editing-change | [editing: boolean] | |
commit | [value: number, previous: number] | |
invalid | [expression: string, reason: NumberExpressionError] | |
detach-request | [source: NumberFieldMutationSource] |
Slots
| Slot | Props | Description |
|---|---|---|
defaultComplete render contract for composing a numeric field. | NumberFieldSlotProps | Complete render contract for composing a numeric field. |
NumberFieldInput
Generated from packages/vue/src/primitives/NumberField/NumberFieldInput.vue
No component-specific props, events, slots, or exposed members.
NumberFieldValue
Generated from packages/vue/src/primitives/NumberField/NumberFieldValue.vue
Slots
| Slot | Props | Description |
|---|---|---|
defaultNon-editing display value plus the complete field render contract. | NumberFieldSlotProps & { value: string; } | Non-editing display value plus the complete field render contract. |