import type { IconProp } from '../icon'; import type { Snippet } from 'svelte'; import type { HTMLInputAttributes } from 'svelte/elements'; export type InputType = 'text' | 'password' | 'email' | 'search' | 'url' | 'tel'; export type InputSize = 'sm' | 'md' | 'lg'; export type InputProps = { value: string | null | undefined; /** @default 'text' */ type?: InputType; /** @default 'md' */ size?: InputSize; disabled?: boolean; /** Non-editable but selectable. The value is still submitted with a form. */ readonly?: boolean; /** Visual display mode — non-focusable, no hover/focus animations, hidden clear button. */ inert?: boolean; /** Visual error state — also sets `aria-invalid="true"`. */ error?: boolean; /** Strip border + background + focus underline. */ borderless?: boolean; /** Show the default × clear button when value is non-empty. */ clearable?: boolean; /** Show the emoji-picker trigger inside the input. */ emoji?: boolean; /** * Strip leading / trailing whitespace when the value is committed — on `change`, on blur, and on * Enter. Typing is never touched, so the committed value always equals what the field shows. * Ignored for `type="password"`, where whitespace can be part of the secret. * @default true */ trim?: boolean; placeholder?: string; title?: string; name?: string; id?: string | null; autofocus?: boolean; maxLength?: number | null; autocomplete?: HTMLInputAttributes['autocomplete']; autocapitalize?: 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters'; inputmode?: 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search'; enterkeyhint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send'; spellcheck?: boolean; 'aria-describedby'?: string; 'aria-label'?: string; 'aria-required'?: boolean; on?: { input?: (value: string) => void; change?: (value: string) => void; mounted?: (data: { input: HTMLInputElement; }) => void; blur?: () => void; focus?: () => void; keydown?: (event: KeyboardEvent) => void; }; /** Primary icon — string SVG source, `{ src, color?, size? }` object, or custom snippet. */ icon?: IconProp; /** Side of the input where the primary icon sits. @default 'leading' */ iconPosition?: 'leading' | 'trailing'; /** Optional secondary icon — always rendered on the opposite side of the input from the primary. */ secondaryIcon?: IconProp; /** * Leading prefix slot — full-height segment rendered flush to the field's left rounded edge, * before all icons. Hands full visual control to the snippet (used by WebsiteInput for the * `https://` chunk). When set, the field's left padding is suppressed; the prefix segment * provides its own inline padding and a trailing gap equal to the field's padding. */ prefix?: Snippet; /** * Trailing suffix slot — free-form trailing addon rendered between the native input and any * trailing icons / clear button. Used for inline badges (e.g. HandleInput's availability pill) * and counters. Unlike `prefix`, this slot is NOT segmented — it carries no background or * separator by default; the snippet supplies its own chrome. */ suffix?: Snippet; }; /** * The subset of `InputProps` that a proxy wrapper (e.g. `WebsiteInput`, `HandleInput`) typically * forwards verbatim. Excludes Input-only visual knobs (`type`, `icon*`, `clearable`, `emoji`, * `prefix`, `suffix`) which a proxy controls itself. * * Proxies should declare their Props as `Omit & OwnProps` * to surgically remove forwarded props that the proxy hard-wires (so consumers can't override them). */ export type InputForwardedProps = Pick;