import { EventEmitter } from '../../stencil-public-runtime'; import type { NumericInputChangeDetail, NumericInputErrorDetail, NumericInputSize, NumericInputStepDetail, NumericInputVariant } from './mud-numeric-input.types'; /** * Numeric Input — numeric-entry control with stacked step buttons. * * Pattern B (atom-interactive, form-associated): renders its own `` * inside shadow DOM and pairs it with a trailing stepper stack (chevron-up * over chevron-bottom). Shares the visual primitives of `mud-input` (border, * focus ring, label, helper / error, sizes, states) and adds a * `--numeric-input-stepper-*` token namespace for the increment / decrement * affordance. * * Why `` instead of * ``: native `type="number"` mixes parsing, locale, and * UI affordances in ways that interact poorly with `precision` rounding and * `min`/`max` clamping. The component delegates parsing + clamping to its own * logic and exposes `inputmode="decimal"` so mobile devices still surface the * numeric keypad. * * @element mud-numeric-input * * @slot label - Rich label content, replaces the `label` prop when present. * @slot helper - Rich helper / hint content, replaces the `helper-text` prop. Hidden when invalid + error-text is shown. * @slot icon-start - Leading icon (a `mud-icon`, icon-leading variant) rendered before the prefix / value. Sized to the square icon box. * @slot prefix - Leading unit / currency symbol rendered before the value (e.g. `€`, `$`, `MDL`). Shares the suffix's text styling — auto-width rather than the fixed icon box, so multi-character symbols don't clip. Distinct from `icon-start`, mirroring the Figma master's separate `prefix` and `leadingIcon` properties. * @slot suffix - Trailing unit text rendered after the value (e.g. `lei`, `kg`). Sits before the stepper stack. */ export declare class MudNumericInput { /** * Color treatment. `destructive` is forced when `invalid` is set. * Numeric inputs ship 3 styles per Figma (no Warning) — invalid numeric * values are typically out-of-range (Destructive) or confirmed-valid * (Success); there is no in-between state worth a Warning tone. * @default 'default' */ variant: NumericInputVariant; /** * Loading state. When true the control becomes uninteractive and a * brand `mud-spinner` replaces the trailing stepper stack. The host * carries `aria-busy="true"` for assistive technologies. * @default false */ loading: boolean; /** * Visual size rung. * @default 'md' */ size: NumericInputSize; /** * Disables interactivity. The internal control receives `aria-disabled` and * the native `disabled` attribute. Stepper buttons are also disabled. * @default false */ disabled: boolean; /** * Marks the field as mandatory. Adds a red asterisk to the label and sets * `aria-required` on the internal control. * @default false */ required: boolean; /** * Renders the field read-only. The control remains focusable; steppers are * suppressed. * @default false */ readonly: boolean; /** * Forces destructive visuals regardless of `variant`. Sets `aria-invalid`. * Use together with `errorText` to surface the message. * @default false */ invalid: boolean; /** * Show the trailing stacked stepper (chevron-up / chevron-bottom) buttons. * Off by default per Figma master, which renders the canonical numeric input * without steppers (suffix-only). Opt in via `show-steppers` for compact * quantity / rating fields where stepper affordance is valuable. * @default false */ showSteppers: boolean; /** * Current numeric value. `undefined` represents an empty field. Reflects to * the host attribute when set. */ value?: number; /** Inclusive lower bound. Stepper-down disables at this value; manual entries below clamp on blur. */ min?: number; /** Inclusive upper bound. Stepper-up disables at this value; manual entries above clamp on blur. */ max?: number; /** * Increment / decrement amount applied by the stepper buttons and arrow keys. * @default 1 */ step: number; /** * Decimal precision applied on blur (number of decimal places). When unset * the value is preserved as typed (subject to clamping). */ precision?: number; /** Form-control `name`. Used during form submission. */ name?: string; /** Placeholder shown when the control is empty. */ placeholder?: string; /** Plain-text label. Use the `label` slot for richer content. */ label?: string; /** Plain-text helper / hint shown below the control. */ helperText?: string; /** * Plain-text error message shown below the control when `invalid` is set. * When present it replaces `helperText` and pairs with the error icon. */ errorText?: string; /** * Accessible label for the increment button. Defaults to Romanian "Crește" * per the institutional voice. * @default 'Crește' */ incrementLabel: string; /** * Accessible label for the decrement button. Defaults to Romanian "Scade". * @default 'Scade' */ decrementLabel: string; /** * Accessible name. Mirrors to the internal control's `aria-label` when no * visible label is present. Setting `aria-label` directly on the host also * works — captured on connect into `resolvedAriaLabel` and stripped to * avoid Stencil's attribute-observer / render-loop antipattern. */ ariaLabel?: string; /** * Human-readable value announcement for screen readers (e.g. `"5 lei"`). * Maps to the native `aria-valuetext` on the spinbutton. Same capture-and-strip * pattern as `ariaLabel`. */ ariaValuetext?: string; /** * Allow fractional input. When `false` the field is integer-only: typing a * decimal separator is blocked and any fractional part is truncated on commit. * @default true */ allowDecimal: boolean; /** * Allow negative input. When `false` the field is positive-only: typing `-` * is blocked and negative entries are rejected on commit. * @default true */ allowNegative: boolean; /** * BCP-47 locale used to group the displayed value with thousands separators * and to parse grouped input back (e.g. `ro-MD` → `1.250,00`). When unset the * value displays ungrouped. Grouping is applied while the field is not being * edited; on focus the raw editable number is shown so the caret stays sane. */ locale?: string; /** * When `true`, renders a trailing clear (×) button while the field holds a * value. Activating it clears the value and emits `mudChange` with `null`. * @default false */ clearable: boolean; /** * Accessible label for the clear button. Defaults to the Romanian "Șterge". * @default 'Șterge' */ clearLabel: string; /** * Maximum number of characters accepted by the field (native `maxlength`). * When set, a character counter renders in the assistive row unless * `show-counter` is `false`. */ maxLength?: number; /** * Force the character counter to show or hide. Auto-shows when `maxlength` * is set; pass `false` to suppress it. * @default true */ showCounter: boolean; private hasLabelSlot; private hasHelperSlot; private hasIconStart; private hasPrefix; private hasSuffix; private isFocused; private fieldsetDisabled; private displayValue; private resolvedAriaLabel?; private resolvedAriaValuetext?; host: HTMLMudNumericInputElement; internals: ElementInternals; /** Fires on every keystroke. `detail.value` is the parsed current value or `null`. */ mudInput: EventEmitter; /** Fires when the value is committed (blur / Enter / stepper). `detail.value` is the clamped, precision-rounded value or `null`. */ mudChange: EventEmitter; /** Fires when a stepper button (or arrow key) bumps the value. */ mudStep: EventEmitter; /** Fires when validation rejects the current input (out-of-range, NaN). */ mudError: EventEmitter; /** Fires when the internal control gains focus. */ mudFocus: EventEmitter; /** Fires when the internal control loses focus. */ mudBlur: EventEmitter; /** Fires when the clear button empties the field. `detail.value` is `null`. */ mudClear: EventEmitter; private readonly instanceId; private readonly labelId; private readonly helperId; private readonly errorId; private readonly counterId; private initialValue; private nativeEl?; componentWillLoad(): void; private captureAriaAttrs; syncAriaLabelProp(next?: string): void; syncAriaValuetextProp(next?: string): void; onRequiredChange(): void; onMinChange(): void; onMaxChange(): void; private syncValidity; validateVariant(next: NumericInputVariant): void; validateSize(next: NumericInputSize): void; handleValueChange(next: number | undefined): void; formDisabledCallback(disabled: boolean): void; formResetCallback(): void; formStateRestoreCallback(state: string | File | FormData | null): void; private syncFormValue; /** * Resolve the active locale's grouping + decimal separators. Empty `locale` * → no grouping and a dot decimal (legacy behaviour; comma is still accepted). */ private localeSeparators; /** * Parse a raw string entry into a number. Strips the locale grouping * separator, normalises the decimal separator (locale / `,` → `.`), trims * whitespace, and rejects everything else. Stays lenient about sign and * fractions — `allow-negative` / `allow-decimal` are enforced in `commit`. */ private parseRaw; /** Clamp a number to `[min, max]`. */ private clamp; /** Round to the configured `precision` decimal places (no-op when unset). */ private round; /** Apply sign / integer policy, then clamp + round, in one step. */ private commit; /** Render a number for display. Grouped per `locale` while not being edited. */ private formatForDisplay; private canStep; private performStep; /** * Choose the seed value when the field is empty and the user presses a * stepper or arrow key: snap into `[min, max]` when defined, else 0. */ private startValueForStep; private onLabelSlotChange; private onHelperSlotChange; private onIconStartSlotChange; private onPrefixSlotChange; private onSuffixSlotChange; private slotHasContent; private handleInput; private handleChange; private handleFocus; private handleClearClick; private canClear; private hasCharacterCounter; private handleBlur; private commitFromDisplay; private handleKeyDown; private handleStepClick; private isInert; private resolvedVariant; private hasVisibleLabel; private hasErrorMessage; private hasHelperMessage; private describedBy; private showSteppersStack; render(): any; }