@aquera/nile-elements 1.6.1 → 1.6.2
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/README.md +6 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +953 -595
- package/dist/internal/enum.cjs.js +1 -1
- package/dist/internal/enum.cjs.js.map +1 -1
- package/dist/internal/enum.esm.js +1 -1
- package/dist/nile-badge/index.cjs.js +1 -1
- package/dist/nile-badge/index.esm.js +1 -1
- package/dist/nile-badge/nile-badge.cjs.js +1 -1
- package/dist/nile-badge/nile-badge.cjs.js.map +1 -1
- package/dist/nile-badge/nile-badge.esm.js +1 -1
- package/dist/nile-button/index.cjs.js +1 -1
- package/dist/nile-button/index.esm.js +1 -1
- package/dist/nile-button/nile-button.cjs.js +1 -1
- package/dist/nile-button/nile-button.cjs.js.map +1 -1
- package/dist/nile-button/nile-button.esm.js +1 -1
- package/dist/nile-carousel/index.cjs.js +1 -1
- package/dist/nile-carousel/index.esm.js +1 -1
- package/dist/nile-carousel/nile-carousel.cjs.js +1 -1
- package/dist/nile-carousel/nile-carousel.cjs.js.map +1 -1
- package/dist/nile-carousel/nile-carousel.esm.js +1 -1
- package/dist/nile-dialog/index.cjs.js +1 -1
- package/dist/nile-dialog/index.esm.js +1 -1
- package/dist/nile-dialog/nile-dialog.cjs.js +1 -1
- package/dist/nile-dialog/nile-dialog.cjs.js.map +1 -1
- package/dist/nile-dialog/nile-dialog.esm.js +1 -1
- package/dist/nile-drawer/index.cjs.js +1 -1
- package/dist/nile-drawer/index.esm.js +1 -1
- package/dist/nile-drawer/nile-drawer.cjs.js +1 -1
- package/dist/nile-drawer/nile-drawer.cjs.js.map +1 -1
- package/dist/nile-drawer/nile-drawer.esm.js +1 -1
- package/dist/nile-floating-panel/nile-floating-panel.cjs.js +1 -1
- package/dist/nile-floating-panel/nile-floating-panel.cjs.js.map +1 -1
- package/dist/nile-floating-panel/nile-floating-panel.esm.js +1 -1
- package/dist/nile-icon/icons/svg/folder_delete.cjs.js +2 -0
- package/dist/nile-icon/icons/svg/folder_delete.cjs.js.map +1 -0
- package/dist/nile-icon/icons/svg/folder_delete.esm.js +1 -0
- package/dist/nile-icon/icons/svg/index.cjs.js +1 -1
- package/dist/nile-icon/icons/svg/index.esm.js +1 -1
- package/dist/nile-icon/icons/svg/layers-three-02.cjs.js +1 -1
- package/dist/nile-icon/icons/svg/layers-three-02.cjs.js.map +1 -1
- package/dist/nile-icon/icons/svg/layers-three-02.esm.js +1 -1
- package/dist/nile-icon/index.cjs.js +1 -1
- package/dist/nile-icon/index.cjs.js.map +1 -1
- package/dist/nile-icon/index.esm.js +1 -1
- package/dist/nile-icon-button/index.cjs.js +1 -1
- package/dist/nile-icon-button/index.esm.js +1 -1
- package/dist/nile-icon-button/nile-icon-button.cjs.js +1 -1
- package/dist/nile-icon-button/nile-icon-button.cjs.js.map +1 -1
- package/dist/nile-icon-button/nile-icon-button.esm.js +1 -1
- package/dist/nile-input/index.cjs.js +1 -1
- package/dist/nile-input/index.esm.js +1 -1
- package/dist/nile-input/nile-input.cjs.js +1 -1
- package/dist/nile-input/nile-input.cjs.js.map +1 -1
- package/dist/nile-input/nile-input.esm.js +1 -1
- package/dist/nile-menu-item/index.cjs.js +1 -1
- package/dist/nile-menu-item/index.esm.js +1 -1
- package/dist/nile-menu-item/nile-menu-item.cjs.js +1 -1
- package/dist/nile-menu-item/nile-menu-item.cjs.js.map +1 -1
- package/dist/nile-menu-item/nile-menu-item.esm.js +1 -1
- package/dist/nile-option/index.cjs.js +1 -1
- package/dist/nile-option/index.esm.js +1 -1
- package/dist/nile-option/nile-option.cjs.js +1 -1
- package/dist/nile-option/nile-option.cjs.js.map +1 -1
- package/dist/nile-option/nile-option.esm.js +1 -1
- package/dist/nile-otp-input/index.cjs.js +2 -0
- package/dist/nile-otp-input/index.cjs.js.map +1 -0
- package/dist/nile-otp-input/index.esm.js +1 -0
- package/dist/nile-otp-input/nile-otp-input.cjs.js +2 -0
- package/dist/nile-otp-input/nile-otp-input.cjs.js.map +1 -0
- package/dist/nile-otp-input/nile-otp-input.css.cjs.js +2 -0
- package/dist/nile-otp-input/nile-otp-input.css.cjs.js.map +1 -0
- package/dist/nile-otp-input/nile-otp-input.css.esm.js +257 -0
- package/dist/nile-otp-input/nile-otp-input.enum.cjs.js +2 -0
- package/dist/nile-otp-input/nile-otp-input.enum.cjs.js.map +1 -0
- package/dist/nile-otp-input/nile-otp-input.enum.esm.js +1 -0
- package/dist/nile-otp-input/nile-otp-input.esm.js +103 -0
- package/dist/nile-select/index.cjs.js +1 -1
- package/dist/nile-select/index.esm.js +1 -1
- package/dist/nile-select/nile-select.cjs.js +1 -1
- package/dist/nile-select/nile-select.cjs.js.map +1 -1
- package/dist/nile-select/nile-select.esm.js +1 -1
- package/dist/nile-side-bar-action-menu-item/index.cjs.js +1 -1
- package/dist/nile-side-bar-action-menu-item/index.esm.js +1 -1
- package/dist/nile-side-bar-action-menu-item/nile-side-bar-action-menu-item.cjs.js +1 -1
- package/dist/nile-side-bar-action-menu-item/nile-side-bar-action-menu-item.cjs.js.map +1 -1
- package/dist/nile-side-bar-action-menu-item/nile-side-bar-action-menu-item.esm.js +1 -1
- package/dist/nile-tab/index.cjs.js +1 -1
- package/dist/nile-tab/index.esm.js +1 -1
- package/dist/nile-tab/nile-tab.cjs.js +1 -1
- package/dist/nile-tab/nile-tab.cjs.js.map +1 -1
- package/dist/nile-tab/nile-tab.esm.js +1 -1
- package/dist/nile-tab-group/index.cjs.js +1 -1
- package/dist/nile-tab-group/index.esm.js +1 -1
- package/dist/nile-tab-group/nile-tab-group.cjs.js +1 -1
- package/dist/nile-tab-group/nile-tab-group.cjs.js.map +1 -1
- package/dist/nile-tab-group/nile-tab-group.esm.js +1 -1
- package/dist/nile-tag/index.cjs.js +1 -1
- package/dist/nile-tag/index.esm.js +1 -1
- package/dist/nile-tag/nile-tag.cjs.js +1 -1
- package/dist/nile-tag/nile-tag.cjs.js.map +1 -1
- package/dist/nile-tag/nile-tag.esm.js +1 -1
- package/dist/nile-toast/index.cjs.js +1 -1
- package/dist/nile-toast/index.esm.js +1 -1
- package/dist/nile-toast/nile-toast.cjs.js +1 -1
- package/dist/nile-toast/nile-toast.cjs.js.map +1 -1
- package/dist/nile-toast/nile-toast.esm.js +1 -1
- package/dist/nile-tree/index.cjs.js +1 -1
- package/dist/nile-tree/index.esm.js +1 -1
- package/dist/nile-tree/nile-tree.cjs.js +1 -1
- package/dist/nile-tree/nile-tree.cjs.js.map +1 -1
- package/dist/nile-tree/nile-tree.esm.js +1 -1
- package/dist/nile-tree-item/index.cjs.js +1 -1
- package/dist/nile-tree-item/index.esm.js +1 -1
- package/dist/nile-tree-item/nile-tree-item.cjs.js +1 -1
- package/dist/nile-tree-item/nile-tree-item.cjs.js.map +1 -1
- package/dist/nile-tree-item/nile-tree-item.esm.js +1 -1
- package/dist/nile-virtual-select/index.cjs.js +1 -1
- package/dist/nile-virtual-select/index.esm.js +1 -1
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js +2 -2
- package/dist/nile-virtual-select/nile-virtual-select.esm.js +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/internal/enum.d.ts +21 -0
- package/dist/src/internal/enum.js +23 -1
- package/dist/src/internal/enum.js.map +1 -1
- package/dist/src/nile-floating-panel/nile-floating-panel.d.ts +2 -0
- package/dist/src/nile-floating-panel/nile-floating-panel.js +12 -1
- package/dist/src/nile-floating-panel/nile-floating-panel.js.map +1 -1
- package/dist/src/nile-icon/icons/svg/folder_delete.d.ts +5 -0
- package/dist/src/nile-icon/icons/svg/folder_delete.js +5 -0
- package/dist/src/nile-icon/icons/svg/folder_delete.js.map +1 -0
- package/dist/src/nile-icon/icons/svg/index.d.ts +1 -0
- package/dist/src/nile-icon/icons/svg/index.js +1 -0
- package/dist/src/nile-icon/icons/svg/index.js.map +1 -1
- package/dist/src/nile-icon/icons/svg/layers-three-02.d.ts +1 -1
- package/dist/src/nile-icon/icons/svg/layers-three-02.js +1 -1
- package/dist/src/nile-icon/icons/svg/layers-three-02.js.map +1 -1
- package/dist/src/nile-otp-input/index.d.ts +1 -0
- package/dist/src/nile-otp-input/index.js +2 -0
- package/dist/src/nile-otp-input/index.js.map +1 -0
- package/dist/src/nile-otp-input/nile-otp-input.css.d.ts +12 -0
- package/dist/src/nile-otp-input/nile-otp-input.css.js +269 -0
- package/dist/src/nile-otp-input/nile-otp-input.css.js.map +1 -0
- package/dist/src/nile-otp-input/nile-otp-input.d.ts +156 -0
- package/dist/src/nile-otp-input/nile-otp-input.enum.d.ts +26 -0
- package/dist/src/nile-otp-input/nile-otp-input.enum.js +32 -0
- package/dist/src/nile-otp-input/nile-otp-input.enum.js.map +1 -0
- package/dist/src/nile-otp-input/nile-otp-input.js +762 -0
- package/dist/src/nile-otp-input/nile-otp-input.js.map +1 -0
- package/dist/src/nile-otp-input/nile-otp-input.test.d.ts +1 -0
- package/dist/src/nile-otp-input/nile-otp-input.test.js +493 -0
- package/dist/src/nile-otp-input/nile-otp-input.test.js.map +1 -0
- package/dist/src/version.js +2 -2
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/plop-templates/lit/index.ts.hbs +1 -1
- package/plop-templates/lit/lit.css.ts.hbs +1 -1
- package/plop-templates/lit/lit.ts.hbs +1 -1
- package/src/index.ts +2 -1
- package/src/internal/enum.ts +23 -1
- package/src/nile-floating-panel/nile-floating-panel.ts +10 -1
- package/src/nile-icon/icons/svg/folder_delete.ts +5 -0
- package/src/nile-icon/icons/svg/index.ts +1 -0
- package/src/nile-icon/icons/svg/layers-three-02.ts +1 -1
- package/src/nile-otp-input/index.ts +1 -0
- package/src/nile-otp-input/nile-otp-input.css.ts +271 -0
- package/src/nile-otp-input/nile-otp-input.enum.ts +30 -0
- package/src/nile-otp-input/nile-otp-input.test.ts +732 -0
- package/src/nile-otp-input/nile-otp-input.ts +835 -0
- package/vscode-html-custom-data.json +171 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nile-otp-input.js","sourceRoot":"","sources":["../../../src/nile-otp-input/nile-otp-input.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Copyright Aquera Inc 2026\n *\n * This source code is licensed under the BSD-3-Clause license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { html } from 'lit';\nimport {\n customElement,\n property,\n query,\n queryAll,\n state,\n} from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { live } from 'lit/directives/live.js';\nimport { defaultValue } from '../internal/default-value';\nimport { FormControlController, validValidityState } from '../internal/form';\nimport { HasSlotController } from '../internal/slot';\nimport { watch } from '../internal/watch';\nimport NileElement from '../internal/nile-element';\nimport { KeyCode, Nile_Events } from '../internal/enum';\nimport type { CSSResultGroup } from 'lit';\nimport type { NileFormControl } from '../internal/nile-element';\nimport { styles } from './nile-otp-input.css';\nimport {\n OtpInputMode,\n OtpInputType,\n OtpEnterKeyHint,\n OtpAutoComplete,\n OtpCellPattern,\n} from './nile-otp-input.enum';\nimport '../nile-form-help-text';\nimport '../nile-form-error-message';\n\n/**\n * @summary OTP input renders a segmented set of cells but behaves like a single logical form control.\n * @tag nile-otp-input\n *\n * @slot label - The input label. Alternatively, use the `label` attribute.\n * @slot help-text - Helpful guidance text. Alternatively, use the `help-text` attribute.\n *\n * @event nile-input - Emitted whenever the OTP value changes from user input.\n * @event nile-change - Emitted whenever the OTP value changes from user input.\n * @event nile-complete - Emitted when all OTP cells are filled.\n * @event nile-focus - Emitted when focus enters the component.\n * @event nile-blur - Emitted when focus leaves the component.\n * @event nile-paste - Emitted when OTP text is pasted.\n * @event nile-invalid - Emitted when the control is invalid.\n *\n * @csspart form-control - Wrapper for label, input, and help/error content.\n * @csspart form-control-label - Label wrapper.\n * @csspart form-control-input - Input wrapper.\n * @csspart form-control-help-text - Help text wrapper.\n * @csspart form-control-error-message - Error message wrapper.\n * @csspart base - OTP cell container.\n * @csspart cell - Individual OTP cell.\n * @csspart separator - Separator element between cell groups.\n */\n@customElement('nile-otp-input')\nexport class NileOtpInput extends NileElement implements NileFormControl {\n static styles: CSSResultGroup = styles;\n\n private readonly formControlController: FormControlController =\n new FormControlController(this, {\n assumeInteractionOn: [Nile_Events.NILE_BLUR, Nile_Events.NILE_INPUT],\n });\n\n private readonly hasSlotController = new HasSlotController(\n this,\n 'help-text',\n 'label'\n );\n\n private customValidationMessage = '';\n private wasComplete = false;\n\n @query('.otp__value-input') valueInput: HTMLInputElement;\n @queryAll('.otp__cell') cellInputs: NodeListOf<HTMLInputElement>;\n\n @state() private hasFocus = false;\n @state() private activeIndex = -1;\n @state() private cells: string[] = this.createCells('');\n\n /** The name of the input, submitted as a name/value pair with form data. */\n @property({ reflect: true, type: String, attribute: true }) name = '';\n\n /** The current value of the OTP control. */\n @property({ reflect: true, type: String, attribute: true }) value = '';\n\n /** The default value of the form control. Primarily used for resetting the form control. */\n @defaultValue() defaultValue = '';\n\n /** Number of OTP cells. Values below 4 are clamped to 4. */\n @property({ type: Number, reflect: true, attribute: true }) length = 6;\n\n /** Restricts input to numeric digits when true. Overridden by `alphanumeric`. */\n @property({ type: Boolean, reflect: true, attribute: true }) numericOnly = true;\n\n /** Allows both letters and digits. When present, overrides `numeric-only`. */\n @property({ type: Boolean, reflect: true, attribute: true }) alphanumeric = false;\n\n /** The input's label. */\n @property({ reflect: true, attribute: true, type: String }) label = '';\n\n @property({ attribute: true, reflect: true, type: String }) helpText = '';\n\n @property({ attribute: true, reflect: true, type: String }) errorMessage = '';\n\n /** Placeholder shown inside each OTP cell. */\n @property({ reflect: true, attribute: true, type: String }) placeholder = '';\n\n /** Optional separator text rendered between configured OTP groups (for example \"-\"). */\n @property({ reflect: true, type: String }) separator = '';\n\n /** Renders a separator after each N cells when `separator` is set. */\n @property({ type: Number, attribute: true, reflect: true }) separatorEvery = 0;\n\n /** Comma-separated zero-based cell indexes after which separators are rendered. */\n @property({ attribute: 'separator-positions', type: String, reflect: true }) separatorPositions = '';\n\n /** Masks filled cells with dots, showing each character briefly while typing. */\n @property({ type: Boolean, reflect: true }) masked = false;\n\n /** Sets the input to a warning state, changing its visual appearance. */\n @property({ type: Boolean, attribute: true, reflect: true }) warning = false;\n\n /** Sets the input to an error state, changing its visual appearance. */\n @property({ type: Boolean, attribute: true, reflect: true }) error = false;\n\n /** Sets the input to a success state, changing its visual appearance. */\n @property({ type: Boolean, attribute: true, reflect: true }) success = false;\n\n /** Disables the control. */\n @property({ type: Boolean, reflect: true, attribute: true }) disabled = false;\n\n /** Makes the control readonly. */\n @property({ type: Boolean, attribute: true, reflect: true }) readonly = false;\n\n /**\n * By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you\n * to place the form control outside of a form and associate it with the form that has this `id`.\n */\n @property({ reflect: true, attribute: true, type: String }) form = '';\n\n /** Makes this field required. */\n @property({ type: Boolean, reflect: true, attribute: true }) required = false;\n\n /** Optional regex pattern for full OTP validation. */\n @property({ reflect: true, attribute: true, type: String }) pattern: string;\n\n /** Indicates that the input should receive focus on page load. */\n @property({ type: Boolean, reflect: true, attribute: true }) autofocus = false;\n\n /** Controls keyboard type shown on supporting virtual keyboards. */\n @property({ reflect: true, attribute: true, type: String }) inputmode:\n | 'none'\n | 'text'\n | 'decimal'\n | 'numeric'\n | 'tel'\n | 'search'\n | 'email'\n | 'url';\n\n /** The autocomplete mode used on the first OTP cell. */\n @property({ reflect: true, type: String }) autocomplete: string = OtpAutoComplete.ONE_TIME_CODE;\n\n connectedCallback() {\n super.connectedCallback();\n this.emit(Nile_Events.NILE_INIT);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.emit(Nile_Events.NILE_DESTROY);\n }\n\n firstUpdated() {\n const normalized = this.normalizeValue(this.value);\n if (normalized !== this.value) {\n this.value = normalized;\n return;\n }\n\n this.syncCellsFromValue(normalized);\n this.wasComplete = this.isComplete(normalized);\n this.valueInput.setCustomValidity(this.customValidationMessage);\n this.formControlController.updateValidity();\n\n if (this.autofocus) {\n this.focus();\n }\n }\n\n /** Gets the validity state object. */\n get validity() {\n return this.valueInput?.validity ?? validValidityState;\n }\n\n /** Gets the validation message. */\n get validationMessage() {\n return this.valueInput?.validationMessage ?? '';\n }\n\n /** Returns true when all OTP cells have values. */\n get complete() {\n return this.isComplete(this.value);\n }\n\n private getNormalizedLength() {\n const parsed = Number.isFinite(this.length) ? Math.trunc(this.length) : 6;\n return Math.max(4, parsed);\n }\n\n private isNumericMode() {\n return this.numericOnly && !this.alphanumeric;\n }\n\n private getResolvedInputMode() {\n return this.inputmode ?? (this.isNumericMode() ? OtpInputMode.NUMERIC : OtpInputMode.TEXT);\n }\n\n private getValidationPattern() {\n if (this.pattern) {\n return this.pattern;\n }\n\n const normalizedLength = this.getNormalizedLength();\n return this.isNumericMode()\n ? `[0-9]{${normalizedLength}}`\n : `[A-Za-z0-9]{${normalizedLength}}`;\n }\n\n private isAllowedCharacter(char: string) {\n return this.isNumericMode() ? /^[0-9]$/.test(char) : /^[A-Za-z0-9]$/.test(char);\n }\n\n private toOtpCharacters(value: string) {\n return Array.from(value ?? '').filter(char =>\n this.isAllowedCharacter(char)\n );\n }\n\n private normalizeValue(value: string) {\n return this.toOtpCharacters(value ?? '')\n .slice(0, this.getNormalizedLength())\n .join('');\n }\n\n private createCells(value: string) {\n const normalizedLength = this.getNormalizedLength();\n const normalizedChars = this.toOtpCharacters(value).slice(\n 0,\n normalizedLength\n );\n return Array.from(\n { length: normalizedLength },\n (_, index) => normalizedChars[index] ?? ''\n );\n }\n\n private syncCellsFromValue(value: string) {\n this.cells = this.createCells(value);\n }\n\n private isComplete(value: string) {\n return value.length === this.getNormalizedLength();\n }\n\n private getFirstEmptyIndex() {\n const index = this.cells.findIndex(char => char === '');\n return index === -1 ? this.getNormalizedLength() - 1 : index;\n }\n\n private getSeparatorIndices() {\n const maxIndex = this.getNormalizedLength() - 2;\n const indices = new Set<number>();\n\n if (Number.isInteger(this.separatorEvery) && this.separatorEvery > 0) {\n for (\n let index = this.separatorEvery - 1;\n index <= maxIndex;\n index += this.separatorEvery\n ) {\n indices.add(index);\n }\n }\n\n if (this.separatorPositions.trim().length > 0) {\n this.separatorPositions\n .split(',')\n .map(value => Number.parseInt(value.trim(), 10))\n .filter(\n index => Number.isInteger(index) && index >= 0 && index <= maxIndex\n )\n .forEach(index => indices.add(index));\n }\n\n return indices;\n }\n\n private getCellPlaceholder(index: number) {\n if (!this.placeholder || this.cells[index]) {\n return undefined;\n }\n\n if (this.activeIndex === -1) {\n return index === this.getFirstEmptyIndex() ? this.placeholder : undefined;\n }\n\n return index === this.activeIndex ? this.placeholder : undefined;\n }\n\n private focusCell(index: number, options?: FocusOptions) {\n const input = this.cellInputs?.[index];\n if (input) {\n input.focus(options);\n input.select();\n }\n }\n\n private updateCell(index: number, value: string) {\n const nextCells = [...this.cells];\n nextCells[index] = value;\n this.cells = nextCells;\n }\n\n private fillFromIndex(startIndex: number, chars: string[]) {\n const nextCells = [...this.cells];\n let cursor = startIndex;\n\n for (const char of chars) {\n if (cursor >= nextCells.length) {\n break;\n }\n\n nextCells[cursor] = char;\n cursor += 1;\n }\n\n this.cells = nextCells;\n return cursor;\n }\n\n private commitUserValueUpdate() {\n const previousValue = this.value;\n const nextValue = this.cells.join('');\n const isNowComplete = this.isComplete(nextValue);\n\n this.value = nextValue;\n this.valueInput.value = nextValue;\n this.valueInput.setCustomValidity(this.customValidationMessage);\n this.formControlController.updateValidity();\n\n this.emit(Nile_Events.NILE_INPUT, { value: nextValue, complete: isNowComplete });\n if (previousValue !== nextValue) {\n this.emit(Nile_Events.NILE_CHANGE, { value: nextValue, complete: isNowComplete });\n }\n\n if (isNowComplete && !this.wasComplete) {\n this.emit(Nile_Events.NILE_COMPLETE, { value: nextValue });\n }\n\n this.wasComplete = isNowComplete;\n }\n\n private handleInvalid(event: Event) {\n this.formControlController.setValidity(false);\n this.formControlController.emitInvalidEvent(event);\n }\n\n private handleCellFocus(event: Event) {\n const target = event.target as HTMLInputElement;\n const index = Number(target.dataset.index ?? -1);\n const firstEmpty = this.getFirstEmptyIndex();\n\n if (index > firstEmpty) {\n this.focusCell(firstEmpty);\n return;\n }\n\n if (index < firstEmpty && !this.cells[index]) {\n this.focusCell(firstEmpty);\n return;\n }\n\n this.activeIndex = index;\n target.select();\n\n if (!this.hasFocus) {\n this.hasFocus = true;\n this.emit(Nile_Events.NILE_FOCUS, { value: this.value });\n }\n }\n\n private handleCellBlur() {\n queueMicrotask(() => {\n const active = this.shadowRoot?.activeElement;\n const isInsideOtp =\n active instanceof HTMLInputElement &&\n active.classList.contains('otp__cell');\n\n if (!isInsideOtp && this.hasFocus) {\n this.hasFocus = false;\n this.activeIndex = -1;\n this.emit(Nile_Events.NILE_BLUR, { value: this.value });\n }\n });\n }\n\n private handleCellInput(event: Event) {\n const target = event.target as HTMLInputElement;\n const index = Number(target.dataset.index ?? 0);\n\n if (this.disabled || this.readonly) {\n target.value = this.cells[index] ?? '';\n return;\n }\n\n const chars = this.toOtpCharacters(target.value);\n\n if (chars.length === 0) {\n this.updateCell(index, '');\n this.commitUserValueUpdate();\n return;\n }\n\n if (chars.length === 1) {\n this.updateCell(index, chars[0]);\n this.commitUserValueUpdate();\n\n const nextEmpty = this.getFirstEmptyIndex();\n this.focusCell(nextEmpty);\n return;\n }\n\n const nextCursor = this.fillFromIndex(index, chars);\n this.commitUserValueUpdate();\n const nextEmpty = this.getFirstEmptyIndex();\n this.focusCell(nextEmpty);\n }\n\n private handleCellPaste(event: ClipboardEvent) {\n if (this.disabled || this.readonly) {\n return;\n }\n\n const pasted = event.clipboardData?.getData('text') ?? '';\n const chars = this.toOtpCharacters(pasted);\n\n if (!chars.length) {\n return;\n }\n\n event.preventDefault();\n\n this.fillFromIndex(0, chars);\n this.commitUserValueUpdate();\n const nextEmpty = this.getFirstEmptyIndex();\n this.focusCell(nextEmpty);\n this.emit(Nile_Events.NILE_PASTE, { value: this.value });\n }\n\n private handleCellKeyDown(event: KeyboardEvent) {\n const hasModifier = event.metaKey || event.ctrlKey || event.altKey;\n const target = event.target as HTMLInputElement;\n const index = Number(target.dataset.index ?? 0);\n\n if (event.key === KeyCode.ENTER && !hasModifier && !event.shiftKey) {\n setTimeout(() => {\n if (!event.defaultPrevented && !event.isComposing) {\n this.formControlController.submit();\n }\n });\n return;\n }\n\n if (this.disabled || this.readonly) {\n return;\n }\n\n const isHandledKey =\n event.key === KeyCode.BACKSPACE ||\n event.key === KeyCode.DELETE ||\n event.key === KeyCode.ARROW_LEFT ||\n event.key === KeyCode.ARROW_RIGHT ||\n event.key === KeyCode.HOME ||\n event.key === KeyCode.END ||\n event.key === KeyCode.SPACE ||\n (event.key.length === 1 && !hasModifier);\n\n if (!isHandledKey) {\n return;\n }\n\n event.preventDefault();\n\n if (event.key === KeyCode.BACKSPACE) {\n if (this.cells[index]) {\n this.updateCell(index, '');\n this.commitUserValueUpdate();\n if (index > 0) {\n this.focusCell(index - 1);\n }\n return;\n }\n\n if (index > 0) {\n this.updateCell(index - 1, '');\n this.commitUserValueUpdate();\n this.focusCell(index - 1);\n }\n\n return;\n }\n\n if (event.key === KeyCode.DELETE) {\n if (this.cells[index]) {\n this.updateCell(index, '');\n this.commitUserValueUpdate();\n }\n return;\n }\n\n if (event.key === KeyCode.ARROW_LEFT) {\n if (index > 0) {\n this.focusCell(index - 1);\n }\n return;\n }\n\n if (event.key === KeyCode.ARROW_RIGHT) {\n const firstEmpty = this.getFirstEmptyIndex();\n if (index < firstEmpty) {\n this.focusCell(index + 1);\n }\n return;\n }\n\n if (event.key === KeyCode.HOME) {\n this.focusCell(0);\n return;\n }\n\n if (event.key === KeyCode.END) {\n this.focusCell(this.getFirstEmptyIndex());\n return;\n }\n\n if (event.key === KeyCode.SPACE) {\n return;\n }\n\n if (event.key.length === 1 && !hasModifier && this.isAllowedCharacter(event.key)) {\n this.updateCell(index, event.key);\n this.commitUserValueUpdate();\n const nextEmpty = this.getFirstEmptyIndex();\n this.focusCell(nextEmpty);\n }\n }\n\n @watch('length', { waitUntilFirstUpdate: true })\n handleLengthChange() {\n const normalizedLength = this.getNormalizedLength();\n if (this.length !== normalizedLength) {\n this.length = normalizedLength;\n return;\n }\n\n const normalizedValue = this.normalizeValue(this.value);\n this.syncCellsFromValue(normalizedValue);\n\n if (normalizedValue !== this.value) {\n this.value = normalizedValue;\n return;\n }\n\n this.wasComplete = this.isComplete(normalizedValue);\n this.valueInput.value = normalizedValue;\n this.valueInput.setCustomValidity(this.customValidationMessage);\n this.formControlController.updateValidity();\n }\n\n @watch('value', { waitUntilFirstUpdate: true })\n handleValueChange() {\n const normalizedValue = this.normalizeValue(this.value);\n if (normalizedValue !== this.value) {\n this.value = normalizedValue;\n return;\n }\n\n this.syncCellsFromValue(normalizedValue);\n this.wasComplete = this.isComplete(normalizedValue);\n this.valueInput.value = normalizedValue;\n this.valueInput.setCustomValidity(this.customValidationMessage);\n this.formControlController.updateValidity();\n }\n\n @watch('disabled', { waitUntilFirstUpdate: true })\n handleDisabledChange() {\n if (this.disabled) {\n this.hasFocus = false;\n this.activeIndex = -1;\n this.formControlController.setValidity(true);\n } else {\n this.formControlController.updateValidity();\n }\n }\n\n @watch('numericOnly', { waitUntilFirstUpdate: true })\n handleNumericOnlyChange() {\n const normalizedValue = this.normalizeValue(this.value);\n if (normalizedValue !== this.value) {\n this.value = normalizedValue;\n return;\n }\n\n this.syncCellsFromValue(normalizedValue);\n this.wasComplete = this.isComplete(normalizedValue);\n this.valueInput.value = normalizedValue;\n this.valueInput.setCustomValidity(this.customValidationMessage);\n this.formControlController.updateValidity();\n }\n\n @watch('pattern', { waitUntilFirstUpdate: true })\n handlePatternChange() {\n this.valueInput.setCustomValidity(this.customValidationMessage);\n this.formControlController.updateValidity();\n }\n\n /** Checks validity without showing browser UI. */\n checkValidity() {\n return this.valueInput.checkValidity();\n }\n\n /** Returns associated form if one exists. */\n getForm(): HTMLFormElement | null {\n return this.formControlController.getForm();\n }\n\n /** Checks validity and shows browser UI when invalid. */\n reportValidity() {\n return this.valueInput.reportValidity();\n }\n\n /** Sets a custom validation message. Pass empty string to restore validity. */\n setCustomValidity(message: string) {\n this.customValidationMessage = message;\n if (this.valueInput) {\n this.valueInput.setCustomValidity(message);\n }\n this.formControlController.updateValidity();\n }\n\n /** Focuses the first empty cell, or the last one when complete. */\n focus(options?: FocusOptions) {\n this.focusCell(this.getFirstEmptyIndex(), options);\n }\n\n /** Removes focus from whichever OTP cell is currently focused. */\n blur() {\n const active = this.shadowRoot?.activeElement;\n if (active instanceof HTMLElement) {\n active.blur();\n }\n }\n\n /** Clears all OTP cells. */\n clear() {\n if (this.disabled || this.readonly) {\n return;\n }\n\n this.cells = Array.from({ length: this.getNormalizedLength() }, () => '');\n this.commitUserValueUpdate();\n this.focusCell(0);\n }\n\n render() {\n const normalizedLength = this.getNormalizedLength();\n const separatorIndices = this.getSeparatorIndices();\n const hasLabelSlot = this.hasSlotController.test('label');\n const hasHelpTextSlot = this.hasSlotController.test('help-text');\n const hasLabel = Boolean(this.label || hasLabelSlot);\n const hasHelpText = Boolean(this.helpText || hasHelpTextSlot);\n const hasErrorMessage = Boolean(this.errorMessage);\n const describedBy = [\n hasHelpText ? 'help-text' : '',\n hasErrorMessage ? 'error-message' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return html`\n <div\n part=\"form-control\"\n class=${classMap({\n 'form-control': true,\n 'form-control--has-label': hasLabel,\n })}\n >\n <label\n id=\"label\"\n part=\"form-control-label\"\n class=\"form-control__label\"\n aria-hidden=${hasLabel ? 'false' : 'true'}\n >\n <slot name=\"label\">${this.label}</slot>\n </label>\n\n <div part=\"form-control-input\" class=\"form-control-input\">\n <div\n part=\"base\"\n class=${classMap({\n otp: true,\n 'otp--warning': this.warning,\n 'otp--error': this.error,\n 'otp--success': this.success,\n 'otp--disabled': this.disabled,\n 'otp--readonly': this.readonly,\n })}\n role=\"group\"\n aria-labelledby=${ifDefined(hasLabel ? 'label' : undefined)}\n aria-label=${ifDefined(hasLabel ? undefined : 'One-time password')}\n aria-describedby=${ifDefined(describedBy || undefined)}\n aria-disabled=${this.disabled ? 'true' : 'false'}\n >\n ${Array.from({ length: normalizedLength }, (_, index) => {\n const value = this.cells[index] ?? '';\n return html`\n <input\n part=\"cell\"\n class=${classMap({\n otp__cell: true,\n 'otp__cell--active': this.activeIndex === index,\n })}\n data-index=${index}\n type=${this.masked && value && this.activeIndex !== index ? OtpInputType.PASSWORD : OtpInputType.TEXT}\n maxlength=\"1\"\n .value=${live(value)}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n placeholder=${ifDefined(this.getCellPlaceholder(index))}\n inputmode=${ifDefined(this.getResolvedInputMode())}\n pattern=${this.isNumericMode() ? OtpCellPattern.NUMERIC : OtpCellPattern.ALPHANUMERIC}\n autocapitalize=\"none\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n autocomplete=${index === 0 ? this.autocomplete : OtpAutoComplete.OFF}\n enterkeyhint=${index === normalizedLength - 1\n ? OtpEnterKeyHint.DONE\n : OtpEnterKeyHint.NEXT}\n aria-label=${`Digit ${index + 1} of ${normalizedLength}`}\n aria-describedby=${ifDefined(describedBy || undefined)}\n aria-invalid=${this.hasAttribute('data-user-invalid')\n ? 'true'\n : 'false'}\n @focus=${this.handleCellFocus}\n @blur=${this.handleCellBlur}\n @keydown=${this.handleCellKeyDown}\n @input=${this.handleCellInput}\n @paste=${this.handleCellPaste}\n />\n ${this.separator && separatorIndices.has(index)\n ? html`\n <span\n class=\"otp__separator\"\n part=\"separator\"\n aria-hidden=\"true\"\n >\n ${this.separator}\n </span>\n `\n : ''}\n `;\n })}\n\n <input\n class=\"otp__value-input\"\n type=\"text\"\n .value=${live(this.value)}\n ?required=${this.required}\n ?disabled=${this.disabled}\n minlength=${normalizedLength}\n maxlength=${normalizedLength}\n pattern=${this.getValidationPattern()}\n tabindex=\"-1\"\n aria-hidden=\"true\"\n @focus=${() => this.focus()}\n @invalid=${this.handleInvalid}\n />\n </div>\n </div>\n\n ${hasHelpText\n ? html`\n <div\n id=\"help-text\"\n part=\"form-control-help-text\"\n class=\"form-control__help-text\"\n >\n <nile-form-help-text>\n <slot name=\"help-text\">${this.helpText}</slot>\n </nile-form-help-text>\n </div>\n `\n : ``}\n ${hasErrorMessage\n ? html`\n <div\n id=\"error-message\"\n part=\"form-control-error-message\"\n class=\"form-control__error-message\"\n >\n <nile-form-error-message\n >${this.errorMessage}</nile-form-error-message\n >\n </div>\n `\n : ``}\n </div>\n `;\n }\n}\n\nexport default NileOtpInput;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nile-otp-input': NileOtpInput;\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './nile-otp-input';
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import { aTimeout, expect, fixture, html } from '@open-wc/testing';
|
|
2
|
+
import './nile-otp-input';
|
|
3
|
+
const getCells = (el) => Array.from(el.shadowRoot.querySelectorAll('.otp__cell'));
|
|
4
|
+
const inputCell = async (el, index, value) => {
|
|
5
|
+
const cell = getCells(el)[index];
|
|
6
|
+
cell.value = value;
|
|
7
|
+
cell.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
8
|
+
await el.updateComplete;
|
|
9
|
+
return cell;
|
|
10
|
+
};
|
|
11
|
+
const pressKey = async (el, index, key, opts = {}) => {
|
|
12
|
+
const cell = getCells(el)[index];
|
|
13
|
+
cell.dispatchEvent(new KeyboardEvent('keydown', {
|
|
14
|
+
key,
|
|
15
|
+
bubbles: true,
|
|
16
|
+
composed: true,
|
|
17
|
+
cancelable: true,
|
|
18
|
+
...opts,
|
|
19
|
+
}));
|
|
20
|
+
await el.updateComplete;
|
|
21
|
+
return cell;
|
|
22
|
+
};
|
|
23
|
+
const pasteInto = async (el, index, text) => {
|
|
24
|
+
const cell = getCells(el)[index];
|
|
25
|
+
const event = new Event('paste', {
|
|
26
|
+
bubbles: true,
|
|
27
|
+
composed: true,
|
|
28
|
+
cancelable: true,
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(event, 'clipboardData', {
|
|
31
|
+
value: { getData: () => text },
|
|
32
|
+
});
|
|
33
|
+
cell.dispatchEvent(event);
|
|
34
|
+
await el.updateComplete;
|
|
35
|
+
};
|
|
36
|
+
describe('NileOtpInput', () => {
|
|
37
|
+
// ---- Rendering ----
|
|
38
|
+
it('renders default 6 cells', async () => {
|
|
39
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
40
|
+
expect(el).to.exist;
|
|
41
|
+
expect(getCells(el).length).to.equal(6);
|
|
42
|
+
});
|
|
43
|
+
it('normalizes incoming value (strips non-numeric in numeric mode)', async () => {
|
|
44
|
+
const el = await fixture(html `<nile-otp-input value="12A34B"></nile-otp-input>`);
|
|
45
|
+
await el.updateComplete;
|
|
46
|
+
expect(el.value).to.equal('1234');
|
|
47
|
+
expect(getCells(el).map(c => c.value)).to.deep.equal([
|
|
48
|
+
'1', '2', '3', '4', '', '',
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
it('supports configurable length and clamps below 4', async () => {
|
|
52
|
+
const el = await fixture(html `<nile-otp-input length="8"></nile-otp-input>`);
|
|
53
|
+
expect(getCells(el).length).to.equal(8);
|
|
54
|
+
el.length = 2;
|
|
55
|
+
await el.updateComplete;
|
|
56
|
+
expect(el.length).to.equal(4);
|
|
57
|
+
expect(getCells(el).length).to.equal(4);
|
|
58
|
+
});
|
|
59
|
+
it('renders label when provided', async () => {
|
|
60
|
+
const el = await fixture(html `<nile-otp-input label="Verification code"></nile-otp-input>`);
|
|
61
|
+
const label = el.shadowRoot.querySelector('.form-control__label');
|
|
62
|
+
expect(label).to.exist;
|
|
63
|
+
expect(label.textContent).to.contain('Verification code');
|
|
64
|
+
});
|
|
65
|
+
it('renders help text when provided', async () => {
|
|
66
|
+
const el = await fixture(html `<nile-otp-input help-text="Enter your code"></nile-otp-input>`);
|
|
67
|
+
const helpText = el.shadowRoot.querySelector('.form-control__help-text');
|
|
68
|
+
expect(helpText).to.exist;
|
|
69
|
+
expect(helpText.textContent).to.contain('Enter your code');
|
|
70
|
+
});
|
|
71
|
+
it('renders error message when provided', async () => {
|
|
72
|
+
const el = await fixture(html `<nile-otp-input error-message="Invalid code"></nile-otp-input>`);
|
|
73
|
+
const errorMsg = el.shadowRoot.querySelector('.form-control__error-message');
|
|
74
|
+
expect(errorMsg).to.exist;
|
|
75
|
+
expect(errorMsg.textContent).to.contain('Invalid code');
|
|
76
|
+
});
|
|
77
|
+
it('renders separators with separator-every', async () => {
|
|
78
|
+
const el = await fixture(html `
|
|
79
|
+
<nile-otp-input separator="-" separator-every="3"></nile-otp-input>
|
|
80
|
+
`);
|
|
81
|
+
const separators = el.shadowRoot.querySelectorAll('.otp__separator');
|
|
82
|
+
expect(separators.length).to.equal(1);
|
|
83
|
+
expect(separators[0].textContent.trim()).to.equal('-');
|
|
84
|
+
});
|
|
85
|
+
it('renders separators from separator-positions', async () => {
|
|
86
|
+
const el = await fixture(html `
|
|
87
|
+
<nile-otp-input
|
|
88
|
+
length="8"
|
|
89
|
+
separator="/"
|
|
90
|
+
separator-positions="1, 3, 5"
|
|
91
|
+
></nile-otp-input>
|
|
92
|
+
`);
|
|
93
|
+
const separators = el.shadowRoot.querySelectorAll('.otp__separator');
|
|
94
|
+
expect(separators.length).to.equal(3);
|
|
95
|
+
separators.forEach(s => expect(s.textContent.trim()).to.equal('/'));
|
|
96
|
+
});
|
|
97
|
+
// ---- Input behavior ----
|
|
98
|
+
it('auto-advances focus to next empty cell after typing', async () => {
|
|
99
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
100
|
+
const cells = getCells(el);
|
|
101
|
+
cells[0].focus();
|
|
102
|
+
await inputCell(el, 0, '1');
|
|
103
|
+
await aTimeout(0);
|
|
104
|
+
expect(el.value).to.equal('1');
|
|
105
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[1]);
|
|
106
|
+
});
|
|
107
|
+
it('typing a character on a filled cell replaces it and advances', async () => {
|
|
108
|
+
const el = await fixture(html `<nile-otp-input value="123456"></nile-otp-input>`);
|
|
109
|
+
await el.updateComplete;
|
|
110
|
+
const cells = getCells(el);
|
|
111
|
+
cells[2].focus();
|
|
112
|
+
await el.updateComplete;
|
|
113
|
+
await pressKey(el, 2, '9');
|
|
114
|
+
await aTimeout(0);
|
|
115
|
+
expect(el.value[2]).to.equal('9');
|
|
116
|
+
});
|
|
117
|
+
it('blocks invalid characters in numeric mode', async () => {
|
|
118
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
119
|
+
const first = getCells(el)[0];
|
|
120
|
+
first.focus();
|
|
121
|
+
const event = new KeyboardEvent('keydown', {
|
|
122
|
+
key: 'A',
|
|
123
|
+
bubbles: true,
|
|
124
|
+
composed: true,
|
|
125
|
+
cancelable: true,
|
|
126
|
+
});
|
|
127
|
+
first.dispatchEvent(event);
|
|
128
|
+
expect(event.defaultPrevented).to.be.true;
|
|
129
|
+
});
|
|
130
|
+
it('allows alphanumeric values when alphanumeric attribute is set', async () => {
|
|
131
|
+
const el = await fixture(html `<nile-otp-input alphanumeric></nile-otp-input>`);
|
|
132
|
+
const cells = getCells(el);
|
|
133
|
+
cells[0].focus();
|
|
134
|
+
await el.updateComplete;
|
|
135
|
+
await pressKey(el, 0, 'A');
|
|
136
|
+
expect(el.value).to.equal('A');
|
|
137
|
+
});
|
|
138
|
+
it('alphanumeric overrides numeric-only', async () => {
|
|
139
|
+
const el = await fixture(html `<nile-otp-input numeric-only alphanumeric></nile-otp-input>`);
|
|
140
|
+
const cells = getCells(el);
|
|
141
|
+
cells[0].focus();
|
|
142
|
+
await el.updateComplete;
|
|
143
|
+
await pressKey(el, 0, 'B');
|
|
144
|
+
expect(el.value).to.equal('B');
|
|
145
|
+
});
|
|
146
|
+
it('supports controlled value updates', async () => {
|
|
147
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
148
|
+
el.value = '2468';
|
|
149
|
+
await el.updateComplete;
|
|
150
|
+
expect(getCells(el).map(c => c.value)).to.deep.equal([
|
|
151
|
+
'2', '4', '6', '8', '', '',
|
|
152
|
+
]);
|
|
153
|
+
});
|
|
154
|
+
// ---- Focus management (ShadCN style) ----
|
|
155
|
+
it('focus() targets the first empty cell', async () => {
|
|
156
|
+
const el = await fixture(html `<nile-otp-input value="12"></nile-otp-input>`);
|
|
157
|
+
await el.updateComplete;
|
|
158
|
+
const cells = getCells(el);
|
|
159
|
+
el.focus();
|
|
160
|
+
await aTimeout(0);
|
|
161
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[2]);
|
|
162
|
+
});
|
|
163
|
+
it('clicking an empty cell beyond the cursor redirects to first empty', async () => {
|
|
164
|
+
const el = await fixture(html `<nile-otp-input value="12"></nile-otp-input>`);
|
|
165
|
+
await el.updateComplete;
|
|
166
|
+
const cells = getCells(el);
|
|
167
|
+
cells[5].focus();
|
|
168
|
+
await aTimeout(0);
|
|
169
|
+
await el.updateComplete;
|
|
170
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[2]);
|
|
171
|
+
});
|
|
172
|
+
it('clicking a filled cell focuses it directly', async () => {
|
|
173
|
+
const el = await fixture(html `<nile-otp-input value="123"></nile-otp-input>`);
|
|
174
|
+
await el.updateComplete;
|
|
175
|
+
const cells = getCells(el);
|
|
176
|
+
cells[1].focus();
|
|
177
|
+
await aTimeout(0);
|
|
178
|
+
await el.updateComplete;
|
|
179
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[1]);
|
|
180
|
+
});
|
|
181
|
+
// ---- Keyboard navigation ----
|
|
182
|
+
it('Backspace clears current cell and retreats', async () => {
|
|
183
|
+
const el = await fixture(html `<nile-otp-input value="123"></nile-otp-input>`);
|
|
184
|
+
await el.updateComplete;
|
|
185
|
+
const cells = getCells(el);
|
|
186
|
+
cells[2].focus();
|
|
187
|
+
await pressKey(el, 2, 'Backspace');
|
|
188
|
+
await aTimeout(0);
|
|
189
|
+
expect(el.value).to.equal('12');
|
|
190
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[1]);
|
|
191
|
+
});
|
|
192
|
+
it('Backspace on empty cell clears previous and moves there', async () => {
|
|
193
|
+
const el = await fixture(html `<nile-otp-input value="12"></nile-otp-input>`);
|
|
194
|
+
await el.updateComplete;
|
|
195
|
+
const cells = getCells(el);
|
|
196
|
+
cells[2].focus();
|
|
197
|
+
await pressKey(el, 2, 'Backspace');
|
|
198
|
+
await aTimeout(0);
|
|
199
|
+
expect(el.value).to.equal('1');
|
|
200
|
+
expect(cells[1].value).to.equal('');
|
|
201
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[1]);
|
|
202
|
+
});
|
|
203
|
+
it('Delete clears current cell without moving', async () => {
|
|
204
|
+
const el = await fixture(html `<nile-otp-input value="123"></nile-otp-input>`);
|
|
205
|
+
await el.updateComplete;
|
|
206
|
+
const cells = getCells(el);
|
|
207
|
+
cells[1].focus();
|
|
208
|
+
await pressKey(el, 1, 'Delete');
|
|
209
|
+
await aTimeout(0);
|
|
210
|
+
expect(cells[1].value).to.equal('');
|
|
211
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[1]);
|
|
212
|
+
});
|
|
213
|
+
it('ArrowLeft moves focus back', async () => {
|
|
214
|
+
const el = await fixture(html `<nile-otp-input value="123"></nile-otp-input>`);
|
|
215
|
+
await el.updateComplete;
|
|
216
|
+
const cells = getCells(el);
|
|
217
|
+
cells[2].focus();
|
|
218
|
+
await pressKey(el, 2, 'ArrowLeft');
|
|
219
|
+
await aTimeout(0);
|
|
220
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[1]);
|
|
221
|
+
});
|
|
222
|
+
it('ArrowRight cannot move past the first empty cell', async () => {
|
|
223
|
+
const el = await fixture(html `<nile-otp-input value="12"></nile-otp-input>`);
|
|
224
|
+
await el.updateComplete;
|
|
225
|
+
const cells = getCells(el);
|
|
226
|
+
cells[1].focus();
|
|
227
|
+
await pressKey(el, 1, 'ArrowRight');
|
|
228
|
+
await aTimeout(0);
|
|
229
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[2]);
|
|
230
|
+
await pressKey(el, 2, 'ArrowRight');
|
|
231
|
+
await aTimeout(0);
|
|
232
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[2]);
|
|
233
|
+
});
|
|
234
|
+
it('Home goes to first cell', async () => {
|
|
235
|
+
const el = await fixture(html `<nile-otp-input value="123"></nile-otp-input>`);
|
|
236
|
+
await el.updateComplete;
|
|
237
|
+
const cells = getCells(el);
|
|
238
|
+
cells[2].focus();
|
|
239
|
+
await pressKey(el, 2, 'Home');
|
|
240
|
+
await aTimeout(0);
|
|
241
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[0]);
|
|
242
|
+
});
|
|
243
|
+
it('End goes to first empty cell', async () => {
|
|
244
|
+
const el = await fixture(html `<nile-otp-input value="123"></nile-otp-input>`);
|
|
245
|
+
await el.updateComplete;
|
|
246
|
+
const cells = getCells(el);
|
|
247
|
+
cells[0].focus();
|
|
248
|
+
await pressKey(el, 0, 'End');
|
|
249
|
+
await aTimeout(0);
|
|
250
|
+
expect(el.shadowRoot.activeElement).to.equal(cells[3]);
|
|
251
|
+
});
|
|
252
|
+
it('Space is blocked', async () => {
|
|
253
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
254
|
+
const cells = getCells(el);
|
|
255
|
+
cells[0].focus();
|
|
256
|
+
const event = new KeyboardEvent('keydown', {
|
|
257
|
+
key: ' ',
|
|
258
|
+
bubbles: true,
|
|
259
|
+
composed: true,
|
|
260
|
+
cancelable: true,
|
|
261
|
+
});
|
|
262
|
+
cells[0].dispatchEvent(event);
|
|
263
|
+
expect(event.defaultPrevented).to.be.true;
|
|
264
|
+
});
|
|
265
|
+
// ---- Paste ----
|
|
266
|
+
it('paste fills from position 0 and focuses next empty', async () => {
|
|
267
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
268
|
+
await pasteInto(el, 3, '987654');
|
|
269
|
+
expect(el.value).to.equal('987654');
|
|
270
|
+
expect(getCells(el).map(c => c.value).join('')).to.equal('987654');
|
|
271
|
+
});
|
|
272
|
+
it('paste emits nile-paste event', async () => {
|
|
273
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
274
|
+
let pasteValue = '';
|
|
275
|
+
el.addEventListener('nile-paste', (e) => {
|
|
276
|
+
pasteValue = e.detail.value;
|
|
277
|
+
});
|
|
278
|
+
await pasteInto(el, 0, '123456');
|
|
279
|
+
expect(pasteValue).to.equal('123456');
|
|
280
|
+
});
|
|
281
|
+
it('paste is ignored when disabled', async () => {
|
|
282
|
+
const el = await fixture(html `<nile-otp-input disabled></nile-otp-input>`);
|
|
283
|
+
await pasteInto(el, 0, '123456');
|
|
284
|
+
expect(el.value).to.equal('');
|
|
285
|
+
});
|
|
286
|
+
// ---- Visual states ----
|
|
287
|
+
it('applies warning class', async () => {
|
|
288
|
+
const el = await fixture(html `<nile-otp-input warning></nile-otp-input>`);
|
|
289
|
+
const base = el.shadowRoot.querySelector('.otp');
|
|
290
|
+
expect(base.classList.contains('otp--warning')).to.be.true;
|
|
291
|
+
});
|
|
292
|
+
it('applies error class', async () => {
|
|
293
|
+
const el = await fixture(html `<nile-otp-input error></nile-otp-input>`);
|
|
294
|
+
const base = el.shadowRoot.querySelector('.otp');
|
|
295
|
+
expect(base.classList.contains('otp--error')).to.be.true;
|
|
296
|
+
});
|
|
297
|
+
it('applies success class', async () => {
|
|
298
|
+
const el = await fixture(html `<nile-otp-input success></nile-otp-input>`);
|
|
299
|
+
const base = el.shadowRoot.querySelector('.otp');
|
|
300
|
+
expect(base.classList.contains('otp--success')).to.be.true;
|
|
301
|
+
});
|
|
302
|
+
it('applies disabled class and blocks input', async () => {
|
|
303
|
+
const el = await fixture(html `<nile-otp-input disabled></nile-otp-input>`);
|
|
304
|
+
const base = el.shadowRoot.querySelector('.otp');
|
|
305
|
+
expect(base.classList.contains('otp--disabled')).to.be.true;
|
|
306
|
+
const first = getCells(el)[0];
|
|
307
|
+
first.value = '9';
|
|
308
|
+
first.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
309
|
+
await el.updateComplete;
|
|
310
|
+
expect(el.value).to.equal('');
|
|
311
|
+
expect(first.value).to.equal('');
|
|
312
|
+
});
|
|
313
|
+
it('applies readonly class and blocks input', async () => {
|
|
314
|
+
const el = await fixture(html `<nile-otp-input readonly value="123456"></nile-otp-input>`);
|
|
315
|
+
const base = el.shadowRoot.querySelector('.otp');
|
|
316
|
+
expect(base.classList.contains('otp--readonly')).to.be.true;
|
|
317
|
+
const first = getCells(el)[0];
|
|
318
|
+
first.value = '9';
|
|
319
|
+
first.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
320
|
+
await el.updateComplete;
|
|
321
|
+
expect(el.value).to.equal('123456');
|
|
322
|
+
});
|
|
323
|
+
// ---- Masked ----
|
|
324
|
+
it('masked cells use type="password" for filled non-active cells', async () => {
|
|
325
|
+
const el = await fixture(html `<nile-otp-input masked value="12"></nile-otp-input>`);
|
|
326
|
+
await el.updateComplete;
|
|
327
|
+
const cells = getCells(el);
|
|
328
|
+
expect(cells[0].type).to.equal('password');
|
|
329
|
+
expect(cells[1].type).to.equal('password');
|
|
330
|
+
expect(cells[2].type).to.equal('text');
|
|
331
|
+
});
|
|
332
|
+
it('active masked cell shows text while typing', async () => {
|
|
333
|
+
const el = await fixture(html `<nile-otp-input masked value="12"></nile-otp-input>`);
|
|
334
|
+
await el.updateComplete;
|
|
335
|
+
const cells = getCells(el);
|
|
336
|
+
cells[1].focus();
|
|
337
|
+
await el.updateComplete;
|
|
338
|
+
expect(cells[1].type).to.equal('text');
|
|
339
|
+
expect(cells[0].type).to.equal('password');
|
|
340
|
+
});
|
|
341
|
+
it('unmasked cells are always type="text"', async () => {
|
|
342
|
+
const el = await fixture(html `<nile-otp-input value="12"></nile-otp-input>`);
|
|
343
|
+
await el.updateComplete;
|
|
344
|
+
const cells = getCells(el);
|
|
345
|
+
cells.forEach(c => expect(c.type).to.equal('text'));
|
|
346
|
+
});
|
|
347
|
+
// ---- Events ----
|
|
348
|
+
it('emits nile-input and nile-change with value detail', async () => {
|
|
349
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
350
|
+
let inputDetail;
|
|
351
|
+
let changeDetail;
|
|
352
|
+
el.addEventListener('nile-input', (e) => {
|
|
353
|
+
inputDetail = e.detail;
|
|
354
|
+
});
|
|
355
|
+
el.addEventListener('nile-change', (e) => {
|
|
356
|
+
changeDetail = e.detail;
|
|
357
|
+
});
|
|
358
|
+
getCells(el)[0].focus();
|
|
359
|
+
await el.updateComplete;
|
|
360
|
+
await pressKey(el, 0, '7');
|
|
361
|
+
expect(inputDetail.value).to.equal('7');
|
|
362
|
+
expect(inputDetail.complete).to.be.false;
|
|
363
|
+
expect(changeDetail.value).to.equal('7');
|
|
364
|
+
});
|
|
365
|
+
it('emits nile-complete when all cells are filled', async () => {
|
|
366
|
+
const el = await fixture(html `<nile-otp-input length="4" value="123"></nile-otp-input>`);
|
|
367
|
+
await el.updateComplete;
|
|
368
|
+
let completedValue = '';
|
|
369
|
+
el.addEventListener('nile-complete', (e) => {
|
|
370
|
+
completedValue = e.detail.value;
|
|
371
|
+
});
|
|
372
|
+
const cells = getCells(el);
|
|
373
|
+
cells[3].focus();
|
|
374
|
+
await el.updateComplete;
|
|
375
|
+
await pressKey(el, 3, '4');
|
|
376
|
+
expect(completedValue).to.equal('1234');
|
|
377
|
+
});
|
|
378
|
+
it('emits nile-focus when entering and nile-blur when leaving', async () => {
|
|
379
|
+
const el = await fixture(html `<nile-otp-input></nile-otp-input>`);
|
|
380
|
+
let focused = false;
|
|
381
|
+
let blurred = false;
|
|
382
|
+
el.addEventListener('nile-focus', () => { focused = true; });
|
|
383
|
+
el.addEventListener('nile-blur', () => { blurred = true; });
|
|
384
|
+
getCells(el)[0].focus();
|
|
385
|
+
await el.updateComplete;
|
|
386
|
+
expect(focused).to.be.true;
|
|
387
|
+
getCells(el)[0].blur();
|
|
388
|
+
await aTimeout(50);
|
|
389
|
+
expect(blurred).to.be.true;
|
|
390
|
+
});
|
|
391
|
+
// ---- Public methods ----
|
|
392
|
+
it('clear() empties all cells', async () => {
|
|
393
|
+
const el = await fixture(html `<nile-otp-input value="123456"></nile-otp-input>`);
|
|
394
|
+
await el.updateComplete;
|
|
395
|
+
el.clear();
|
|
396
|
+
await el.updateComplete;
|
|
397
|
+
expect(el.value).to.equal('');
|
|
398
|
+
getCells(el).forEach(c => expect(c.value).to.equal(''));
|
|
399
|
+
});
|
|
400
|
+
it('clear() is blocked when disabled', async () => {
|
|
401
|
+
const el = await fixture(html `<nile-otp-input disabled value="123456"></nile-otp-input>`);
|
|
402
|
+
await el.updateComplete;
|
|
403
|
+
el.clear();
|
|
404
|
+
await el.updateComplete;
|
|
405
|
+
expect(el.value).to.equal('123456');
|
|
406
|
+
});
|
|
407
|
+
it('complete getter returns true when all cells filled', async () => {
|
|
408
|
+
const el = await fixture(html `<nile-otp-input value="123456"></nile-otp-input>`);
|
|
409
|
+
await el.updateComplete;
|
|
410
|
+
expect(el.complete).to.be.true;
|
|
411
|
+
});
|
|
412
|
+
it('complete getter returns false when cells are empty', async () => {
|
|
413
|
+
const el = await fixture(html `<nile-otp-input value="12"></nile-otp-input>`);
|
|
414
|
+
await el.updateComplete;
|
|
415
|
+
expect(el.complete).to.be.false;
|
|
416
|
+
});
|
|
417
|
+
// ---- Validation ----
|
|
418
|
+
it('validates required and exact length using checkValidity', async () => {
|
|
419
|
+
const el = await fixture(html `<nile-otp-input required></nile-otp-input>`);
|
|
420
|
+
el.value = '12';
|
|
421
|
+
await el.updateComplete;
|
|
422
|
+
expect(el.checkValidity()).to.be.false;
|
|
423
|
+
el.value = '123456';
|
|
424
|
+
await el.updateComplete;
|
|
425
|
+
expect(el.checkValidity()).to.be.true;
|
|
426
|
+
});
|
|
427
|
+
it('supports custom validity messaging', async () => {
|
|
428
|
+
const el = await fixture(html `<nile-otp-input value="123456"></nile-otp-input>`);
|
|
429
|
+
el.setCustomValidity('Invalid OTP');
|
|
430
|
+
await el.updateComplete;
|
|
431
|
+
expect(el.checkValidity()).to.be.false;
|
|
432
|
+
expect(el.validationMessage).to.equal('Invalid OTP');
|
|
433
|
+
el.setCustomValidity('');
|
|
434
|
+
await el.updateComplete;
|
|
435
|
+
expect(el.checkValidity()).to.be.true;
|
|
436
|
+
});
|
|
437
|
+
it('validates against custom pattern', async () => {
|
|
438
|
+
const el = await fixture(html `<nile-otp-input pattern="[0-9]{6}" value="1234"></nile-otp-input>`);
|
|
439
|
+
await el.updateComplete;
|
|
440
|
+
expect(el.checkValidity()).to.be.false;
|
|
441
|
+
el.value = '123456';
|
|
442
|
+
await el.updateComplete;
|
|
443
|
+
expect(el.checkValidity()).to.be.true;
|
|
444
|
+
});
|
|
445
|
+
// ---- Form integration ----
|
|
446
|
+
it('participates in form data submission', async () => {
|
|
447
|
+
const form = await fixture(html `
|
|
448
|
+
<form id="otp-form">
|
|
449
|
+
<nile-otp-input name="otp" value="321654"></nile-otp-input>
|
|
450
|
+
</form>
|
|
451
|
+
`);
|
|
452
|
+
const data = new FormData(form);
|
|
453
|
+
expect(data.get('otp')).to.equal('321654');
|
|
454
|
+
});
|
|
455
|
+
// ---- Placeholder ----
|
|
456
|
+
it('shows no placeholder by default', async () => {
|
|
457
|
+
const el = await fixture(html `
|
|
458
|
+
<nile-otp-input value="12"></nile-otp-input>
|
|
459
|
+
`);
|
|
460
|
+
const placeholders = getCells(el).map(c => c.getAttribute('placeholder'));
|
|
461
|
+
expect(placeholders).to.deep.equal([null, null, null, null, null, null]);
|
|
462
|
+
});
|
|
463
|
+
it('moves custom placeholder to active cell on focus', async () => {
|
|
464
|
+
const el = await fixture(html `<nile-otp-input placeholder="0"></nile-otp-input>`);
|
|
465
|
+
const cells = getCells(el);
|
|
466
|
+
cells[0].focus();
|
|
467
|
+
await el.updateComplete;
|
|
468
|
+
const placeholders = getCells(el).map(c => c.getAttribute('placeholder'));
|
|
469
|
+
expect(placeholders[0]).to.equal('0');
|
|
470
|
+
expect(placeholders.slice(1).every(p => p === null)).to.be.true;
|
|
471
|
+
});
|
|
472
|
+
// ---- CSS parts ----
|
|
473
|
+
it('exposes all required CSS parts', async () => {
|
|
474
|
+
const el = await fixture(html `
|
|
475
|
+
<nile-otp-input
|
|
476
|
+
label="Test"
|
|
477
|
+
help-text="Help"
|
|
478
|
+
error-message="Error"
|
|
479
|
+
separator="-"
|
|
480
|
+
separator-every="3"
|
|
481
|
+
></nile-otp-input>
|
|
482
|
+
`);
|
|
483
|
+
expect(el.shadowRoot.querySelector('[part="form-control"]')).to.exist;
|
|
484
|
+
expect(el.shadowRoot.querySelector('[part="form-control-label"]')).to.exist;
|
|
485
|
+
expect(el.shadowRoot.querySelector('[part="form-control-input"]')).to.exist;
|
|
486
|
+
expect(el.shadowRoot.querySelector('[part="base"]')).to.exist;
|
|
487
|
+
expect(el.shadowRoot.querySelector('[part="cell"]')).to.exist;
|
|
488
|
+
expect(el.shadowRoot.querySelector('[part="separator"]')).to.exist;
|
|
489
|
+
expect(el.shadowRoot.querySelector('[part="form-control-help-text"]')).to.exist;
|
|
490
|
+
expect(el.shadowRoot.querySelector('[part="form-control-error-message"]')).to.exist;
|
|
491
|
+
});
|
|
492
|
+
});
|
|
493
|
+
//# sourceMappingURL=nile-otp-input.test.js.map
|