import type { JSX } from "@solidjs/web"; import { type Accessor } from "solid-js"; import { REASONS } from "../internals/change-event-details.js"; import { type MaybeAccessor } from "../internals/maybe-accessor.js"; import type { NumberFieldRootChangeEventDetails, NumberFieldRootCommitEventDetails } from "./root/number-field-root-context.js"; import type { EventWithOptionalKeyState, IncrementValueParameters } from "./utils/types.js"; export type { NumberFieldRootChangeEventDetails, NumberFieldRootCommitEventDetails, }; export type NumberFieldChangeReason = typeof REASONS.inputChange | typeof REASONS.inputClear | typeof REASONS.inputBlur | typeof REASONS.inputPaste | typeof REASONS.keyboard | typeof REASONS.incrementPress | typeof REASONS.decrementPress | typeof REASONS.wheel | typeof REASONS.scrub | typeof REASONS.none; export type NumberFieldCommitReason = typeof REASONS.inputBlur | typeof REASONS.inputClear | typeof REASONS.keyboard | typeof REASONS.incrementPress | typeof REASONS.decrementPress | typeof REASONS.wheel | typeof REASONS.scrub | typeof REASONS.none; export type NumberFieldInputMode = "numeric" | "decimal" | "text"; /** * Options for {@link createNumberField}. * * All reactive inputs accept `MaybeAccessor`. No internal state — the * consumer's signal is the sole source of truth. */ export interface CreateNumberFieldOptions { /** Consumer-owned value. `null` means empty. */ value: MaybeAccessor; /** @default 0.1 */ smallStep?: MaybeAccessor; /** @default 1 */ step?: MaybeAccessor; /** @default 10 */ largeStep?: MaybeAccessor; min?: MaybeAccessor; max?: MaybeAccessor; /** * When true, keyboard/button/wheel changes still clamp, but direct text * entry may exceed the range so native `rangeUnderflow`/`rangeOverflow` * validation can fire. * @default false */ allowOutOfRange?: MaybeAccessor; /** @default false */ snapOnStep?: MaybeAccessor; format?: MaybeAccessor; locale?: MaybeAccessor; /** * Pure event-emitter. The consumer's signal write is the only writer. * Use `runWithOwner(null, ...)` pattern — already applied internally. */ onValueChange?: (value: number | null, details: NumberFieldRootChangeEventDetails) => void; /** * Guard checked before syncing `inputValue` after a `setValue` call. * Pass `() => allowInputSyncRef.current` from the wrapper to suppress * input sync during IME composition. */ shouldSyncInput?: MaybeAccessor; onValueCommitted?: (value: number | null, details: NumberFieldRootCommitEventDetails) => void; } /** * Public API returned by {@link createNumberField}. */ export interface NumberFieldApi { /** Consumer-supplied value (memoized, null = empty). */ value: Accessor; /** Formatted display string for the visible input. */ inputValue: Accessor; /** Resolved `min` (defaults to `Number.MIN_SAFE_INTEGER`). */ minWithDefault: Accessor; /** Resolved `max` (defaults to `Number.MAX_SAFE_INTEGER`). */ maxWithDefault: Accessor; /** Raw `min` (undefined if not set). */ min: Accessor; /** Raw `max` (undefined if not set). */ max: Accessor; /** Resolved step amount (never "any" — "any" coerces to 1). */ step: Accessor; /** Small-step amount (Alt+Arrow). */ smallStep: Accessor; /** Large-step amount (Shift+Arrow). */ largeStep: Accessor; /** `inputmode` attribute for the visible input (iOS-aware). */ inputMode: Accessor; /** * Validated + formatted write. Returns whether a change was emitted. * Validation, clamping, step-snap, and formatting are applied before * `onValueChange` fires. */ setValue: (raw: number | null, details: NumberFieldRootChangeEventDetails) => boolean; /** * Step-based increment / decrement. Adds `amount * direction` to the * current value (or `max(0, min)` when empty) then validates. */ increment: (amount: number, params: IncrementValueParameters) => boolean; /** Fire `onValueCommitted`. */ commitValue: (next: number | null, details: NumberFieldRootCommitEventDetails) => void; /** * Step amount for a given keyboard event — `smallStep` (Alt), `largeStep` * (Shift), or `step`. */ getStepAmount: (event?: EventWithOptionalKeyState) => number | undefined; /** * Set of non-numeric characters the visible input should accept. Computed * from locale + format options. */ getAllowedNonNumericKeys: () => Set; /** Resolved locale (undefined = runtime default). */ locale: Accessor; /** * Override the displayed input string. Called by `` to * hold partial input while editing (e.g. mid-entry decimal). */ setInputValue: (next: string) => void; /** * Context provider. Wrap a subtree to make the api accessible via * `useNumberField()` without prop-drilling. */ Provider: (props: { children: JSX.Element; }) => JSX.Element; } /** * Read the nearest {@link NumberFieldApi} provided by `c.Provider`. Throws if * called outside a Provider. */ export declare function useNumberField(): NumberFieldApi; /** * Solid 2.0-native headless primitive for a number field. Owns logical * state: value normalization, step math, formatting, and increment/decrement. * DOM concerns (visible input ref, hidden input, wheel listener, field * validation wiring) stay in ``. */ export declare function createNumberField(options: CreateNumberFieldOptions): NumberFieldApi; //# sourceMappingURL=create-number-field.d.ts.map