@sky.ui/core 0.0.53 → 0.0.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/custom-elements.json +3785 -3679
- package/dist/helper/controllers/popover-controller.js +1 -1
- package/dist/helper/controllers/popover-controller.js.map +1 -1
- package/dist/helper/index.js +1 -1
- package/dist/helper/utils/index.d.ts +1 -0
- package/dist/helper/utils/index.js +1 -1
- package/dist/helper/utils/stable-array.d.ts +6 -0
- package/dist/helper/utils/stable-array.js +2 -0
- package/dist/helper/utils/stable-array.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/sky-avatar/sky-avatar.js +5 -5
- package/dist/sky-avatar/sky-avatar.js.map +1 -1
- package/dist/sky-chip/sky-chip.d.ts +8 -2
- package/dist/sky-chip/sky-chip.js +10 -10
- package/dist/sky-chip/sky-chip.js.map +1 -1
- package/dist/sky-combobox/sky-combobox.d.ts +2 -0
- package/dist/sky-combobox/sky-combobox.js +16 -16
- package/dist/sky-combobox/sky-combobox.js.map +1 -1
- package/dist/sky-flexbox/sky-flexbox.d.ts +2 -0
- package/dist/sky-flexbox/sky-flexbox.js +3 -3
- package/dist/sky-flexbox/sky-flexbox.js.map +1 -1
- package/dist/sky-form/sky-form.js +7 -7
- package/dist/sky-form/sky-form.js.map +1 -1
- package/dist/sky-image/sky-image.js +5 -5
- package/dist/sky-image/sky-image.js.map +1 -1
- package/dist/sky-input/sky-input.js +6 -6
- package/dist/sky-input/sky-input.js.map +1 -1
- package/dist/sky-list/sky-list.js +3 -3
- package/dist/sky-list/sky-list.js.map +1 -1
- package/dist/sky-listitem/sky-listitem.d.ts +1 -0
- package/dist/sky-listitem/sky-listitem.js +4 -2
- package/dist/sky-listitem/sky-listitem.js.map +1 -1
- package/dist/sky-radio/sky-radio.js +1 -1
- package/dist/sky-radio/sky-radio.js.map +1 -1
- package/dist/sky-simple-table/sky-simple-table.d.ts +7 -2
- package/dist/sky-simple-table/sky-simple-table.js +9 -9
- package/dist/sky-simple-table/sky-simple-table.js.map +1 -1
- package/dist/sky-theme-provider/sky-theme-provider.js +2 -2
- package/dist/sky-theme-provider/sky-theme-provider.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sky-input.js","sources":["../../src/sky-input/sky-input.ts"],"sourcesContent":["import { LitElement, html, css, nothing } from \"lit\";\r\nimport { ifDefined } from \"lit/directives/if-defined.js\";\r\nimport { styleMap } from \"lit/directives/style-map.js\";\r\nimport { customElement, property, query, state } from \"lit/decorators.js\";\r\nimport { resolveColor } from \"../helper/utils/color-resolver\";\r\nimport { PresetController } from \"../helper/controllers/preset-controller\";\r\nimport { live } from \"lit/directives/live.js\";\r\nimport { FormControlBase } from \"../helper/internals/form-control-base\";\r\nimport { SkyIcon } from \"../sky-icon/sky-icon.js\";\r\n\r\nexport type SkyInputValue = string | number | File[] | null;\r\nexport type SkyInputType = string;\r\nexport type SkyInputErrorDisplayMode = \"none\" | \"single\" | \"all\";\r\nexport type SkyInputIconPosition = \"left\" | \"right\";\r\nexport type SkyInputValidation = (value: string | File[]) => true | string;\r\nexport type SkyInputValueChangedDetail = { value: string | number };\r\nexport type SkyInputValueClearedDetail = { value: string | number };\r\nexport type SkyInputFileSelectedDetail = {\r\n files: File[];\r\n fileName: string;\r\n totalSize: number;\r\n fileCount: number;\r\n};\r\nexport type SkyInputValidationErrorDetail = { errors: string[] };\r\nexport type SkyInputIconClickDetail = {\r\n position: SkyInputIconPosition;\r\n eventType: string | null;\r\n eventData: Event | null;\r\n};\r\n\r\n/**\r\n * @element sky-input\r\n *\r\n * @summary Versatile form input supporting text, password, number, textarea, and file workflows.\r\n *\r\n * @status stable\r\n * @since 1.0.0\r\n *\r\n * @documentation https://sky-ui.com/components/input\r\n * @dependency sky-icon\r\n *\r\n * @uiVModel value value-changed\r\n *\r\n * @slot icon-left - Optional icon/content placed in the left slot.\r\n * @slot icon-right - Optional icon/content placed in the right slot.\r\n * @property {SkyInputValue} value - Current input value.\r\n * @property {string} placeholder - Placeholder text.\r\n * @property {string} label - Label text. Above the field by default; on the border for `fieldset`; inside the field for `inside`.\r\n * @property {string} variant - Visual style: `default`, `highlight`, `fieldset`, or `inside`.\r\n * @property {SkyInputType} type - Input type (`text`, `password`, `number`, `textarea`, `file`, etc.).\r\n * @property {string} suffix - Optional suffix label fragment.\r\n * @property {string} prefix - Optional prefix label fragment.\r\n * @property {string} prefixColor - Prefix color override.\r\n * @property {string} suffixColor - Suffix color override.\r\n * @property {string} color - Accent color token/value.\r\n * @property {SkyInputValidation[]} validations - Validation functions.\r\n * @property {boolean} compact - Compact display mode.\r\n * @property {string} preset - Named prop preset from nearest `sky-config-provider`. Default: `\"\"`.\r\n * @property {boolean} loading - Loading state.\r\n * @property {boolean} showErrors - Enables error rendering.\r\n * @property {boolean} clearable - Enables clear button.\r\n * @property {SkyInputErrorDisplayMode} errorDisplayMode - Error rendering mode.\r\n * @property {boolean} showNumberButtons - Enables number increment/decrement controls.\r\n * @property {boolean} showPasswordToggle - Enables password visibility toggle.\r\n * @property {string} passwordVisibleIcon - Icon used when password is visible.\r\n * @property {string} passwordHiddenIcon - Icon used when password is hidden.\r\n *\r\n * @fires {CustomEvent<SkyInputValueChangedDetail>} value-changed - Fired when value changes.\r\n * @fires {CustomEvent<SkyInputValueClearedDetail>} value-cleared - Fired after clear action.\r\n * @fires {CustomEvent<SkyInputFileSelectedDetail>} file-selected - Fired after file selection changes.\r\n * @fires {CustomEvent<SkyInputValidationErrorDetail>} validation-error - Fired after validations run.\r\n * @fires {CustomEvent<SkyInputIconClickDetail>} left-icon-click - Fired when left icon slot is clicked.\r\n * @fires {CustomEvent<SkyInputIconClickDetail>} right-icon-click - Fired when right icon slot is clicked.\r\n *\r\n * @method validateInput Runs configured validations and updates invalid state.\r\n * @method handleClear Clears value and emits corresponding events.\r\n * @method formatFileSize Formats byte size for UI display.\r\n * @method focusInput Focuses the underlying native input or textarea.\r\n *\r\n * @csspart input-container - The outer container wrapping label and input wrapper.\r\n * @csspart label - The label element above the input.\r\n * @csspart input-wrapper - The wrapper around input/textarea and icons.\r\n * @csspart icon-slot - Base class for left/right icon slots.\r\n * @csspart icon-slot-left - Left icon slot.\r\n * @csspart icon-slot-right - Right icon slot.\r\n * @csspart clear-button - The clear/reset button.\r\n * @csspart toggle-password - The toggle icon for password visibility.\r\n * @csspart loading-indicator - The spinner shown when loading.\r\n * @csspart error-list - UL element containing validation errors.\r\n * @csspart error - Individual error message.\r\n * @csspart file-info - File count and size info below the file input.\r\n * @csspart input-prefix - Inline prefix fragment inside the field.\r\n * @csspart input-suffix - Inline suffix fragment inside the field.\r\n *\r\n * @Behavior\r\n * - Extends `FormControlBase` for automatic form association and validation integration\r\n * - Supports all standard HTML input types with enhanced styling and functionality\r\n * - File inputs with multi-file support, preview, and size tracking\r\n * - Automatic validation integration with parent forms via `sky-form`\r\n *\r\n * - **none**: No error messages displayed\r\n * - **single**: Show only the first error message\r\n * - **all**: Show all validation error messages\r\n *\r\n * @example\r\n * ```html\r\n * <sky-input\r\n * label=\"Password\"\r\n * type=\"password\"\r\n * placeholder=\"Enter your password\"\r\n * clearable\r\n * show-password-toggle\r\n * required\r\n * >\r\n * <sky-icon slot=\"icon-left\" icon=\"ion:lock-closed\"></sky-icon>\r\n * </sky-input>\r\n * ```\r\n * ```vue\r\n * <template>\r\n * <sky-input label=\"Password\" type=\"password\" clearable show-password-toggle required>\r\n * <sky-icon slot=\"icon-left\" icon=\"ion:lock-closed\"></sky-icon>\r\n * </sky-input>\r\n * </template>\r\n * ```\r\n * ```jsx\r\n * export default function Demo() {\r\n * return (\r\n * <sky-input label=\"Password\" type=\"password\" clearable show-password-toggle required>\r\n * <sky-icon slot=\"icon-left\" icon=\"ion:lock-closed\"></sky-icon>\r\n * </sky-input>\r\n * );\r\n * }\r\n * ```\r\n */\r\n@customElement(\"sky-input\")\r\nexport class SkyInput extends FormControlBase {\r\n\r\n static dependencies: Record<string, CustomElementConstructor> = {\r\n \"sky-icon\": SkyIcon,\r\n };\r\n\r\n @property({ type: String }) value: SkyInputValue = \"\";\r\n @property({ type: String }) placeholder = \"\";\r\n @property({ type: String }) label = \"\";\r\n @property({ type: String }) type: SkyInputType = \"text\";\r\n @property({ type: String }) suffix = \"\";\r\n @property({ type: String }) prefix = \"\";\r\n @property({ type: String }) prefixColor = \"\";\r\n @property({ type: String }) suffixColor = \"\";\r\n @property({ type: String }) color = \"primary\";\r\n private _validations: SkyInputValidation[] = [];\r\n @property({ type: Array })\r\n get validations(): SkyInputValidation[] {\r\n return this._validations;\r\n }\r\n set validations(value: SkyInputValidation[] | null | undefined) {\r\n const old = this._validations;\r\n this._validations = Array.isArray(value) ? value : [];\r\n this.requestUpdate(\"validations\", old);\r\n }\r\n @property({ type: Boolean, reflect: true }) compact = false;\r\n @property({ type: Boolean, reflect: true }) loading = false;\r\n @property({ type: Boolean }) showErrors = false;\r\n @property({ type: Boolean, reflect: true }) clearable = false;\r\n @property({ type: String }) errorDisplayMode: SkyInputErrorDisplayMode = \"single\";\r\n @property({ type: Boolean, reflect: true }) override required = false;\r\n @property({ type: String }) step: string | null = null;\r\n @property({ type: String }) min: string | null = null;\r\n @property({ type: String }) max: string | null = null;\r\n @property({ type: String }) override autocapitalize = \"off\";\r\n @property({ type: String }) autocomplete = \"off\";\r\n @property({ type: Boolean }) override spellcheck = false;\r\n @property({ type: String }) override dir = \"ltr\";\r\n @property({ type: Number }) rows = 6;\r\n @property({ type: String }) resizable = \"none\";\r\n @property({ type: String }) accept = \"\";\r\n @property({ type: Boolean }) multiple = false;\r\n @property({ type: String }) inputmode: string | null = null;\r\n @property({ type: String }) enterkeyhint: string | null = null;\r\n @property({ type: String }) pattern: string | null = null;\r\n @property({ type: Number }) minlength: number | null = null;\r\n @property({ type: Number }) maxlength: number | null = null;\r\n @property({ type: String }) list: string | null = null;\r\n @property({ type: Number }) size: number | null = null;\r\n @property({ type: Number }) cols: number | null = null;\r\n @property({ type: Boolean }) autofocus = false;\r\n @property({ type: Boolean }) capture = false;\r\n @property({ type: String }) inputRole: string | null = null;\r\n @property({ type: String }) ariaLabel: string | null = null;\r\n @property({ type: String }) ariaLabelledby: string | null = null;\r\n @property({ type: String }) ariaDescribedby: string | null = null;\r\n @property({ type: Boolean }) showNumberButtons = false;\r\n @property({ type: Boolean }) showPasswordToggle = true;\r\n @property({ type: String }) passwordVisibleIcon = \"material-symbols:visibility-off\";\r\n @property({ type: String }) passwordHiddenIcon = \"material-symbols:visibility\";\r\n @property({ type: Boolean, reflect: true }) validationActive = false;\r\n @property({ type: Boolean, reflect: true }) invalid = false;\r\n @property({ type: String, reflect: true }) variant:\r\n | \"default\"\r\n | \"highlight\"\r\n | \"fieldset\"\r\n | \"inside\" = \"default\";\r\n\r\n /** Named prop preset from nearest `sky-config-provider`. */\r\n @property({ type: String, reflect: true }) preset = \"\";\r\n\r\n private _presets = new PresetController(this);\r\n\r\n @state() private selectedFileName = \"\";\r\n @state() private selectedFiles: File[] = [];\r\n @state() private focused = false;\r\n @state() private validationStatus: boolean[] = [];\r\n @state() private validationErrors: string[] = [];\r\n @state() private typingStarted = false;\r\n @state() private autofillIconSlot = \"left\";\r\n @state() private autofillGuardActive = false;\r\n @state() private showPassword = false;\r\n @state() private totalFileSize = 0;\r\n @state() private selectedFileCount = 0;\r\n @state() private filePreview: string | ArrayBuffer | null = null;\r\n\r\n @query(\".input-wrapper\") private inputWrapperEl!: HTMLElement;\r\n @query(\"input, textarea\") private nativeInputEl!:\r\n | HTMLInputElement\r\n | HTMLTextAreaElement;\r\n\r\n private _leftIconSlot: HTMLSlotElement | null = null;\r\n private _rightIconSlot: HTMLSlotElement | null = null;\r\n private _iconClickWired = new WeakSet<HTMLElement>();\r\n private _onLeftIconSlotChange = () =>\r\n this._wireIconSlot(\"left\", this._leftIconSlot);\r\n private _onRightIconSlotChange = () =>\r\n this._wireIconSlot(\"right\", this._rightIconSlot);\r\n\r\n static override styles = css`\r\n :host {\r\n display: block;\r\n font-family: var(--sky-font);\r\n width: 100%;\r\n /* Control size */\r\n --sky-input-height: 36px;\r\n --sky-input-height-compact: 28px;\r\n --sky-input-border-width: 1px;\r\n /* Spacing scale — tight internal joins, softer outer edge */\r\n --sky-input-pad-x: var(--sky-space-3, 12px);\r\n --sky-input-pad-x-sm: var(--sky-space-1, 4px);\r\n --sky-input-pad-x-xs: 0px;\r\n --sky-input-pad-y: var(--sky-space-1, 4px);\r\n --sky-input-pad-y-sm: 0px;\r\n --sky-input-gap: var(--sky-space-1, 4px);\r\n --sky-input-icon-width: 2rem;\r\n }\r\n\r\n :host([data-sky-compact]) {\r\n --sky-input-pad-x: var(--sky-space-2, 8px);\r\n --sky-input-pad-x-sm: var(--sky-space-1, 4px);\r\n --sky-input-icon-width: 1.75rem;\r\n }\r\n\r\n /* Compact typography + denser chrome for every variant */\r\n :host([data-sky-compact]) .input-container > .label {\r\n font-size: var(--sky-font-size-xs);\r\n margin-bottom: var(--sky-space-1, 4px);\r\n line-height: 1.2;\r\n }\r\n\r\n :host([data-sky-compact]) input,\r\n :host([data-sky-compact]) textarea,\r\n :host([data-sky-compact]) .input-affix,\r\n :host([data-sky-compact]) .custom-file-label__text {\r\n font-size: var(--sky-font-size-sm);\r\n }\r\n\r\n :host([data-sky-compact]) .icon-slot {\r\n font-size: var(--sky-font-size-lg);\r\n }\r\n\r\n :host([data-sky-compact]) .toggle-password,\r\n :host([data-sky-compact]) .clear-button {\r\n font-size: var(--sky-font-size-md);\r\n }\r\n\r\n :host([data-sky-compact]) .custom-file-label {\r\n border-radius: var(--sky-radius-primary);\r\n }\r\n\r\n :host([disabled]) .input-container {\r\n opacity: var(--sky-opacity-disabled, 0.6);\r\n }\r\n :host([disabled]) * {\r\n pointer-events: none;\r\n }\r\n\r\n :host([data-sky-variant=\"highlight\"]){\r\n .label{\r\n color: var(--sky-input-color);\r\n }\r\n }\r\n\r\n /* Fieldset / legend: native fieldset+legend; wrapper keeps solid fill */\r\n :host([data-sky-variant=\"fieldset\"]) {\r\n overflow: visible;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) .input-container {\r\n overflow: visible;\r\n /* Room for legend text sitting on the top border — keep off :host */\r\n padding-block-start: 0.65em;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper {\r\n display: block;\r\n height: auto;\r\n margin: 0;\r\n min-inline-size: 0;\r\n min-width: 0;\r\n padding: 0;\r\n overflow: visible;\r\n background: var(--sky-glass-solid);\r\n box-shadow: none;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper[compact] {\r\n height: auto;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) .input-fieldset-body {\r\n display: flex;\r\n width: 100%;\r\n align-items: center;\r\n box-sizing: border-box;\r\n /* Match default control outer height once fieldset border is included */\r\n height: calc(\r\n var(--sky-input-height) - 2 * var(--sky-input-border-width)\r\n );\r\n min-height: calc(\r\n var(--sky-input-height) - 2 * var(--sky-input-border-width)\r\n );\r\n background: transparent;\r\n border-radius: inherit;\r\n min-width: 0;\r\n overflow: hidden;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper[compact] .input-fieldset-body {\r\n height: calc(\r\n var(--sky-input-height-compact) - 2 * var(--sky-input-border-width)\r\n );\r\n min-height: calc(\r\n var(--sky-input-height-compact) - 2 * var(--sky-input-border-width)\r\n );\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper:has(textarea) {\r\n height: auto;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper:has(textarea) .input-fieldset-body {\r\n height: calc((var(--rows)) * 23px);\r\n min-height: calc((var(--rows)) * 23px);\r\n align-items: flex-start;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) legend.label {\r\n float: unset;\r\n width: auto;\r\n max-width: calc(100% - 2 * var(--sky-input-pad-x));\r\n margin-inline-start: var(--sky-input-pad-x);\r\n margin-block: 0;\r\n padding-inline: var(--sky-input-pad-x-sm);\r\n padding-block: 0;\r\n border: none;\r\n background: transparent;\r\n background-color: transparent;\r\n color: var(--sky-text-secondary);\r\n font-size: var(--sky-font-size-xs);\r\n /* Take no in-flow space; inner text is centered on the border notch */\r\n height: 0;\r\n line-height: 0;\r\n overflow: visible;\r\n white-space: nowrap;\r\n pointer-events: none;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) legend.label .legend-text {\r\n display: inline-block;\r\n max-width: 100%;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n line-height: 1.2;\r\n transform: translateY(-50%);\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) .input-container:focus-within legend.label {\r\n color: var(--sky-input-color);\r\n font-size: var(--sky-font-size-xs);\r\n }\r\n\r\n /* Focus via real border — ::after would paint over the legend gap */\r\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper::after {\r\n content: none;\r\n display: none;\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper:has(input:focus),\r\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper:has(input:focus-visible),\r\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper:has(textarea:focus),\r\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper:has(textarea:focus-visible) {\r\n border-color: var(--sky-input-color);\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"][validationActive]:invalid) .input-wrapper {\r\n border-color: var(--sky-danger-primary);\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"][validationActive]:invalid) legend.label {\r\n color: var(--sky-danger-primary);\r\n }\r\n\r\n :host([data-sky-variant=\"fieldset\"][compact]) legend.label,\r\n :host([data-sky-variant=\"fieldset\"][compact]) .input-container:focus-within legend.label {\r\n font-size: var(--sky-font-size-xs);\r\n }\r\n\r\n /* Inside: label lives in the wrapper above the value row */\r\n :host([data-sky-variant=\"inside\"]) {\r\n --sky-input-height-inside: 40px;\r\n /* Two lines (label + value) need a bit more than single-line compact */\r\n --sky-input-height-inside-compact: 36px;\r\n --sky-input-inside-label-block: 2px;\r\n --sky-input-inside-value-min: 1.15em;\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-wrapper {\r\n height: auto;\r\n min-height: var(--sky-input-height-inside);\r\n align-items: center;\r\n padding-block: var(--sky-input-pad-y-sm, 0px);\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-wrapper[compact] {\r\n height: auto;\r\n min-height: var(--sky-input-height-inside-compact);\r\n padding-block: var(--sky-input-pad-y-sm, 0px);\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-inside-main {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n gap: 0;\r\n padding-block: var(--sky-input-inside-label-block);\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-inside-main > .label {\r\n margin: 0;\r\n padding-inline: var(--sky-input-pad-x);\r\n font-size: var(--sky-font-size-xs);\r\n line-height: 1.15;\r\n min-height: 0;\r\n color: var(--sky-text-secondary);\r\n pointer-events: none;\r\n overflow: visible;\r\n text-overflow: unset;\r\n flex-shrink: 0;\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"][compact]) .input-inside-main > .label {\r\n font-size: 0.6875rem; /* ~11px — denser than xs for two-line compact */\r\n line-height: 1.15;\r\n min-height: 0;\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"][compact]) .input-inside-row input,\r\n :host([data-sky-variant=\"inside\"][compact]) .input-inside-row textarea {\r\n font-size: var(--sky-font-size-sm);\r\n line-height: 1.15;\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-container:focus-within .input-inside-main > .label {\r\n color: var(--sky-input-color);\r\n font-size: var(--sky-font-size-xs);\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"][compact]) .input-container:focus-within .input-inside-main > .label {\r\n font-size: 0.6875rem;\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"][validationActive]:invalid) .input-inside-main > .label {\r\n color: var(--sky-danger-primary);\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-inside-row {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n width: 100%;\r\n min-height: var(--sky-input-inside-value-min);\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-wrapper:has(.icon-slot[filled].left) .input-inside-main > .label,\r\n :host([data-sky-variant=\"inside\"]) .input-wrapper:has(.input-affix.prefix) .input-inside-main > .label {\r\n padding-inline-start: 0;\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-inside-row input,\r\n :host([data-sky-variant=\"inside\"]) .input-inside-row textarea {\r\n padding-block: 0;\r\n height: auto;\r\n min-height: 0;\r\n line-height: 1.2;\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .input-wrapper:has(textarea) {\r\n height: auto;\r\n min-height: var(--sky-input-height-inside);\r\n align-items: flex-start;\r\n }\r\n\r\n :host([data-sky-variant=\"inside\"]) .icon-slot,\r\n :host([data-sky-variant=\"inside\"]) .icon-slot[filled] {\r\n align-self: center;\r\n height: auto;\r\n max-height: none;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n\r\n .input-container {\r\n position: relative;\r\n display: flex;\r\n flex-direction: column;\r\n width: inherit;\r\n cursor: text;\r\n }\r\n\r\n sky-icon {\r\n display: inline-block;\r\n width: 1em;\r\n height: 1em;\r\n }\r\n\r\n /* Outside labels only — never bump fieldset/inside fonts (clips legends) */\r\n .input-container:focus-within > .label {\r\n color: var(--sky-input-color);\r\n transition: color var(--sky-transition-normal, 200ms ease);\r\n }\r\n\r\n :host([data-sky-compact]) .input-container:focus-within > .label {\r\n font-size: var(--sky-font-size-xs);\r\n }\r\n\r\n .label {\r\n font-size: var(--sky-font-size-sm);\r\n margin-bottom: var(--sky-space-1, 4px);\r\n text-align: start;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n font-family: var(--sky-font);\r\n line-height: 1.35;\r\n }\r\n\r\n .input-wrapper {\r\n position: relative;\r\n display: flex;\r\n width: 100%;\r\n align-items: center;\r\n box-sizing: border-box;\r\n height: var(--sky-input-height);\r\n min-height: var(--sky-input-height);\r\n pointer-events: auto;\r\n background: var(--sky-glass-solid);\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n border-radius: var(--sky-radius-secondary);\r\n border: var(--sky-border-primary);\r\n box-shadow: var(--sky-box-shadow-primary);\r\n transition:\r\n border-color var(--sky-transition-normal, 200ms ease),\r\n box-shadow var(--sky-transition-normal, 200ms ease);\r\n }\r\n\r\n .input-wrapper::after {\r\n content: \"\";\r\n position: absolute;\r\n top: -1px;\r\n left: -1px;\r\n right: -1px;\r\n bottom: -1px;\r\n border-radius: inherit;\r\n border: 1px solid transparent;\r\n border-bottom-color: transparent;\r\n opacity: 0;\r\n transition:\r\n opacity 0.3s ease,\r\n border-color 0.3s ease;\r\n pointer-events: none;\r\n }\r\n\r\n .input-wrapper:has(input:focus-visible)::after,\r\n .input-wrapper:has(textarea:focus-visible)::after {\r\n opacity: 1;\r\n border-bottom-color: var(--sky-input-color);\r\n }\r\n\r\n .input-wrapper:has(input:focus)::after,\r\n .input-wrapper:has(textarea:focus)::after {\r\n opacity: 1;\r\n border-bottom-color: var(--sky-input-color);\r\n }\r\n\r\n :host([validationActive]:invalid) .input-wrapper::after {\r\n opacity: 1;\r\n border-bottom-color: var(--sky-danger-primary);\r\n }\r\n :host([validationActive]:invalid) .label {\r\n color: var(--sky-danger-primary);\r\n }\r\n\r\n :host([validationActive]:invalid) .icon-slot {\r\n color: var(--sky-danger-primary);\r\n }\r\n\r\n .input-wrapper[compact] {\r\n height: var(--sky-input-height-compact);\r\n min-height: var(--sky-input-height-compact);\r\n border: var(--sky-border-primary);\r\n border-radius: var(--sky-radius-primary);\r\n }\r\n\r\n input[type=\"date\"],\r\n input[type=\"time\"],\r\n input[type=\"week\"],\r\n input[type=\"month\"],\r\n input[type=\"datetime-local\"] {\r\n -webkit-appearance: none;\r\n -moz-appearance: none;\r\n appearance: none;\r\n background: none;\r\n border: none;\r\n font-family: inherit;\r\n }\r\n\r\n input[type=\"date\"]::-webkit-calendar-picker-indicator,\r\n input[type=\"time\"]::-webkit-calendar-picker-indicator,\r\n input[type=\"week\"]::-webkit-calendar-picker-indicator,\r\n input[type=\"month\"]::-webkit-calendar-picker-indicator,\r\n input[type=\"datetime-local\"]::-webkit-calendar-picker-indicator {\r\n display: none;\r\n }\r\n\r\n .input-wrapper:has(input:focus)[compact]::after {\r\n border: 1px solid var(--sky-input-color);\r\n }\r\n\r\n .toggle-password[compact] {\r\n font-size: var(--sky-font-size-md);\r\n }\r\n\r\n input {\r\n font-family: var(--sky-font);\r\n font-size: var(--sky-font-size-md);\r\n line-height: 1.2;\r\n text-align: left;\r\n transition: color var(--sky-transition-normal, 200ms ease);\r\n }\r\n\r\n input:-webkit-autofill {\r\n -webkit-text-fill-color: var(--sky-text-secondary, inherit) !important;\r\n transition: background-color 9999s ease-in-out 0s !important;\r\n }\r\n\r\n :dir(rtl) input {\r\n text-align: right;\r\n }\r\n\r\n input[type=\"number\"] {\r\n appearance: textfield;\r\n -moz-appearance: textfield;\r\n }\r\n\r\n input[type=\"number\"]::-webkit-inner-spin-button,\r\n input[type=\"number\"]::-webkit-outer-spin-button {\r\n -webkit-appearance: none;\r\n margin: 0;\r\n }\r\n .number-btn {\r\n display: flex;\r\n flex-shrink: 0;\r\n margin-inline-end: var(--sky-input-pad-x-sm);\r\n gap: var(--sky-input-gap);\r\n }\r\n\r\n :dir(rtl).number-btn {\r\n margin-inline-end: var(--sky-input-pad-x-sm);\r\n }\r\n\r\n .file-info {\r\n display: flex;\r\n justify-content: flex-end;\r\n font-size: var(--sky-font-size-xs);\r\n color: var(--sky-text-secondary);\r\n font-family: var(--sky-font);\r\n }\r\n\r\n :dir(rtl).file-info {\r\n flex-direction: row-reverse;\r\n }\r\n\r\n .increment-btn,\r\n .decrement-btn {\r\n background: var(--sky-glass-solid);\r\n color: var(--sky-text-primary);\r\n border: var(--sky-border-primary);\r\n border-radius: var(--sky-radius-primary);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: var(--sky-input-pad-x-xs) var(--sky-input-pad-x-sm);\r\n font-size: var(--sky-font-size-sm);\r\n cursor: pointer;\r\n transition: color var(--sky-transition-normal, 200ms ease);\r\n font-family: var(--sky-font);\r\n }\r\n\r\n .increment-btn:hover,\r\n .decrement-btn:hover {\r\n color: var(--sky-input-color);\r\n }\r\n\r\n .toggle-password {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-inline-end: var(--sky-input-pad-x-sm);\r\n font-size: var(--sky-font-size-lg);\r\n color: var(--sky-text-tertiary);\r\n cursor: pointer;\r\n }\r\n\r\n .toggle-password:hover {\r\n color: var(--sky-input-color);\r\n }\r\n\r\n input {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n border: none;\r\n outline: none;\r\n background: transparent;\r\n box-sizing: border-box;\r\n color: var(--sky-text-primary);\r\n padding-block: 0;\r\n padding-inline: var(--sky-input-pad-x);\r\n }\r\n\r\n input::placeholder {\r\n color: var(--sky-text-tertiary);\r\n }\r\n\r\n .input-affix {\r\n flex: 0 0 auto;\r\n font-family: var(--sky-font);\r\n font-size: var(--sky-font-size-md);\r\n font-weight: var(--sky-font-weight-medium);\r\n color: var(--sky-text-secondary);\r\n user-select: none;\r\n white-space: nowrap;\r\n line-height: 1;\r\n }\r\n\r\n .input-affix.prefix {\r\n padding-inline-start: var(--sky-input-pad-x);\r\n padding-inline-end: var(--sky-input-pad-x-sm);\r\n }\r\n\r\n .input-affix.suffix {\r\n padding-inline-start: var(--sky-input-pad-x-sm);\r\n padding-inline-end: var(--sky-input-pad-x);\r\n }\r\n\r\n .input-wrapper[compact] .input-affix {\r\n font-size: var(--sky-font-size-sm);\r\n }\r\n\r\n .input-wrapper:has(.input-affix.prefix) input,\r\n .input-wrapper:has(.input-affix.prefix) textarea {\r\n padding-inline-start: 0;\r\n }\r\n\r\n .input-wrapper:has(.icon-slot[filled].left) input,\r\n .input-wrapper:has(.icon-slot[filled].left) textarea {\r\n padding-inline-start: 0;\r\n }\r\n\r\n .input-wrapper:has(.icon-slot[filled].right) input,\r\n .input-wrapper:has(.icon-slot[filled].right) textarea,\r\n .input-wrapper:has(.clear-button) input,\r\n .input-wrapper:has(.clear-button) textarea,\r\n .input-wrapper:has(.toggle-password) input,\r\n .input-wrapper:has(.toggle-password) textarea,\r\n .input-wrapper:has(.number-btn) input,\r\n .input-wrapper:has(.loading-indicator) input {\r\n padding-inline-end: 0;\r\n }\r\n\r\n .input-wrapper:has(.input-affix.suffix) input,\r\n .input-wrapper:has(.input-affix.suffix) textarea {\r\n padding-inline-end: 0;\r\n }\r\n\r\n .custom-file-label__text {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n color: var(--sky-text-tertiary);\r\n padding-inline-end: var(--sky-input-pad-x);\r\n }\r\n\r\n .custom-file-label:not(:has(.input-affix.prefix)) .custom-file-label__text {\r\n padding-inline-start: var(--sky-input-pad-x);\r\n }\r\n\r\n .custom-file-label__text[data-filled] {\r\n color: var(--sky-text-primary);\r\n }\r\n\r\n .icon-slot {\r\n display: none;\r\n justify-content: center;\r\n font-size: var(--sky-font-size-xl);\r\n align-items: center;\r\n color: var(--sky-text-primary);\r\n height: inherit;\r\n max-height: 100%;\r\n box-sizing: border-box;\r\n flex: 0 0 var(--sky-input-icon-width);\r\n width: var(--sky-input-icon-width);\r\n min-width: var(--sky-input-icon-width);\r\n padding: 0;\r\n background: none;\r\n border: none;\r\n transition: color var(--sky-transition-normal, 200ms ease);\r\n }\r\n\r\n .input-wrapper:has(textarea) .icon-slot {\r\n max-height: var(--sky-input-height);\r\n }\r\n\r\n .icon-slot[filled] {\r\n display: flex;\r\n flex-shrink: 0;\r\n cursor: pointer;\r\n }\r\n\r\n .icon-slot[filled]:hover,\r\n .icon-slot[filled]:active,\r\n .icon-slot.focused {\r\n color: var(--sky-input-color);\r\n }\r\n\r\n .progress-message {\r\n pointer-events: none;\r\n width: 100%;\r\n overflow: hidden;\r\n white-space: nowrap;\r\n text-overflow: ellipsis;\r\n font-size: var(--sky-font-size-sm);\r\n margin-inline-start: var(--sky-input-pad-x-sm);\r\n font-family: var(--sky-font);\r\n }\r\n\r\n :dir(rtl) .progress-message {\r\n margin-inline-start: unset;\r\n margin-inline-end: var(--sky-input-pad-x-sm);\r\n }\r\n\r\n .error-list {\r\n list-style: none;\r\n margin: 0;\r\n padding: 0;\r\n width: 100%;\r\n }\r\n\r\n .error {\r\n font-size: var(--sky-font-size-xs);\r\n color: var(--sky-danger-primary);\r\n text-align: start;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n font-family: var(--sky-font);\r\n }\r\n\r\n ::slotted(.icon-slot) {\r\n display: block;\r\n }\r\n\r\n .input-wrapper[loading] input {\r\n cursor: wait;\r\n }\r\n\r\n .loading-indicator {\r\n flex-shrink: 0;\r\n margin-inline-end: var(--sky-input-pad-x-sm);\r\n width: 16px;\r\n height: 16px;\r\n border: 2px solid var(--sky-hover-primary);\r\n border-top: 2px solid var(--sky-input-color);\r\n border-radius: var(--sky-radius-full);\r\n animation: spin 1s linear infinite;\r\n }\r\n\r\n .loading-indicator[compact] {\r\n width: 10px;\r\n height: 10px;\r\n }\r\n\r\n .input-wrapper[loading] .icon-slot.right {\r\n display: none;\r\n }\r\n\r\n @keyframes spin {\r\n 0% {\r\n transform: rotate(0deg);\r\n }\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n }\r\n\r\n .clear-button {\r\n flex-shrink: 0;\r\n margin-inline-end: var(--sky-input-pad-x-sm);\r\n border: none;\r\n font-size: var(--sky-font-size-xl);\r\n color: var(--sky-input-color);\r\n background-color: var(--sky-hover-primary);\r\n border-radius: var(--sky-radius-full);\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n cursor: pointer;\r\n transition: color var(--sky-transition-normal, 200ms ease);\r\n }\r\n\r\n .clear-button[compact] {\r\n font-size: var(--sky-font-size-md);\r\n }\r\n\r\n .clear-button[loading] {\r\n opacity: 0.6;\r\n pointer-events: none;\r\n }\r\n\r\n input[type=\"file\"] {\r\n position: absolute;\r\n width: 100%;\r\n height: 100%;\r\n opacity: 0;\r\n pointer-events: auto;\r\n z-index: -1;\r\n }\r\n\r\n .custom-file-label {\r\n position: relative;\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n gap: var(--sky-input-gap);\r\n text-align: left;\r\n padding: 0;\r\n color: var(--sky-input-color);\r\n border-radius: var(--sky-radius-secondary);\r\n overflow: hidden;\r\n white-space: nowrap;\r\n text-overflow: ellipsis;\r\n cursor: pointer;\r\n transition:\r\n background 0.3s ease,\r\n padding 0.3s ease;\r\n font-family: var(--sky-font);\r\n }\r\n\r\n .custom-file-label:hover .custom-file-label__text {\r\n padding-inline-start: var(--sky-input-pad-x-sm);\r\n }\r\n\r\n .custom-file-label:empty::after {\r\n content: \"Choose file\";\r\n color: var(--sky-input-color);\r\n }\r\n\r\n .clear-button:hover {\r\n color: var(--sky-danger-primary);\r\n }\r\n\r\n textarea {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n border: none;\r\n outline: none;\r\n background: transparent;\r\n box-sizing: border-box;\r\n color: var(--sky-text-primary);\r\n padding: var(--sky-input-pad-y) var(--sky-input-pad-x);\r\n resize: none;\r\n overflow: auto;\r\n font-family: var(--sky-font);\r\n }\r\n\r\n textarea[resizable=\"vertical\"] {\r\n resize: vertical;\r\n }\r\n\r\n textarea[resizable=\"both\"] {\r\n resize: both;\r\n }\r\n\r\n textarea {\r\n scrollbar-width: thin;\r\n scrollbar-color: var(--sky-scrollbar-thumb) var(--sky-scrollbar-track);\r\n }\r\n\r\n textarea::-webkit-scrollbar {\r\n width: 6px;\r\n height: 6px;\r\n }\r\n\r\n textarea::-webkit-scrollbar-thumb {\r\n background-color: var(--sky-scrollbar-thumb);\r\n border-radius: var(--sky-radius-full, 9999px);\r\n transition: background-color var(--sky-duration-normal, 200ms)\r\n var(--sky-ease-default, ease);\r\n cursor: grab;\r\n }\r\n\r\n textarea::-webkit-scrollbar-thumb:hover {\r\n background-color: var(--sky-scrollbar-thumb-hover);\r\n }\r\n\r\n textarea::-webkit-scrollbar-track {\r\n background: var(--sky-scrollbar-track);\r\n }\r\n\r\n textarea::-webkit-scrollbar-button {\r\n display: none;\r\n }\r\n\r\n textarea::placeholder {\r\n color: var(--sky-text-tertiary);\r\n }\r\n\r\n .input-wrapper:has(textarea) {\r\n height: calc((var(--rows)) * 23px);\r\n align-items: flex-start;\r\n }\r\n textarea {\r\n height: calc((var(--rows)) * 23px);\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .loading-indicator {\r\n animation: none;\r\n }\r\n\r\n .input-container:focus-within > .label,\r\n .input-wrapper,\r\n .icon-slot,\r\n .increment-btn,\r\n .decrement-btn,\r\n .clear-button,\r\n input,\r\n textarea,\r\n .custom-file-label {\r\n transition: none;\r\n }\r\n }\r\n `;\r\n\r\n static override shadowRootOptions = {\r\n ...LitElement.shadowRootOptions,\r\n delegatesFocus: true,\r\n };\r\n\r\n override connectedCallback(): void {\r\n super.connectedCallback();\r\n this.autofillGuardActive = this.type === \"search\";\r\n\r\n if (!this.hasAttribute(\"tabindex\")) {\r\n this.tabIndex = this.disabled ? -1 : 0;\r\n }\r\n\r\n if (this.hasUpdated) {\r\n this._setupIconSlots();\r\n }\r\n }\r\n\r\n override disconnectedCallback(): void {\r\n this._leftIconSlot?.removeEventListener(\r\n \"slotchange\",\r\n this._onLeftIconSlotChange,\r\n );\r\n this._rightIconSlot?.removeEventListener(\r\n \"slotchange\",\r\n this._onRightIconSlotChange,\r\n );\r\n this._leftIconSlot = null;\r\n this._rightIconSlot = null;\r\n super.disconnectedCallback();\r\n }\r\n\r\n private _setupIconSlots(): void {\r\n if (!this._leftIconSlot) {\r\n this._leftIconSlot =\r\n this.shadowRoot?.querySelector<HTMLSlotElement>(\r\n 'slot[name=\"icon-left\"]',\r\n ) ?? null;\r\n this._leftIconSlot?.addEventListener(\r\n \"slotchange\",\r\n this._onLeftIconSlotChange,\r\n );\r\n }\r\n if (!this._rightIconSlot) {\r\n this._rightIconSlot =\r\n this.shadowRoot?.querySelector<HTMLSlotElement>(\r\n 'slot[name=\"icon-right\"]',\r\n ) ?? null;\r\n this._rightIconSlot?.addEventListener(\r\n \"slotchange\",\r\n this._onRightIconSlotChange,\r\n );\r\n }\r\n this._wireIconSlot(\"left\", this._leftIconSlot);\r\n this._wireIconSlot(\"right\", this._rightIconSlot);\r\n }\r\n\r\n private _wireIconSlot(\r\n side: \"left\" | \"right\",\r\n slot: HTMLSlotElement | null,\r\n ): void {\r\n if (!slot) return;\r\n for (const node of slot.assignedElements({ flatten: true })) {\r\n if (!(node instanceof HTMLElement)) continue;\r\n if (this._iconClickWired.has(node)) continue;\r\n this._iconClickWired.add(node);\r\n node.addEventListener(\"click\", () => this.handleIconClick(side));\r\n }\r\n }\r\n\r\n override firstUpdated(\r\n _changedProperties: Map<string | number | symbol, unknown>,\r\n ) {\r\n super.firstUpdated(_changedProperties);\r\n\r\n // default/reset value\r\n this.captureDefaultValue(this.value as string);\r\n\r\n // initial sync into form\r\n this.syncFormValue();\r\n this.syncValidity();\r\n\r\n this._setupIconSlots();\r\n }\r\n\r\n override willUpdate(\r\n changedProperties: Map<string | number | symbol, unknown>,\r\n ) {\r\n if (\r\n changedProperties.has(\"validations\") &&\r\n Array.isArray(this.validations)\r\n ) {\r\n this.validationStatus = this.validations.map(() => false);\r\n }\r\n\r\n if (changedProperties.has(\"value\") && this.type === \"file\") {\r\n if (this.value == null || String(this.value).trim() === \"\") {\r\n this.selectedFileName = \"\";\r\n this.selectedFiles = [];\r\n this.totalFileSize = 0;\r\n this.selectedFileCount = 0;\r\n this.filePreview = null;\r\n } else if (!this.selectedFileName) {\r\n this.selectedFileName = this.value as string;\r\n }\r\n }\r\n if (changedProperties.has(\"type\") && this.type === \"search\") {\r\n this.autofillGuardActive = true;\r\n }\r\n }\r\n\r\n override updated(changedProperties: Map<string | number | symbol, unknown>) {\r\n super.updated(changedProperties);\r\n\r\n // After PresetController hostUpdate — keep host attrs in sync with props.\r\n this.setAttribute(\"data-sky-variant\", this.variant);\r\n this.toggleAttribute(\"data-sky-compact\", this.compact);\r\n\r\n if (this.color) {\r\n this.style.setProperty(\r\n \"--sky-input-color\",\r\n resolveColor(this.color),\r\n );\r\n }\r\n\r\n if (changedProperties.has(\"rows\")) {\r\n const inputWrapper = this.inputWrapperEl;\r\n if (inputWrapper) {\r\n inputWrapper.style.setProperty(\"--rows\", String(this.rows));\r\n }\r\n }\r\n\r\n if (\r\n changedProperties.has(\"value\") ||\r\n changedProperties.has(\"selectedFiles\") ||\r\n changedProperties.has(\"selectedFileName\") ||\r\n changedProperties.has(\"type\") ||\r\n changedProperties.has(\"multiple\") ||\r\n changedProperties.has(\"name\") ||\r\n changedProperties.has(\"disabled\")\r\n ) {\r\n this.syncFormValue();\r\n }\r\n\r\n if (\r\n changedProperties.has(\"value\") ||\r\n changedProperties.has(\"selectedFiles\") ||\r\n changedProperties.has(\"selectedFileName\") ||\r\n changedProperties.has(\"validationErrors\") ||\r\n changedProperties.has(\"required\") ||\r\n changedProperties.has(\"disabled\") ||\r\n changedProperties.has(\"readonly\")\r\n ) {\r\n this.syncValidity();\r\n }\r\n }\r\n\r\n /** @protected */\r\n protected override getFormValue(): string | File | FormData | null {\r\n if (!this.name) return null;\r\n\r\n if (this.type === \"file\") {\r\n if (!this.selectedFiles || this.selectedFiles.length === 0) return null;\r\n\r\n if (this.multiple) {\r\n const fd = new FormData();\r\n for (const f of this.selectedFiles) fd.append(this.name, f);\r\n return fd;\r\n }\r\n return this.selectedFiles[0];\r\n }\r\n\r\n return this.value as string ?? \"\";\r\n }\r\n\r\n /** @protected */\r\n protected override setValueFromFormState(\r\n state: string | File | FormData | null,\r\n ) {\r\n // For SkyInput, state restore is typically string\r\n if (typeof state === \"string\") {\r\n this.value = state;\r\n // for textarea/input UI to refresh, you already use live()\r\n return;\r\n }\r\n\r\n // For file state restore: browsers usually won't restore actual File objects for security.\r\n // So do a safe reset:\r\n this.value = \"\";\r\n this.selectedFileName = \"\";\r\n this.selectedFiles = [];\r\n this.totalFileSize = 0;\r\n this.selectedFileCount = 0;\r\n this.filePreview = null;\r\n }\r\n\r\n /** @protected */\r\n protected override getValidityAnchor(): HTMLElement | undefined {\r\n return this;\r\n }\r\n\r\n /** @protected */\r\n protected override isEmpty(): boolean {\r\n if (this.type === \"file\") {\r\n return !this.selectedFiles || this.selectedFiles.length === 0;\r\n }\r\n return !this.value || this.value.toString().trim() === \"\";\r\n }\r\n\r\n /** @protected */\r\n protected override getCustomErrorMessage(): string {\r\n if (!this.validationErrors?.length) return \"\";\r\n\r\n // single message that includes all\r\n if (this.errorDisplayMode === \"all\") {\r\n return this.validationErrors.join(\"\\n\");\r\n }\r\n\r\n // single mode\r\n return this.validationErrors[0];\r\n }\r\n\r\n /** @protected */\r\n protected override getNativeControl(): HTMLElement | null {\r\n if (this.type === \"textarea\") {\r\n return this.shadowRoot?.querySelector(\r\n \"textarea\",\r\n ) as HTMLTextAreaElement | null;\r\n }\r\n // for all other types (text/email/password/date/...)\r\n return this.shadowRoot?.querySelector(\"input\") as HTMLInputElement | null;\r\n }\r\n\r\n /** @protected */\r\n protected override onNativeValueMutated(native: any): void {\r\n // File input value is managed via change handler; do not mirror native.value here.\r\n if (this.type !== \"file\") {\r\n this.value = native?.value ?? \"\";\r\n }\r\n // keep SkyInput custom validations in sync\r\n this.validateInput();\r\n }\r\n\r\n /**\r\n * Resets the input field to its initial state.\r\n * @public\r\n */\r\n reset() {\r\n this.value = \"\";\r\n this.selectedFileName = \"\";\r\n this.filePreview = null;\r\n this.selectedFiles = [];\r\n this.selectedFileCount = 0;\r\n this.validationErrors = [];\r\n this.typingStarted = false;\r\n this.validationActive = false;\r\n this.selectedFileCount = 0;\r\n this.totalFileSize = 0;\r\n }\r\n\r\n /** @private */\r\n private get nativeRequiredMessage(): string {\r\n if (!this.validationActive) return \"\";\r\n if (this.disabled) return \"\";\r\n if (this.required && this.isEmpty())\r\n return this.requiredMessage || \"This field is required.\";\r\n return \"\";\r\n }\r\n\r\n /** @private */\r\n private getEmittedValue(): string | number {\r\n if (this.type !== \"number\") return this.value as string;\r\n\r\n // allow empty to stay empty (important for clearing)\r\n if (this.value === \"\" || this.value == null) return \"\";\r\n\r\n const n = Number(this.value);\r\n // if user is still typing an invalid numeric token, keep as string\r\n return Number.isFinite(n) ? n : this.value as string;\r\n }\r\n\r\n /**\r\n * Clears the input value and resets typing state.\r\n * @public\r\n */\r\n handleClear() {\r\n if (this.disabled || this.readonly) {\r\n return;\r\n }\r\n this.reset();\r\n this.validationActive = true;\r\n this.validateInput();\r\n this.dispatchEvent(\r\n new CustomEvent<SkyInputValueChangedDetail>(\"value-changed\", {\r\n detail: { value: this.getEmittedValue() },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n this.dispatchEvent(\r\n new CustomEvent<SkyInputValueClearedDetail>(\"value-cleared\", {\r\n detail: { value: this.getEmittedValue() },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n }\r\n\r\n /**\r\n * Handles the `change` event triggered by the file input element.\r\n * @param {Event} event - The event object generated by the file input element when files are selected.\r\n * @public\r\n */\r\n handleFileChange(event: Event): void {\r\n if (this.disabled || this.readonly) {\r\n return;\r\n }\r\n const input = event.target as HTMLInputElement;\r\n const files = input.files;\r\n\r\n if (files && files.length) {\r\n const fileList: File[] = Array.from(files);\r\n this.selectedFiles = fileList;\r\n this.selectedFileName = fileList\r\n .map((file: File) => file.name)\r\n .join(\", \");\r\n this.value = this.selectedFileName;\r\n\r\n this.syncFormValue();\r\n this.syncValidity();\r\n\r\n const totalSize: number = fileList.reduce(\r\n (total: number, file: File) => total + file.size,\r\n 0,\r\n );\r\n this.totalFileSize = totalSize;\r\n\r\n this.selectedFileCount = fileList.length;\r\n\r\n if (fileList[0].type.startsWith(\"image/\")) {\r\n const reader = new FileReader();\r\n reader.onload = (e: ProgressEvent<FileReader>) => {\r\n if (e.target) {\r\n this.filePreview = e.target.result;\r\n }\r\n };\r\n reader.readAsDataURL(fileList[0]);\r\n } else {\r\n this.filePreview = null;\r\n }\r\n\r\n this.reemitNativeEvent(\"change\", event);\r\n this.reemitNativeEvent(\"input\", event);\r\n\r\n this.dispatchEvent(\r\n new CustomEvent<SkyInputFileSelectedDetail>(\"file-selected\", {\r\n detail: {\r\n files: fileList,\r\n fileName: this.selectedFileName,\r\n totalSize,\r\n fileCount: this.selectedFileCount,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n\r\n this.validateInput();\r\n } else {\r\n this.value = \"\";\r\n this.filePreview = null;\r\n this.totalFileSize = 0;\r\n this.selectedFileCount = 0;\r\n this.selectedFiles = [];\r\n this.validateInput();\r\n }\r\n }\r\n\r\n /**\r\n * Handles the keydown event for the input component.\r\n * @param event - The keyboard event triggered by the user.\r\n * @private\r\n */\r\n private handleKeydown(event: KeyboardEvent) {\r\n if (this.disabled || this.readonly) {\r\n return;\r\n }\r\n if (event.key === \"Enter\" && this.type === \"file\") {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.triggerNativeDropdown();\r\n }\r\n }\r\n\r\n /**\r\n * Gets the current file preview.\r\n * @returns The preview of the file, as stored in `filePreview`.\r\n * @public\r\n */\r\n get preview() {\r\n return this.filePreview;\r\n }\r\n\r\n /**\r\n * Handles the input event for the input field.\r\n * @param {Event} event - The input event triggered by user interaction.\r\n * @public\r\n */\r\n handleInput(event: Event) {\r\n event.stopPropagation();\r\n\r\n if (this.disabled || this.readonly) {\r\n event.preventDefault();\r\n return;\r\n }\r\n\r\n this.value = (event.target as HTMLInputElement | HTMLTextAreaElement).value;\r\n\r\n this.syncFormValue();\r\n this.syncValidity();\r\n\r\n if (!this.typingStarted) this.typingStarted = true;\r\n\r\n this.validateInput();\r\n\r\n this.reemitNativeEvent(\"input\", event);\r\n\r\n this.dispatchEvent(\r\n new CustomEvent<SkyInputValueChangedDetail>(\"value-changed\", {\r\n detail: { value: this.getEmittedValue() },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n }\r\n\r\n /**\r\n * Handles the focus event for the input field.\r\n * @public\r\n */\r\n handleFocus(event: Event) {\r\n event.stopPropagation();\r\n this.releaseAutofillGuard();\r\n this.focused = true;\r\n this.reemitNativeEvent(\"focus\", event);\r\n }\r\n\r\n /** Chrome may autofill saved usernames into filter fields; readonly until interaction blocks that. */\r\n private releaseAutofillGuard(): void {\r\n if (!this.autofillGuardActive) return;\r\n this.autofillGuardActive = false;\r\n }\r\n\r\n private handleAutofillGuardPointerDown(event: Event): void {\r\n this.releaseAutofillGuard();\r\n event.stopPropagation();\r\n }\r\n\r\n /** @protected */\r\n protected override onFormReset() {\r\n this.setValueFromFormState(this.defaultValue);\r\n\r\n this.validationActive = false;\r\n this.invalid = false;\r\n this.typingStarted = false;\r\n this.validationErrors = [];\r\n this.validationStatus = [];\r\n\r\n if (this.type === \"file\") {\r\n this.selectedFiles = [];\r\n this.selectedFileName = \"\";\r\n this.totalFileSize = 0;\r\n this.selectedFileCount = 0;\r\n this.filePreview = null;\r\n }\r\n\r\n if (this.type === \"search\") {\r\n this.autofillGuardActive = true;\r\n }\r\n }\r\n\r\n /**\r\n * Handles the blur event for the input field.\r\n * @public\r\n */\r\n handleBlur(event: Event) {\r\n event.stopPropagation();\r\n this.validationActive = true;\r\n this.focused = false;\r\n this.reemitNativeEvent(\"blur\", event);\r\n }\r\n\r\n /** @protected */\r\n protected override validateForForm(): string {\r\n // run your `this.validations` against current value even if validationActive is false\r\n const payload =\r\n this.type === \"file\" ? (this.selectedFiles ?? []) : (this.value ?? \"\");\r\n\r\n for (const v of this.validations ?? []) {\r\n const r = v(payload as string | File[]);\r\n if (r !== true) return typeof r === \"string\" ? r : \"Invalid value.\";\r\n }\r\n\r\n return \"\";\r\n }\r\n\r\n /**\r\n * Validates the input value against the configured validation rules.\r\n * @returns {boolean} True if validation passes, false otherwise.\r\n * @public\r\n */\r\n validateInput(): boolean {\r\n // reset\r\n this.validationErrors = [];\r\n this.validationStatus = [];\r\n\r\n const isFileInput = this.type === \"file\";\r\n const isEmpty = isFileInput\r\n ? !this.selectedFiles || this.selectedFiles.length === 0\r\n : !this.value || this.value.toString().trim() === \"\";\r\n\r\n // 1) If empty + required -> let SkyFormControlBase handle native required\r\n // (do NOT push required into validationErrors)\r\n if (this.required && isEmpty) {\r\n this.syncValidity(); // will set valueMissing\r\n }\r\n\r\n // 2) Run custom validations only if there is something to validate\r\n if (Array.isArray(this.validations) && this.validations.length) {\r\n const payload: string | File[] = isFileInput\r\n ? (this.selectedFiles ?? [])\r\n : (this.value as string ?? \"\");\r\n\r\n this.validationStatus = this.validations.map((validation, index) => {\r\n try {\r\n if (typeof validation !== \"function\") {\r\n throw new Error(`Validation at index ${index} must be a function.`);\r\n }\r\n\r\n const result = validation(payload);\r\n\r\n if (result !== true) {\r\n this.validationErrors.push(\r\n typeof result === \"string\"\r\n ? result\r\n : `Validation ${index} failed.`,\r\n );\r\n return false;\r\n }\r\n\r\n return true;\r\n } catch (error) {\r\n const message =\r\n typeof error === \"object\" && error !== null && \"message\" in error\r\n ? String((error as any).message)\r\n : typeof error === \"string\"\r\n ? error\r\n : \"Unknown error\";\r\n\r\n this.validationErrors.push(\r\n `Error in validation ${index}: ${message}`,\r\n );\r\n return false;\r\n }\r\n });\r\n }\r\n // 3) Dispatch event with all accumulated errors\r\n this.dispatchEvent(\r\n new CustomEvent<SkyInputValidationErrorDetail>(\"validation-error\", {\r\n detail: { errors: this.validationErrors },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n\r\n this.syncValidity();\r\n\r\n const isValid = this.validationErrors.length === 0;\r\n this.invalid = !isValid;\r\n\r\n return isValid;\r\n }\r\n\r\n /**\r\n * Retrieves validation error messages based on the configured error display mode.\r\n * @returns {Array} - An array of error messages to display.\r\n * @private\r\n */\r\n private getErrorMessages() {\r\n switch (this.errorDisplayMode) {\r\n case \"single\":\r\n return this.validationErrors.slice(0, 1);\r\n case \"all\":\r\n return this.validationErrors;\r\n case \"none\":\r\n default:\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Handles click events for the left or right icon slots.\r\n * @param {String} position - The position of the icon (\"left\" or \"right\").\r\n * @param {Event|null} event - The original event triggered by the click (optional).\r\n * @public\r\n */\r\n handleIconClick(position: \"left\" | \"right\", event: Event | null = null) {\r\n this.dispatchEvent(\r\n new CustomEvent<SkyInputIconClickDetail>(`${position}-icon-click`, {\r\n detail: {\r\n position,\r\n eventType: event ? event.type : null,\r\n eventData: event,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n }\r\n\r\n /**\r\n * Formats a file size in bytes into a human-readable string.\r\n * @param {number} bytes - The file size in bytes.\r\n * @returns {string} - The formatted file size string.\r\n * @public\r\n */\r\n formatFileSize(bytes: number): string {\r\n if (bytes === 0) return \"0 Bytes\";\r\n\r\n const k = 1024;\r\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n\r\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;\r\n }\r\n\r\n /**\r\n * Increments the input value by the specified step, respecting min/max constraints.\r\n * @private\r\n */\r\n private incrementValue() {\r\n if (this.disabled || this.readonly) return;\r\n const currentValue = parseFloat(this.value as string) || 0;\r\n const step = parseFloat(this.step ?? \"\") || 1;\r\n const max = this.max ? parseFloat(this.max) : Infinity;\r\n\r\n if (currentValue + step <= max) {\r\n this.value = (currentValue + step).toString();\r\n this.validateInput();\r\n this.dispatchEvent(\r\n new CustomEvent<SkyInputValueChangedDetail>(\"value-changed\", {\r\n detail: { value: this.getEmittedValue() },\r\n }),\r\n );\r\n }\r\n this.refocusInput();\r\n }\r\n\r\n /**\r\n * Decrements the input value by the specified step, respecting min/max constraints.\r\n * @private\r\n */\r\n private decrementValue() {\r\n if (this.disabled || this.readonly) return;\r\n const currentValue = parseFloat(this.value as string) || 0;\r\n const step = parseFloat(this.step ?? \"\") || 1;\r\n const min = this.min ? parseFloat(this.min) : -Infinity;\r\n\r\n if (currentValue - step >= min) {\r\n this.value = (currentValue - step).toString();\r\n this.validateInput();\r\n this.dispatchEvent(\r\n new CustomEvent<SkyInputValueChangedDetail>(\"value-changed\", {\r\n detail: { value: this.getEmittedValue() },\r\n }),\r\n );\r\n }\r\n this.refocusInput();\r\n }\r\n\r\n /**\r\n * Renders validation error messages if applicable.\r\n * @returns {TemplateResult|null} - The rendered error messages or null.\r\n * @private\r\n */\r\n private renderValidationErrors() {\r\n\r\n if (!this.showErrors || !this.validationActive) return null;\r\n\r\n const requiredMsg = this.nativeRequiredMessage;\r\n const customMsgs = this.getErrorMessages(); // already respects errorDisplayMode for custom\r\n\r\n let msgs: string[] = [];\r\n\r\n if (this.errorDisplayMode === \"single\") {\r\n // Required message takes precedence over custom errors.\r\n if (requiredMsg) msgs = [requiredMsg];\r\n else if (customMsgs.length) msgs = [customMsgs[0]];\r\n } else {\r\n msgs = requiredMsg ? [requiredMsg, ...customMsgs] : customMsgs;\r\n }\r\n\r\n if (!msgs.length) return null;\r\n\r\n const errId = `${this.id || \"sky-input\"}-errors`;\r\n\r\n return html`\r\n <div class=\"progress-message\">\r\n <ul id=${errId} class=\"error-list\" part=\"error-list\">\r\n ${msgs.map((m) => html`<li class=\"error\" part=\"error\">${m}</li>`)}\r\n </ul>\r\n </div>\r\n `;\r\n }\r\n\r\n /**\r\n * Toggles the visibility of the password input.\r\n * @public\r\n */\r\n togglePasswordVisibility() {\r\n this.showPassword = !this.showPassword;\r\n }\r\n\r\n public focusInput(): void {\r\n const input = this.nativeInputEl;\r\n if (\r\n input &&\r\n typeof (input as HTMLInputElement | HTMLTextAreaElement).focus === \"function\"\r\n ) {\r\n (input as HTMLInputElement | HTMLTextAreaElement).focus();\r\n }\r\n }\r\n\r\n /**\r\n * Handles click events on the input wrapper.\r\n * @param {Event} event - The original click event.\r\n * @private\r\n */\r\n private handleWrapperClick(event: Event) {\r\n event.stopPropagation();\r\n if (this.disabled) return;\r\n const input = this.nativeInputEl;\r\n if (\r\n input &&\r\n typeof (input as HTMLInputElement | HTMLTextAreaElement).focus ===\r\n \"function\"\r\n ) {\r\n (input as HTMLInputElement | HTMLTextAreaElement).focus();\r\n }\r\n }\r\n\r\n /** @private */\r\n private get isInvalid(): boolean {\r\n return (\r\n this.matches(\":invalid\") ||\r\n (this.validationActive && this.validationErrors.length > 0)\r\n );\r\n }\r\n\r\n /** @private */\r\n private get describedById(): string | undefined {\r\n return (\r\n this.ariaDescribedby ??\r\n (this.showErrors ? `${this.id || \"sky-input\"}-errors` : undefined)\r\n );\r\n }\r\n\r\n /**\r\n * Refocuses the input element.\r\n * @private\r\n */\r\n private refocusInput() {\r\n const el = this.shadowRoot?.querySelector(\r\n \"input\",\r\n ) as HTMLInputElement | null;\r\n el?.focus({ preventScroll: true });\r\n }\r\n\r\n /**\r\n * Keeps the input focused when interacting with related controls.\r\n * @param {Event} e - The original event.\r\n * @private\r\n */\r\n private keepInputFocused = (e: Event) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.refocusInput();\r\n };\r\n\r\n /**\r\n * Triggers the native dropdown for date/time/file inputs.\r\n * @private\r\n */\r\n private triggerNativeDropdown() {\r\n if (this.disabled || this.readonly) return;\r\n const input = this.shadowRoot?.querySelector(\r\n 'input[type=\"date\"], input[type=\"time\"], input[type=\"week\"], input[type=\"month\"], input[type=\"datetime-local\"], input[type=\"file\"]',\r\n ) as HTMLInputElement | null;\r\n\r\n if (input) {\r\n if (this.type === \"file\") {\r\n input.click();\r\n } else {\r\n this.showPicker();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Filter/search inputs (`type=\"search\"`) are rendered as plain text fields so\r\n * Chrome does not treat them as login username targets. Credential autofill is\r\n * further blocked with readonly-until-focus (Chrome ignores autocomplete tokens).\r\n */\r\n private isFilterSearchInput(): boolean {\r\n return this.type === \"search\";\r\n }\r\n\r\n private nativeAutocomplete(): string {\r\n if (this.isFilterSearchInput()) {\r\n return \"off\";\r\n }\r\n return this.autocomplete;\r\n }\r\n\r\n private nativeTextInputType(isPassword: boolean): string {\r\n if (isPassword && this.showPassword) return \"text\";\r\n if (this.isFilterSearchInput()) return \"text\";\r\n return this.type;\r\n }\r\n\r\n private nativeInputMode(): string | undefined {\r\n if (this.inputmode) return this.inputmode;\r\n if (this.isFilterSearchInput()) return \"search\";\r\n return undefined;\r\n }\r\n\r\n private nativeEnterKeyHint():\r\n | \"enter\"\r\n | \"done\"\r\n | \"go\"\r\n | \"next\"\r\n | \"previous\"\r\n | \"search\"\r\n | \"send\"\r\n | undefined {\r\n if (this.enterkeyhint) {\r\n return this.enterkeyhint as\r\n | \"enter\"\r\n | \"done\"\r\n | \"go\"\r\n | \"next\"\r\n | \"previous\"\r\n | \"search\"\r\n | \"send\";\r\n }\r\n if (this.isFilterSearchInput()) return \"search\";\r\n return undefined;\r\n }\r\n\r\n private nativeInputRole(): string | undefined {\r\n if (this.inputRole) return this.inputRole;\r\n if (this.type === \"search\") return \"searchbox\";\r\n return undefined;\r\n }\r\n\r\n private affixColorStyle(color: string) {\r\n const trimmed = String(color ?? \"\").trim();\r\n if (!trimmed) return undefined;\r\n return { color: resolveColor(trimmed) };\r\n }\r\n\r\n private renderInputAffix(kind: \"prefix\" | \"suffix\") {\r\n const value = kind === \"prefix\" ? this.prefix : this.suffix;\r\n if (!String(value ?? \"\").length) return nothing;\r\n const color = kind === \"prefix\" ? this.prefixColor : this.suffixColor;\r\n const style = this.affixColorStyle(color);\r\n return html`<span\r\n class=\"input-affix ${kind}\"\r\n part=\"input-${kind}\"\r\n style=${style ? styleMap(style) : nothing}\r\n >${value}</span\r\n >`;\r\n }\r\n\r\n override render() {\r\n const isFileInput = this.type === \"file\";\r\n const isTextarea = this.type === \"textarea\";\r\n const isNumberInput = this.type === \"number\";\r\n const isPassword = this.type === \"password\";\r\n const supportsInlineAffixes = !isFileInput && !isTextarea;\r\n\r\n const hasLeftSlot = !!this.querySelector('[slot=\"icon-left\"]');\r\n const hasRightSlot = !!this.querySelector('[slot=\"icon-right\"]');\r\n\r\n let autoIcon: unknown = null;\r\n if (this.type === \"date\")\r\n autoIcon = html`<sky-icon icon=\"ion:calendar\"></sky-icon>`;\r\n else if (this.type === \"time\")\r\n autoIcon = html`<sky-icon icon=\"ion:time\"></sky-icon>`;\r\n else if (this.type === \"week\")\r\n autoIcon = html`<sky-icon icon=\"ion:calendar\"></sky-icon>`;\r\n else if (this.type === \"month\")\r\n autoIcon = html`<sky-icon icon=\"ion:calendar\"></sky-icon>`;\r\n else if (this.type === \"datetime-local\")\r\n autoIcon = html`<sky-icon icon=\"ion:time\"></sky-icon>`;\r\n\r\n const showFilePreview = this.filePreview && (hasLeftSlot || hasRightSlot);\r\n const showAutoIconInLeft = this.autofillIconSlot === \"left\" && autoIcon;\r\n const showAutoIconInRight = this.autofillIconSlot === \"right\" && autoIcon;\r\n\r\n const ImagePreview = () => html`\r\n <img\r\n src=${ifDefined(\r\n typeof this.filePreview === \"string\" ? this.filePreview : undefined,\r\n )}\r\n alt=\"Preview\"\r\n style=\"width:100%;height:100%;object-fit:cover;border-radius:12px;\"\r\n />\r\n `;\r\n\r\n const LeftIconSlot = () => html`\r\n <div\r\n class=\"icon-slot left ${this.focused ? \"focused\" : \"\"}\"\r\n part=\"icon-slot icon-slot-left\"\r\n ?filled=${Boolean(showFilePreview && hasLeftSlot) ||\r\n Boolean(showAutoIconInLeft) ||\r\n hasLeftSlot}\r\n @click=${() => {\r\n if (isFileInput || showAutoIconInLeft) this.triggerNativeDropdown();\r\n }}\r\n >\r\n ${showFilePreview && hasLeftSlot\r\n ? ImagePreview()\r\n : showAutoIconInLeft\r\n ? autoIcon\r\n : html`<slot name=\"icon-left\"></slot>`}\r\n </div>\r\n `;\r\n\r\n const RightIconSlot = () =>\r\n this.loading\r\n ? html`<div\r\n class=\"loading-indicator\"\r\n part=\"loading-indicator\"\r\n ?compact=${this.compact}\r\n ></div>`\r\n : html`\r\n <div\r\n class=\"icon-slot right ${this.focused ? \"focused\" : \"\"}\"\r\n part=\"icon-slot icon-slot-right\"\r\n ?filled=${Boolean(showFilePreview && hasRightSlot) ||\r\n Boolean(showAutoIconInRight) ||\r\n hasRightSlot}\r\n @click=${() => {\r\n if (isFileInput || showAutoIconInRight)\r\n this.triggerNativeDropdown();\r\n }}\r\n >\r\n ${showFilePreview && hasRightSlot\r\n ? ImagePreview()\r\n : showAutoIconInRight\r\n ? autoIcon\r\n : html`<slot name=\"icon-right\"></slot>`}\r\n </div>\r\n `;\r\n\r\n const FileControl = () => html`\r\n <label\r\n class=\"custom-file-label\"\r\n part=\"custom-file-label\"\r\n for=\"fileInput\"\r\n ?disabled=${this.disabled}\r\n >\r\n ${this.renderInputAffix(\"prefix\")}\r\n <span\r\n class=\"custom-file-label__text\"\r\n part=\"custom-file-label-text\"\r\n ?data-filled=${Boolean(this.selectedFileName)}\r\n >\r\n ${this.selectedFileName || this.placeholder || \"Choose file\"}\r\n </span>\r\n ${this.renderInputAffix(\"suffix\")}\r\n </label>\r\n\r\n <input\r\n id=\"fileInput\"\r\n type=\"file\"\r\n @change=${this.handleFileChange}\r\n ?disabled=${this.disabled}\r\n accept=${this.accept || \"\"}\r\n ?multiple=${this.multiple}\r\n .required=${this.required}\r\n @keydown=${this.handleKeydown}\r\n .dir=${this.dir}\r\n name=${ifDefined(this.name || undefined)}\r\n .autocomplete=${this.nativeAutocomplete()}\r\n .autocapitalize=${this.autocapitalize}\r\n spellcheck=${this.spellcheck}\r\n ?autofocus=${this.autofocus}\r\n inputmode=${ifDefined(this.inputmode || undefined)}\r\n enterkeyhint=${ifDefined(\r\n this.enterkeyhint as\r\n | \"enter\"\r\n | \"done\"\r\n | \"go\"\r\n | \"next\"\r\n | \"previous\"\r\n | \"search\"\r\n | \"send\"\r\n | undefined,\r\n )}\r\n list=${ifDefined(this.list || undefined)}\r\n capture=${ifDefined(this.capture ? \"environment\" : undefined)}\r\n .aria-invalid=${String(this.isInvalid)}\r\n .aria-required=${String(this.required)}\r\n aria-label=${ifDefined(this.ariaLabel || undefined)}\r\n aria-labelledby=${ifDefined(this.ariaLabelledby || undefined)}\r\n aria-describedby=${ifDefined(this.describedById)}\r\n />\r\n `;\r\n\r\n const TextareaControl = () => html`\r\n <textarea\r\n .value=${live(this.value)}\r\n @input=${this.handleInput}\r\n @focus=${this.handleFocus}\r\n @blur=${this.handleBlur}\r\n ?compact=${this.compact}\r\n ?disabled=${this.disabled}\r\n .required=${this.required}\r\n .rows=${this.rows}\r\n placeholder=${this.placeholder}\r\n resizable=${this.resizable || \"none\"}\r\n style=\"width:100%;border:none;outline:none;\"\r\n .autocapitalize=${this.autocapitalize}\r\n ?spellcheck=${this.spellcheck}\r\n name=${ifDefined(this.name || undefined)}\r\n .autocomplete=${this.nativeAutocomplete()}\r\n inputmode=${ifDefined(this.inputmode || undefined)}\r\n enterkeyhint=${ifDefined(\r\n this.enterkeyhint as\r\n | \"enter\"\r\n | \"done\"\r\n | \"go\"\r\n | \"next\"\r\n | \"previous\"\r\n | \"search\"\r\n | \"send\"\r\n | undefined,\r\n )}\r\n minlength=${ifDefined(this.minlength ?? undefined)}\r\n maxlength=${ifDefined(this.maxlength ?? undefined)}\r\n ?autofocus=${this.autofocus}\r\n .aria-invalid=${String(this.isInvalid)}\r\n .aria-required=${String(this.required)}\r\n aria-label=${ifDefined(this.ariaLabel || undefined)}\r\n aria-labelledby=${ifDefined(this.ariaLabelledby || undefined)}\r\n aria-describedby=${ifDefined(this.describedById)}\r\n role=${ifDefined(this.nativeInputRole() as\r\n | \"textbox\"\r\n | \"searchbox\"\r\n | \"combobox\"\r\n | \"listbox\"\r\n | \"menuitem\"\r\n | \"option\"\r\n | \"slider\"\r\n | \"spinbutton\"\r\n | \"treeitem\"\r\n | undefined)}\r\n ></textarea>\r\n `;\r\n\r\n const TextInputControl = () => html`\r\n <input\r\n .type=${this.nativeTextInputType(isPassword)}\r\n .value=${live(this.value)}\r\n @input=${this.handleInput}\r\n @focus=${this.handleFocus}\r\n @blur=${this.handleBlur}\r\n @pointerdown=${this.handleAutofillGuardPointerDown}\r\n ?compact=${this.compact}\r\n ?disabled=${this.disabled}\r\n .required=${this.required}\r\n .readOnly=${this.readonly || this.autofillGuardActive}\r\n style=\"appearance:none;pointer-events:auto;\"\r\n placeholder=${this.placeholder}\r\n name=${ifDefined(this.name || undefined)}\r\n .autocomplete=${this.nativeAutocomplete()}\r\n .autocapitalize=${this.autocapitalize}\r\n spellcheck=${this.spellcheck}\r\n inputmode=${ifDefined(this.nativeInputMode())}\r\n enterkeyhint=${ifDefined(this.nativeEnterKeyHint())}\r\n data-form-type=${this.isFilterSearchInput() ? \"other\" : nothing}\r\n ?data-1p-ignore=${this.isFilterSearchInput()}\r\n ?data-lpignore=${this.isFilterSearchInput()}\r\n list=${ifDefined(this.list || undefined)}\r\n pattern=${ifDefined(this.pattern || undefined)}\r\n minlength=${ifDefined(this.minlength ?? undefined)}\r\n maxlength=${ifDefined(this.maxlength ?? undefined)}\r\n size=${ifDefined(this.size ?? undefined)}\r\n step=${ifDefined(this.step !== null ? Number(this.step) : undefined)}\r\n min=${ifDefined(this.min ?? undefined)}\r\n max=${ifDefined(this.max ?? undefined)}\r\n ?autofocus=${this.autofocus}\r\n .aria-invalid=${String(this.isInvalid)}\r\n .aria-required=${String(this.required)}\r\n aria-label=${ifDefined(this.ariaLabel || undefined)}\r\n aria-labelledby=${ifDefined(this.ariaLabelledby || undefined)}\r\n aria-describedby=${ifDefined(this.describedById)}\r\n role=${ifDefined(this.nativeInputRole() as\r\n | \"textbox\"\r\n | \"searchbox\"\r\n | \"combobox\"\r\n | \"listbox\"\r\n | \"menuitem\"\r\n | \"option\"\r\n | \"slider\"\r\n | \"spinbutton\"\r\n | \"treeitem\"\r\n | undefined)}\r\n />\r\n `;\r\n\r\n const NumberButtons = () =>\r\n isNumberInput && this.showNumberButtons\r\n ? html`\r\n <div class=\"number-btn\">\r\n <button\r\n class=\"decrement-btn\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n @mousedown=${this.keepInputFocused}\r\n @pointerdown=${this.keepInputFocused}\r\n @click=${(e: Event) => {\r\n e.stopPropagation();\r\n this.decrementValue();\r\n }}\r\n aria-label=\"Decrease value\"\r\n >\r\n <sky-icon icon=\"ion:minus\"></sky-icon>\r\n </button>\r\n <button\r\n class=\"increment-btn\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n @mousedown=${this.keepInputFocused}\r\n @pointerdown=${this.keepInputFocused}\r\n @click=${(e: Event) => {\r\n e.stopPropagation();\r\n this.incrementValue();\r\n }}\r\n aria-label=\"Increase value\"\r\n >\r\n <sky-icon icon=\"ion:add\"></sky-icon>\r\n </button>\r\n </div>\r\n `\r\n : null;\r\n\r\n const PasswordToggle = () =>\r\n isPassword && this.showPasswordToggle\r\n ? html`\r\n <sky-icon\r\n class=\"toggle-password\"\r\n part=\"toggle-password\"\r\n ?compact=${this.compact}\r\n icon=${this.showPassword\r\n ? this.passwordVisibleIcon\r\n : this.passwordHiddenIcon}\r\n @click=${this.togglePasswordVisibility}\r\n ></sky-icon>\r\n `\r\n : null;\r\n\r\n const ClearButton = () =>\r\n this.clearable &&\r\n (this.value || this.selectedFileName || this.selectedFileCount > 0)\r\n ? html`\r\n <sky-icon\r\n class=\"clear-button\"\r\n part=\"clear-button\"\r\n ?compact=${this.compact}\r\n @click=${this.handleClear}\r\n ?loading=${this.loading}\r\n icon=\"ion:close\"\r\n ></sky-icon>\r\n `\r\n : null;\r\n\r\n const FileInfo = () =>\r\n isFileInput && this.totalFileSize\r\n ? html`\r\n <div class=\"file-info\" part=\"file-info\">\r\n <span>\r\n ${this.selectedFileCount}\r\n file${this.selectedFileCount !== 1 ? \"s selected\" : \" selected\"} </span\r\n >,\r\n <span>${this.formatFileSize(this.totalFileSize)}</span>\r\n </div>\r\n `\r\n : null;\r\n\r\n const Control = () =>\r\n isFileInput\r\n ? FileControl()\r\n : isTextarea\r\n ? TextareaControl()\r\n : TextInputControl();\r\n\r\n const isFieldset = this.variant === \"fieldset\";\r\n const isInside = this.variant === \"inside\";\r\n const labelEl = this.label\r\n ? isFieldset\r\n ? html`<legend class=\"label\" part=\"label\"><span class=\"legend-text\">${this.label}</span></legend>`\r\n : html`<div class=\"label\" part=\"label\">${this.label}</div>`\r\n : null;\r\n\r\n const fieldControls = html`\r\n ${supportsInlineAffixes ? this.renderInputAffix(\"prefix\") : nothing}\r\n ${Control()}\r\n ${supportsInlineAffixes ? this.renderInputAffix(\"suffix\") : nothing}\r\n ${NumberButtons()} ${PasswordToggle()}\r\n ${ClearButton()}\r\n `;\r\n\r\n const defaultFieldContent = html`\r\n ${LeftIconSlot()}\r\n ${supportsInlineAffixes ? this.renderInputAffix(\"prefix\") : nothing}\r\n ${Control()}\r\n ${supportsInlineAffixes ? this.renderInputAffix(\"suffix\") : nothing}\r\n ${NumberButtons()} ${PasswordToggle()}\r\n ${ClearButton()} ${RightIconSlot()}\r\n `;\r\n\r\n const insideFieldContent = html`\r\n ${LeftIconSlot()}\r\n <div class=\"input-inside-main\">\r\n ${labelEl}\r\n <div class=\"input-inside-row\">${fieldControls}</div>\r\n </div>\r\n ${RightIconSlot()}\r\n `;\r\n\r\n return html`\r\n <div\r\n class=\"input-container\"\r\n @click=${this.handleWrapperClick}\r\n part=\"input-container\"\r\n >\r\n ${isFieldset || isInside ? nothing : labelEl}\r\n ${isFieldset\r\n ? html`<fieldset\r\n class=\"input-wrapper\"\r\n part=\"input-wrapper\"\r\n ?compact=${this.compact}\r\n ?loading=${this.loading}\r\n >\r\n ${labelEl}\r\n <div class=\"input-fieldset-body\">\r\n ${LeftIconSlot()}\r\n ${supportsInlineAffixes ? this.renderInputAffix(\"prefix\") : nothing}\r\n ${Control()}\r\n ${supportsInlineAffixes ? this.renderInputAffix(\"suffix\") : nothing}\r\n ${NumberButtons()} ${PasswordToggle()}\r\n ${ClearButton()} ${RightIconSlot()}\r\n </div>\r\n </fieldset>`\r\n : html`<div\r\n class=\"input-wrapper\"\r\n part=\"input-wrapper\"\r\n ?compact=${this.compact}\r\n ?loading=${this.loading}\r\n >\r\n ${isInside ? insideFieldContent : defaultFieldContent}\r\n </div>`}\r\n\r\n ${FileInfo()} ${this.renderValidationErrors()}\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"names":["SkyInput","FormControlBase","constructor","super","arguments","this","value","placeholder","label","type","suffix","prefix","prefixColor","suffixColor","color","_validations","compact","loading","showErrors","clearable","errorDisplayMode","required","step","min","max","autocapitalize","autocomplete","spellcheck","dir","rows","resizable","accept","multiple","inputmode","enterkeyhint","pattern","minlength","maxlength","list","size","cols","autofocus","capture","inputRole","ariaLabel","ariaLabelledby","ariaDescribedby","showNumberButtons","showPasswordToggle","passwordVisibleIcon","passwordHiddenIcon","validationActive","invalid","variant","preset","_presets","PresetController","selectedFileName","selectedFiles","focused","validationStatus","validationErrors","typingStarted","autofillIconSlot","autofillGuardActive","showPassword","totalFileSize","selectedFileCount","filePreview","_leftIconSlot","_rightIconSlot","_iconClickWired","WeakSet","_onLeftIconSlotChange","_wireIconSlot","_onRightIconSlotChange","keepInputFocused","e","preventDefault","stopPropagation","refocusInput","validations","old","Array","isArray","requestUpdate","connectedCallback","hasAttribute","tabIndex","disabled","hasUpdated","_setupIconSlots","disconnectedCallback","removeEventListener","shadowRoot","querySelector","addEventListener","side","slot","node","assignedElements","flatten","HTMLElement","has","add","handleIconClick","firstUpdated","_changedProperties","captureDefaultValue","syncFormValue","syncValidity","willUpdate","changedProperties","map","String","trim","updated","setAttribute","toggleAttribute","style","setProperty","resolveColor","inputWrapper","inputWrapperEl","getFormValue","name","length","fd","FormData","f","append","setValueFromFormState","state","getValidityAnchor","isEmpty","toString","getCustomErrorMessage","join","getNativeControl","onNativeValueMutated","native","validateInput","reset","nativeRequiredMessage","requiredMessage","getEmittedValue","n","Number","isFinite","handleClear","readonly","dispatchEvent","CustomEvent","detail","bubbles","composed","handleFileChange","event","files","target","fileList","from","file","totalSize","reduce","total","startsWith","reader","FileReader","onload","result","readAsDataURL","reemitNativeEvent","fileName","fileCount","handleKeydown","key","triggerNativeDropdown","preview","handleInput","handleFocus","releaseAutofillGuard","handleAutofillGuardPointerDown","onFormReset","defaultValue","handleBlur","validateForForm","payload","v","r","isFileInput","validation","index","Error","push","error","message","errors","isValid","getErrorMessages","slice","position","eventType","eventData","formatFileSize","bytes","i","Math","floor","log","parseFloat","pow","toFixed","incrementValue","currentValue","Infinity","decrementValue","renderValidationErrors","requiredMsg","customMsgs","msgs","errId","id","html","m","togglePasswordVisibility","focusInput","input","nativeInputEl","focus","handleWrapperClick","isInvalid","matches","describedById","el","preventScroll","click","showPicker","isFilterSearchInput","nativeAutocomplete","nativeTextInputType","isPassword","nativeInputMode","nativeEnterKeyHint","nativeInputRole","affixColorStyle","trimmed","renderInputAffix","kind","nothing","styleMap","render","isTextarea","isNumberInput","supportsInlineAffixes","hasLeftSlot","hasRightSlot","autoIcon","showFilePreview","showAutoIconInLeft","showAutoIconInRight","ImagePreview","ifDefined","LeftIconSlot","Boolean","RightIconSlot","FileControl","TextareaControl","live","TextInputControl","NumberButtons","PasswordToggle","ClearButton","Control","isFieldset","isInside","labelEl","fieldControls","defaultFieldContent","insideFieldContent","FileInfo","dependencies","SkyIcon","styles","css","shadowRootOptions","LitElement","delegatesFocus","__decorateClass","property","prototype","reflect","query","customElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sky-input.js","sources":["../../src/sky-input/sky-input.ts"],"sourcesContent":["import { LitElement, html, css, nothing } from \"lit\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport { customElement, property, query, state } from \"lit/decorators.js\";\nimport { resolveColor } from \"../helper/utils/color-resolver\";\nimport { PresetController } from \"../helper/controllers/preset-controller\";\nimport { live } from \"lit/directives/live.js\";\nimport { FormControlBase } from \"../helper/internals/form-control-base\";\nimport { SkyIcon } from \"../sky-icon/sky-icon.js\";\n\nexport type SkyInputValue = string | number | File[] | null;\nexport type SkyInputType = string;\nexport type SkyInputErrorDisplayMode = \"none\" | \"single\" | \"all\";\nexport type SkyInputIconPosition = \"left\" | \"right\";\nexport type SkyInputValidation = (value: string | File[]) => true | string;\nexport type SkyInputValueChangedDetail = { value: string | number };\nexport type SkyInputValueClearedDetail = { value: string | number };\nexport type SkyInputFileSelectedDetail = {\n files: File[];\n fileName: string;\n totalSize: number;\n fileCount: number;\n};\nexport type SkyInputValidationErrorDetail = { errors: string[] };\nexport type SkyInputIconClickDetail = {\n position: SkyInputIconPosition;\n eventType: string | null;\n eventData: Event | null;\n};\n\nconst EMPTY_VALIDATIONS: SkyInputValidation[] = Object.freeze(\n [],\n) as unknown as SkyInputValidation[];\n\nfunction samePrimitiveArray(a: unknown[], b: unknown[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\nfunction inputValidationsHasChanged(value: unknown, old: unknown): boolean {\n const next = Array.isArray(value) ? value : EMPTY_VALIDATIONS;\n const prev = Array.isArray(old) ? old : EMPTY_VALIDATIONS;\n if (next === prev) return false;\n if (next.length === 0 && prev.length === 0) return false;\n return true;\n}\n\n/**\n * @element sky-input\n *\n * @summary Versatile form input supporting text, password, number, textarea, and file workflows.\n *\n * @status stable\n * @since 1.0.0\n *\n * @documentation https://sky-ui.com/components/input\n * @dependency sky-icon\n *\n * @uiVModel value value-changed\n *\n * @slot icon-left - Optional icon/content placed in the left slot.\n * @slot icon-right - Optional icon/content placed in the right slot.\n * @property {SkyInputValue} value - Current input value.\n * @property {string} placeholder - Placeholder text.\n * @property {string} label - Label text. Above the field by default; on the border for `fieldset`; inside the field for `inside`.\n * @property {string} variant - Visual style: `default`, `highlight`, `fieldset`, or `inside`.\n * @property {SkyInputType} type - Input type (`text`, `password`, `number`, `textarea`, `file`, etc.).\n * @property {string} suffix - Optional suffix label fragment.\n * @property {string} prefix - Optional prefix label fragment.\n * @property {string} prefixColor - Prefix color override.\n * @property {string} suffixColor - Suffix color override.\n * @property {string} color - Accent color token/value.\n * @property {SkyInputValidation[]} validations - Validation functions.\n * @property {boolean} compact - Compact display mode.\n * @property {string} preset - Named prop preset from nearest `sky-config-provider`. Default: `\"\"`.\n * @property {boolean} loading - Loading state.\n * @property {boolean} showErrors - Enables error rendering.\n * @property {boolean} clearable - Enables clear button.\n * @property {SkyInputErrorDisplayMode} errorDisplayMode - Error rendering mode.\n * @property {boolean} showNumberButtons - Enables number increment/decrement controls.\n * @property {boolean} showPasswordToggle - Enables password visibility toggle.\n * @property {string} passwordVisibleIcon - Icon used when password is visible.\n * @property {string} passwordHiddenIcon - Icon used when password is hidden.\n *\n * @fires {CustomEvent<SkyInputValueChangedDetail>} value-changed - Fired when value changes.\n * @fires {CustomEvent<SkyInputValueClearedDetail>} value-cleared - Fired after clear action.\n * @fires {CustomEvent<SkyInputFileSelectedDetail>} file-selected - Fired after file selection changes.\n * @fires {CustomEvent<SkyInputValidationErrorDetail>} validation-error - Fired after validations run.\n * @fires {CustomEvent<SkyInputIconClickDetail>} left-icon-click - Fired when left icon slot is clicked.\n * @fires {CustomEvent<SkyInputIconClickDetail>} right-icon-click - Fired when right icon slot is clicked.\n *\n * @method validateInput Runs configured validations and updates invalid state.\n * @method handleClear Clears value and emits corresponding events.\n * @method formatFileSize Formats byte size for UI display.\n * @method focusInput Focuses the underlying native input or textarea.\n *\n * @csspart input-container - The outer container wrapping label and input wrapper.\n * @csspart label - The label element above the input.\n * @csspart input-wrapper - The wrapper around input/textarea and icons.\n * @csspart icon-slot - Base class for left/right icon slots.\n * @csspart icon-slot-left - Left icon slot.\n * @csspart icon-slot-right - Right icon slot.\n * @csspart clear-button - The clear/reset button.\n * @csspart toggle-password - The toggle icon for password visibility.\n * @csspart loading-indicator - The spinner shown when loading.\n * @csspart error-list - UL element containing validation errors.\n * @csspart error - Individual error message.\n * @csspart file-info - File count and size info below the file input.\n * @csspart input-prefix - Inline prefix fragment inside the field.\n * @csspart input-suffix - Inline suffix fragment inside the field.\n *\n * @Behavior\n * - Extends `FormControlBase` for automatic form association and validation integration\n * - Supports all standard HTML input types with enhanced styling and functionality\n * - File inputs with multi-file support, preview, and size tracking\n * - Automatic validation integration with parent forms via `sky-form`\n *\n * - **none**: No error messages displayed\n * - **single**: Show only the first error message\n * - **all**: Show all validation error messages\n *\n * @example\n * ```html\n * <sky-input\n * label=\"Password\"\n * type=\"password\"\n * placeholder=\"Enter your password\"\n * clearable\n * show-password-toggle\n * required\n * >\n * <sky-icon slot=\"icon-left\" icon=\"ion:lock-closed\"></sky-icon>\n * </sky-input>\n * ```\n * ```vue\n * <template>\n * <sky-input label=\"Password\" type=\"password\" clearable show-password-toggle required>\n * <sky-icon slot=\"icon-left\" icon=\"ion:lock-closed\"></sky-icon>\n * </sky-input>\n * </template>\n * ```\n * ```jsx\n * export default function Demo() {\n * return (\n * <sky-input label=\"Password\" type=\"password\" clearable show-password-toggle required>\n * <sky-icon slot=\"icon-left\" icon=\"ion:lock-closed\"></sky-icon>\n * </sky-input>\n * );\n * }\n * ```\n */\n@customElement(\"sky-input\")\nexport class SkyInput extends FormControlBase {\n\n static dependencies: Record<string, CustomElementConstructor> = {\n \"sky-icon\": SkyIcon,\n };\n\n @property({ type: String }) value: SkyInputValue = \"\";\n @property({ type: String }) placeholder = \"\";\n @property({ type: String }) label = \"\";\n @property({ type: String }) type: SkyInputType = \"text\";\n @property({ type: String }) suffix = \"\";\n @property({ type: String }) prefix = \"\";\n @property({ type: String }) prefixColor = \"\";\n @property({ type: String }) suffixColor = \"\";\n @property({ type: String }) color = \"primary\";\n private _validations: SkyInputValidation[] = EMPTY_VALIDATIONS;\n @property({ type: Array, hasChanged: inputValidationsHasChanged })\n get validations(): SkyInputValidation[] {\n return this._validations;\n }\n set validations(value: SkyInputValidation[] | null | undefined) {\n this._validations =\n Array.isArray(value) && value.length > 0 ? value : EMPTY_VALIDATIONS;\n }\n @property({ type: Boolean, reflect: true }) compact = false;\n @property({ type: Boolean, reflect: true }) loading = false;\n @property({ type: Boolean }) showErrors = false;\n @property({ type: Boolean, reflect: true }) clearable = false;\n @property({ type: String }) errorDisplayMode: SkyInputErrorDisplayMode = \"single\";\n @property({ type: Boolean, reflect: true }) override required = false;\n @property({ type: String }) step: string | null = null;\n @property({ type: String }) min: string | null = null;\n @property({ type: String }) max: string | null = null;\n @property({ type: String }) override autocapitalize = \"off\";\n @property({ type: String }) autocomplete = \"off\";\n @property({ type: Boolean }) override spellcheck = false;\n @property({ type: String }) override dir = \"ltr\";\n @property({ type: Number }) rows = 6;\n @property({ type: String }) resizable = \"none\";\n @property({ type: String }) accept = \"\";\n @property({ type: Boolean }) multiple = false;\n @property({ type: String }) inputmode: string | null = null;\n @property({ type: String }) enterkeyhint: string | null = null;\n @property({ type: String }) pattern: string | null = null;\n @property({ type: Number }) minlength: number | null = null;\n @property({ type: Number }) maxlength: number | null = null;\n @property({ type: String }) list: string | null = null;\n @property({ type: Number }) size: number | null = null;\n @property({ type: Number }) cols: number | null = null;\n @property({ type: Boolean }) autofocus = false;\n @property({ type: Boolean }) capture = false;\n @property({ type: String }) inputRole: string | null = null;\n @property({ type: String }) ariaLabel: string | null = null;\n @property({ type: String }) ariaLabelledby: string | null = null;\n @property({ type: String }) ariaDescribedby: string | null = null;\n @property({ type: Boolean }) showNumberButtons = false;\n @property({ type: Boolean }) showPasswordToggle = true;\n @property({ type: String }) passwordVisibleIcon = \"material-symbols:visibility-off\";\n @property({ type: String }) passwordHiddenIcon = \"material-symbols:visibility\";\n @property({ type: Boolean, reflect: true }) validationActive = false;\n @property({ type: Boolean, reflect: true }) invalid = false;\n @property({ type: String, reflect: true }) variant:\n | \"default\"\n | \"highlight\"\n | \"fieldset\"\n | \"inside\" = \"default\";\n\n /** Named prop preset from nearest `sky-config-provider`. */\n @property({ type: String, reflect: true }) preset = \"\";\n\n private _presets = new PresetController(this);\n\n @state() private selectedFileName = \"\";\n @state() private selectedFiles: File[] = [];\n @state() private focused = false;\n @state() private validationStatus: boolean[] = [];\n @state() private validationErrors: string[] = [];\n @state() private typingStarted = false;\n @state() private autofillIconSlot = \"left\";\n @state() private autofillGuardActive = false;\n @state() private showPassword = false;\n @state() private totalFileSize = 0;\n @state() private selectedFileCount = 0;\n @state() private filePreview: string | ArrayBuffer | null = null;\n\n @query(\".input-wrapper\") private inputWrapperEl!: HTMLElement;\n @query(\"input, textarea\") private nativeInputEl!:\n | HTMLInputElement\n | HTMLTextAreaElement;\n\n private _leftIconSlot: HTMLSlotElement | null = null;\n private _rightIconSlot: HTMLSlotElement | null = null;\n private _iconClickWired = new WeakSet<HTMLElement>();\n private _onLeftIconSlotChange = () =>\n this._wireIconSlot(\"left\", this._leftIconSlot);\n private _onRightIconSlotChange = () =>\n this._wireIconSlot(\"right\", this._rightIconSlot);\n\n static override styles = css`\n :host {\n display: block;\n font-family: var(--sky-font);\n width: 100%;\n /* Control size */\n --sky-input-height: 36px;\n --sky-input-height-compact: 28px;\n --sky-input-border-width: 1px;\n /* Spacing scale — tight internal joins, softer outer edge */\n --sky-input-pad-x: var(--sky-space-3, 12px);\n --sky-input-pad-x-sm: var(--sky-space-1, 4px);\n --sky-input-pad-x-xs: 0px;\n --sky-input-pad-y: var(--sky-space-1, 4px);\n --sky-input-pad-y-sm: 0px;\n --sky-input-gap: var(--sky-space-1, 4px);\n --sky-input-icon-width: 2rem;\n }\n\n :host([data-sky-compact]) {\n --sky-input-pad-x: var(--sky-space-2, 8px);\n --sky-input-pad-x-sm: var(--sky-space-1, 4px);\n --sky-input-icon-width: 1.75rem;\n }\n\n /* Compact typography + denser chrome for every variant */\n :host([data-sky-compact]) .input-container > .label {\n font-size: var(--sky-font-size-xs);\n margin-bottom: var(--sky-space-1, 4px);\n line-height: 1.2;\n }\n\n :host([data-sky-compact]) input,\n :host([data-sky-compact]) textarea,\n :host([data-sky-compact]) .input-affix,\n :host([data-sky-compact]) .custom-file-label__text {\n font-size: var(--sky-font-size-sm);\n }\n\n :host([data-sky-compact]) .icon-slot {\n font-size: var(--sky-font-size-lg);\n }\n\n :host([data-sky-compact]) .toggle-password,\n :host([data-sky-compact]) .clear-button {\n font-size: var(--sky-font-size-md);\n }\n\n :host([data-sky-compact]) .custom-file-label {\n border-radius: var(--sky-radius-primary);\n }\n\n :host([disabled]) .input-container {\n opacity: var(--sky-opacity-disabled, 0.6);\n }\n :host([disabled]) * {\n pointer-events: none;\n }\n\n :host([data-sky-variant=\"highlight\"]){\n .label{\n color: var(--sky-input-color);\n }\n }\n\n /* Fieldset / legend: native fieldset+legend; wrapper keeps solid fill */\n :host([data-sky-variant=\"fieldset\"]) {\n overflow: visible;\n }\n\n :host([data-sky-variant=\"fieldset\"]) .input-container {\n overflow: visible;\n /* Room for legend text sitting on the top border — keep off :host */\n padding-block-start: 0.65em;\n }\n\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper {\n display: block;\n height: auto;\n margin: 0;\n min-inline-size: 0;\n min-width: 0;\n padding: 0;\n overflow: visible;\n background: var(--sky-glass-solid);\n box-shadow: none;\n }\n\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper[compact] {\n height: auto;\n }\n\n :host([data-sky-variant=\"fieldset\"]) .input-fieldset-body {\n display: flex;\n width: 100%;\n align-items: center;\n box-sizing: border-box;\n /* Match default control outer height once fieldset border is included */\n height: calc(\n var(--sky-input-height) - 2 * var(--sky-input-border-width)\n );\n min-height: calc(\n var(--sky-input-height) - 2 * var(--sky-input-border-width)\n );\n background: transparent;\n border-radius: inherit;\n min-width: 0;\n overflow: hidden;\n }\n\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper[compact] .input-fieldset-body {\n height: calc(\n var(--sky-input-height-compact) - 2 * var(--sky-input-border-width)\n );\n min-height: calc(\n var(--sky-input-height-compact) - 2 * var(--sky-input-border-width)\n );\n }\n\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper:has(textarea) {\n height: auto;\n }\n\n :host([data-sky-variant=\"fieldset\"]) fieldset.input-wrapper:has(textarea) .input-fieldset-body {\n height: calc((var(--rows)) * 23px);\n min-height: calc((var(--rows)) * 23px);\n align-items: flex-start;\n }\n\n :host([data-sky-variant=\"fieldset\"]) legend.label {\n float: unset;\n width: auto;\n max-width: calc(100% - 2 * var(--sky-input-pad-x));\n margin-inline-start: var(--sky-input-pad-x);\n margin-block: 0;\n padding-inline: var(--sky-input-pad-x-sm);\n padding-block: 0;\n border: none;\n background: transparent;\n background-color: transparent;\n color: var(--sky-text-secondary);\n font-size: var(--sky-font-size-xs);\n /* Take no in-flow space; inner text is centered on the border notch */\n height: 0;\n line-height: 0;\n overflow: visible;\n white-space: nowrap;\n pointer-events: none;\n }\n\n :host([data-sky-variant=\"fieldset\"]) legend.label .legend-text {\n display: inline-block;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.2;\n transform: translateY(-50%);\n }\n\n :host([data-sky-variant=\"fieldset\"]) .input-container:focus-within legend.label {\n color: var(--sky-input-color);\n font-size: var(--sky-font-size-xs);\n }\n\n /* Focus via real border — ::after would paint over the legend gap */\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper::after {\n content: none;\n display: none;\n }\n\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper:has(input:focus),\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper:has(input:focus-visible),\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper:has(textarea:focus),\n :host([data-sky-variant=\"fieldset\"]) .input-wrapper:has(textarea:focus-visible) {\n border-color: var(--sky-input-color);\n }\n\n :host([data-sky-variant=\"fieldset\"][validationActive]:invalid) .input-wrapper {\n border-color: var(--sky-danger-primary);\n }\n\n :host([data-sky-variant=\"fieldset\"][validationActive]:invalid) legend.label {\n color: var(--sky-danger-primary);\n }\n\n :host([data-sky-variant=\"fieldset\"][compact]) legend.label,\n :host([data-sky-variant=\"fieldset\"][compact]) .input-container:focus-within legend.label {\n font-size: var(--sky-font-size-xs);\n }\n\n /* Inside: label lives in the wrapper above the value row */\n :host([data-sky-variant=\"inside\"]) {\n --sky-input-height-inside: 40px;\n /* Two lines (label + value) need a bit more than single-line compact */\n --sky-input-height-inside-compact: 36px;\n --sky-input-inside-label-block: 2px;\n --sky-input-inside-value-min: 1.15em;\n }\n\n :host([data-sky-variant=\"inside\"]) .input-wrapper {\n height: auto;\n min-height: var(--sky-input-height-inside);\n align-items: center;\n padding-block: var(--sky-input-pad-y-sm, 0px);\n }\n\n :host([data-sky-variant=\"inside\"]) .input-wrapper[compact] {\n height: auto;\n min-height: var(--sky-input-height-inside-compact);\n padding-block: var(--sky-input-pad-y-sm, 0px);\n }\n\n :host([data-sky-variant=\"inside\"]) .input-inside-main {\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 0;\n padding-block: var(--sky-input-inside-label-block);\n }\n\n :host([data-sky-variant=\"inside\"]) .input-inside-main > .label {\n margin: 0;\n padding-inline: var(--sky-input-pad-x);\n font-size: var(--sky-font-size-xs);\n line-height: 1.15;\n min-height: 0;\n color: var(--sky-text-secondary);\n pointer-events: none;\n overflow: visible;\n text-overflow: unset;\n flex-shrink: 0;\n }\n\n :host([data-sky-variant=\"inside\"][compact]) .input-inside-main > .label {\n font-size: 0.6875rem; /* ~11px — denser than xs for two-line compact */\n line-height: 1.15;\n min-height: 0;\n }\n\n :host([data-sky-variant=\"inside\"][compact]) .input-inside-row input,\n :host([data-sky-variant=\"inside\"][compact]) .input-inside-row textarea {\n font-size: var(--sky-font-size-sm);\n line-height: 1.15;\n }\n\n :host([data-sky-variant=\"inside\"]) .input-container:focus-within .input-inside-main > .label {\n color: var(--sky-input-color);\n font-size: var(--sky-font-size-xs);\n }\n\n :host([data-sky-variant=\"inside\"][compact]) .input-container:focus-within .input-inside-main > .label {\n font-size: 0.6875rem;\n }\n\n :host([data-sky-variant=\"inside\"][validationActive]:invalid) .input-inside-main > .label {\n color: var(--sky-danger-primary);\n }\n\n :host([data-sky-variant=\"inside\"]) .input-inside-row {\n display: flex;\n align-items: center;\n min-width: 0;\n width: 100%;\n min-height: var(--sky-input-inside-value-min);\n }\n\n :host([data-sky-variant=\"inside\"]) .input-wrapper:has(.icon-slot[filled].left) .input-inside-main > .label,\n :host([data-sky-variant=\"inside\"]) .input-wrapper:has(.input-affix.prefix) .input-inside-main > .label {\n padding-inline-start: 0;\n }\n\n :host([data-sky-variant=\"inside\"]) .input-inside-row input,\n :host([data-sky-variant=\"inside\"]) .input-inside-row textarea {\n padding-block: 0;\n height: auto;\n min-height: 0;\n line-height: 1.2;\n }\n\n :host([data-sky-variant=\"inside\"]) .input-wrapper:has(textarea) {\n height: auto;\n min-height: var(--sky-input-height-inside);\n align-items: flex-start;\n }\n\n :host([data-sky-variant=\"inside\"]) .icon-slot,\n :host([data-sky-variant=\"inside\"]) .icon-slot[filled] {\n align-self: center;\n height: auto;\n max-height: none;\n align-items: center;\n justify-content: center;\n }\n\n .input-container {\n position: relative;\n display: flex;\n flex-direction: column;\n width: inherit;\n cursor: text;\n }\n\n sky-icon {\n display: inline-block;\n width: 1em;\n height: 1em;\n }\n\n /* Outside labels only — never bump fieldset/inside fonts (clips legends) */\n .input-container:focus-within > .label {\n color: var(--sky-input-color);\n transition: color var(--sky-transition-normal, 200ms ease);\n }\n\n :host([data-sky-compact]) .input-container:focus-within > .label {\n font-size: var(--sky-font-size-xs);\n }\n\n .label {\n font-size: var(--sky-font-size-sm);\n margin-bottom: var(--sky-space-1, 4px);\n text-align: start;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-family: var(--sky-font);\n line-height: 1.35;\n }\n\n .input-wrapper {\n position: relative;\n display: flex;\n width: 100%;\n align-items: center;\n box-sizing: border-box;\n height: var(--sky-input-height);\n min-height: var(--sky-input-height);\n pointer-events: auto;\n background: var(--sky-glass-solid);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n border-radius: var(--sky-radius-secondary);\n border: var(--sky-border-primary);\n box-shadow: var(--sky-box-shadow-primary);\n transition:\n border-color var(--sky-transition-normal, 200ms ease),\n box-shadow var(--sky-transition-normal, 200ms ease);\n }\n\n .input-wrapper::after {\n content: \"\";\n position: absolute;\n top: -1px;\n left: -1px;\n right: -1px;\n bottom: -1px;\n border-radius: inherit;\n border: 1px solid transparent;\n border-bottom-color: transparent;\n opacity: 0;\n transition:\n opacity 0.3s ease,\n border-color 0.3s ease;\n pointer-events: none;\n }\n\n .input-wrapper:has(input:focus-visible)::after,\n .input-wrapper:has(textarea:focus-visible)::after {\n opacity: 1;\n border-bottom-color: var(--sky-input-color);\n }\n\n .input-wrapper:has(input:focus)::after,\n .input-wrapper:has(textarea:focus)::after {\n opacity: 1;\n border-bottom-color: var(--sky-input-color);\n }\n\n :host([validationActive]:invalid) .input-wrapper::after {\n opacity: 1;\n border-bottom-color: var(--sky-danger-primary);\n }\n :host([validationActive]:invalid) .label {\n color: var(--sky-danger-primary);\n }\n\n :host([validationActive]:invalid) .icon-slot {\n color: var(--sky-danger-primary);\n }\n\n .input-wrapper[compact] {\n height: var(--sky-input-height-compact);\n min-height: var(--sky-input-height-compact);\n border: var(--sky-border-primary);\n border-radius: var(--sky-radius-primary);\n }\n\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"week\"],\n input[type=\"month\"],\n input[type=\"datetime-local\"] {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n background: none;\n border: none;\n font-family: inherit;\n }\n\n input[type=\"date\"]::-webkit-calendar-picker-indicator,\n input[type=\"time\"]::-webkit-calendar-picker-indicator,\n input[type=\"week\"]::-webkit-calendar-picker-indicator,\n input[type=\"month\"]::-webkit-calendar-picker-indicator,\n input[type=\"datetime-local\"]::-webkit-calendar-picker-indicator {\n display: none;\n }\n\n .input-wrapper:has(input:focus)[compact]::after {\n border: 1px solid var(--sky-input-color);\n }\n\n .toggle-password[compact] {\n font-size: var(--sky-font-size-md);\n }\n\n input {\n font-family: var(--sky-font);\n font-size: var(--sky-font-size-md);\n line-height: 1.2;\n text-align: left;\n transition: color var(--sky-transition-normal, 200ms ease);\n }\n\n input:-webkit-autofill {\n -webkit-text-fill-color: var(--sky-text-secondary, inherit) !important;\n transition: background-color 9999s ease-in-out 0s !important;\n }\n\n :dir(rtl) input {\n text-align: right;\n }\n\n input[type=\"number\"] {\n appearance: textfield;\n -moz-appearance: textfield;\n }\n\n input[type=\"number\"]::-webkit-inner-spin-button,\n input[type=\"number\"]::-webkit-outer-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n .number-btn {\n display: flex;\n flex-shrink: 0;\n margin-inline-end: var(--sky-input-pad-x-sm);\n gap: var(--sky-input-gap);\n }\n\n :dir(rtl).number-btn {\n margin-inline-end: var(--sky-input-pad-x-sm);\n }\n\n .file-info {\n display: flex;\n justify-content: flex-end;\n font-size: var(--sky-font-size-xs);\n color: var(--sky-text-secondary);\n font-family: var(--sky-font);\n }\n\n :dir(rtl).file-info {\n flex-direction: row-reverse;\n }\n\n .increment-btn,\n .decrement-btn {\n background: var(--sky-glass-solid);\n color: var(--sky-text-primary);\n border: var(--sky-border-primary);\n border-radius: var(--sky-radius-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--sky-input-pad-x-xs) var(--sky-input-pad-x-sm);\n font-size: var(--sky-font-size-sm);\n cursor: pointer;\n transition: color var(--sky-transition-normal, 200ms ease);\n font-family: var(--sky-font);\n }\n\n .increment-btn:hover,\n .decrement-btn:hover {\n color: var(--sky-input-color);\n }\n\n .toggle-password {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-inline-end: var(--sky-input-pad-x-sm);\n font-size: var(--sky-font-size-lg);\n color: var(--sky-text-tertiary);\n cursor: pointer;\n }\n\n .toggle-password:hover {\n color: var(--sky-input-color);\n }\n\n input {\n flex: 1 1 auto;\n min-width: 0;\n border: none;\n outline: none;\n background: transparent;\n box-sizing: border-box;\n color: var(--sky-text-primary);\n padding-block: 0;\n padding-inline: var(--sky-input-pad-x);\n }\n\n input::placeholder {\n color: var(--sky-text-tertiary);\n }\n\n .input-affix {\n flex: 0 0 auto;\n font-family: var(--sky-font);\n font-size: var(--sky-font-size-md);\n font-weight: var(--sky-font-weight-medium);\n color: var(--sky-text-secondary);\n user-select: none;\n white-space: nowrap;\n line-height: 1;\n }\n\n .input-affix.prefix {\n padding-inline-start: var(--sky-input-pad-x);\n padding-inline-end: var(--sky-input-pad-x-sm);\n }\n\n .input-affix.suffix {\n padding-inline-start: var(--sky-input-pad-x-sm);\n padding-inline-end: var(--sky-input-pad-x);\n }\n\n .input-wrapper[compact] .input-affix {\n font-size: var(--sky-font-size-sm);\n }\n\n .input-wrapper:has(.input-affix.prefix) input,\n .input-wrapper:has(.input-affix.prefix) textarea {\n padding-inline-start: 0;\n }\n\n .input-wrapper:has(.icon-slot[filled].left) input,\n .input-wrapper:has(.icon-slot[filled].left) textarea {\n padding-inline-start: 0;\n }\n\n .input-wrapper:has(.icon-slot[filled].right) input,\n .input-wrapper:has(.icon-slot[filled].right) textarea,\n .input-wrapper:has(.clear-button) input,\n .input-wrapper:has(.clear-button) textarea,\n .input-wrapper:has(.toggle-password) input,\n .input-wrapper:has(.toggle-password) textarea,\n .input-wrapper:has(.number-btn) input,\n .input-wrapper:has(.loading-indicator) input {\n padding-inline-end: 0;\n }\n\n .input-wrapper:has(.input-affix.suffix) input,\n .input-wrapper:has(.input-affix.suffix) textarea {\n padding-inline-end: 0;\n }\n\n .custom-file-label__text {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--sky-text-tertiary);\n padding-inline-end: var(--sky-input-pad-x);\n }\n\n .custom-file-label:not(:has(.input-affix.prefix)) .custom-file-label__text {\n padding-inline-start: var(--sky-input-pad-x);\n }\n\n .custom-file-label__text[data-filled] {\n color: var(--sky-text-primary);\n }\n\n .icon-slot {\n display: none;\n justify-content: center;\n font-size: var(--sky-font-size-xl);\n align-items: center;\n color: var(--sky-text-primary);\n height: inherit;\n max-height: 100%;\n box-sizing: border-box;\n flex: 0 0 var(--sky-input-icon-width);\n width: var(--sky-input-icon-width);\n min-width: var(--sky-input-icon-width);\n padding: 0;\n background: none;\n border: none;\n transition: color var(--sky-transition-normal, 200ms ease);\n }\n\n .input-wrapper:has(textarea) .icon-slot {\n max-height: var(--sky-input-height);\n }\n\n .icon-slot[filled] {\n display: flex;\n flex-shrink: 0;\n cursor: pointer;\n }\n\n .icon-slot[filled]:hover,\n .icon-slot[filled]:active,\n .icon-slot.focused {\n color: var(--sky-input-color);\n }\n\n .progress-message {\n pointer-events: none;\n width: 100%;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n font-size: var(--sky-font-size-sm);\n margin-inline-start: var(--sky-input-pad-x-sm);\n font-family: var(--sky-font);\n }\n\n :dir(rtl) .progress-message {\n margin-inline-start: unset;\n margin-inline-end: var(--sky-input-pad-x-sm);\n }\n\n .error-list {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n }\n\n .error {\n font-size: var(--sky-font-size-xs);\n color: var(--sky-danger-primary);\n text-align: start;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-family: var(--sky-font);\n }\n\n ::slotted(.icon-slot) {\n display: block;\n }\n\n .input-wrapper[loading] input {\n cursor: wait;\n }\n\n .loading-indicator {\n flex-shrink: 0;\n margin-inline-end: var(--sky-input-pad-x-sm);\n width: 16px;\n height: 16px;\n border: 2px solid var(--sky-hover-primary);\n border-top: 2px solid var(--sky-input-color);\n border-radius: var(--sky-radius-full);\n animation: spin 1s linear infinite;\n }\n\n .loading-indicator[compact] {\n width: 10px;\n height: 10px;\n }\n\n .input-wrapper[loading] .icon-slot.right {\n display: none;\n }\n\n @keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n }\n\n .clear-button {\n flex-shrink: 0;\n margin-inline-end: var(--sky-input-pad-x-sm);\n border: none;\n font-size: var(--sky-font-size-xl);\n color: var(--sky-input-color);\n background-color: var(--sky-hover-primary);\n border-radius: var(--sky-radius-full);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n cursor: pointer;\n transition: color var(--sky-transition-normal, 200ms ease);\n }\n\n .clear-button[compact] {\n font-size: var(--sky-font-size-md);\n }\n\n .clear-button[loading] {\n opacity: 0.6;\n pointer-events: none;\n }\n\n input[type=\"file\"] {\n position: absolute;\n width: 100%;\n height: 100%;\n opacity: 0;\n pointer-events: auto;\n z-index: -1;\n }\n\n .custom-file-label {\n position: relative;\n flex: 1;\n display: flex;\n align-items: center;\n gap: var(--sky-input-gap);\n text-align: left;\n padding: 0;\n color: var(--sky-input-color);\n border-radius: var(--sky-radius-secondary);\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n cursor: pointer;\n transition:\n background 0.3s ease,\n padding 0.3s ease;\n font-family: var(--sky-font);\n }\n\n .custom-file-label:hover .custom-file-label__text {\n padding-inline-start: var(--sky-input-pad-x-sm);\n }\n\n .custom-file-label:empty::after {\n content: \"Choose file\";\n color: var(--sky-input-color);\n }\n\n .clear-button:hover {\n color: var(--sky-danger-primary);\n }\n\n textarea {\n flex: 1 1 auto;\n min-width: 0;\n border: none;\n outline: none;\n background: transparent;\n box-sizing: border-box;\n color: var(--sky-text-primary);\n padding: var(--sky-input-pad-y) var(--sky-input-pad-x);\n resize: none;\n overflow: auto;\n font-family: var(--sky-font);\n }\n\n textarea[resizable=\"vertical\"] {\n resize: vertical;\n }\n\n textarea[resizable=\"both\"] {\n resize: both;\n }\n\n textarea {\n scrollbar-width: thin;\n scrollbar-color: var(--sky-scrollbar-thumb) var(--sky-scrollbar-track);\n }\n\n textarea::-webkit-scrollbar {\n width: 6px;\n height: 6px;\n }\n\n textarea::-webkit-scrollbar-thumb {\n background-color: var(--sky-scrollbar-thumb);\n border-radius: var(--sky-radius-full, 9999px);\n transition: background-color var(--sky-duration-normal, 200ms)\n var(--sky-ease-default, ease);\n cursor: grab;\n }\n\n textarea::-webkit-scrollbar-thumb:hover {\n background-color: var(--sky-scrollbar-thumb-hover);\n }\n\n textarea::-webkit-scrollbar-track {\n background: var(--sky-scrollbar-track);\n }\n\n textarea::-webkit-scrollbar-button {\n display: none;\n }\n\n textarea::placeholder {\n color: var(--sky-text-tertiary);\n }\n\n .input-wrapper:has(textarea) {\n height: calc((var(--rows)) * 23px);\n align-items: flex-start;\n }\n textarea {\n height: calc((var(--rows)) * 23px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .loading-indicator {\n animation: none;\n }\n\n .input-container:focus-within > .label,\n .input-wrapper,\n .icon-slot,\n .increment-btn,\n .decrement-btn,\n .clear-button,\n input,\n textarea,\n .custom-file-label {\n transition: none;\n }\n }\n `;\n\n static override shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.autofillGuardActive = this.type === \"search\";\n\n if (!this.hasAttribute(\"tabindex\")) {\n this.tabIndex = this.disabled ? -1 : 0;\n }\n\n if (this.hasUpdated) {\n this._setupIconSlots();\n }\n }\n\n override disconnectedCallback(): void {\n this._leftIconSlot?.removeEventListener(\n \"slotchange\",\n this._onLeftIconSlotChange,\n );\n this._rightIconSlot?.removeEventListener(\n \"slotchange\",\n this._onRightIconSlotChange,\n );\n this._leftIconSlot = null;\n this._rightIconSlot = null;\n super.disconnectedCallback();\n }\n\n private _setupIconSlots(): void {\n if (!this._leftIconSlot) {\n this._leftIconSlot =\n this.shadowRoot?.querySelector<HTMLSlotElement>(\n 'slot[name=\"icon-left\"]',\n ) ?? null;\n this._leftIconSlot?.addEventListener(\n \"slotchange\",\n this._onLeftIconSlotChange,\n );\n }\n if (!this._rightIconSlot) {\n this._rightIconSlot =\n this.shadowRoot?.querySelector<HTMLSlotElement>(\n 'slot[name=\"icon-right\"]',\n ) ?? null;\n this._rightIconSlot?.addEventListener(\n \"slotchange\",\n this._onRightIconSlotChange,\n );\n }\n this._wireIconSlot(\"left\", this._leftIconSlot);\n this._wireIconSlot(\"right\", this._rightIconSlot);\n }\n\n private _wireIconSlot(\n side: \"left\" | \"right\",\n slot: HTMLSlotElement | null,\n ): void {\n if (!slot) return;\n for (const node of slot.assignedElements({ flatten: true })) {\n if (!(node instanceof HTMLElement)) continue;\n if (this._iconClickWired.has(node)) continue;\n this._iconClickWired.add(node);\n node.addEventListener(\"click\", () => this.handleIconClick(side));\n }\n }\n\n override firstUpdated(\n _changedProperties: Map<string | number | symbol, unknown>,\n ) {\n super.firstUpdated(_changedProperties);\n\n // default/reset value\n this.captureDefaultValue(this.value as string);\n\n // initial sync into form\n this.syncFormValue();\n this.syncValidity();\n\n this._setupIconSlots();\n }\n\n override willUpdate(\n changedProperties: Map<string | number | symbol, unknown>,\n ) {\n if (\n changedProperties.has(\"validations\") &&\n Array.isArray(this.validations)\n ) {\n this.validationStatus = this.validations.map(() => false);\n }\n\n if (changedProperties.has(\"value\") && this.type === \"file\") {\n if (this.value == null || String(this.value).trim() === \"\") {\n this.selectedFileName = \"\";\n this.selectedFiles = [];\n this.totalFileSize = 0;\n this.selectedFileCount = 0;\n this.filePreview = null;\n } else if (!this.selectedFileName) {\n this.selectedFileName = this.value as string;\n }\n }\n if (changedProperties.has(\"type\") && this.type === \"search\") {\n this.autofillGuardActive = true;\n }\n }\n\n override updated(changedProperties: Map<string | number | symbol, unknown>) {\n super.updated(changedProperties);\n\n // After PresetController hostUpdate — keep host attrs in sync with props.\n this.setAttribute(\"data-sky-variant\", this.variant);\n this.toggleAttribute(\"data-sky-compact\", this.compact);\n\n if (this.color) {\n this.style.setProperty(\n \"--sky-input-color\",\n resolveColor(this.color),\n );\n }\n\n if (changedProperties.has(\"rows\")) {\n const inputWrapper = this.inputWrapperEl;\n if (inputWrapper) {\n inputWrapper.style.setProperty(\"--rows\", String(this.rows));\n }\n }\n\n if (\n changedProperties.has(\"value\") ||\n changedProperties.has(\"selectedFiles\") ||\n changedProperties.has(\"selectedFileName\") ||\n changedProperties.has(\"type\") ||\n changedProperties.has(\"multiple\") ||\n changedProperties.has(\"name\") ||\n changedProperties.has(\"disabled\")\n ) {\n this.syncFormValue();\n }\n\n if (\n changedProperties.has(\"value\") ||\n changedProperties.has(\"selectedFiles\") ||\n changedProperties.has(\"selectedFileName\") ||\n changedProperties.has(\"validationErrors\") ||\n changedProperties.has(\"required\") ||\n changedProperties.has(\"disabled\") ||\n changedProperties.has(\"readonly\")\n ) {\n this.syncValidity();\n }\n }\n\n /** @protected */\n protected override getFormValue(): string | File | FormData | null {\n if (!this.name) return null;\n\n if (this.type === \"file\") {\n if (!this.selectedFiles || this.selectedFiles.length === 0) return null;\n\n if (this.multiple) {\n const fd = new FormData();\n for (const f of this.selectedFiles) fd.append(this.name, f);\n return fd;\n }\n return this.selectedFiles[0];\n }\n\n return this.value as string ?? \"\";\n }\n\n /** @protected */\n protected override setValueFromFormState(\n state: string | File | FormData | null,\n ) {\n // For SkyInput, state restore is typically string\n if (typeof state === \"string\") {\n this.value = state;\n // for textarea/input UI to refresh, you already use live()\n return;\n }\n\n // For file state restore: browsers usually won't restore actual File objects for security.\n // So do a safe reset:\n this.value = \"\";\n this.selectedFileName = \"\";\n this.selectedFiles = [];\n this.totalFileSize = 0;\n this.selectedFileCount = 0;\n this.filePreview = null;\n }\n\n /** @protected */\n protected override getValidityAnchor(): HTMLElement | undefined {\n return this;\n }\n\n /** @protected */\n protected override isEmpty(): boolean {\n if (this.type === \"file\") {\n return !this.selectedFiles || this.selectedFiles.length === 0;\n }\n return !this.value || this.value.toString().trim() === \"\";\n }\n\n /** @protected */\n protected override getCustomErrorMessage(): string {\n if (!this.validationErrors?.length) return \"\";\n\n // single message that includes all\n if (this.errorDisplayMode === \"all\") {\n return this.validationErrors.join(\"\\n\");\n }\n\n // single mode\n return this.validationErrors[0];\n }\n\n /** @protected */\n protected override getNativeControl(): HTMLElement | null {\n if (this.type === \"textarea\") {\n return this.shadowRoot?.querySelector(\n \"textarea\",\n ) as HTMLTextAreaElement | null;\n }\n // for all other types (text/email/password/date/...)\n return this.shadowRoot?.querySelector(\"input\") as HTMLInputElement | null;\n }\n\n /** @protected */\n protected override onNativeValueMutated(native: any): void {\n // File input value is managed via change handler; do not mirror native.value here.\n if (this.type !== \"file\") {\n this.value = native?.value ?? \"\";\n }\n // keep SkyInput custom validations in sync\n this.validateInput();\n }\n\n /**\n * Resets the input field to its initial state.\n * @public\n */\n reset() {\n this.value = \"\";\n this.selectedFileName = \"\";\n this.filePreview = null;\n this.selectedFiles = [];\n this.selectedFileCount = 0;\n this.validationErrors = [];\n this.typingStarted = false;\n this.validationActive = false;\n this.selectedFileCount = 0;\n this.totalFileSize = 0;\n }\n\n /** @private */\n private get nativeRequiredMessage(): string {\n if (!this.validationActive) return \"\";\n if (this.disabled) return \"\";\n if (this.required && this.isEmpty())\n return this.requiredMessage || \"This field is required.\";\n return \"\";\n }\n\n /** @private */\n private getEmittedValue(): string | number {\n if (this.type !== \"number\") return this.value as string;\n\n // allow empty to stay empty (important for clearing)\n if (this.value === \"\" || this.value == null) return \"\";\n\n const n = Number(this.value);\n // if user is still typing an invalid numeric token, keep as string\n return Number.isFinite(n) ? n : this.value as string;\n }\n\n /**\n * Clears the input value and resets typing state.\n * @public\n */\n handleClear() {\n if (this.disabled || this.readonly) {\n return;\n }\n this.reset();\n this.validationActive = true;\n this.validateInput();\n this.dispatchEvent(\n new CustomEvent<SkyInputValueChangedDetail>(\"value-changed\", {\n detail: { value: this.getEmittedValue() },\n bubbles: true,\n composed: true,\n }),\n );\n this.dispatchEvent(\n new CustomEvent<SkyInputValueClearedDetail>(\"value-cleared\", {\n detail: { value: this.getEmittedValue() },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n /**\n * Handles the `change` event triggered by the file input element.\n * @param {Event} event - The event object generated by the file input element when files are selected.\n * @public\n */\n handleFileChange(event: Event): void {\n if (this.disabled || this.readonly) {\n return;\n }\n const input = event.target as HTMLInputElement;\n const files = input.files;\n\n if (files && files.length) {\n const fileList: File[] = Array.from(files);\n this.selectedFiles = fileList;\n this.selectedFileName = fileList\n .map((file: File) => file.name)\n .join(\", \");\n this.value = this.selectedFileName;\n\n this.syncFormValue();\n this.syncValidity();\n\n const totalSize: number = fileList.reduce(\n (total: number, file: File) => total + file.size,\n 0,\n );\n this.totalFileSize = totalSize;\n\n this.selectedFileCount = fileList.length;\n\n if (fileList[0].type.startsWith(\"image/\")) {\n const reader = new FileReader();\n reader.onload = (e: ProgressEvent<FileReader>) => {\n if (e.target) {\n this.filePreview = e.target.result;\n }\n };\n reader.readAsDataURL(fileList[0]);\n } else {\n this.filePreview = null;\n }\n\n this.reemitNativeEvent(\"change\", event);\n this.reemitNativeEvent(\"input\", event);\n\n this.dispatchEvent(\n new CustomEvent<SkyInputFileSelectedDetail>(\"file-selected\", {\n detail: {\n files: fileList,\n fileName: this.selectedFileName,\n totalSize,\n fileCount: this.selectedFileCount,\n },\n bubbles: true,\n composed: true,\n }),\n );\n\n this.validateInput();\n } else {\n this.value = \"\";\n this.filePreview = null;\n this.totalFileSize = 0;\n this.selectedFileCount = 0;\n this.selectedFiles = [];\n this.validateInput();\n }\n }\n\n /**\n * Handles the keydown event for the input component.\n * @param event - The keyboard event triggered by the user.\n * @private\n */\n private handleKeydown(event: KeyboardEvent) {\n if (this.disabled || this.readonly) {\n return;\n }\n if (event.key === \"Enter\" && this.type === \"file\") {\n event.preventDefault();\n event.stopPropagation();\n this.triggerNativeDropdown();\n }\n }\n\n /**\n * Gets the current file preview.\n * @returns The preview of the file, as stored in `filePreview`.\n * @public\n */\n get preview() {\n return this.filePreview;\n }\n\n /**\n * Handles the input event for the input field.\n * @param {Event} event - The input event triggered by user interaction.\n * @public\n */\n handleInput(event: Event) {\n event.stopPropagation();\n\n if (this.disabled || this.readonly) {\n event.preventDefault();\n return;\n }\n\n this.value = (event.target as HTMLInputElement | HTMLTextAreaElement).value;\n\n this.syncFormValue();\n this.syncValidity();\n\n if (!this.typingStarted) this.typingStarted = true;\n\n // Live-validate only after the field has been blurred once (or submit activated).\n if (this.validationActive) {\n this.validateInput();\n }\n\n this.reemitNativeEvent(\"input\", event);\n\n this.dispatchEvent(\n new CustomEvent<SkyInputValueChangedDetail>(\"value-changed\", {\n detail: { value: this.getEmittedValue() },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n /**\n * Handles the focus event for the input field.\n * @public\n */\n handleFocus(event: Event) {\n event.stopPropagation();\n this.releaseAutofillGuard();\n this.focused = true;\n this.reemitNativeEvent(\"focus\", event);\n }\n\n /** Chrome may autofill saved usernames into filter fields; readonly until interaction blocks that. */\n private releaseAutofillGuard(): void {\n if (!this.autofillGuardActive) return;\n this.autofillGuardActive = false;\n }\n\n private handleAutofillGuardPointerDown(event: Event): void {\n this.releaseAutofillGuard();\n event.stopPropagation();\n }\n\n /** @protected */\n protected override onFormReset() {\n this.setValueFromFormState(this.defaultValue);\n\n this.validationActive = false;\n this.invalid = false;\n this.typingStarted = false;\n this.validationErrors = [];\n this.validationStatus = [];\n\n if (this.type === \"file\") {\n this.selectedFiles = [];\n this.selectedFileName = \"\";\n this.totalFileSize = 0;\n this.selectedFileCount = 0;\n this.filePreview = null;\n }\n\n if (this.type === \"search\") {\n this.autofillGuardActive = true;\n }\n }\n\n /**\n * Handles the blur event for the input field.\n * @public\n */\n handleBlur(event: Event) {\n event.stopPropagation();\n this.validationActive = true;\n this.focused = false;\n this.reemitNativeEvent(\"blur\", event);\n }\n\n /** @protected */\n protected override validateForForm(): string {\n // run your `this.validations` against current value even if validationActive is false\n const payload =\n this.type === \"file\" ? (this.selectedFiles ?? []) : (this.value ?? \"\");\n\n for (const v of this.validations ?? []) {\n const r = v(payload as string | File[]);\n if (r !== true) return typeof r === \"string\" ? r : \"Invalid value.\";\n }\n\n return \"\";\n }\n\n /**\n * Validates the input value against the configured validation rules.\n * @returns {boolean} True if validation passes, false otherwise.\n * @public\n */\n validateInput(): boolean {\n const nextErrors: string[] = [];\n const nextStatus: boolean[] = [];\n\n const isFileInput = this.type === \"file\";\n const isEmpty = isFileInput\n ? !this.selectedFiles || this.selectedFiles.length === 0\n : !this.value || this.value.toString().trim() === \"\";\n\n // 1) If empty + required -> let SkyFormControlBase handle native required\n // (do NOT push required into validationErrors)\n if (this.required && isEmpty) {\n this.syncValidity(); // will set valueMissing\n }\n\n // 2) Run custom validations only if there is something to validate\n if (Array.isArray(this.validations) && this.validations.length) {\n const payload: string | File[] = isFileInput\n ? (this.selectedFiles ?? [])\n : (this.value as string ?? \"\");\n\n for (let index = 0; index < this.validations.length; index++) {\n const validation = this.validations[index];\n try {\n if (typeof validation !== \"function\") {\n throw new Error(`Validation at index ${index} must be a function.`);\n }\n\n const result = validation(payload);\n\n if (result !== true) {\n nextErrors.push(\n typeof result === \"string\"\n ? result\n : `Validation ${index} failed.`,\n );\n nextStatus.push(false);\n } else {\n nextStatus.push(true);\n }\n } catch (error) {\n const message =\n typeof error === \"object\" && error !== null && \"message\" in error\n ? String((error as any).message)\n : typeof error === \"string\"\n ? error\n : \"Unknown error\";\n\n nextErrors.push(`Error in validation ${index}: ${message}`);\n nextStatus.push(false);\n }\n }\n }\n\n const errorsChanged = !samePrimitiveArray(this.validationErrors, nextErrors);\n const statusChanged = !samePrimitiveArray(this.validationStatus, nextStatus);\n if (errorsChanged) this.validationErrors = nextErrors;\n if (statusChanged) this.validationStatus = nextStatus;\n\n if (errorsChanged) {\n this.dispatchEvent(\n new CustomEvent<SkyInputValidationErrorDetail>(\"validation-error\", {\n detail: { errors: this.validationErrors },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n this.syncValidity();\n\n const isValid = nextErrors.length === 0;\n if (this.invalid !== !isValid) this.invalid = !isValid;\n\n return isValid;\n }\n\n /**\n * Retrieves validation error messages based on the configured error display mode.\n * @returns {Array} - An array of error messages to display.\n * @private\n */\n private getErrorMessages() {\n switch (this.errorDisplayMode) {\n case \"single\":\n return this.validationErrors.slice(0, 1);\n case \"all\":\n return this.validationErrors;\n case \"none\":\n default:\n return [];\n }\n }\n\n /**\n * Handles click events for the left or right icon slots.\n * @param {String} position - The position of the icon (\"left\" or \"right\").\n * @param {Event|null} event - The original event triggered by the click (optional).\n * @public\n */\n handleIconClick(position: \"left\" | \"right\", event: Event | null = null) {\n this.dispatchEvent(\n new CustomEvent<SkyInputIconClickDetail>(`${position}-icon-click`, {\n detail: {\n position,\n eventType: event ? event.type : null,\n eventData: event,\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n /**\n * Formats a file size in bytes into a human-readable string.\n * @param {number} bytes - The file size in bytes.\n * @returns {string} - The formatted file size string.\n * @public\n */\n formatFileSize(bytes: number): string {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;\n }\n\n /**\n * Increments the input value by the specified step, respecting min/max constraints.\n * @private\n */\n private incrementValue() {\n if (this.disabled || this.readonly) return;\n const currentValue = parseFloat(this.value as string) || 0;\n const step = parseFloat(this.step ?? \"\") || 1;\n const max = this.max ? parseFloat(this.max) : Infinity;\n\n if (currentValue + step <= max) {\n this.value = (currentValue + step).toString();\n this.validateInput();\n this.dispatchEvent(\n new CustomEvent<SkyInputValueChangedDetail>(\"value-changed\", {\n detail: { value: this.getEmittedValue() },\n }),\n );\n }\n this.refocusInput();\n }\n\n /**\n * Decrements the input value by the specified step, respecting min/max constraints.\n * @private\n */\n private decrementValue() {\n if (this.disabled || this.readonly) return;\n const currentValue = parseFloat(this.value as string) || 0;\n const step = parseFloat(this.step ?? \"\") || 1;\n const min = this.min ? parseFloat(this.min) : -Infinity;\n\n if (currentValue - step >= min) {\n this.value = (currentValue - step).toString();\n this.validateInput();\n this.dispatchEvent(\n new CustomEvent<SkyInputValueChangedDetail>(\"value-changed\", {\n detail: { value: this.getEmittedValue() },\n }),\n );\n }\n this.refocusInput();\n }\n\n /**\n * Renders validation error messages if applicable.\n * @returns {TemplateResult|null} - The rendered error messages or null.\n * @private\n */\n private renderValidationErrors() {\n\n if (!this.showErrors || !this.validationActive) return null;\n\n const requiredMsg = this.nativeRequiredMessage;\n const customMsgs = this.getErrorMessages(); // already respects errorDisplayMode for custom\n\n let msgs: string[] = [];\n\n if (this.errorDisplayMode === \"single\") {\n // Required message takes precedence over custom errors.\n if (requiredMsg) msgs = [requiredMsg];\n else if (customMsgs.length) msgs = [customMsgs[0]];\n } else {\n msgs = requiredMsg ? [requiredMsg, ...customMsgs] : customMsgs;\n }\n\n if (!msgs.length) return null;\n\n const errId = `${this.id || \"sky-input\"}-errors`;\n\n return html`\n <div class=\"progress-message\">\n <ul id=${errId} class=\"error-list\" part=\"error-list\">\n ${msgs.map((m) => html`<li class=\"error\" part=\"error\">${m}</li>`)}\n </ul>\n </div>\n `;\n }\n\n /**\n * Toggles the visibility of the password input.\n * @public\n */\n togglePasswordVisibility() {\n this.showPassword = !this.showPassword;\n }\n\n public focusInput(): void {\n const input = this.nativeInputEl;\n if (\n input &&\n typeof (input as HTMLInputElement | HTMLTextAreaElement).focus === \"function\"\n ) {\n (input as HTMLInputElement | HTMLTextAreaElement).focus();\n }\n }\n\n /**\n * Handles click events on the input wrapper.\n * @param {Event} event - The original click event.\n * @private\n */\n private handleWrapperClick(event: Event) {\n event.stopPropagation();\n if (this.disabled) return;\n const input = this.nativeInputEl;\n if (\n input &&\n typeof (input as HTMLInputElement | HTMLTextAreaElement).focus ===\n \"function\"\n ) {\n (input as HTMLInputElement | HTMLTextAreaElement).focus();\n }\n }\n\n /** @private */\n private get isInvalid(): boolean {\n return (\n this.matches(\":invalid\") ||\n (this.validationActive && this.validationErrors.length > 0)\n );\n }\n\n /** @private */\n private get describedById(): string | undefined {\n return (\n this.ariaDescribedby ??\n (this.showErrors ? `${this.id || \"sky-input\"}-errors` : undefined)\n );\n }\n\n /**\n * Refocuses the input element.\n * @private\n */\n private refocusInput() {\n const el = this.shadowRoot?.querySelector(\n \"input\",\n ) as HTMLInputElement | null;\n el?.focus({ preventScroll: true });\n }\n\n /**\n * Keeps the input focused when interacting with related controls.\n * @param {Event} e - The original event.\n * @private\n */\n private keepInputFocused = (e: Event) => {\n e.preventDefault();\n e.stopPropagation();\n this.refocusInput();\n };\n\n /**\n * Triggers the native dropdown for date/time/file inputs.\n * @private\n */\n private triggerNativeDropdown() {\n if (this.disabled || this.readonly) return;\n const input = this.shadowRoot?.querySelector(\n 'input[type=\"date\"], input[type=\"time\"], input[type=\"week\"], input[type=\"month\"], input[type=\"datetime-local\"], input[type=\"file\"]',\n ) as HTMLInputElement | null;\n\n if (input) {\n if (this.type === \"file\") {\n input.click();\n } else {\n this.showPicker();\n }\n }\n }\n\n /**\n * Filter/search inputs (`type=\"search\"`) are rendered as plain text fields so\n * Chrome does not treat them as login username targets. Credential autofill is\n * further blocked with readonly-until-focus (Chrome ignores autocomplete tokens).\n */\n private isFilterSearchInput(): boolean {\n return this.type === \"search\";\n }\n\n private nativeAutocomplete(): string {\n if (this.isFilterSearchInput()) {\n return \"off\";\n }\n return this.autocomplete;\n }\n\n private nativeTextInputType(isPassword: boolean): string {\n if (isPassword && this.showPassword) return \"text\";\n if (this.isFilterSearchInput()) return \"text\";\n return this.type;\n }\n\n private nativeInputMode(): string | undefined {\n if (this.inputmode) return this.inputmode;\n if (this.isFilterSearchInput()) return \"search\";\n return undefined;\n }\n\n private nativeEnterKeyHint():\n | \"enter\"\n | \"done\"\n | \"go\"\n | \"next\"\n | \"previous\"\n | \"search\"\n | \"send\"\n | undefined {\n if (this.enterkeyhint) {\n return this.enterkeyhint as\n | \"enter\"\n | \"done\"\n | \"go\"\n | \"next\"\n | \"previous\"\n | \"search\"\n | \"send\";\n }\n if (this.isFilterSearchInput()) return \"search\";\n return undefined;\n }\n\n private nativeInputRole(): string | undefined {\n if (this.inputRole) return this.inputRole;\n if (this.type === \"search\") return \"searchbox\";\n return undefined;\n }\n\n private affixColorStyle(color: string) {\n const trimmed = String(color ?? \"\").trim();\n if (!trimmed) return undefined;\n return { color: resolveColor(trimmed) };\n }\n\n private renderInputAffix(kind: \"prefix\" | \"suffix\") {\n const value = kind === \"prefix\" ? this.prefix : this.suffix;\n if (!String(value ?? \"\").length) return nothing;\n const color = kind === \"prefix\" ? this.prefixColor : this.suffixColor;\n const style = this.affixColorStyle(color);\n return html`<span\n class=\"input-affix ${kind}\"\n part=\"input-${kind}\"\n style=${style ? styleMap(style) : nothing}\n >${value}</span\n >`;\n }\n\n override render() {\n const isFileInput = this.type === \"file\";\n const isTextarea = this.type === \"textarea\";\n const isNumberInput = this.type === \"number\";\n const isPassword = this.type === \"password\";\n const supportsInlineAffixes = !isFileInput && !isTextarea;\n\n const hasLeftSlot = !!this.querySelector('[slot=\"icon-left\"]');\n const hasRightSlot = !!this.querySelector('[slot=\"icon-right\"]');\n\n let autoIcon: unknown = null;\n if (this.type === \"date\")\n autoIcon = html`<sky-icon icon=\"ion:calendar\"></sky-icon>`;\n else if (this.type === \"time\")\n autoIcon = html`<sky-icon icon=\"ion:time\"></sky-icon>`;\n else if (this.type === \"week\")\n autoIcon = html`<sky-icon icon=\"ion:calendar\"></sky-icon>`;\n else if (this.type === \"month\")\n autoIcon = html`<sky-icon icon=\"ion:calendar\"></sky-icon>`;\n else if (this.type === \"datetime-local\")\n autoIcon = html`<sky-icon icon=\"ion:time\"></sky-icon>`;\n\n const showFilePreview = this.filePreview && (hasLeftSlot || hasRightSlot);\n const showAutoIconInLeft = this.autofillIconSlot === \"left\" && autoIcon;\n const showAutoIconInRight = this.autofillIconSlot === \"right\" && autoIcon;\n\n const ImagePreview = () => html`\n <img\n src=${ifDefined(\n typeof this.filePreview === \"string\" ? this.filePreview : undefined,\n )}\n alt=\"Preview\"\n style=\"width:100%;height:100%;object-fit:cover;border-radius:12px;\"\n />\n `;\n\n const LeftIconSlot = () => html`\n <div\n class=\"icon-slot left ${this.focused ? \"focused\" : \"\"}\"\n part=\"icon-slot icon-slot-left\"\n ?filled=${Boolean(showFilePreview && hasLeftSlot) ||\n Boolean(showAutoIconInLeft) ||\n hasLeftSlot}\n @click=${() => {\n if (isFileInput || showAutoIconInLeft) this.triggerNativeDropdown();\n }}\n >\n ${showFilePreview && hasLeftSlot\n ? ImagePreview()\n : showAutoIconInLeft\n ? autoIcon\n : html`<slot name=\"icon-left\"></slot>`}\n </div>\n `;\n\n const RightIconSlot = () =>\n this.loading\n ? html`<div\n class=\"loading-indicator\"\n part=\"loading-indicator\"\n ?compact=${this.compact}\n ></div>`\n : html`\n <div\n class=\"icon-slot right ${this.focused ? \"focused\" : \"\"}\"\n part=\"icon-slot icon-slot-right\"\n ?filled=${Boolean(showFilePreview && hasRightSlot) ||\n Boolean(showAutoIconInRight) ||\n hasRightSlot}\n @click=${() => {\n if (isFileInput || showAutoIconInRight)\n this.triggerNativeDropdown();\n }}\n >\n ${showFilePreview && hasRightSlot\n ? ImagePreview()\n : showAutoIconInRight\n ? autoIcon\n : html`<slot name=\"icon-right\"></slot>`}\n </div>\n `;\n\n const FileControl = () => html`\n <label\n class=\"custom-file-label\"\n part=\"custom-file-label\"\n for=\"fileInput\"\n ?disabled=${this.disabled}\n >\n ${this.renderInputAffix(\"prefix\")}\n <span\n class=\"custom-file-label__text\"\n part=\"custom-file-label-text\"\n ?data-filled=${Boolean(this.selectedFileName)}\n >\n ${this.selectedFileName || this.placeholder || \"Choose file\"}\n </span>\n ${this.renderInputAffix(\"suffix\")}\n </label>\n\n <input\n id=\"fileInput\"\n type=\"file\"\n @change=${this.handleFileChange}\n ?disabled=${this.disabled}\n accept=${this.accept || \"\"}\n ?multiple=${this.multiple}\n .required=${this.required}\n @keydown=${this.handleKeydown}\n .dir=${this.dir}\n name=${ifDefined(this.name || undefined)}\n .autocomplete=${this.nativeAutocomplete()}\n .autocapitalize=${this.autocapitalize}\n spellcheck=${this.spellcheck}\n ?autofocus=${this.autofocus}\n inputmode=${ifDefined(this.inputmode || undefined)}\n enterkeyhint=${ifDefined(\n this.enterkeyhint as\n | \"enter\"\n | \"done\"\n | \"go\"\n | \"next\"\n | \"previous\"\n | \"search\"\n | \"send\"\n | undefined,\n )}\n list=${ifDefined(this.list || undefined)}\n capture=${ifDefined(this.capture ? \"environment\" : undefined)}\n .aria-invalid=${String(this.isInvalid)}\n .aria-required=${String(this.required)}\n aria-label=${ifDefined(this.ariaLabel || undefined)}\n aria-labelledby=${ifDefined(this.ariaLabelledby || undefined)}\n aria-describedby=${ifDefined(this.describedById)}\n />\n `;\n\n const TextareaControl = () => html`\n <textarea\n .value=${live(this.value)}\n @input=${this.handleInput}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n ?compact=${this.compact}\n ?disabled=${this.disabled}\n .required=${this.required}\n .rows=${this.rows}\n placeholder=${this.placeholder}\n resizable=${this.resizable || \"none\"}\n style=\"width:100%;border:none;outline:none;\"\n .autocapitalize=${this.autocapitalize}\n ?spellcheck=${this.spellcheck}\n name=${ifDefined(this.name || undefined)}\n .autocomplete=${this.nativeAutocomplete()}\n inputmode=${ifDefined(this.inputmode || undefined)}\n enterkeyhint=${ifDefined(\n this.enterkeyhint as\n | \"enter\"\n | \"done\"\n | \"go\"\n | \"next\"\n | \"previous\"\n | \"search\"\n | \"send\"\n | undefined,\n )}\n minlength=${ifDefined(this.minlength ?? undefined)}\n maxlength=${ifDefined(this.maxlength ?? undefined)}\n ?autofocus=${this.autofocus}\n .aria-invalid=${String(this.isInvalid)}\n .aria-required=${String(this.required)}\n aria-label=${ifDefined(this.ariaLabel || undefined)}\n aria-labelledby=${ifDefined(this.ariaLabelledby || undefined)}\n aria-describedby=${ifDefined(this.describedById)}\n role=${ifDefined(this.nativeInputRole() as\n | \"textbox\"\n | \"searchbox\"\n | \"combobox\"\n | \"listbox\"\n | \"menuitem\"\n | \"option\"\n | \"slider\"\n | \"spinbutton\"\n | \"treeitem\"\n | undefined)}\n ></textarea>\n `;\n\n const TextInputControl = () => html`\n <input\n .type=${this.nativeTextInputType(isPassword)}\n .value=${live(this.value)}\n @input=${this.handleInput}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n @pointerdown=${this.handleAutofillGuardPointerDown}\n ?compact=${this.compact}\n ?disabled=${this.disabled}\n .required=${this.required}\n .readOnly=${this.readonly || this.autofillGuardActive}\n style=\"appearance:none;pointer-events:auto;\"\n placeholder=${this.placeholder}\n name=${ifDefined(this.name || undefined)}\n .autocomplete=${this.nativeAutocomplete()}\n .autocapitalize=${this.autocapitalize}\n spellcheck=${this.spellcheck}\n inputmode=${ifDefined(this.nativeInputMode())}\n enterkeyhint=${ifDefined(this.nativeEnterKeyHint())}\n data-form-type=${this.isFilterSearchInput() ? \"other\" : nothing}\n ?data-1p-ignore=${this.isFilterSearchInput()}\n ?data-lpignore=${this.isFilterSearchInput()}\n list=${ifDefined(this.list || undefined)}\n pattern=${ifDefined(this.pattern || undefined)}\n minlength=${ifDefined(this.minlength ?? undefined)}\n maxlength=${ifDefined(this.maxlength ?? undefined)}\n size=${ifDefined(this.size ?? undefined)}\n step=${ifDefined(this.step !== null ? Number(this.step) : undefined)}\n min=${ifDefined(this.min ?? undefined)}\n max=${ifDefined(this.max ?? undefined)}\n ?autofocus=${this.autofocus}\n .aria-invalid=${String(this.isInvalid)}\n .aria-required=${String(this.required)}\n aria-label=${ifDefined(this.ariaLabel || undefined)}\n aria-labelledby=${ifDefined(this.ariaLabelledby || undefined)}\n aria-describedby=${ifDefined(this.describedById)}\n role=${ifDefined(this.nativeInputRole() as\n | \"textbox\"\n | \"searchbox\"\n | \"combobox\"\n | \"listbox\"\n | \"menuitem\"\n | \"option\"\n | \"slider\"\n | \"spinbutton\"\n | \"treeitem\"\n | undefined)}\n />\n `;\n\n const NumberButtons = () =>\n isNumberInput && this.showNumberButtons\n ? html`\n <div class=\"number-btn\">\n <button\n class=\"decrement-btn\"\n type=\"button\"\n tabindex=\"-1\"\n @mousedown=${this.keepInputFocused}\n @pointerdown=${this.keepInputFocused}\n @click=${(e: Event) => {\n e.stopPropagation();\n this.decrementValue();\n }}\n aria-label=\"Decrease value\"\n >\n <sky-icon icon=\"ion:minus\"></sky-icon>\n </button>\n <button\n class=\"increment-btn\"\n type=\"button\"\n tabindex=\"-1\"\n @mousedown=${this.keepInputFocused}\n @pointerdown=${this.keepInputFocused}\n @click=${(e: Event) => {\n e.stopPropagation();\n this.incrementValue();\n }}\n aria-label=\"Increase value\"\n >\n <sky-icon icon=\"ion:add\"></sky-icon>\n </button>\n </div>\n `\n : null;\n\n const PasswordToggle = () =>\n isPassword && this.showPasswordToggle\n ? html`\n <sky-icon\n class=\"toggle-password\"\n part=\"toggle-password\"\n ?compact=${this.compact}\n icon=${this.showPassword\n ? this.passwordVisibleIcon\n : this.passwordHiddenIcon}\n @click=${this.togglePasswordVisibility}\n ></sky-icon>\n `\n : null;\n\n const ClearButton = () =>\n this.clearable &&\n (this.value || this.selectedFileName || this.selectedFileCount > 0)\n ? html`\n <sky-icon\n class=\"clear-button\"\n part=\"clear-button\"\n ?compact=${this.compact}\n @click=${this.handleClear}\n ?loading=${this.loading}\n icon=\"ion:close\"\n ></sky-icon>\n `\n : null;\n\n const FileInfo = () =>\n isFileInput && this.totalFileSize\n ? html`\n <div class=\"file-info\" part=\"file-info\">\n <span>\n ${this.selectedFileCount}\n file${this.selectedFileCount !== 1 ? \"s selected\" : \" selected\"} </span\n >,\n <span>${this.formatFileSize(this.totalFileSize)}</span>\n </div>\n `\n : null;\n\n const Control = () =>\n isFileInput\n ? FileControl()\n : isTextarea\n ? TextareaControl()\n : TextInputControl();\n\n const isFieldset = this.variant === \"fieldset\";\n const isInside = this.variant === \"inside\";\n const labelEl = this.label\n ? isFieldset\n ? html`<legend class=\"label\" part=\"label\"><span class=\"legend-text\">${this.label}</span></legend>`\n : html`<div class=\"label\" part=\"label\">${this.label}</div>`\n : null;\n\n const fieldControls = html`\n ${supportsInlineAffixes ? this.renderInputAffix(\"prefix\") : nothing}\n ${Control()}\n ${supportsInlineAffixes ? this.renderInputAffix(\"suffix\") : nothing}\n ${NumberButtons()} ${PasswordToggle()}\n ${ClearButton()}\n `;\n\n const defaultFieldContent = html`\n ${LeftIconSlot()}\n ${supportsInlineAffixes ? this.renderInputAffix(\"prefix\") : nothing}\n ${Control()}\n ${supportsInlineAffixes ? this.renderInputAffix(\"suffix\") : nothing}\n ${NumberButtons()} ${PasswordToggle()}\n ${ClearButton()} ${RightIconSlot()}\n `;\n\n const insideFieldContent = html`\n ${LeftIconSlot()}\n <div class=\"input-inside-main\">\n ${labelEl}\n <div class=\"input-inside-row\">${fieldControls}</div>\n </div>\n ${RightIconSlot()}\n `;\n\n return html`\n <div\n class=\"input-container\"\n @click=${this.handleWrapperClick}\n part=\"input-container\"\n >\n ${isFieldset || isInside ? nothing : labelEl}\n ${isFieldset\n ? html`<fieldset\n class=\"input-wrapper\"\n part=\"input-wrapper\"\n ?compact=${this.compact}\n ?loading=${this.loading}\n >\n ${labelEl}\n <div class=\"input-fieldset-body\">\n ${LeftIconSlot()}\n ${supportsInlineAffixes ? this.renderInputAffix(\"prefix\") : nothing}\n ${Control()}\n ${supportsInlineAffixes ? this.renderInputAffix(\"suffix\") : nothing}\n ${NumberButtons()} ${PasswordToggle()}\n ${ClearButton()} ${RightIconSlot()}\n </div>\n </fieldset>`\n : html`<div\n class=\"input-wrapper\"\n part=\"input-wrapper\"\n ?compact=${this.compact}\n ?loading=${this.loading}\n >\n ${isInside ? insideFieldContent : defaultFieldContent}\n </div>`}\n\n ${FileInfo()} ${this.renderValidationErrors()}\n </div>\n `;\n }\n}\n"],"names":["EMPTY_VALIDATIONS","Object","freeze","samePrimitiveArray","a","b","length","i","SkyInput","FormControlBase","constructor","super","arguments","this","value","placeholder","label","type","suffix","prefix","prefixColor","suffixColor","color","_validations","compact","loading","showErrors","clearable","errorDisplayMode","required","step","min","max","autocapitalize","autocomplete","spellcheck","dir","rows","resizable","accept","multiple","inputmode","enterkeyhint","pattern","minlength","maxlength","list","size","cols","autofocus","capture","inputRole","ariaLabel","ariaLabelledby","ariaDescribedby","showNumberButtons","showPasswordToggle","passwordVisibleIcon","passwordHiddenIcon","validationActive","invalid","variant","preset","_presets","PresetController","selectedFileName","selectedFiles","focused","validationStatus","validationErrors","typingStarted","autofillIconSlot","autofillGuardActive","showPassword","totalFileSize","selectedFileCount","filePreview","_leftIconSlot","_rightIconSlot","_iconClickWired","WeakSet","_onLeftIconSlotChange","_wireIconSlot","_onRightIconSlotChange","keepInputFocused","e","preventDefault","stopPropagation","refocusInput","validations","Array","isArray","connectedCallback","hasAttribute","tabIndex","disabled","hasUpdated","_setupIconSlots","disconnectedCallback","removeEventListener","shadowRoot","querySelector","addEventListener","side","slot","node","assignedElements","flatten","HTMLElement","has","add","handleIconClick","firstUpdated","_changedProperties","captureDefaultValue","syncFormValue","syncValidity","willUpdate","changedProperties","map","String","trim","updated","setAttribute","toggleAttribute","style","setProperty","resolveColor","inputWrapper","inputWrapperEl","getFormValue","name","fd","FormData","f","append","setValueFromFormState","state","getValidityAnchor","isEmpty","toString","getCustomErrorMessage","join","getNativeControl","onNativeValueMutated","native","validateInput","reset","nativeRequiredMessage","requiredMessage","getEmittedValue","n","Number","isFinite","handleClear","readonly","dispatchEvent","CustomEvent","detail","bubbles","composed","handleFileChange","event","files","target","fileList","from","file","totalSize","reduce","total","startsWith","reader","FileReader","onload","result","readAsDataURL","reemitNativeEvent","fileName","fileCount","handleKeydown","key","triggerNativeDropdown","preview","handleInput","handleFocus","releaseAutofillGuard","handleAutofillGuardPointerDown","onFormReset","defaultValue","handleBlur","validateForForm","payload","v","r","nextErrors","nextStatus","isFileInput","index","validation","Error","push","error","message","errorsChanged","statusChanged","errors","isValid","getErrorMessages","slice","position","eventType","eventData","formatFileSize","bytes","Math","floor","log","parseFloat","pow","toFixed","incrementValue","currentValue","Infinity","decrementValue","renderValidationErrors","requiredMsg","customMsgs","msgs","errId","id","html","m","togglePasswordVisibility","focusInput","input","nativeInputEl","focus","handleWrapperClick","isInvalid","matches","describedById","el","preventScroll","click","showPicker","isFilterSearchInput","nativeAutocomplete","nativeTextInputType","isPassword","nativeInputMode","nativeEnterKeyHint","nativeInputRole","affixColorStyle","trimmed","renderInputAffix","kind","nothing","styleMap","render","isTextarea","isNumberInput","supportsInlineAffixes","hasLeftSlot","hasRightSlot","autoIcon","showFilePreview","showAutoIconInLeft","showAutoIconInRight","ImagePreview","ifDefined","LeftIconSlot","Boolean","RightIconSlot","FileControl","TextareaControl","live","TextInputControl","NumberButtons","PasswordToggle","ClearButton","Control","isFieldset","isInside","labelEl","fieldControls","defaultFieldContent","insideFieldContent","FileInfo","dependencies","SkyIcon","styles","css","shadowRootOptions","LitElement","delegatesFocus","__decorateClass","property","prototype","hasChanged","old","next","prev","reflect","query","customElement"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{css as e,LitElement as t,html as s}from"lit";import{property as i,queryAssignedElements as r,customElement as n}from"lit/decorators.js";import{PresetController as o}from"../helper/controllers/preset-controller.js";var
|
|
1
|
+
import{css as e,LitElement as t,html as s}from"lit";import{property as i,queryAssignedElements as r,customElement as n}from"lit/decorators.js";import{PresetController as o}from"../helper/controllers/preset-controller.js";import{arrayPropHasChanged as a,EMPTY_ARRAY as l,coerceArray as c}from"../helper/utils/stable-array.js";var h=Object.defineProperty,d=Object.getOwnPropertyDescriptor,u=(e,t,s,i)=>{for(var r,n=i>1?void 0:i?d(t,s):t,o=e.length-1;o>=0;o--)(r=e[o])&&(n=(i?r(t,s,n):r(n))||n);return i&&n&&h(t,s,n),n};let m=class extends t{constructor(){super(...arguments),this.preset="",this._presets=new o(this),this.selection="none",this._selectedValues=l,this.currentIndex=0,this._syncingSelectedValues=!1,this._onItemActivate=e=>this.onItemActivate(e),this._onSlotChange=()=>{this._applySelectedValuesFromProp(),this._focusFirstNavigable()}}get selectedValues(){return this._selectedValues}set selectedValues(e){this._selectedValues=c(e)}firstUpdated(){this.syncAriaRole(),this.addEventListener("keydown",this.onKeydown),this.addEventListener("item-activate",this._onItemActivate),this._applySelectedValuesFromProp(),this._focusFirstNavigable()}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("keydown",this.onKeydown),this.removeEventListener("item-activate",this._onItemActivate)}syncAriaRole(){if("none"===this.selection)return this.setAttribute("role","list"),void this.removeAttribute("aria-multiselectable");this.setAttribute("role","listbox"),"multiple"===this.selection?this.setAttribute("aria-multiselectable","true"):this.removeAttribute("aria-multiselectable")}navigableItems(){return(this.items??[]).filter(e=>this.isNavigableItem(e))}isNavigableItem(e){return!!e&&!e.disabled&&!e.subheader}itemIndex(e){return(this.items??[]).indexOf(e)}onItemActivate(e){const t=e.detail.item;if(!this.isNavigableItem(t))return;"single"===this.selection?(this.items.forEach(e=>e.setSelected(!1)),t.setSelected(!0)):"multiple"===this.selection&&t.setSelected(!t.selected);const s=this.items.filter(e=>e.selected),i=s.map(e=>e.value||"");this._syncingSelectedValues=!0,this.selectedValues=[...i],this._syncingSelectedValues=!1,this.dispatchEvent(new CustomEvent("list-change",{detail:{selectedItems:s,selectedValues:i},bubbles:!0,composed:!0}))}_applySelectedValuesFromProp(){if(!this.items?.length||"none"===this.selection)return;const e=new Set(this.selectedValues??[]);if("single"===this.selection){const t=[...e][0];for(const e of this.items)e.subheader||e.setSelected(void 0!==t&&e.value===t);return}for(const t of this.items)t.subheader||t.setSelected(e.has(t.value))}updated(e){super.updated(e),e.has("selection")&&this.syncAriaRole(),!e.has("selectedValues")&&!e.has("selection")||this._syncingSelectedValues||this._applySelectedValuesFromProp()}onKeydown(e){const t=this.navigableItems();if(t.length)switch(e.key){case"ArrowDown":e.preventDefault(),this.focusStep(1);break;case"ArrowUp":e.preventDefault(),this.focusStep(-1);break;case"Home":e.preventDefault(),this.focusItem(this.itemIndex(t[0]));break;case"End":e.preventDefault(),this.focusItem(this.itemIndex(t[t.length-1]));break;case" ":case"Enter":e.preventDefault(),this.items[this.currentIndex]?.dispatchEvent(new CustomEvent("item-activate",{detail:{item:this.items[this.currentIndex]},bubbles:!0,composed:!0}))}}focusStep(e){const t=this.navigableItems();if(!t.length)return;const s=this.items[this.currentIndex];let i=s?t.indexOf(s):-1;i<0&&(i=e>0?-1:t.length);const r=t[Math.max(0,Math.min(i+e,t.length-1))];r&&this.focusItem(this.itemIndex(r))}_focusFirstNavigable(){const e=this.navigableItems()[0];e&&this.focusItem(this.itemIndex(e))}focusItem(e){if(!this.items?.length)return;const t=this.items.length;let s=Math.max(0,Math.min(e,t-1));if(!this.isNavigableItem(this.items[s])){const e=this.navigableItems(),t=e.find(e=>this.itemIndex(e)>=s)??e[0];if(!t)return;s=this.itemIndex(t)}const i=this.items[this.currentIndex];i&&i.shadowRoot?.querySelector(".list-item")?.setAttribute("tabindex","-1"),this.currentIndex=s;const r=this.items[this.currentIndex];if(r&&this.isNavigableItem(r)){const e=r.shadowRoot?.querySelector(".list-item");e&&(e.setAttribute("tabindex","0"),e.focus())}}focusListItem(e){this.focusItem(e)}getItems(){return[...this.items??[]]}render(){return s`
|
|
2
2
|
<div class="list-container" part="list-container">
|
|
3
3
|
<slot @slotchange=${this._onSlotChange}></slot>
|
|
4
4
|
</div>
|
|
5
|
-
`}};
|
|
5
|
+
`}};m.styles=e`
|
|
6
6
|
:host {
|
|
7
7
|
display: block;
|
|
8
8
|
font-family: var(--sky-font);
|
|
@@ -27,5 +27,5 @@ import{css as e,LitElement as t,html as s}from"lit";import{property as i,queryAs
|
|
|
27
27
|
top: 0;
|
|
28
28
|
z-index: 1;
|
|
29
29
|
}
|
|
30
|
-
`,
|
|
30
|
+
`,u([i({type:String,reflect:!0})],m.prototype,"preset",2),u([i({type:String})],m.prototype,"selection",2),u([i({type:Array,hasChanged:a})],m.prototype,"selectedValues",1),u([r({flatten:!0})],m.prototype,"items",2),m=u([n("sky-list")],m);export{m as SkyList};
|
|
31
31
|
//# sourceMappingURL=sky-list.js.map
|