import type { EventEmitter } from '../../stencil-public-runtime';
import type { NumericInputChangeDetail, NumericInputErrorDetail, NumericInputSize, NumericInputStepDetail, NumericInputVariant } from './mud-numeric-input.types';
import type { LocaleProp } from '../../utils/locale';
/**
* 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-text-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. Overrides the `locale`'s copy when set to a
* non-empty string.
* @default 'Crește' (ro-MD)
*/
incrementLabel?: string;
/**
* Accessible label for the decrement button. Overrides the `locale`'s copy when set to a
* non-empty string.
* @default 'Scade' (ro-MD)
*/
decrementLabel?: string;
/**
* Validation message reported when the field is `required` and empty. Overrides the
* `locale`'s copy when set to a non-empty string.
* @default 'Acest câmp este obligatoriu.' (ro-MD)
*/
requiredMessage?: string;
/**
* Validation message reported when the value is below `min`. Carries a `{min}` placeholder.
* Overrides the `locale`'s copy when set to a non-empty string.
* @default 'Valoarea minimă este {min}.' (ro-MD)
*/
minMessage?: string;
/**
* Validation message reported when the value is above `max`. Carries a `{max}` placeholder.
* Overrides the `locale`'s copy when set to a non-empty string.
* @default 'Valoarea maximă este {max}.' (ro-MD)
*/
maxMessage?: string;
/**
* Text of the `mudError` (`reason: 'ambiguous'`) raised for an entry that could be a thousands
* group or a decimal, such as `1.234` under `ro-MD`. `{decimal}` is replaced by the locale's
* decimal separator. Overrides the `locale`'s copy when set to a non-empty string.
* @default 'Valoarea este ambiguă. Scrieți numărul fără separator de mii și folosiți „{decimal}” pentru zecimale.' (ro-MD)
*/
ambiguousMessage?: string;
/**
* Human-readable value announcement for screen readers (e.g. `"5 lei"`).
* Maps to the native `aria-valuetext` on the spinbutton. An `aria-valuetext`
* attribute on the host is read once on load and stripped; later updates go
* through this prop, and setting it empty does not clear the value.
*/
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
* (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 number is shown
* with the locale's decimal separator and no grouping (`1250,00`) so the caret
* stays sane. Typed input is read the same way under every locale: spaces and `'`
* are ignored, and when both `.` and `,` occur the last one is the decimal. A
* single separator is a decimal, except the locale's own grouping character
* followed by exactly three digits (`1.234` under `ro-MD`), which raises `mudError`
* with `reason: 'ambiguous'` instead of guessing.
*
* Also selects the language of the built-in copy (steppers, clear button, validation
* messages): unset, the copy follows the closest ancestor `lang` (``
* included), else `ro-MD`. Number grouping is unaffected by that fallback — it stays off
* unless `locale` itself is set.
*/
locale?: LocaleProp;
/**
* 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. Overrides the `locale`'s copy when set to a
* non-empty string.
* @default 'Șterge' (ro-MD)
*/
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;
/**
* The host's `aria-label` (attribute or native `ariaLabel` property), moved onto the
* internal control when no visible label is present.
*/
private resolvedAriaLabel?;
private resolvedAriaValuetext?;
/**
* Whether the current value falls outside `min` / `max`. Kept as state so the
* control can carry `aria-invalid` for a value that is actually wrong, the
* way `internals.validity` already reports it to the form.
*/
private outOfRange;
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?;
private stopAriaLabel?;
private stopLang?;
syncAriaValuetextProp(next?: string): void;
onRequiredChange(): void;
onMinChange(): void;
onMaxChange(): void;
onLocaleChange(): void;
validateVariant(next: NumericInputVariant): void;
validateSize(next: NumericInputSize): void;
handleValueChange(next: number | undefined): void;
connectedCallback(): void;
disconnectedCallback(): void;
/** Built-in strings in the resolved locale, with the override props on top. */
private messages;
componentWillLoad(): void;
formDisabledCallback(disabled: boolean): void;
formResetCallback(): void;
formStateRestoreCallback(state: string | File | FormData | null): void;
private captureAriaValuetext;
private syncValidity;
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;
/**
* Read a typed or pasted entry, the same way under every locale. Every Unicode space and `'`
* is dropped and the Unicode minus (U+2212, which `ru-*` writes) counts as `-`. Then:
* - `.` and `,` both present: the last one is the decimal, the other groups thousands;
* - one of them repeated: it groups thousands (`1.234.567`);
* - one of them once: it is the decimal (`1.5`, `1,5`, `1234.5`) — except the locale's own
* grouping character followed by exactly three digits (`1.234` under `ro-MD`), which could
* be either, so the entry is `ambiguous` rather than guessed.
* 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;
/**
* The field's own number rule, also used for the `{min}` / `{max}` of its messages so they
* read like the field. With a `locale`: its decimal separator, grouped unless `focused`
* (typing needs a plain number, and the parser never sees a group separator this component
* wrote). Without one: `String(value)`, or `toFixed(precision)`.
*/
private formatNumber;
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;
/** Ambiguous entries yield no value; the raw text stays so the user can fix it. */
private emitAmbiguous;
private ambiguousText;
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;
}