@felleslosninger/minid-elements 0.1.6 → 0.1.7
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/components/code-input.component.d.ts +2 -0
- package/dist/components/code-input.component.d.ts.map +1 -1
- package/dist/components/code-input.js +22 -2
- package/dist/components/code-input.js.map +1 -1
- package/dist/components/textfield.component.d.ts +1 -0
- package/dist/components/textfield.component.d.ts.map +1 -1
- package/dist/components/textfield.js +148 -42
- package/dist/components/textfield.js.map +1 -1
- package/dist/mixins/form-control.mixin.d.ts.map +1 -1
- package/dist/mixins/form-control.mixin.js +19 -0
- package/dist/mixins/form-control.mixin.js.map +1 -1
- package/dist/types/form-control.d.ts +1 -0
- package/dist/types/form-control.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -76,6 +76,7 @@ export declare class MinidCodeInput extends MinidCodeInput_base {
|
|
|
76
76
|
pattern?: string;
|
|
77
77
|
private isFocused;
|
|
78
78
|
private caretPosition;
|
|
79
|
+
private lastFormValue;
|
|
79
80
|
static get formControlValidators(): import('../types/validator.type.ts').Validator[];
|
|
80
81
|
get validationTarget(): HTMLInputElement;
|
|
81
82
|
protected firstUpdated(_changedProperties: PropertyValues): void;
|
|
@@ -103,6 +104,7 @@ export declare class MinidCodeInput extends MinidCodeInput_base {
|
|
|
103
104
|
clear(): void;
|
|
104
105
|
resetFormControl(): void;
|
|
105
106
|
focus(options?: FocusOptions): void;
|
|
107
|
+
private focusInput;
|
|
106
108
|
handleLengthChange(): void;
|
|
107
109
|
handleValueChange(): void;
|
|
108
110
|
render(): import('lit').TemplateResult<1>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-input.component.d.ts","sourceRoot":"","sources":["../../src/components/code-input.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,cAAc,EAAE,MAAM,KAAK,CAAC;AASrE,OAAO,0BAA0B,CAAC;AASlC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,cAAc,CAAC;KAClC;CACF;;AA2PD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBACa,cAAe,SAAQ,mBAEnC;IACC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAI/B;IACF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IACpE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkD;IAChF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiD;IAG9E,OAAO,CAAC,YAAY,CAAoB;IAGxC,KAAK,SAAM;IAGX,KAAK,SAAM;IAGX,WAAW,SAAM;IAGjB,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAU;IAEjC;;OAEG;IAEH,SAAS,EAAE,SAAS,GAAG,MAAM,CAAa;IAE1C;;OAEG;IAEH,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAQ;IAGhC,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAE/B;;OAEG;IAEH,MAAM,SAAK;IAGX,QAAQ,UAAS;IAEjB;;OAEG;IAEH,SAAS,UAAS;IAElB;;OAEG;IAEH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IAEH,cAAc,SAAM;IAEpB;;OAEG;IAEH,SAAS,UAAS;IAGlB,eAAe,UAAS;IAExB;;OAEG;IAEH,QAAQ,UAAS;IAEjB;;OAEG;IAEH,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,aAAa,CAAK;IAE1B,MAAM,KAAK,qBAAqB,qDAO/B;IAED,IAAI,gBAAgB,qBAEnB;IAED,SAAS,CAAC,YAAY,CAAC,kBAAkB,EAAE,cAAc,GAAG,IAAI;IAIvD,iBAAiB;IAQjB,oBAAoB;IAQ7B,OAAO,CAAC,cAAc;IAYtB;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB,CAK3B;IAEF,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,WAAW;IAqCnB,OAAO,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"code-input.component.d.ts","sourceRoot":"","sources":["../../src/components/code-input.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,cAAc,EAAE,MAAM,KAAK,CAAC;AASrE,OAAO,0BAA0B,CAAC;AASlC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,cAAc,CAAC;KAClC;CACF;;AA2PD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBACa,cAAe,SAAQ,mBAEnC;IACC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAI/B;IACF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IACpE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkD;IAChF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiD;IAG9E,OAAO,CAAC,YAAY,CAAoB;IAGxC,KAAK,SAAM;IAGX,KAAK,SAAM;IAGX,WAAW,SAAM;IAGjB,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAU;IAEjC;;OAEG;IAEH,SAAS,EAAE,SAAS,GAAG,MAAM,CAAa;IAE1C;;OAEG;IAEH,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAQ;IAGhC,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAE/B;;OAEG;IAEH,MAAM,SAAK;IAGX,QAAQ,UAAS;IAEjB;;OAEG;IAEH,SAAS,UAAS;IAElB;;OAEG;IAEH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IAEH,cAAc,SAAM;IAEpB;;OAEG;IAEH,SAAS,UAAS;IAGlB,eAAe,UAAS;IAExB;;OAEG;IAEH,QAAQ,UAAS;IAEjB;;OAEG;IAEH,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,aAAa,CAAK;IAE1B,OAAO,CAAC,aAAa,CAAuB;IAE5C,MAAM,KAAK,qBAAqB,qDAO/B;IAED,IAAI,gBAAgB,qBAEnB;IAED,SAAS,CAAC,YAAY,CAAC,kBAAkB,EAAE,cAAc,GAAG,IAAI;IAIvD,iBAAiB;IAQjB,oBAAoB;IAQ7B,OAAO,CAAC,cAAc;IAYtB;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB,CAK3B;IAEF,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,WAAW;IAqCnB,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,aAAa;IAiBrB,KAAK;IAQL,gBAAgB;IAIhB,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAYnC,OAAO,CAAC,UAAU;IAclB,kBAAkB;IAOlB,iBAAiB;IAeR,MAAM;CAsIhB"}
|
|
@@ -295,6 +295,7 @@ let MinidCodeInput = class extends FormControlMixin(
|
|
|
295
295
|
this.required = false;
|
|
296
296
|
this.isFocused = false;
|
|
297
297
|
this.caretPosition = 0;
|
|
298
|
+
this.lastFormValue = null;
|
|
298
299
|
this.handleSelectionChange = () => {
|
|
299
300
|
if (this.isFocused) {
|
|
300
301
|
this.syncCaretPosition();
|
|
@@ -399,6 +400,7 @@ let MinidCodeInput = class extends FormControlMixin(
|
|
|
399
400
|
this.syncCaretPosition();
|
|
400
401
|
if (this.value !== value) {
|
|
401
402
|
this.value = value;
|
|
403
|
+
this.lastFormValue = value;
|
|
402
404
|
this.setValue(value);
|
|
403
405
|
}
|
|
404
406
|
this.inputElement.dispatchEvent(
|
|
@@ -430,6 +432,7 @@ let MinidCodeInput = class extends FormControlMixin(
|
|
|
430
432
|
}
|
|
431
433
|
clear() {
|
|
432
434
|
this.value = "";
|
|
435
|
+
this.lastFormValue = "";
|
|
433
436
|
this.setValue("");
|
|
434
437
|
this.invalidmessage = "";
|
|
435
438
|
this.caretPosition = 0;
|
|
@@ -438,7 +441,21 @@ let MinidCodeInput = class extends FormControlMixin(
|
|
|
438
441
|
this.clear();
|
|
439
442
|
}
|
|
440
443
|
focus(options) {
|
|
441
|
-
this.inputElement
|
|
444
|
+
if (!this.inputElement) {
|
|
445
|
+
this.updateComplete.then(() => {
|
|
446
|
+
if (this.isConnected) {
|
|
447
|
+
this.focusInput(options);
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
this.focusInput(options);
|
|
453
|
+
}
|
|
454
|
+
focusInput(options) {
|
|
455
|
+
if (!this.inputElement) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
this.inputElement.focus(options);
|
|
442
459
|
if (this.value.length > 0) {
|
|
443
460
|
const length = this.value.length;
|
|
444
461
|
this.inputElement.setSelectionRange(length, length);
|
|
@@ -456,7 +473,10 @@ let MinidCodeInput = class extends FormControlMixin(
|
|
|
456
473
|
this.value = filtered;
|
|
457
474
|
}
|
|
458
475
|
this.caretPosition = Math.min(this.caretPosition, this.value.length);
|
|
459
|
-
this.
|
|
476
|
+
if (filtered !== this.lastFormValue) {
|
|
477
|
+
this.lastFormValue = filtered;
|
|
478
|
+
this.syncFormValue(filtered);
|
|
479
|
+
}
|
|
460
480
|
}
|
|
461
481
|
render() {
|
|
462
482
|
const hasLabelSlot = this.hasSlotControler.test("label");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-input.js","sources":["../../src/components/code-input.component.ts"],"sourcesContent":["import { css, html, LitElement, nothing, PropertyValues } from 'lit';\nimport { customElement, property, query, state } 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 { watch } from '../internal/watch.ts';\nimport { FormControlMixin } from '../mixins/form-control.mixin.ts';\nimport { styled } from '../mixins/tailwind.mixin.ts';\nimport { HasSlotController } from '../internal/slot.ts';\nimport './icon/icon.component.ts';\nimport {\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n requiredValidator,\n} from '../mixins/validators.ts';\nimport { webOtpApiInit } from '../utilities/web-otp-api.ts';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mid-code-input': MinidCodeInput;\n }\n}\n\nlet nextUniqueId = 0;\n\nconst styles = [\n css`\n :host {\n display: block;\n }\n\n .code-input-label {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n margin-block-end: 0.5rem;\n font-weight: 500;\n }\n\n .code-input-label--with-description {\n margin-block-end: 0.25rem;\n }\n\n .code-input-label--sm {\n font-size: var(--ds-body-sm-font-size, 1rem);\n line-height: var(--ds-body-md-line-height, 1.5);\n }\n\n .code-input-label--md {\n font-size: var(--ds-body-md-font-size, 1.125rem);\n line-height: var(--ds-body-md-line-height, 1.5);\n }\n\n .code-input-label--lg {\n font-size: var(--ds-body-lg-font-size, 1.3125rem);\n line-height: var(--ds-body-md-line-height, 1.5);\n }\n\n .code-input-description {\n margin-block-end: 0.5rem;\n color: var(--ds-color-neutral-text-subtle, #545e6b);\n }\n\n .code-input-label--hidden,\n .code-input-description--hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n .code-input-label--disabled,\n .code-input-description--disabled,\n .input-wrapper--disabled {\n opacity: var(--ds-opacity-disabled, 0.38);\n }\n\n .input-wrapper {\n position: relative;\n cursor: text;\n width: fit-content;\n font-size: 1rem;\n line-height: 1.3;\n font-weight: 500;\n }\n\n .input-wrapper--sm {\n font-size: var(--ds-heading-sm-font-size, 1.125rem);\n line-height: var(--ds-heading-sm-line-height, 1.3);\n font-weight: var(--ds-heading-sm-font-weight, 500);\n }\n\n .input-wrapper--md {\n font-size: var(--ds-heading-md-font-size, 1.25rem);\n line-height: var(--ds-heading-md-line-height, 1.3);\n font-weight: var(--ds-heading-md-font-weight, 500);\n }\n\n .input-wrapper--lg {\n font-size: var(--ds-heading-lg-font-size, 1.5rem);\n line-height: var(--ds-heading-lg-line-height, 1.3);\n font-weight: var(--ds-heading-lg-font-weight, 500);\n }\n\n .input-wrapper--disabled {\n cursor: not-allowed;\n }\n\n .character-boxes {\n display: inline-flex;\n gap: var(--mid-code-input-gap, 0.5rem);\n }\n\n .character-box {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n box-sizing: border-box;\n width: var(--mid-code-input-box-size, var(--ds-size-13, 3.25rem));\n height: var(--mid-code-input-box-size, var(--ds-size-13, 3.25rem));\n padding-inline: 0.25rem;\n user-select: none;\n text-align: center;\n font-family:\n ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,\n 'Liberation Mono', 'Courier New', monospace;\n line-height: 1;\n border: var(--ds-border-width-default, 1px) solid\n var(\n --mid-code-input-border-color,\n var(--ds-color-neutral-border-default, #717a84)\n );\n border-radius: var(\n --mid-code-input-border-radius,\n var(--ds-border-radius-md, 0.25rem)\n );\n background-color: var(\n --mid-code-input-background,\n var(--ds-color-neutral-background-default, #ffffff)\n );\n color: var(--mid-code-input-text-color, inherit);\n }\n\n .character-box--empty {\n color: var(\n --mid-code-input-placeholder-color,\n var(--ds-color-neutral-surface-active, #c7cacf)\n );\n }\n\n .character-box--empty::before {\n content: '';\n box-sizing: border-box;\n width: 0.55em;\n height: 0.55em;\n border: 2px solid currentColor;\n border-radius: 50%;\n }\n\n .character-box--invalid {\n border-width: 2px;\n border-color: var(\n --mid-code-input-danger-border-color,\n var(--ds-color-danger-border-default, #ce4d4d)\n );\n background-color: var(\n --mid-code-input-danger-background,\n var(--ds-color-danger-surface-tinted, #f8e4e4)\n );\n }\n\n .character-box--invalid.character-box--empty {\n color: var(\n --mid-code-input-danger-placeholder-color,\n var(--ds-color-danger-surface-active, #edbfbf)\n );\n }\n\n .focus-ring-sm {\n outline: 2px solid var(--ds-color-focus-outer, #1f2c3d);\n outline-offset: 2px;\n box-shadow: 0 0 0 2px var(--ds-color-focus-inner, #ffffff);\n }\n\n /* Ensure hidden attribute always hides elements even when Tailwind's\n @layer base [hidden] rule is not available in the shadow DOM */\n [hidden] {\n display: none !important;\n }\n\n .hidden-input {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n margin: 0;\n background: transparent;\n border: none;\n outline: none;\n color: transparent;\n caret-color: transparent;\n font-size: 16px; /* Minimum 16px prevents iOS zoom on focus */\n pointer-events: none;\n -webkit-appearance: none;\n appearance: none;\n }\n\n .hidden-input:focus {\n outline: none;\n }\n\n .hidden-input:disabled {\n cursor: not-allowed;\n }\n\n @keyframes blink {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n }\n }\n\n .character-box--caret::after {\n content: '';\n position: absolute;\n width: 2px;\n height: 60%;\n background-color: var(\n --color-accent-base,\n var(--ds-color-accent-base-default, blue)\n );\n animation: blink 1s step-end infinite;\n }\n\n .character-box--caret-leading::after {\n inset-inline-start: 0;\n }\n\n /* Hide placeholder circle when the caret is at this position */\n .character-box--caret.character-box--empty {\n color: transparent;\n }\n\n .validation-message {\n display: flex;\n gap: 0.25rem;\n color: var(--ds-color-danger-text-subtle, #a22e2e);\n }\n\n .validation-message--visible {\n margin-block-start: 0.5rem;\n }\n\n .validation-icon {\n margin-block-start: 0.25rem;\n min-width: 1.25rem;\n min-height: 1.25rem;\n }\n `,\n];\n\n/**\n *\n * @event mid-change - Emitted when a change to the input value is comitted by the user\n * @event mid-input - Emitted when the input element recieves input\n * @event mid-complete - Emitted when all characters have been entered.\n * @event {detail: { validity: ValidityState }} mid-invalid-hide - Emitted when the error message should be hidden\n * @event {detail: { validity: ValidityState }} mid-invalid-show - Emitted when the error message should be shown\n *\n * @slot label - The input's label if you need to use HTML. Alternatively, you can use the `label` attribute.\n * @slot description - The input's description if you need to use HTML. Alternatively, you can use the `description` attribute.\n *\n * @csspart input-container - The wrapper around the input elements. This can be used to adjust font-size.\n * @csspart description - The description shown between the label and the character boxes.\n * @csspart character-boxes - The container for the visual character boxes.\n * @csspart character-box - An individual character box.\n * @csspart validation-message - The error message shown by `invalidmessage`.\n *\n * @method focus - Focuses the input element\n * @method clear - Clears the input\n */\n@customElement('mid-code-input')\nexport class MinidCodeInput extends FormControlMixin(\n styled(LitElement, styles)\n) {\n private readonly hasSlotControler = new HasSlotController(\n this,\n 'label',\n 'description'\n );\n private readonly labelId = `mid-code-input-label-${nextUniqueId++}`;\n private readonly descriptionId = `mid-code-input-description-${nextUniqueId++}`;\n private readonly validationId = `mid-code-input-validation-${nextUniqueId++}`;\n\n @query('.hidden-input')\n private inputElement!: HTMLInputElement;\n\n @property({ reflect: true })\n value = '';\n\n @property()\n label = '';\n\n @property()\n description = '';\n\n @property()\n type: 'number' | 'text' = 'text';\n\n /**\n * For displaying appropriate virtual keyboard\n */\n @property()\n inputmode: 'numeric' | 'text' = 'numeric';\n\n /**\n * Adjusts the font-size of the code inputs\n */\n @property()\n size: 'sm' | 'md' | 'lg' = 'sm';\n\n @property()\n labelsize?: 'sm' | 'md' | 'lg';\n\n /**\n * Number of input characters or digits\n */\n @property({ type: Number })\n length = 5;\n\n @property({ type: Boolean })\n disabled = false;\n\n /**\n * Focuses the first input element on page load\n */\n @property({ type: Boolean })\n autofocus = false;\n\n /**\n * The minimum length of input that will be considered valid.\n */\n @property({ type: Number })\n minlength?: number;\n\n /**\n * Error message to display when the input is invalid, also activates invalid styling\n */\n @property()\n invalidmessage = '';\n\n /**\n * Visually hides `label` (still available for screen readers)\n */\n @property({ type: Boolean })\n hidelabel = false;\n\n @property({ type: Boolean })\n hidedescription = false;\n\n /**\n * Makes the input required\n */\n @property({ type: Boolean })\n required = false;\n\n /**\n * A regular expression pattern to validate input against.\n */\n @property()\n pattern?: string;\n\n @state()\n private isFocused = false;\n\n @state()\n private caretPosition = 0;\n\n static get formControlValidators() {\n return [\n requiredValidator,\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n ];\n }\n\n get validationTarget() {\n return this.inputElement;\n }\n\n protected firstUpdated(_changedProperties: PropertyValues): void {\n webOtpApiInit(this.renderRoot);\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this.ownerDocument.addEventListener(\n 'selectionchange',\n this.handleSelectionChange\n );\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.ownerDocument.removeEventListener(\n 'selectionchange',\n this.handleSelectionChange\n );\n }\n\n private handleBoxClick(index: number) {\n if (this.disabled) {\n return;\n }\n\n // Truncate the value to the clicked position\n this.value = this.value.substring(0, index);\n\n // Focus the input to move the caret\n this.focus();\n }\n\n /**\n * Catches caret moves we did not make - arrow keys, Home/End, word jumps,\n * shift-selection - without enumerating keys, and keeps up while a key is held.\n *\n * Must be listened for on the document: for a caret move the user made,\n * Chromium fires it only there, not at the input and not into the shadow root,\n * so an `@selectionchange` binding on either never runs.\n */\n private handleSelectionChange = () => {\n // Fires for selection changes anywhere on the page\n if (this.isFocused) {\n this.syncCaretPosition();\n }\n };\n\n private syncCaretPosition() {\n const input = this.inputElement;\n\n if (!input) {\n return;\n }\n\n this.caretPosition =\n (input.selectionDirection === 'backward'\n ? input.selectionStart\n : input.selectionEnd) ?? this.value.length;\n }\n\n private handleFocus() {\n this.isFocused = true;\n /* don't select text, move caret to the end */\n if (this.value.length > 0) {\n const length = this.value.length;\n this.inputElement.setSelectionRange(length, length);\n }\n this.syncCaretPosition();\n }\n\n private handleBlur() {\n this.isFocused = false;\n }\n\n private filterValue(value: string) {\n return this.type === 'number' ? value.replace(/\\D/g, '') : value;\n }\n\n private handleBeforeInput(e: InputEvent) {\n if (this.type === 'number' && e.inputType === 'insertText' && e.data) {\n if (!/\\d/.test(e.data)) {\n e.preventDefault();\n }\n }\n }\n\n private handlePaste(event: ClipboardEvent) {\n if (this.type !== 'number') {\n return;\n }\n\n const pasted = event.clipboardData?.getData('text') ?? '';\n const digits = this.filterValue(pasted);\n\n if (digits === pasted) {\n return;\n }\n\n event.preventDefault();\n\n const input = this.inputElement;\n const start = input.selectionStart ?? input.value.length;\n const end = input.selectionEnd ?? start;\n const next = (\n input.value.slice(0, start) +\n digits +\n input.value.slice(end)\n ).substring(0, this.length);\n\n if (next === input.value) {\n return;\n }\n\n input.value = next;\n input.dispatchEvent(\n new InputEvent('input', { bubbles: true, composed: true })\n );\n\n const caret = Math.min(start + digits.length, input.value.length);\n input.setSelectionRange(caret, caret);\n this.syncCaretPosition();\n }\n\n private handleInput(event: InputEvent) {\n const input = event.target as HTMLInputElement;\n let value = this.filterValue(input.value);\n\n value = value.substring(0, this.length);\n\n if (input.value !== value) {\n input.value = value;\n }\n\n this.syncCaretPosition();\n\n // Update the component's public `value` property if it has changed.\n if (this.value !== value) {\n this.value = value;\n this.setValue(value);\n }\n\n this.inputElement.dispatchEvent(\n new Event('mid-input', { bubbles: true, composed: true })\n );\n\n if (this.value.length === this.length && this.value.length > 0) {\n this.inputElement.dispatchEvent(\n new Event('mid-complete', { bubbles: true, composed: true })\n );\n }\n }\n\n private handleChange() {\n this.inputElement.dispatchEvent(\n new Event('mid-change', {\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleKeydown(event: KeyboardEvent) {\n const hasModifier =\n event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;\n\n if (event.key === 'Enter' && !hasModifier) {\n // Pressing enter when focused on an input should submit the form like a native input, but we wait a tick before\n // submitting to allow users to cancel the keydown event if they need to\n setTimeout(() => {\n // When using an Input Method Editor (IME), pressing enter will cause the form to submit unexpectedly. One way\n // to check for this is to look at event.isComposing, which will be true when the IME is open.\n if (!event.defaultPrevented && !event.isComposing) {\n this.form?.requestSubmit();\n }\n });\n }\n }\n\n clear() {\n this.value = '';\n this.setValue('');\n this.invalidmessage = '';\n this.caretPosition = 0;\n }\n\n resetFormControl() {\n this.clear();\n }\n\n focus(options?: FocusOptions): void {\n this.inputElement?.focus(options);\n /* don't select text, move caret to the end */\n if (this.value.length > 0) {\n const length = this.value.length;\n this.inputElement.setSelectionRange(length, length);\n }\n this.syncCaretPosition();\n }\n\n @watch('length')\n handleLengthChange() {\n if (this.value.length > this.length) {\n this.value = this.value.substring(0, this.length);\n }\n }\n\n @watch(['value', 'type'])\n handleValueChange() {\n const filtered = this.filterValue(this.value);\n\n if (filtered !== this.value) {\n this.value = filtered;\n }\n\n this.caretPosition = Math.min(this.caretPosition, this.value.length);\n this.setValue(filtered);\n }\n\n override render() {\n const hasLabelSlot = this.hasSlotControler.test('label');\n const hasLabel = !!this.label || !!hasLabelSlot;\n const hasDescriptionSlot = this.hasSlotControler.test('description');\n const hasDescription = !!this.description || !!hasDescriptionSlot;\n const describedBy =\n [\n hasDescription ? this.descriptionId : undefined,\n this.invalidmessage ? this.validationId : undefined,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n const chars = this.value.split('');\n const displayValues = Array.from(\n { length: this.length },\n (_, i) => chars[i] || ''\n );\n const caretIndex =\n this.disabled || this.length === 0\n ? -1\n : Math.min(this.caretPosition, this.length - 1);\n const caretIsInABox = this.caretPosition < this.length;\n\n return html`\n <label\n id=\"${this.labelId}\"\n for=\"mid-code-input-hidden\"\n class=\"code-input-label ${classMap({\n 'code-input-label--sm': this.labelsize === 'sm',\n 'code-input-label--md': this.labelsize === 'md',\n 'code-input-label--lg': this.labelsize === 'lg',\n 'code-input-label--hidden': this.hidelabel || !hasLabel,\n 'code-input-label--with-description': hasDescription,\n 'code-input-label--disabled': this.disabled,\n })}\"\n >\n <slot name=\"label\"> ${this.label} </slot>\n </label>\n ${hasDescription\n ? html`\n <div\n id=\"${this.descriptionId}\"\n part=\"description\"\n aria-hidden=\"true\"\n class=\"code-input-description ${classMap({\n 'code-input-description--hidden': this.hidedescription,\n 'code-input-description--disabled': this.disabled,\n })}\"\n >\n <slot name=\"description\"> ${this.description} </slot>\n </div>\n `\n : nothing}\n <div\n part=\"input-container\"\n class=\"input-wrapper ${classMap({\n 'input-wrapper--sm': this.size === 'sm',\n 'input-wrapper--md': this.size === 'md',\n 'input-wrapper--lg': this.size === 'lg',\n 'input-wrapper--disabled': this.disabled,\n })}\"\n @click=${() => this.focus()}\n >\n <div part=\"character-boxes\" class=\"character-boxes\" aria-hidden=\"true\">\n ${displayValues.map((char, index) => {\n const isFocusTarget = this.isFocused && index === caretIndex;\n const hasCaret = isFocusTarget && caretIsInABox;\n return html`\n <div\n part=\"character-box\"\n aria-hidden=\"true\"\n class=\"character-box ${classMap({\n 'character-box--invalid': !!this.invalidmessage,\n 'character-box--caret': hasCaret,\n 'character-box--caret-leading': hasCaret && !!char,\n 'character-box--empty': !char,\n 'focus-ring-sm': isFocusTarget,\n })}\"\n @click=${(e: MouseEvent) => {\n e.stopPropagation();\n this.handleBoxClick(index);\n }}\n >\n ${char}\n </div>\n `;\n })}\n </div>\n <input\n class=\"hidden-input\"\n .value=\"${live(this.value)}\"\n id=\"mid-code-input-hidden\"\n type=\"text\"\n aria-labelledby=\"${this.labelId}\"\n aria-describedby=${ifDefined(describedBy)}\n aria-invalid=${this.invalidmessage ? 'true' : 'false'}\n aria-errormessage=${ifDefined(\n this.invalidmessage ? this.validationId : undefined\n )}\n maxlength=\"${this.length}\"\n ?autofocus=\"${this.autofocus}\"\n ?disabled=\"${this.disabled}\"\n ?required=\"${this.required}\"\n pattern=${ifDefined(this.pattern)}\n inputmode=\"${this.inputmode}\"\n autocomplete=\"one-time-code\"\n @beforeinput=\"${this.handleBeforeInput}\"\n @paste=\"${this.handlePaste}\"\n @input=\"${this.handleInput}\"\n @change=\"${this.handleChange}\"\n @keydown=\"${this.handleKeydown}\"\n @focus=\"${this.handleFocus}\"\n @blur=\"${this.handleBlur}\"\n />\n </div>\n <div\n class=\"validation-message ${classMap({\n 'validation-message--visible': !!this.invalidmessage,\n })}\"\n part=\"validation-message\"\n id=\"${this.validationId}\"\n aria-live=\"polite\"\n >\n ${this.invalidmessage\n ? html`<mid-icon\n name=\"xmark-octagon-fill\"\n class=\"validation-icon\"\n ></mid-icon>\n ${this.invalidmessage}`\n : nothing}\n </div>\n `;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAI,eAAe;AAEnB,MAAM,SAAS;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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"}
|
|
1
|
+
{"version":3,"file":"code-input.js","sources":["../../src/components/code-input.component.ts"],"sourcesContent":["import { css, html, LitElement, nothing, PropertyValues } from 'lit';\nimport { customElement, property, query, state } 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 { watch } from '../internal/watch.ts';\nimport { FormControlMixin } from '../mixins/form-control.mixin.ts';\nimport { styled } from '../mixins/tailwind.mixin.ts';\nimport { HasSlotController } from '../internal/slot.ts';\nimport './icon/icon.component.ts';\nimport {\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n requiredValidator,\n} from '../mixins/validators.ts';\nimport { webOtpApiInit } from '../utilities/web-otp-api.ts';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mid-code-input': MinidCodeInput;\n }\n}\n\nlet nextUniqueId = 0;\n\nconst styles = [\n css`\n :host {\n display: block;\n }\n\n .code-input-label {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n margin-block-end: 0.5rem;\n font-weight: 500;\n }\n\n .code-input-label--with-description {\n margin-block-end: 0.25rem;\n }\n\n .code-input-label--sm {\n font-size: var(--ds-body-sm-font-size, 1rem);\n line-height: var(--ds-body-md-line-height, 1.5);\n }\n\n .code-input-label--md {\n font-size: var(--ds-body-md-font-size, 1.125rem);\n line-height: var(--ds-body-md-line-height, 1.5);\n }\n\n .code-input-label--lg {\n font-size: var(--ds-body-lg-font-size, 1.3125rem);\n line-height: var(--ds-body-md-line-height, 1.5);\n }\n\n .code-input-description {\n margin-block-end: 0.5rem;\n color: var(--ds-color-neutral-text-subtle, #545e6b);\n }\n\n .code-input-label--hidden,\n .code-input-description--hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n .code-input-label--disabled,\n .code-input-description--disabled,\n .input-wrapper--disabled {\n opacity: var(--ds-opacity-disabled, 0.38);\n }\n\n .input-wrapper {\n position: relative;\n cursor: text;\n width: fit-content;\n font-size: 1rem;\n line-height: 1.3;\n font-weight: 500;\n }\n\n .input-wrapper--sm {\n font-size: var(--ds-heading-sm-font-size, 1.125rem);\n line-height: var(--ds-heading-sm-line-height, 1.3);\n font-weight: var(--ds-heading-sm-font-weight, 500);\n }\n\n .input-wrapper--md {\n font-size: var(--ds-heading-md-font-size, 1.25rem);\n line-height: var(--ds-heading-md-line-height, 1.3);\n font-weight: var(--ds-heading-md-font-weight, 500);\n }\n\n .input-wrapper--lg {\n font-size: var(--ds-heading-lg-font-size, 1.5rem);\n line-height: var(--ds-heading-lg-line-height, 1.3);\n font-weight: var(--ds-heading-lg-font-weight, 500);\n }\n\n .input-wrapper--disabled {\n cursor: not-allowed;\n }\n\n .character-boxes {\n display: inline-flex;\n gap: var(--mid-code-input-gap, 0.5rem);\n }\n\n .character-box {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n box-sizing: border-box;\n width: var(--mid-code-input-box-size, var(--ds-size-13, 3.25rem));\n height: var(--mid-code-input-box-size, var(--ds-size-13, 3.25rem));\n padding-inline: 0.25rem;\n user-select: none;\n text-align: center;\n font-family:\n ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,\n 'Liberation Mono', 'Courier New', monospace;\n line-height: 1;\n border: var(--ds-border-width-default, 1px) solid\n var(\n --mid-code-input-border-color,\n var(--ds-color-neutral-border-default, #717a84)\n );\n border-radius: var(\n --mid-code-input-border-radius,\n var(--ds-border-radius-md, 0.25rem)\n );\n background-color: var(\n --mid-code-input-background,\n var(--ds-color-neutral-background-default, #ffffff)\n );\n color: var(--mid-code-input-text-color, inherit);\n }\n\n .character-box--empty {\n color: var(\n --mid-code-input-placeholder-color,\n var(--ds-color-neutral-surface-active, #c7cacf)\n );\n }\n\n .character-box--empty::before {\n content: '';\n box-sizing: border-box;\n width: 0.55em;\n height: 0.55em;\n border: 2px solid currentColor;\n border-radius: 50%;\n }\n\n .character-box--invalid {\n border-width: 2px;\n border-color: var(\n --mid-code-input-danger-border-color,\n var(--ds-color-danger-border-default, #ce4d4d)\n );\n background-color: var(\n --mid-code-input-danger-background,\n var(--ds-color-danger-surface-tinted, #f8e4e4)\n );\n }\n\n .character-box--invalid.character-box--empty {\n color: var(\n --mid-code-input-danger-placeholder-color,\n var(--ds-color-danger-surface-active, #edbfbf)\n );\n }\n\n .focus-ring-sm {\n outline: 2px solid var(--ds-color-focus-outer, #1f2c3d);\n outline-offset: 2px;\n box-shadow: 0 0 0 2px var(--ds-color-focus-inner, #ffffff);\n }\n\n /* Ensure hidden attribute always hides elements even when Tailwind's\n @layer base [hidden] rule is not available in the shadow DOM */\n [hidden] {\n display: none !important;\n }\n\n .hidden-input {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n margin: 0;\n background: transparent;\n border: none;\n outline: none;\n color: transparent;\n caret-color: transparent;\n font-size: 16px; /* Minimum 16px prevents iOS zoom on focus */\n pointer-events: none;\n -webkit-appearance: none;\n appearance: none;\n }\n\n .hidden-input:focus {\n outline: none;\n }\n\n .hidden-input:disabled {\n cursor: not-allowed;\n }\n\n @keyframes blink {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n }\n }\n\n .character-box--caret::after {\n content: '';\n position: absolute;\n width: 2px;\n height: 60%;\n background-color: var(\n --color-accent-base,\n var(--ds-color-accent-base-default, blue)\n );\n animation: blink 1s step-end infinite;\n }\n\n .character-box--caret-leading::after {\n inset-inline-start: 0;\n }\n\n /* Hide placeholder circle when the caret is at this position */\n .character-box--caret.character-box--empty {\n color: transparent;\n }\n\n .validation-message {\n display: flex;\n gap: 0.25rem;\n color: var(--ds-color-danger-text-subtle, #a22e2e);\n }\n\n .validation-message--visible {\n margin-block-start: 0.5rem;\n }\n\n .validation-icon {\n margin-block-start: 0.25rem;\n min-width: 1.25rem;\n min-height: 1.25rem;\n }\n `,\n];\n\n/**\n *\n * @event mid-change - Emitted when a change to the input value is comitted by the user\n * @event mid-input - Emitted when the input element recieves input\n * @event mid-complete - Emitted when all characters have been entered.\n * @event {detail: { validity: ValidityState }} mid-invalid-hide - Emitted when the error message should be hidden\n * @event {detail: { validity: ValidityState }} mid-invalid-show - Emitted when the error message should be shown\n *\n * @slot label - The input's label if you need to use HTML. Alternatively, you can use the `label` attribute.\n * @slot description - The input's description if you need to use HTML. Alternatively, you can use the `description` attribute.\n *\n * @csspart input-container - The wrapper around the input elements. This can be used to adjust font-size.\n * @csspart description - The description shown between the label and the character boxes.\n * @csspart character-boxes - The container for the visual character boxes.\n * @csspart character-box - An individual character box.\n * @csspart validation-message - The error message shown by `invalidmessage`.\n *\n * @method focus - Focuses the input element\n * @method clear - Clears the input\n */\n@customElement('mid-code-input')\nexport class MinidCodeInput extends FormControlMixin(\n styled(LitElement, styles)\n) {\n private readonly hasSlotControler = new HasSlotController(\n this,\n 'label',\n 'description'\n );\n private readonly labelId = `mid-code-input-label-${nextUniqueId++}`;\n private readonly descriptionId = `mid-code-input-description-${nextUniqueId++}`;\n private readonly validationId = `mid-code-input-validation-${nextUniqueId++}`;\n\n @query('.hidden-input')\n private inputElement!: HTMLInputElement;\n\n @property({ reflect: true })\n value = '';\n\n @property()\n label = '';\n\n @property()\n description = '';\n\n @property()\n type: 'number' | 'text' = 'text';\n\n /**\n * For displaying appropriate virtual keyboard\n */\n @property()\n inputmode: 'numeric' | 'text' = 'numeric';\n\n /**\n * Adjusts the font-size of the code inputs\n */\n @property()\n size: 'sm' | 'md' | 'lg' = 'sm';\n\n @property()\n labelsize?: 'sm' | 'md' | 'lg';\n\n /**\n * Number of input characters or digits\n */\n @property({ type: Number })\n length = 5;\n\n @property({ type: Boolean })\n disabled = false;\n\n /**\n * Focuses the first input element on page load\n */\n @property({ type: Boolean })\n autofocus = false;\n\n /**\n * The minimum length of input that will be considered valid.\n */\n @property({ type: Number })\n minlength?: number;\n\n /**\n * Error message to display when the input is invalid, also activates invalid styling\n */\n @property()\n invalidmessage = '';\n\n /**\n * Visually hides `label` (still available for screen readers)\n */\n @property({ type: Boolean })\n hidelabel = false;\n\n @property({ type: Boolean })\n hidedescription = false;\n\n /**\n * Makes the input required\n */\n @property({ type: Boolean })\n required = false;\n\n /**\n * A regular expression pattern to validate input against.\n */\n @property()\n pattern?: string;\n\n @state()\n private isFocused = false;\n\n @state()\n private caretPosition = 0;\n\n private lastFormValue: string | null = null;\n\n static get formControlValidators() {\n return [\n requiredValidator,\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n ];\n }\n\n get validationTarget() {\n return this.inputElement;\n }\n\n protected firstUpdated(_changedProperties: PropertyValues): void {\n webOtpApiInit(this.renderRoot);\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this.ownerDocument.addEventListener(\n 'selectionchange',\n this.handleSelectionChange\n );\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.ownerDocument.removeEventListener(\n 'selectionchange',\n this.handleSelectionChange\n );\n }\n\n private handleBoxClick(index: number) {\n if (this.disabled) {\n return;\n }\n\n // Truncate the value to the clicked position\n this.value = this.value.substring(0, index);\n\n // Focus the input to move the caret\n this.focus();\n }\n\n /**\n * Catches caret moves we did not make - arrow keys, Home/End, word jumps,\n * shift-selection - without enumerating keys, and keeps up while a key is held.\n *\n * Must be listened for on the document: for a caret move the user made,\n * Chromium fires it only there, not at the input and not into the shadow root,\n * so an `@selectionchange` binding on either never runs.\n */\n private handleSelectionChange = () => {\n // Fires for selection changes anywhere on the page\n if (this.isFocused) {\n this.syncCaretPosition();\n }\n };\n\n private syncCaretPosition() {\n const input = this.inputElement;\n\n if (!input) {\n return;\n }\n\n this.caretPosition =\n (input.selectionDirection === 'backward'\n ? input.selectionStart\n : input.selectionEnd) ?? this.value.length;\n }\n\n private handleFocus() {\n this.isFocused = true;\n /* don't select text, move caret to the end */\n if (this.value.length > 0) {\n const length = this.value.length;\n this.inputElement.setSelectionRange(length, length);\n }\n this.syncCaretPosition();\n }\n\n private handleBlur() {\n this.isFocused = false;\n }\n\n private filterValue(value: string) {\n return this.type === 'number' ? value.replace(/\\D/g, '') : value;\n }\n\n private handleBeforeInput(e: InputEvent) {\n if (this.type === 'number' && e.inputType === 'insertText' && e.data) {\n if (!/\\d/.test(e.data)) {\n e.preventDefault();\n }\n }\n }\n\n private handlePaste(event: ClipboardEvent) {\n if (this.type !== 'number') {\n return;\n }\n\n const pasted = event.clipboardData?.getData('text') ?? '';\n const digits = this.filterValue(pasted);\n\n if (digits === pasted) {\n return;\n }\n\n event.preventDefault();\n\n const input = this.inputElement;\n const start = input.selectionStart ?? input.value.length;\n const end = input.selectionEnd ?? start;\n const next = (\n input.value.slice(0, start) +\n digits +\n input.value.slice(end)\n ).substring(0, this.length);\n\n if (next === input.value) {\n return;\n }\n\n input.value = next;\n input.dispatchEvent(\n new InputEvent('input', { bubbles: true, composed: true })\n );\n\n const caret = Math.min(start + digits.length, input.value.length);\n input.setSelectionRange(caret, caret);\n this.syncCaretPosition();\n }\n\n private handleInput(event: InputEvent) {\n const input = event.target as HTMLInputElement;\n let value = this.filterValue(input.value);\n\n value = value.substring(0, this.length);\n\n if (input.value !== value) {\n input.value = value;\n }\n\n this.syncCaretPosition();\n\n // Update the component's public `value` property if it has changed.\n if (this.value !== value) {\n this.value = value;\n this.lastFormValue = value;\n this.setValue(value);\n }\n\n this.inputElement.dispatchEvent(\n new Event('mid-input', { bubbles: true, composed: true })\n );\n\n if (this.value.length === this.length && this.value.length > 0) {\n this.inputElement.dispatchEvent(\n new Event('mid-complete', { bubbles: true, composed: true })\n );\n }\n }\n\n private handleChange() {\n this.inputElement.dispatchEvent(\n new Event('mid-change', {\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleKeydown(event: KeyboardEvent) {\n const hasModifier =\n event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;\n\n if (event.key === 'Enter' && !hasModifier) {\n // Pressing enter when focused on an input should submit the form like a native input, but we wait a tick before\n // submitting to allow users to cancel the keydown event if they need to\n setTimeout(() => {\n // When using an Input Method Editor (IME), pressing enter will cause the form to submit unexpectedly. One way\n // to check for this is to look at event.isComposing, which will be true when the IME is open.\n if (!event.defaultPrevented && !event.isComposing) {\n this.form?.requestSubmit();\n }\n });\n }\n }\n\n clear() {\n this.value = '';\n this.lastFormValue = '';\n this.setValue('');\n this.invalidmessage = '';\n this.caretPosition = 0;\n }\n\n resetFormControl() {\n this.clear();\n }\n\n focus(options?: FocusOptions): void {\n if (!this.inputElement) {\n this.updateComplete.then(() => {\n if (this.isConnected) {\n this.focusInput(options);\n }\n });\n return;\n }\n this.focusInput(options);\n }\n\n private focusInput(options?: FocusOptions) {\n if (!this.inputElement) {\n return;\n }\n this.inputElement.focus(options);\n /* don't select text, move caret to the end */\n if (this.value.length > 0) {\n const length = this.value.length;\n this.inputElement.setSelectionRange(length, length);\n }\n this.syncCaretPosition();\n }\n\n @watch('length')\n handleLengthChange() {\n if (this.value.length > this.length) {\n this.value = this.value.substring(0, this.length);\n }\n }\n\n @watch(['value', 'type'])\n handleValueChange() {\n const filtered = this.filterValue(this.value);\n\n if (filtered !== this.value) {\n this.value = filtered;\n }\n\n this.caretPosition = Math.min(this.caretPosition, this.value.length);\n\n if (filtered !== this.lastFormValue) {\n this.lastFormValue = filtered;\n this.syncFormValue(filtered);\n }\n }\n\n override render() {\n const hasLabelSlot = this.hasSlotControler.test('label');\n const hasLabel = !!this.label || !!hasLabelSlot;\n const hasDescriptionSlot = this.hasSlotControler.test('description');\n const hasDescription = !!this.description || !!hasDescriptionSlot;\n const describedBy =\n [\n hasDescription ? this.descriptionId : undefined,\n this.invalidmessage ? this.validationId : undefined,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n const chars = this.value.split('');\n const displayValues = Array.from(\n { length: this.length },\n (_, i) => chars[i] || ''\n );\n const caretIndex =\n this.disabled || this.length === 0\n ? -1\n : Math.min(this.caretPosition, this.length - 1);\n const caretIsInABox = this.caretPosition < this.length;\n\n return html`\n <label\n id=\"${this.labelId}\"\n for=\"mid-code-input-hidden\"\n class=\"code-input-label ${classMap({\n 'code-input-label--sm': this.labelsize === 'sm',\n 'code-input-label--md': this.labelsize === 'md',\n 'code-input-label--lg': this.labelsize === 'lg',\n 'code-input-label--hidden': this.hidelabel || !hasLabel,\n 'code-input-label--with-description': hasDescription,\n 'code-input-label--disabled': this.disabled,\n })}\"\n >\n <slot name=\"label\"> ${this.label} </slot>\n </label>\n ${hasDescription\n ? html`\n <div\n id=\"${this.descriptionId}\"\n part=\"description\"\n aria-hidden=\"true\"\n class=\"code-input-description ${classMap({\n 'code-input-description--hidden': this.hidedescription,\n 'code-input-description--disabled': this.disabled,\n })}\"\n >\n <slot name=\"description\"> ${this.description} </slot>\n </div>\n `\n : nothing}\n <div\n part=\"input-container\"\n class=\"input-wrapper ${classMap({\n 'input-wrapper--sm': this.size === 'sm',\n 'input-wrapper--md': this.size === 'md',\n 'input-wrapper--lg': this.size === 'lg',\n 'input-wrapper--disabled': this.disabled,\n })}\"\n @click=${() => this.focus()}\n >\n <div part=\"character-boxes\" class=\"character-boxes\" aria-hidden=\"true\">\n ${displayValues.map((char, index) => {\n const isFocusTarget = this.isFocused && index === caretIndex;\n const hasCaret = isFocusTarget && caretIsInABox;\n return html`\n <div\n part=\"character-box\"\n aria-hidden=\"true\"\n class=\"character-box ${classMap({\n 'character-box--invalid': !!this.invalidmessage,\n 'character-box--caret': hasCaret,\n 'character-box--caret-leading': hasCaret && !!char,\n 'character-box--empty': !char,\n 'focus-ring-sm': isFocusTarget,\n })}\"\n @click=${(e: MouseEvent) => {\n e.stopPropagation();\n this.handleBoxClick(index);\n }}\n >\n ${char}\n </div>\n `;\n })}\n </div>\n <input\n class=\"hidden-input\"\n .value=\"${live(this.value)}\"\n id=\"mid-code-input-hidden\"\n type=\"text\"\n aria-labelledby=\"${this.labelId}\"\n aria-describedby=${ifDefined(describedBy)}\n aria-invalid=${this.invalidmessage ? 'true' : 'false'}\n aria-errormessage=${ifDefined(\n this.invalidmessage ? this.validationId : undefined\n )}\n maxlength=\"${this.length}\"\n ?autofocus=\"${this.autofocus}\"\n ?disabled=\"${this.disabled}\"\n ?required=\"${this.required}\"\n pattern=${ifDefined(this.pattern)}\n inputmode=\"${this.inputmode}\"\n autocomplete=\"one-time-code\"\n @beforeinput=\"${this.handleBeforeInput}\"\n @paste=\"${this.handlePaste}\"\n @input=\"${this.handleInput}\"\n @change=\"${this.handleChange}\"\n @keydown=\"${this.handleKeydown}\"\n @focus=\"${this.handleFocus}\"\n @blur=\"${this.handleBlur}\"\n />\n </div>\n <div\n class=\"validation-message ${classMap({\n 'validation-message--visible': !!this.invalidmessage,\n })}\"\n part=\"validation-message\"\n id=\"${this.validationId}\"\n aria-live=\"polite\"\n >\n ${this.invalidmessage\n ? html`<mid-icon\n name=\"xmark-octagon-fill\"\n class=\"validation-icon\"\n ></mid-icon>\n ${this.invalidmessage}`\n : nothing}\n </div>\n `;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAI,eAAe;AAEnB,MAAM,SAAS;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoPF;AAuBO,IAAM,iBAAN,cAA6B;AAAA,EAClC,OAAO,YAAY,MAAM;AAC3B,EAAE;AAAA,EAFK,cAAA;AAAA,UAAA,GAAA,SAAA;AAGL,SAAiB,mBAAmB,IAAI;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,SAAiB,UAAU,wBAAwB,cAAc;AACjE,SAAiB,gBAAgB,8BAA8B,cAAc;AAC7E,SAAiB,eAAe,6BAA6B,cAAc;AAM3E,SAAA,QAAQ;AAGR,SAAA,QAAQ;AAGR,SAAA,cAAc;AAGd,SAAA,OAA0B;AAM1B,SAAA,YAAgC;AAMhC,SAAA,OAA2B;AAS3B,SAAA,SAAS;AAGT,SAAA,WAAW;AAMX,SAAA,YAAY;AAYZ,SAAA,iBAAiB;AAMjB,SAAA,YAAY;AAGZ,SAAA,kBAAkB;AAMlB,SAAA,WAAW;AASX,SAAQ,YAAY;AAGpB,SAAQ,gBAAgB;AAExB,SAAQ,gBAA+B;AAuDvC,SAAQ,wBAAwB,MAAM;AAEpC,UAAI,KAAK,WAAW;AAClB,aAAK,kBAAA;AAAA,MACP;AAAA,IACF;AAAA,EAAA;AAAA,EA1DA,WAAW,wBAAwB;AACjC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,IAAI,mBAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEU,aAAa,oBAA0C;AAC/D,kBAAc,KAAK,UAAU;AAAA,EAC/B;AAAA,EAES,oBAAoB;AAC3B,UAAM,kBAAA;AACN,SAAK,cAAc;AAAA,MACjB;AAAA,MACA,KAAK;AAAA,IAAA;AAAA,EAET;AAAA,EAES,uBAAuB;AAC9B,UAAM,qBAAA;AACN,SAAK,cAAc;AAAA,MACjB;AAAA,MACA,KAAK;AAAA,IAAA;AAAA,EAET;AAAA,EAEQ,eAAe,OAAe;AACpC,QAAI,KAAK,UAAU;AACjB;AAAA,IACF;AAGA,SAAK,QAAQ,KAAK,MAAM,UAAU,GAAG,KAAK;AAG1C,SAAK,MAAA;AAAA,EACP;AAAA,EAiBQ,oBAAoB;AAC1B,UAAM,QAAQ,KAAK;AAEnB,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAEA,SAAK,iBACF,MAAM,uBAAuB,aAC1B,MAAM,iBACN,MAAM,iBAAiB,KAAK,MAAM;AAAA,EAC1C;AAAA,EAEQ,cAAc;AACpB,SAAK,YAAY;AAEjB,QAAI,KAAK,MAAM,SAAS,GAAG;AACzB,YAAM,SAAS,KAAK,MAAM;AAC1B,WAAK,aAAa,kBAAkB,QAAQ,MAAM;AAAA,IACpD;AACA,SAAK,kBAAA;AAAA,EACP;AAAA,EAEQ,aAAa;AACnB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,YAAY,OAAe;AACjC,WAAO,KAAK,SAAS,WAAW,MAAM,QAAQ,OAAO,EAAE,IAAI;AAAA,EAC7D;AAAA,EAEQ,kBAAkB,GAAe;AACvC,QAAI,KAAK,SAAS,YAAY,EAAE,cAAc,gBAAgB,EAAE,MAAM;AACpE,UAAI,CAAC,KAAK,KAAK,EAAE,IAAI,GAAG;AACtB,UAAE,eAAA;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAY,OAAuB;AACzC,QAAI,KAAK,SAAS,UAAU;AAC1B;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,eAAe,QAAQ,MAAM,KAAK;AACvD,UAAM,SAAS,KAAK,YAAY,MAAM;AAEtC,QAAI,WAAW,QAAQ;AACrB;AAAA,IACF;AAEA,UAAM,eAAA;AAEN,UAAM,QAAQ,KAAK;AACnB,UAAM,QAAQ,MAAM,kBAAkB,MAAM,MAAM;AAClD,UAAM,MAAM,MAAM,gBAAgB;AAClC,UAAM,QACJ,MAAM,MAAM,MAAM,GAAG,KAAK,IAC1B,SACA,MAAM,MAAM,MAAM,GAAG,GACrB,UAAU,GAAG,KAAK,MAAM;AAE1B,QAAI,SAAS,MAAM,OAAO;AACxB;AAAA,IACF;AAEA,UAAM,QAAQ;AACd,UAAM;AAAA,MACJ,IAAI,WAAW,SAAS,EAAE,SAAS,MAAM,UAAU,MAAM;AAAA,IAAA;AAG3D,UAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO,QAAQ,MAAM,MAAM,MAAM;AAChE,UAAM,kBAAkB,OAAO,KAAK;AACpC,SAAK,kBAAA;AAAA,EACP;AAAA,EAEQ,YAAY,OAAmB;AACrC,UAAM,QAAQ,MAAM;AACpB,QAAI,QAAQ,KAAK,YAAY,MAAM,KAAK;AAExC,YAAQ,MAAM,UAAU,GAAG,KAAK,MAAM;AAEtC,QAAI,MAAM,UAAU,OAAO;AACzB,YAAM,QAAQ;AAAA,IAChB;AAEA,SAAK,kBAAA;AAGL,QAAI,KAAK,UAAU,OAAO;AACxB,WAAK,QAAQ;AACb,WAAK,gBAAgB;AACrB,WAAK,SAAS,KAAK;AAAA,IACrB;AAEA,SAAK,aAAa;AAAA,MAChB,IAAI,MAAM,aAAa,EAAE,SAAS,MAAM,UAAU,MAAM;AAAA,IAAA;AAG1D,QAAI,KAAK,MAAM,WAAW,KAAK,UAAU,KAAK,MAAM,SAAS,GAAG;AAC9D,WAAK,aAAa;AAAA,QAChB,IAAI,MAAM,gBAAgB,EAAE,SAAS,MAAM,UAAU,MAAM;AAAA,MAAA;AAAA,IAE/D;AAAA,EACF;AAAA,EAEQ,eAAe;AACrB,SAAK,aAAa;AAAA,MAChB,IAAI,MAAM,cAAc;AAAA,QACtB,SAAS;AAAA,QACT,UAAU;AAAA,MAAA,CACX;AAAA,IAAA;AAAA,EAEL;AAAA,EAEQ,cAAc,OAAsB;AAC1C,UAAM,cACJ,MAAM,WAAW,MAAM,WAAW,MAAM,YAAY,MAAM;AAE5D,QAAI,MAAM,QAAQ,WAAW,CAAC,aAAa;AAGzC,iBAAW,MAAM;AAGf,YAAI,CAAC,MAAM,oBAAoB,CAAC,MAAM,aAAa;AACjD,eAAK,MAAM,cAAA;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,QAAQ;AACN,SAAK,QAAQ;AACb,SAAK,gBAAgB;AACrB,SAAK,SAAS,EAAE;AAChB,SAAK,iBAAiB;AACtB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,mBAAmB;AACjB,SAAK,MAAA;AAAA,EACP;AAAA,EAEA,MAAM,SAA8B;AAClC,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,eAAe,KAAK,MAAM;AAC7B,YAAI,KAAK,aAAa;AACpB,eAAK,WAAW,OAAO;AAAA,QACzB;AAAA,MACF,CAAC;AACD;AAAA,IACF;AACA,SAAK,WAAW,OAAO;AAAA,EACzB;AAAA,EAEQ,WAAW,SAAwB;AACzC,QAAI,CAAC,KAAK,cAAc;AACtB;AAAA,IACF;AACA,SAAK,aAAa,MAAM,OAAO;AAE/B,QAAI,KAAK,MAAM,SAAS,GAAG;AACzB,YAAM,SAAS,KAAK,MAAM;AAC1B,WAAK,aAAa,kBAAkB,QAAQ,MAAM;AAAA,IACpD;AACA,SAAK,kBAAA;AAAA,EACP;AAAA,EAGA,qBAAqB;AACnB,QAAI,KAAK,MAAM,SAAS,KAAK,QAAQ;AACnC,WAAK,QAAQ,KAAK,MAAM,UAAU,GAAG,KAAK,MAAM;AAAA,IAClD;AAAA,EACF;AAAA,EAGA,oBAAoB;AAClB,UAAM,WAAW,KAAK,YAAY,KAAK,KAAK;AAE5C,QAAI,aAAa,KAAK,OAAO;AAC3B,WAAK,QAAQ;AAAA,IACf;AAEA,SAAK,gBAAgB,KAAK,IAAI,KAAK,eAAe,KAAK,MAAM,MAAM;AAEnE,QAAI,aAAa,KAAK,eAAe;AACnC,WAAK,gBAAgB;AACrB,WAAK,cAAc,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA,EAES,SAAS;AAChB,UAAM,eAAe,KAAK,iBAAiB,KAAK,OAAO;AACvD,UAAM,WAAW,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;AACnC,UAAM,qBAAqB,KAAK,iBAAiB,KAAK,aAAa;AACnE,UAAM,iBAAiB,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC;AAC/C,UAAM,cACJ;AAAA,MACE,iBAAiB,KAAK,gBAAgB;AAAA,MACtC,KAAK,iBAAiB,KAAK,eAAe;AAAA,IAAA,EAEzC,OAAO,OAAO,EACd,KAAK,GAAG,KAAK;AAElB,UAAM,QAAQ,KAAK,MAAM,MAAM,EAAE;AACjC,UAAM,gBAAgB,MAAM;AAAA,MAC1B,EAAE,QAAQ,KAAK,OAAA;AAAA,MACf,CAAC,GAAG,MAAM,MAAM,CAAC,KAAK;AAAA,IAAA;AAExB,UAAM,aACJ,KAAK,YAAY,KAAK,WAAW,IAC7B,KACA,KAAK,IAAI,KAAK,eAAe,KAAK,SAAS,CAAC;AAClD,UAAM,gBAAgB,KAAK,gBAAgB,KAAK;AAEhD,WAAO;AAAA;AAAA,cAEG,KAAK,OAAO;AAAA;AAAA,kCAEQ,SAAS;AAAA,MACjC,wBAAwB,KAAK,cAAc;AAAA,MAC3C,wBAAwB,KAAK,cAAc;AAAA,MAC3C,wBAAwB,KAAK,cAAc;AAAA,MAC3C,4BAA4B,KAAK,aAAa,CAAC;AAAA,MAC/C,sCAAsC;AAAA,MACtC,8BAA8B,KAAK;AAAA,IAAA,CACpC,CAAC;AAAA;AAAA,8BAEoB,KAAK,KAAK;AAAA;AAAA,QAEhC,iBACE;AAAA;AAAA,oBAEU,KAAK,aAAa;AAAA;AAAA;AAAA,8CAGQ,SAAS;AAAA,MACvC,kCAAkC,KAAK;AAAA,MACvC,oCAAoC,KAAK;AAAA,IAAA,CAC1C,CAAC;AAAA;AAAA,0CAE0B,KAAK,WAAW;AAAA;AAAA,cAGhD,OAAO;AAAA;AAAA;AAAA,+BAGc,SAAS;AAAA,MAC9B,qBAAqB,KAAK,SAAS;AAAA,MACnC,qBAAqB,KAAK,SAAS;AAAA,MACnC,qBAAqB,KAAK,SAAS;AAAA,MACnC,2BAA2B,KAAK;AAAA,IAAA,CACjC,CAAC;AAAA,iBACO,MAAM,KAAK,MAAA,CAAO;AAAA;AAAA;AAAA,YAGvB,cAAc,IAAI,CAAC,MAAM,UAAU;AACnC,YAAM,gBAAgB,KAAK,aAAa,UAAU;AAClD,YAAM,WAAW,iBAAiB;AAClC,aAAO;AAAA;AAAA;AAAA;AAAA,uCAIoB,SAAS;AAAA,QAC9B,0BAA0B,CAAC,CAAC,KAAK;AAAA,QACjC,wBAAwB;AAAA,QACxB,gCAAgC,YAAY,CAAC,CAAC;AAAA,QAC9C,wBAAwB,CAAC;AAAA,QACzB,iBAAiB;AAAA,MAAA,CAClB,CAAC;AAAA,yBACO,CAAC,MAAkB;AAC1B,UAAE,gBAAA;AACF,aAAK,eAAe,KAAK;AAAA,MAC3B,CAAC;AAAA;AAAA,kBAEC,IAAI;AAAA;AAAA;AAAA,IAGZ,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,oBAIQ,KAAK,KAAK,KAAK,CAAC;AAAA;AAAA;AAAA,6BAGP,KAAK,OAAO;AAAA,6BACZ,UAAU,WAAW,CAAC;AAAA,yBAC1B,KAAK,iBAAiB,SAAS,OAAO;AAAA,8BACjC;AAAA,MAClB,KAAK,iBAAiB,KAAK,eAAe;AAAA,IAAA,CAC3C;AAAA,uBACY,KAAK,MAAM;AAAA,wBACV,KAAK,SAAS;AAAA,uBACf,KAAK,QAAQ;AAAA,uBACb,KAAK,QAAQ;AAAA,oBAChB,UAAU,KAAK,OAAO,CAAC;AAAA,uBACpB,KAAK,SAAS;AAAA;AAAA,0BAEX,KAAK,iBAAiB;AAAA,oBAC5B,KAAK,WAAW;AAAA,oBAChB,KAAK,WAAW;AAAA,qBACf,KAAK,YAAY;AAAA,sBAChB,KAAK,aAAa;AAAA,oBACpB,KAAK,WAAW;AAAA,mBACjB,KAAK,UAAU;AAAA;AAAA;AAAA;AAAA,oCAIE,SAAS;AAAA,MACnC,+BAA+B,CAAC,CAAC,KAAK;AAAA,IAAA,CACvC,CAAC;AAAA;AAAA,cAEI,KAAK,YAAY;AAAA;AAAA;AAAA,UAGrB,KAAK,iBACH;AAAA;AAAA;AAAA;AAAA,gBAII,KAAK,cAAc,KACvB,OAAO;AAAA;AAAA;AAAA,EAGjB;AACF;AAvdU,gBAAA;AAAA,EADP,MAAM,eAAe;AAAA,GAZX,eAaH,WAAA,gBAAA,CAAA;AAGR,gBAAA;AAAA,EADC,SAAS,EAAE,SAAS,KAAA,CAAM;AAAA,GAfhB,eAgBX,WAAA,SAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GAlBC,eAmBX,WAAA,SAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GArBC,eAsBX,WAAA,eAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GAxBC,eAyBX,WAAA,QAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GA9BC,eA+BX,WAAA,aAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GApCC,eAqCX,WAAA,QAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GAvCC,eAwCX,WAAA,aAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA7Cf,eA8CX,WAAA,UAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GAhDhB,eAiDX,WAAA,YAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GAtDhB,eAuDX,WAAA,aAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA5Df,eA6DX,WAAA,aAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GAlEC,eAmEX,WAAA,kBAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GAxEhB,eAyEX,WAAA,aAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GA3EhB,eA4EX,WAAA,mBAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GAjFhB,eAkFX,WAAA,YAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GAvFC,eAwFX,WAAA,WAAA,CAAA;AAGQ,gBAAA;AAAA,EADP,MAAA;AAAM,GA1FI,eA2FH,WAAA,aAAA,CAAA;AAGA,gBAAA;AAAA,EADP,MAAA;AAAM,GA7FI,eA8FH,WAAA,iBAAA,CAAA;AA0OR,gBAAA;AAAA,EADC,MAAM,QAAQ;AAAA,GAvUJ,eAwUX,WAAA,sBAAA,CAAA;AAOA,gBAAA;AAAA,EADC,MAAM,CAAC,SAAS,MAAM,CAAC;AAAA,GA9Ub,eA+UX,WAAA,qBAAA,CAAA;AA/UW,iBAAN,gBAAA;AAAA,EADN,cAAc,gBAAgB;AAAA,GAClB,cAAA;"}
|
|
@@ -122,6 +122,7 @@ export declare class MinidTextfield extends MinidTextfield_base {
|
|
|
122
122
|
private handleInput;
|
|
123
123
|
private handleFocus;
|
|
124
124
|
private handlePasswordToggle;
|
|
125
|
+
private handleInFieldButtonMousedown;
|
|
125
126
|
private handleClearClick;
|
|
126
127
|
focus(): void;
|
|
127
128
|
resetFormControl(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textfield.component.d.ts","sourceRoot":"","sources":["../../src/components/textfield.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAiB1E,OAAO,0BAA0B,CAAC;AAClC,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAKjD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,eAAe,EAAE,cAAc,CAAC;KACjC;CACF;;
|
|
1
|
+
{"version":3,"file":"textfield.component.d.ts","sourceRoot":"","sources":["../../src/components/textfield.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAiB1E,OAAO,0BAA0B,CAAC;AAClC,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAKjD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,eAAe,EAAE,cAAc,CAAC;KACjC;CACF;;AAgID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBACa,cAAe,SAAQ,mBAA4C;IAC9E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4D;IAC7F,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,YAAY,CAAM;IAG1B,KAAK,EAAG,gBAAgB,CAAC;IAGzB,KAAK,SAAM;IAGX,WAAW,SAAM;IAGjB,KAAK,SAAM;IAGX,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAQ;IAGhC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IAEH,SAAS,UAAS;IAElB;;OAEG;IAEH,YAAY,CAAC,EAAE,QAAQ,CAAC;IAExB;;OAEG;IAEH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IAEH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IAEH,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEtB;;OAEG;IAEH,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEtB;;OAEG;IAEH,cAAc,SAAM;IAGpB,IAAI,EACA,MAAM,GACN,gBAAgB,GAChB,OAAO,GACP,MAAM,GACN,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,KAAK,GACL,MAAM,GACN,MAAM,GACN,KAAK,GACL,MAAM,CAAU;IAEpB;;OAEG;IAEH,SAAS,EACL,MAAM,GACN,MAAM,GACN,KAAK,GACL,KAAK,GACL,OAAO,GACP,SAAS,GACT,SAAS,CAAU;IAEvB;;OAEG;IAEH,SAAS,UAAS;IAElB;;;OAGG;IAEH,cAAc,UAAS;IAEvB;;;OAGG;IAEH,eAAe,UAAS;IAGxB,QAAQ,UAAS;IAGjB,QAAQ,UAAS;IAEjB;;OAEG;IAEH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IAEH,QAAQ,UAAS;IAEjB;;OAEG;IAEH,SAAS,UAAS;IAElB;;;;;;OAMG;IAEH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAGhB,QAAQ,UAAS;IAEjB,MAAM,KAAK,qBAAqB,qDAQ/B;;IAYQ,iBAAiB,IAAI,IAAI;IAKlC,IAAI,gBAAgB,qBAEnB;IAED,SAAS,CAAC,YAAY,CAAC,kBAAkB,EAAE,cAAc,GAAG,IAAI;IAKhE,oBAAoB,IAAI,IAAI;IAI5B,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,4BAA4B;IAIpC,OAAO,CAAC,gBAAgB;IAmBxB,KAAK;IAKL,gBAAgB;IAKhB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAKlC,iBAAiB;IAKX,gBAAgB;IAUb,MAAM;CA8JhB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { css, LitElement,
|
|
1
|
+
import { css, LitElement, html, nothing } from "lit";
|
|
2
2
|
import { query, property, state, customElement } from "lit/decorators.js";
|
|
3
3
|
import { live } from "lit/directives/live.js";
|
|
4
4
|
import { stringConverter } from "../internal/string-converter.js";
|
|
@@ -43,6 +43,98 @@ const styles = [
|
|
|
43
43
|
background: var(--ds-color-neutral-background-tinted);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
.has-field-buttons {
|
|
47
|
+
--mid-field-button-size: var(--ds-size-7);
|
|
48
|
+
--mid-field-button-gap: var(--ds-size-3);
|
|
49
|
+
--mid-field-button-border: var(--ds-border-width-default);
|
|
50
|
+
position: relative;
|
|
51
|
+
display: block;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.has-field-buttons .ds-input {
|
|
55
|
+
padding-inline-end: calc(
|
|
56
|
+
var(--mid-field-button-size) + 2 * var(--mid-field-button-gap)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.has-field-buttons--two .ds-input {
|
|
61
|
+
padding-inline-end: calc(
|
|
62
|
+
2 * (var(--mid-field-button-size) + 2 * var(--mid-field-button-gap))
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.password-toggle-input::-ms-reveal,
|
|
67
|
+
.password-toggle-input::-ms-clear {
|
|
68
|
+
display: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.has-field-buttons .ds-input::-webkit-credentials-auto-fill-button {
|
|
72
|
+
margin-inline-end: calc(
|
|
73
|
+
var(--mid-field-button-size) + 2 * var(--mid-field-button-gap)
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.has-field-buttons--two .ds-input::-webkit-credentials-auto-fill-button {
|
|
78
|
+
margin-inline-end: calc(
|
|
79
|
+
2 * (var(--mid-field-button-size) + 2 * var(--mid-field-button-gap))
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.has-field-buttons:hover
|
|
84
|
+
.ds-input:not(:focus-visible, :disabled, [readonly], [aria-readonly='true']) {
|
|
85
|
+
outline: var(--dsc-input-outline-width--hover)
|
|
86
|
+
var(--dsc-input-outline-style--hover)
|
|
87
|
+
var(--dsc-input-outline-color--hover);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.has-field-buttons:hover
|
|
91
|
+
.ds-input[aria-invalid='true']:not(:focus-visible, :disabled, [readonly], [aria-readonly='true']) {
|
|
92
|
+
outline-color: var(--dsc-input-accent-color--invalid);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.field-buttons {
|
|
96
|
+
position: absolute;
|
|
97
|
+
inset-block: var(--mid-field-button-border);
|
|
98
|
+
inset-inline-end: var(--mid-field-button-border);
|
|
99
|
+
display: flex;
|
|
100
|
+
pointer-events: none;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.field-button {
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
color: var(--ds-color-neutral-text-subtle);
|
|
108
|
+
pointer-events: auto;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.field-buttons .field-button {
|
|
112
|
+
padding-inline: var(--mid-field-button-gap);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.field-button > span {
|
|
116
|
+
display: flex;
|
|
117
|
+
align-items: center;
|
|
118
|
+
justify-content: center;
|
|
119
|
+
border-radius: var(--ds-border-radius-sm);
|
|
120
|
+
block-size: var(--mid-field-button-size, var(--ds-size-7));
|
|
121
|
+
inline-size: var(--mid-field-button-size, var(--ds-size-7));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.field-button mid-icon {
|
|
125
|
+
font-size: var(--mid-field-button-size, var(--ds-size-7));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.field-button:focus-visible {
|
|
129
|
+
outline: none;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.field-button:focus-visible > span {
|
|
133
|
+
box-shadow: 0 0 0 var(--ds-border-width-focus) var(--ds-color-focus-inner);
|
|
134
|
+
outline: var(--ds-color-focus-outer) solid var(--ds-border-width-focus);
|
|
135
|
+
outline-offset: var(--ds-border-width-focus);
|
|
136
|
+
}
|
|
137
|
+
|
|
46
138
|
/* The validation message stays in the DOM so its text lands in a live region
|
|
47
139
|
the screen reader is already watching - WebKit does not reliably announce
|
|
48
140
|
one revealed at the same moment the text arrives. When empty it must paint
|
|
@@ -149,6 +241,9 @@ let MinidTextfield = class extends FormControlMixin(styled(LitElement, styles))
|
|
|
149
241
|
handlePasswordToggle() {
|
|
150
242
|
this.passwordvisible = !this.passwordvisible;
|
|
151
243
|
}
|
|
244
|
+
handleInFieldButtonMousedown(event) {
|
|
245
|
+
event.preventDefault();
|
|
246
|
+
}
|
|
152
247
|
handleClearClick(event) {
|
|
153
248
|
event.preventDefault();
|
|
154
249
|
if (this.value !== "") {
|
|
@@ -196,12 +291,46 @@ let MinidTextfield = class extends FormControlMixin(styled(LitElement, styles))
|
|
|
196
291
|
const hasPrefix = this.hasSlotControler.test("prefix");
|
|
197
292
|
const hasSuffix = this.hasSlotControler.test("suffix");
|
|
198
293
|
const hasClearIcon = this.clearable && !this.disabled && !this.readonly;
|
|
199
|
-
const
|
|
294
|
+
const hasPasswordToggle = this.passwordtoggle && !this.disabled;
|
|
295
|
+
const overlayFieldButtons = (hasClearIcon || hasPasswordToggle) && !hasPrefix && !hasSuffix;
|
|
296
|
+
const hasAffixes = hasPrefix || hasSuffix;
|
|
200
297
|
const isClearIconVisible = hasClearIcon && (typeof this.value === "number" || this.value.length > 0);
|
|
201
298
|
const describedBy = [
|
|
202
299
|
this.description ? this.descriptionId : void 0,
|
|
203
300
|
this.invalidmessage ? this.validationId : void 0
|
|
204
301
|
].filter(Boolean).join(" ");
|
|
302
|
+
const passwordToggleButton = html`
|
|
303
|
+
<button
|
|
304
|
+
type="button"
|
|
305
|
+
part="password-toggle-button"
|
|
306
|
+
class="field-button"
|
|
307
|
+
aria-label=${this.passwordvisible ? t.hidePassword : t.showPassword}
|
|
308
|
+
aria-controls=${this.inputId}
|
|
309
|
+
@mousedown=${this.handleInFieldButtonMousedown}
|
|
310
|
+
@click=${this.handlePasswordToggle}
|
|
311
|
+
>
|
|
312
|
+
<span>
|
|
313
|
+
<mid-icon
|
|
314
|
+
library="system"
|
|
315
|
+
name=${this.passwordvisible ? "eye-slash" : "eye"}
|
|
316
|
+
></mid-icon>
|
|
317
|
+
</span>
|
|
318
|
+
</button>
|
|
319
|
+
`;
|
|
320
|
+
const clearButton = html`
|
|
321
|
+
<button
|
|
322
|
+
type="button"
|
|
323
|
+
part="clear-button"
|
|
324
|
+
class="field-button"
|
|
325
|
+
aria-label=${t.clear}
|
|
326
|
+
@mousedown=${this.handleInFieldButtonMousedown}
|
|
327
|
+
@click=${this.handleClearClick}
|
|
328
|
+
>
|
|
329
|
+
<span>
|
|
330
|
+
<mid-icon library="nav-aksel" name="trash"></mid-icon>
|
|
331
|
+
</span>
|
|
332
|
+
</button>
|
|
333
|
+
`;
|
|
205
334
|
return html`
|
|
206
335
|
<ds-field
|
|
207
336
|
part="field"
|
|
@@ -230,12 +359,19 @@ let MinidTextfield = class extends FormControlMixin(styled(LitElement, styles))
|
|
|
230
359
|
` : nothing}
|
|
231
360
|
<div
|
|
232
361
|
part="base"
|
|
233
|
-
class="${
|
|
362
|
+
class="${classMap({
|
|
363
|
+
"ds-field-affixes": hasAffixes,
|
|
364
|
+
"has-field-buttons": overlayFieldButtons,
|
|
365
|
+
"has-field-buttons--two": overlayFieldButtons && hasClearIcon && hasPasswordToggle
|
|
366
|
+
})}"
|
|
234
367
|
>
|
|
235
368
|
${hasPrefix ? html`<span class="ds-field-affix"><slot name="prefix"></slot></span>` : html`<slot name="prefix"></slot>`}
|
|
236
369
|
<input
|
|
237
370
|
id="${this.inputId}"
|
|
238
|
-
class="
|
|
371
|
+
class="${classMap({
|
|
372
|
+
"ds-input": true,
|
|
373
|
+
"password-toggle-input": hasPasswordToggle
|
|
374
|
+
})}"
|
|
239
375
|
part="input"
|
|
240
376
|
lang=${lang}
|
|
241
377
|
.value=${live(this.value)}
|
|
@@ -263,44 +399,14 @@ let MinidTextfield = class extends FormControlMixin(styled(LitElement, styles))
|
|
|
263
399
|
@blur=${this.handleBlur}
|
|
264
400
|
@keydown=${this.handleKeydown}
|
|
265
401
|
/>
|
|
266
|
-
${
|
|
267
|
-
<
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
<mid-icon
|
|
275
|
-
class="size-7"
|
|
276
|
-
library="nav-aksel"
|
|
277
|
-
name="trash"
|
|
278
|
-
></mid-icon>
|
|
279
|
-
</button>
|
|
280
|
-
</span>
|
|
281
|
-
` : ""}
|
|
282
|
-
${this.passwordtoggle && !this.disabled ? html`
|
|
283
|
-
<span class="ds-field-affix" part="password-toggle-button">
|
|
284
|
-
<button
|
|
285
|
-
type="button"
|
|
286
|
-
class="focus-visible:focus-ring flex items-center justify-center rounded-sm"
|
|
287
|
-
aria-label=${this.passwordvisible ? t.hidePassword : t.showPassword}
|
|
288
|
-
@click=${this.handlePasswordToggle}
|
|
289
|
-
>
|
|
290
|
-
${this.passwordvisible ? html` <mid-icon
|
|
291
|
-
class="size-7"
|
|
292
|
-
library="system"
|
|
293
|
-
name="eye-slash"
|
|
294
|
-
></mid-icon>` : html`
|
|
295
|
-
<mid-icon
|
|
296
|
-
class="size-7"
|
|
297
|
-
library="system"
|
|
298
|
-
name="eye"
|
|
299
|
-
></mid-icon>
|
|
300
|
-
`}
|
|
301
|
-
</button>
|
|
302
|
-
</span>
|
|
303
|
-
` : ""}
|
|
402
|
+
${overlayFieldButtons ? html`
|
|
403
|
+
<div class="field-buttons">
|
|
404
|
+
${isClearIconVisible ? clearButton : nothing}
|
|
405
|
+
${hasPasswordToggle ? passwordToggleButton : nothing}
|
|
406
|
+
</div>
|
|
407
|
+
` : nothing}
|
|
408
|
+
${!overlayFieldButtons && isClearIconVisible ? html`<span class="ds-field-affix">${clearButton}</span>` : nothing}
|
|
409
|
+
${!overlayFieldButtons && hasPasswordToggle ? html`<span class="ds-field-affix">${passwordToggleButton}</span>` : nothing}
|
|
304
410
|
${hasSuffix ? html`<span part="suffix" class="ds-field-affix"><slot name="suffix"></slot></span>` : html`<slot name="suffix"></slot>`}
|
|
305
411
|
</div>
|
|
306
412
|
<p
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textfield.js","sources":["../../src/components/textfield.component.ts"],"sourcesContent":["import { css, html, LitElement, nothing, type PropertyValues } from 'lit';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { live } from 'lit/directives/live.js';\nimport { stringConverter } from '../internal/string-converter';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { styled } from '../mixins/tailwind.mixin.ts';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HasSlotController } from '../internal/slot';\nimport { FormControlMixin } from '../mixins/form-control.mixin';\nimport {\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n requiredValidator,\n typeMismatchValidator,\n} from '../mixins/validators';\nimport { watch } from '../internal/watch';\nimport './icon/icon.component.ts';\nimport { MaskInput, type MaskType } from 'maska';\nimport { getLang } from '../utilities/lang';\nimport { getTranslations } from '../utilities/translations';\nimport { LangController } from '../controllers/lang.controller.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mid-textfield': MinidTextfield;\n }\n}\n\nconst styles = [\n css`\n :host {\n display: block;\n }\n\n /* Hide increment/decrement buttons on inputs */\n input[type='number']::-webkit-outer-spin-button,\n input[type='number']::-webkit-inner-spin-button,\n input[type='number'] {\n -webkit-appearance: none;\n margin: 0;\n -moz-appearance: textfield !important;\n }\n\n .ds-field-affixes {\n background: var(--ds-color-neutral-background-tinted);\n }\n\n /* The validation message stays in the DOM so its text lands in a live region\n the screen reader is already watching - WebKit does not reliably announce\n one revealed at the same moment the text arrives. When empty it must paint\n nothing and take no room: the element drops the ds-validation-message class\n (whose ::before paints an error icon regardless of the text) and this rule\n cancels the sibling spacing from .ds-field > * + *, which the .ds-field >\n prefix is enough to outrank without !important. */\n .ds-field > .validation-message--empty {\n margin-top: 0;\n }\n `,\n];\n\nlet nextUniqueId = 0;\n\n/**\n *\n * @event mid-change - Emitted when a change to the input value is comitted by the user\n * @event mid-input - Emitted when the input element recieves input\n * @event mid-clear - Emitted when the input value is cleared\n * @event mid-focus - Emitted when input element is focused\n * @event mid-blur - Emitted when focus moves away from input element\n * @event {detail: { validity: ValidityState }} mid-invalid-hide - Emitted when the error message should be hidden\n * @event {detail: { validity: ValidityState }} mid-invalid-show - Emitted when the error message should be shown\n *\n * @slot prefix - Used for decoration to the left of the input\n * @slot suffix - Used for decoration to the right of the input\n * @slot label - The input's label. Alternatively, you can use the `label` attribute.\n *\n * @csspart base - The input's wrapper that has the input field styling.\n * @csspart input - The internal `<input>` element.\n * @csspart field - The element that wraps the label, input, and help text.\n * @csspart clear-button - The clear button\n * @csspart password-toggle-button - The button for toggling password visibility\n * @csspart validation-message - The error message shown by `invalidmessage`.\n */\n@customElement('mid-textfield')\nexport class MinidTextfield extends FormControlMixin(styled(LitElement, styles)) {\n private readonly inputId!: string;\n private readonly descriptionId!: string;\n private readonly validationId!: string;\n private readonly hasSlotControler = new HasSlotController(this, 'label', 'prefix', 'suffix');\n private inputMask?: MaskInput;\n private initialValue = '';\n\n @query('input')\n input!: HTMLInputElement;\n\n @property()\n label = '';\n\n @property()\n description = '';\n\n @property()\n value = '';\n\n @property()\n size: 'sm' | 'md' | 'lg' = 'md';\n\n @property({ converter: stringConverter })\n placeholder?: string;\n\n /**\n * Autofocus the input field on page load\n */\n @property({ type: Boolean })\n autofocus = false;\n\n /**\n * User agent autocomplete hint\n */\n @property()\n autocomplete?: AutoFill;\n\n /**\n * The minimum length of input that will be considered valid.\n */\n @property({ type: Number })\n minlength?: number;\n\n /**\n * The maximum length of input that will be considered valid.\n */\n @property({ type: Number })\n maxlength?: number;\n\n /**\n * The input's minimum value. Only applies to date and number input types.\n */\n @property()\n min?: number | string;\n\n /**\n * The input's maximum value. Only applies to date and number input types.\n */\n @property()\n max?: number | string;\n\n /**\n * Error message to display when the input is invalid, also activates invalid styling\n */\n @property()\n invalidmessage = '';\n\n @property()\n type:\n | 'date'\n | 'datetime-local'\n | 'email'\n | 'file'\n | 'month'\n | 'number'\n | 'password'\n | 'search'\n | 'tel'\n | 'text'\n | 'time'\n | 'url'\n | 'week' = 'text';\n\n /**\n * For displaying appropriate virtual keyboard\n */\n @property()\n inputmode:\n | 'none'\n | 'text'\n | 'tel'\n | 'url'\n | 'email'\n | 'numeric'\n | 'decimal' = 'text';\n\n /**\n * Adds a clear button when the input is not empty.\n */\n @property({ type: Boolean })\n clearable = false;\n\n /**\n * Adds a button to toggle the password's visibility.\n * Only applies if type is password\n */\n @property({ type: Boolean })\n passwordtoggle = false;\n\n /**\n * Determines wether the password is currently visible.\n * Only applies if type is password\n */\n @property({ type: Boolean })\n passwordvisible = false;\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: Boolean, reflect: true })\n readonly = false;\n\n /**\n * A regular expression pattern to validate input against.\n */\n @property()\n pattern?: string;\n\n /**\n * Makes the input required\n */\n @property({ type: Boolean })\n required = false;\n\n /**\n * Visually hides `label` and `description` (still available for screen readers)\n */\n @property({ type: Boolean })\n hidelabel = false;\n\n /**\n * Modify input value based on mask e.g: `\"##:##\"` = 12:34.\n * `#`: /[0-9]/\n * `@`: /[a-zA-Z]/\n * `*`: /[a-zA-Z0-9]/\n * For more information go to https://beholdr.github.io/maska\n */\n @property()\n mask?: MaskType;\n\n @state()\n hasFocus = false;\n\n static get formControlValidators() {\n return [\n requiredValidator,\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n typeMismatchValidator,\n ];\n }\n\n constructor() {\n super();\n new LangController(this);\n nextUniqueId++;\n this.inputId = `mid-textfield-input-${nextUniqueId}`;\n this.descriptionId = `mid-textfield-description-${nextUniqueId}`;\n this.validationId = `mid-textfield-validation-${nextUniqueId}`;\n this.setValue(this.value);\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.initialValue = this.value;\n }\n\n get validationTarget() {\n return this.input;\n }\n\n protected firstUpdated(_changedProperties: PropertyValues): void {\n super.firstUpdated(_changedProperties);\n this.setValue(this.value);\n }\n\n disconnectedCallback(): void {\n this.inputMask?.destroy();\n }\n\n private handleKeydown(event: KeyboardEvent) {\n const hasModifier =\n event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;\n\n if (event.key === 'Enter' && !hasModifier) {\n setTimeout(() => {\n if (!event.defaultPrevented && !event.isComposing) {\n this.form.requestSubmit();\n }\n });\n }\n }\n\n private handleBlur() {\n this.hasFocus = false;\n this.dispatchEvent(\n new Event('mid-blur', { bubbles: true, composed: true })\n );\n }\n\n private handleChange() {\n this.value = this.input.value;\n this.dispatchEvent(\n new Event('mid-change', { bubbles: true, composed: true })\n );\n }\n\n private handleInput() {\n let tmp_value = this.input.value;\n\n if (this.type === 'number') {\n tmp_value = tmp_value.replace(/[^0-9]/g, '');\n }\n\n this.value = tmp_value;\n this.setValue(this.value);\n this.dispatchEvent(\n new Event('mid-input', { bubbles: true, composed: true })\n );\n }\n\n private handleFocus() {\n this.hasFocus = true;\n this.dispatchEvent(\n new Event('mid-focus', { composed: true, bubbles: true })\n );\n }\n\n private handlePasswordToggle() {\n this.passwordvisible = !this.passwordvisible;\n }\n\n private handleClearClick(event: MouseEvent) {\n event.preventDefault();\n\n if (this.value !== '') {\n this.value = '';\n this.dispatchEvent(\n new Event('mid-clear', { composed: true, bubbles: true })\n );\n this.dispatchEvent(\n new Event('mid-input', { composed: true, bubbles: true })\n );\n this.dispatchEvent(\n new Event('mid-change', { composed: true, bubbles: true })\n );\n }\n\n this.input.focus();\n }\n\n focus() {\n this.hasFocus = true;\n this.input.focus();\n }\n\n resetFormControl() {\n this.invalidmessage = '';\n this.value = this.initialValue;\n }\n\n forceError(message?: string): void {\n super.forceError(message);\n }\n\n @watch('value')\n handleValueUpdate() {\n this.setValue(this.value);\n }\n\n @watch('mask')\n async handleMaskUpdate() {\n if (!this.mask) return;\n await this.updateComplete;\n this.inputMask?.destroy();\n this.inputMask = new MaskInput(this.input, {\n mask: this.mask,\n eager: true,\n });\n }\n\n override render() {\n const lang = getLang(this);\n const t = getTranslations(lang);\n const hasLabelSlot = this.hasSlotControler.test('label');\n const hasLabel = !!this.label || !!hasLabelSlot;\n const hasPrefix = this.hasSlotControler.test('prefix');\n const hasSuffix = this.hasSlotControler.test('suffix');\n const hasClearIcon = this.clearable && !this.disabled && !this.readonly;\n const hasAffixes = hasPrefix || hasSuffix || hasClearIcon || (this.passwordtoggle && !this.disabled);\n const isClearIconVisible =\n hasClearIcon && (typeof this.value === 'number' || this.value.length > 0);\n const describedBy = [\n this.description ? this.descriptionId : undefined,\n this.invalidmessage ? this.validationId : undefined,\n ]\n .filter(Boolean)\n .join(' ');\n\n return html`\n <ds-field\n part=\"field\"\n class=\"ds-field\"\n data-size=${this.size}\n >\n <label\n for=\"${this.inputId}\"\n class=\"${classMap({\n 'sr-only': this.hidelabel || !hasLabel,\n })} ds-label\"\n >\n <slot name=\"label\"> ${this.label} </slot>\n </label>\n ${this.description\n ? html`\n <div\n id=\"${this.descriptionId}\"\n part=\"description\"\n aria-hidden=\"true\"\n class=\"${classMap({\n 'sr-only': this.hidelabel,\n })}\"\n >\n ${this.description}\n </div>\n `\n : nothing}\n <div\n part=\"base\"\n class=\"${hasAffixes ? 'ds-field-affixes' : ''}\"\n >\n ${hasPrefix ? html`<span class=\"ds-field-affix\"><slot name=\"prefix\"></slot></span>` : html`<slot name=\"prefix\"></slot>`}\n <input\n id=\"${this.inputId}\"\n class=\"ds-input\"\n part=\"input\"\n lang=${lang}\n .value=${live(this.value)}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n ?autofocus=${this.autofocus}\n autocomplete=${ifDefined(this.autocomplete as any)}\n type=${this.type === 'password' && this.passwordvisible\n ? 'text'\n : this.type}\n aria-describedby=${ifDefined(describedBy || undefined)}\n aria-invalid=${this.invalidmessage ? 'true' : 'false'}\n aria-errormessage=${ifDefined(\n this.invalidmessage ? this.validationId : undefined\n )}\n placeholder=${ifDefined(this.placeholder)}\n minlength=${ifDefined(this.minlength)}\n maxlength=${ifDefined(this.maxlength)}\n min=${ifDefined(this.min)}\n max=${ifDefined(this.max)}\n pattern=${ifDefined(this.pattern)}\n inputmode=${this.inputmode}\n @input=${this.handleInput}\n @change=${this.handleChange}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n @keydown=${this.handleKeydown}\n />\n ${isClearIconVisible\n ? html`\n <span class=\"ds-field-affix\" part=\"clear-button\">\n <button\n type=\"button\"\n class=\"focus-visible:focus-ring flex items-center justify-center rounded-sm\"\n aria-label=${t.clear}\n @click=${this.handleClearClick}\n >\n <mid-icon\n class=\"size-7\"\n library=\"nav-aksel\"\n name=\"trash\"\n ></mid-icon>\n </button>\n </span>\n `\n : ''}\n ${this.passwordtoggle && !this.disabled\n ? html`\n <span class=\"ds-field-affix\" part=\"password-toggle-button\">\n <button\n type=\"button\"\n class=\"focus-visible:focus-ring flex items-center justify-center rounded-sm\"\n aria-label=${this.passwordvisible\n ? t.hidePassword\n : t.showPassword}\n @click=${this.handlePasswordToggle}\n >\n ${this.passwordvisible\n ? html` <mid-icon\n class=\"size-7\"\n library=\"system\"\n name=\"eye-slash\"\n ></mid-icon>`\n : html`\n <mid-icon\n class=\"size-7\"\n library=\"system\"\n name=\"eye\"\n ></mid-icon>\n `}\n </button>\n </span>\n `\n : ''}\n ${hasSuffix ? html`<span part=\"suffix\" class=\"ds-field-affix\"><slot name=\"suffix\"></slot></span>` : html`<slot name=\"suffix\"></slot>`}\n </div>\n <p\n class=\"${classMap({\n 'ds-validation-message': !!this.invalidmessage,\n 'validation-message--empty': !this.invalidmessage,\n })}\"\n part=\"validation-message\"\n id=\"${this.validationId}\"\n aria-live=\"polite\"\n >\n ${this.invalidmessage}\n </p>\n </ds-field>\n `;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAM,SAAS;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BF;AAEA,IAAI,eAAe;AAwBZ,IAAM,iBAAN,cAA6B,iBAAiB,OAAO,YAAY,MAAM,CAAC,EAAE;AAAA,EAoK/E,cAAc;AACZ,UAAA;AAjKF,SAAiB,mBAAmB,IAAI,kBAAkB,MAAM,SAAS,UAAU,QAAQ;AAE3F,SAAQ,eAAe;AAMvB,SAAA,QAAQ;AAGR,SAAA,cAAc;AAGd,SAAA,QAAQ;AAGR,SAAA,OAA2B;AAS3B,SAAA,YAAY;AAoCZ,SAAA,iBAAiB;AAGjB,SAAA,OAaa;AAMb,SAAA,YAOgB;AAMhB,SAAA,YAAY;AAOZ,SAAA,iBAAiB;AAOjB,SAAA,kBAAkB;AAGlB,SAAA,WAAW;AAGX,SAAA,WAAW;AAYX,SAAA,WAAW;AAMX,SAAA,YAAY;AAaZ,SAAA,WAAW;AAcT,QAAI,eAAe,IAAI;AACvB;AACA,SAAK,UAAU,uBAAuB,YAAY;AAClD,SAAK,gBAAgB,6BAA6B,YAAY;AAC9D,SAAK,eAAe,4BAA4B,YAAY;AAC5D,SAAK,SAAS,KAAK,KAAK;AAAA,EAC1B;AAAA,EAlBA,WAAW,wBAAwB;AACjC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAYS,oBAA0B;AACjC,UAAM,kBAAA;AACN,SAAK,eAAe,KAAK;AAAA,EAC3B;AAAA,EAEA,IAAI,mBAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEU,aAAa,oBAA0C;AAC/D,UAAM,aAAa,kBAAkB;AACrC,SAAK,SAAS,KAAK,KAAK;AAAA,EAC1B;AAAA,EAEA,uBAA6B;AAC3B,SAAK,WAAW,QAAA;AAAA,EAClB;AAAA,EAEQ,cAAc,OAAsB;AAC1C,UAAM,cACJ,MAAM,WAAW,MAAM,WAAW,MAAM,YAAY,MAAM;AAE5D,QAAI,MAAM,QAAQ,WAAW,CAAC,aAAa;AACzC,iBAAW,MAAM;AACf,YAAI,CAAC,MAAM,oBAAoB,CAAC,MAAM,aAAa;AACjD,eAAK,KAAK,cAAA;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,aAAa;AACnB,SAAK,WAAW;AAChB,SAAK;AAAA,MACH,IAAI,MAAM,YAAY,EAAE,SAAS,MAAM,UAAU,MAAM;AAAA,IAAA;AAAA,EAE3D;AAAA,EAEQ,eAAe;AACrB,SAAK,QAAQ,KAAK,MAAM;AACxB,SAAK;AAAA,MACH,IAAI,MAAM,cAAc,EAAE,SAAS,MAAM,UAAU,MAAM;AAAA,IAAA;AAAA,EAE7D;AAAA,EAEQ,cAAc;AACpB,QAAI,YAAY,KAAK,MAAM;AAE3B,QAAI,KAAK,SAAS,UAAU;AAC1B,kBAAY,UAAU,QAAQ,WAAW,EAAE;AAAA,IAC7C;AAEA,SAAK,QAAQ;AACb,SAAK,SAAS,KAAK,KAAK;AACxB,SAAK;AAAA,MACH,IAAI,MAAM,aAAa,EAAE,SAAS,MAAM,UAAU,MAAM;AAAA,IAAA;AAAA,EAE5D;AAAA,EAEQ,cAAc;AACpB,SAAK,WAAW;AAChB,SAAK;AAAA,MACH,IAAI,MAAM,aAAa,EAAE,UAAU,MAAM,SAAS,MAAM;AAAA,IAAA;AAAA,EAE5D;AAAA,EAEQ,uBAAuB;AAC7B,SAAK,kBAAkB,CAAC,KAAK;AAAA,EAC/B;AAAA,EAEQ,iBAAiB,OAAmB;AAC1C,UAAM,eAAA;AAEN,QAAI,KAAK,UAAU,IAAI;AACrB,WAAK,QAAQ;AACb,WAAK;AAAA,QACH,IAAI,MAAM,aAAa,EAAE,UAAU,MAAM,SAAS,MAAM;AAAA,MAAA;AAE1D,WAAK;AAAA,QACH,IAAI,MAAM,aAAa,EAAE,UAAU,MAAM,SAAS,MAAM;AAAA,MAAA;AAE1D,WAAK;AAAA,QACH,IAAI,MAAM,cAAc,EAAE,UAAU,MAAM,SAAS,MAAM;AAAA,MAAA;AAAA,IAE7D;AAEA,SAAK,MAAM,MAAA;AAAA,EACb;AAAA,EAEA,QAAQ;AACN,SAAK,WAAW;AAChB,SAAK,MAAM,MAAA;AAAA,EACb;AAAA,EAEA,mBAAmB;AACjB,SAAK,iBAAiB;AACtB,SAAK,QAAQ,KAAK;AAAA,EACpB;AAAA,EAEA,WAAW,SAAwB;AACjC,UAAM,WAAW,OAAO;AAAA,EAC1B;AAAA,EAGA,oBAAoB;AAClB,SAAK,SAAS,KAAK,KAAK;AAAA,EAC1B;AAAA,EAGA,MAAM,mBAAmB;AACvB,QAAI,CAAC,KAAK,KAAM;AAChB,UAAM,KAAK;AACX,SAAK,WAAW,QAAA;AAChB,SAAK,YAAY,IAAI,UAAU,KAAK,OAAO;AAAA,MACzC,MAAM,KAAK;AAAA,MACX,OAAO;AAAA,IAAA,CACR;AAAA,EACH;AAAA,EAES,SAAS;AAChB,UAAM,OAAO,QAAQ,IAAI;AACzB,UAAM,IAAI,gBAAgB,IAAI;AAC9B,UAAM,eAAe,KAAK,iBAAiB,KAAK,OAAO;AACvD,UAAM,WAAW,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;AACnC,UAAM,YAAY,KAAK,iBAAiB,KAAK,QAAQ;AACrD,UAAM,YAAY,KAAK,iBAAiB,KAAK,QAAQ;AACrD,UAAM,eAAe,KAAK,aAAa,CAAC,KAAK,YAAY,CAAC,KAAK;AAC/D,UAAM,aAAa,aAAa,aAAa,gBAAiB,KAAK,kBAAkB,CAAC,KAAK;AAC3F,UAAM,qBACJ,iBAAiB,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,SAAS;AACzE,UAAM,cAAc;AAAA,MAClB,KAAK,cAAc,KAAK,gBAAgB;AAAA,MACxC,KAAK,iBAAiB,KAAK,eAAe;AAAA,IAAA,EAEzC,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,WAAO;AAAA;AAAA;AAAA;AAAA,oBAIS,KAAK,IAAI;AAAA;AAAA;AAAA,iBAGZ,KAAK,OAAO;AAAA,mBACV,SAAS;AAAA,MAChB,WAAW,KAAK,aAAa,CAAC;AAAA,IAAA,CAC/B,CAAC;AAAA;AAAA,gCAEoB,KAAK,KAAK;AAAA;AAAA,UAEhC,KAAK,cACH;AAAA;AAAA,sBAEU,KAAK,aAAa;AAAA;AAAA;AAAA,yBAGf,SAAS;AAAA,MAChB,WAAW,KAAK;AAAA,IAAA,CACjB,CAAC;AAAA;AAAA,kBAEA,KAAK,WAAW;AAAA;AAAA,gBAGtB,OAAO;AAAA;AAAA;AAAA,mBAGA,aAAa,qBAAqB,EAAE;AAAA;AAAA,YAE3C,YAAY,wEAAwE,iCAAiC;AAAA;AAAA,kBAE/G,KAAK,OAAO;AAAA;AAAA;AAAA,mBAGX,IAAI;AAAA,qBACF,KAAK,KAAK,KAAK,CAAC;AAAA,wBACb,KAAK,QAAQ;AAAA,wBACb,KAAK,QAAQ;AAAA,wBACb,KAAK,QAAQ;AAAA,yBACZ,KAAK,SAAS;AAAA,2BACZ,UAAU,KAAK,YAAmB,CAAC;AAAA,mBAC3C,KAAK,SAAS,cAAc,KAAK,kBACpC,SACA,KAAK,IAAI;AAAA,+BACM,UAAU,eAAe,MAAS,CAAC;AAAA,2BACvC,KAAK,iBAAiB,SAAS,OAAO;AAAA,gCACjC;AAAA,MAClB,KAAK,iBAAiB,KAAK,eAAe;AAAA,IAAA,CAC3C;AAAA,0BACa,UAAU,KAAK,WAAW,CAAC;AAAA,wBAC7B,UAAU,KAAK,SAAS,CAAC;AAAA,wBACzB,UAAU,KAAK,SAAS,CAAC;AAAA,kBAC/B,UAAU,KAAK,GAAG,CAAC;AAAA,kBACnB,UAAU,KAAK,GAAG,CAAC;AAAA,sBACf,UAAU,KAAK,OAAO,CAAC;AAAA,wBACrB,KAAK,SAAS;AAAA,qBACjB,KAAK,WAAW;AAAA,sBACf,KAAK,YAAY;AAAA,qBAClB,KAAK,WAAW;AAAA,oBACjB,KAAK,UAAU;AAAA,uBACZ,KAAK,aAAa;AAAA;AAAA,YAE7B,qBACE;AAAA;AAAA;AAAA;AAAA;AAAA,iCAKmB,EAAE,KAAK;AAAA,6BACX,KAAK,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAUpC,EAAE;AAAA,YACJ,KAAK,kBAAkB,CAAC,KAAK,WAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,iCAKmB,KAAK,kBACd,EAAE,eACF,EAAE,YAAY;AAAA,6BACT,KAAK,oBAAoB;AAAA;AAAA,sBAEhC,KAAK,kBACH;AAAA;AAAA;AAAA;AAAA,wCAKA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAMC;AAAA;AAAA;AAAA,kBAIX,EAAE;AAAA,YACJ,YAAY,sFAAsF,iCAAiC;AAAA;AAAA;AAAA,mBAG5H,SAAS;AAAA,MAChB,yBAAyB,CAAC,CAAC,KAAK;AAAA,MAChC,6BAA6B,CAAC,KAAK;AAAA,IAAA,CACpC,CAAC;AAAA;AAAA,gBAEI,KAAK,YAAY;AAAA;AAAA;AAAA,YAGrB,KAAK,cAAc;AAAA;AAAA;AAAA;AAAA,EAI7B;AACF;AA7aE,gBAAA;AAAA,EADC,MAAM,OAAO;AAAA,GARH,eASX,WAAA,SAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GAXC,eAYX,WAAA,SAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GAdC,eAeX,WAAA,eAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GAjBC,eAkBX,WAAA,SAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GApBC,eAqBX,WAAA,QAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAE,WAAW,gBAAA,CAAiB;AAAA,GAvB7B,eAwBX,WAAA,eAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GA7BhB,eA8BX,WAAA,aAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GAnCC,eAoCX,WAAA,gBAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAzCf,eA0CX,WAAA,aAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA/Cf,eAgDX,WAAA,aAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GArDC,eAsDX,WAAA,OAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GA3DC,eA4DX,WAAA,OAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GAjEC,eAkEX,WAAA,kBAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAA;AAAS,GApEC,eAqEX,WAAA,QAAA,CAAA;AAmBA,gBAAA;AAAA,EADC,SAAA;AAAS,GAvFC,eAwFX,WAAA,aAAA,CAAA;AAaA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GApGhB,eAqGX,WAAA,aAAA,CAAA;AAOA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GA3GhB,eA4GX,WAAA,kBAAA,CAAA;AAOA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GAlHhB,eAmHX,WAAA,mBAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,GArH/B,eAsHX,WAAA,YAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM;AAAA,GAxH/B,eAyHX,WAAA,YAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAA;AAAS,GA9HC,eA+HX,WAAA,WAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GApIhB,eAqIX,WAAA,YAAA,CAAA;AAMA,gBAAA;AAAA,EADC,SAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GA1IhB,eA2IX,WAAA,aAAA,CAAA;AAUA,gBAAA;AAAA,EADC,SAAA;AAAS,GApJC,eAqJX,WAAA,QAAA,CAAA;AAGA,gBAAA;AAAA,EADC,MAAA;AAAM,GAvJI,eAwJX,WAAA,YAAA,CAAA;AA8HA,gBAAA;AAAA,EADC,MAAM,OAAO;AAAA,GArRH,eAsRX,WAAA,qBAAA,CAAA;AAKM,gBAAA;AAAA,EADL,MAAM,MAAM;AAAA,GA1RF,eA2RL,WAAA,oBAAA,CAAA;AA3RK,iBAAN,gBAAA;AAAA,EADN,cAAc,eAAe;AAAA,GACjB,cAAA;"}
|
|
1
|
+
{"version":3,"file":"textfield.js","sources":["../../src/components/textfield.component.ts"],"sourcesContent":["import { css, html, LitElement, nothing, type PropertyValues } from 'lit';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { live } from 'lit/directives/live.js';\nimport { stringConverter } from '../internal/string-converter';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { styled } from '../mixins/tailwind.mixin.ts';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HasSlotController } from '../internal/slot';\nimport { FormControlMixin } from '../mixins/form-control.mixin';\nimport {\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n requiredValidator,\n typeMismatchValidator,\n} from '../mixins/validators';\nimport { watch } from '../internal/watch';\nimport './icon/icon.component.ts';\nimport { MaskInput, type MaskType } from 'maska';\nimport { getLang } from '../utilities/lang';\nimport { getTranslations } from '../utilities/translations';\nimport { LangController } from '../controllers/lang.controller.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mid-textfield': MinidTextfield;\n }\n}\n\nconst styles = [\n css`\n :host {\n display: block;\n }\n\n /* Hide increment/decrement buttons on inputs */\n input[type='number']::-webkit-outer-spin-button,\n input[type='number']::-webkit-inner-spin-button,\n input[type='number'] {\n -webkit-appearance: none;\n margin: 0;\n -moz-appearance: textfield !important;\n }\n\n .ds-field-affixes {\n background: var(--ds-color-neutral-background-tinted);\n }\n\n .has-field-buttons {\n --mid-field-button-size: var(--ds-size-7);\n --mid-field-button-gap: var(--ds-size-3);\n --mid-field-button-border: var(--ds-border-width-default);\n position: relative;\n display: block;\n }\n\n .has-field-buttons .ds-input {\n padding-inline-end: calc(\n var(--mid-field-button-size) + 2 * var(--mid-field-button-gap)\n );\n }\n\n .has-field-buttons--two .ds-input {\n padding-inline-end: calc(\n 2 * (var(--mid-field-button-size) + 2 * var(--mid-field-button-gap))\n );\n }\n\n .password-toggle-input::-ms-reveal,\n .password-toggle-input::-ms-clear {\n display: none;\n }\n\n .has-field-buttons .ds-input::-webkit-credentials-auto-fill-button {\n margin-inline-end: calc(\n var(--mid-field-button-size) + 2 * var(--mid-field-button-gap)\n );\n }\n\n .has-field-buttons--two .ds-input::-webkit-credentials-auto-fill-button {\n margin-inline-end: calc(\n 2 * (var(--mid-field-button-size) + 2 * var(--mid-field-button-gap))\n );\n }\n\n .has-field-buttons:hover\n .ds-input:not(:focus-visible, :disabled, [readonly], [aria-readonly='true']) {\n outline: var(--dsc-input-outline-width--hover)\n var(--dsc-input-outline-style--hover)\n var(--dsc-input-outline-color--hover);\n }\n\n .has-field-buttons:hover\n .ds-input[aria-invalid='true']:not(:focus-visible, :disabled, [readonly], [aria-readonly='true']) {\n outline-color: var(--dsc-input-accent-color--invalid);\n }\n\n .field-buttons {\n position: absolute;\n inset-block: var(--mid-field-button-border);\n inset-inline-end: var(--mid-field-button-border);\n display: flex;\n pointer-events: none;\n }\n\n .field-button {\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--ds-color-neutral-text-subtle);\n pointer-events: auto;\n }\n\n .field-buttons .field-button {\n padding-inline: var(--mid-field-button-gap);\n }\n\n .field-button > span {\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--ds-border-radius-sm);\n block-size: var(--mid-field-button-size, var(--ds-size-7));\n inline-size: var(--mid-field-button-size, var(--ds-size-7));\n }\n\n .field-button mid-icon {\n font-size: var(--mid-field-button-size, var(--ds-size-7));\n }\n\n .field-button:focus-visible {\n outline: none;\n }\n\n .field-button:focus-visible > span {\n box-shadow: 0 0 0 var(--ds-border-width-focus) var(--ds-color-focus-inner);\n outline: var(--ds-color-focus-outer) solid var(--ds-border-width-focus);\n outline-offset: var(--ds-border-width-focus);\n }\n\n /* The validation message stays in the DOM so its text lands in a live region\n the screen reader is already watching - WebKit does not reliably announce\n one revealed at the same moment the text arrives. When empty it must paint\n nothing and take no room: the element drops the ds-validation-message class\n (whose ::before paints an error icon regardless of the text) and this rule\n cancels the sibling spacing from .ds-field > * + *, which the .ds-field >\n prefix is enough to outrank without !important. */\n .ds-field > .validation-message--empty {\n margin-top: 0;\n }\n `,\n];\n\nlet nextUniqueId = 0;\n\n/**\n *\n * @event mid-change - Emitted when a change to the input value is comitted by the user\n * @event mid-input - Emitted when the input element recieves input\n * @event mid-clear - Emitted when the input value is cleared\n * @event mid-focus - Emitted when input element is focused\n * @event mid-blur - Emitted when focus moves away from input element\n * @event {detail: { validity: ValidityState }} mid-invalid-hide - Emitted when the error message should be hidden\n * @event {detail: { validity: ValidityState }} mid-invalid-show - Emitted when the error message should be shown\n *\n * @slot prefix - Used for decoration to the left of the input\n * @slot suffix - Used for decoration to the right of the input\n * @slot label - The input's label. Alternatively, you can use the `label` attribute.\n *\n * @csspart base - The input's wrapper that has the input field styling.\n * @csspart input - The internal `<input>` element.\n * @csspart field - The element that wraps the label, input, and help text.\n * @csspart clear-button - The clear button\n * @csspart password-toggle-button - The button for toggling password visibility\n * @csspart validation-message - The error message shown by `invalidmessage`.\n */\n@customElement('mid-textfield')\nexport class MinidTextfield extends FormControlMixin(styled(LitElement, styles)) {\n private readonly inputId!: string;\n private readonly descriptionId!: string;\n private readonly validationId!: string;\n private readonly hasSlotControler = new HasSlotController(this, 'label', 'prefix', 'suffix');\n private inputMask?: MaskInput;\n private initialValue = '';\n\n @query('input')\n input!: HTMLInputElement;\n\n @property()\n label = '';\n\n @property()\n description = '';\n\n @property()\n value = '';\n\n @property()\n size: 'sm' | 'md' | 'lg' = 'md';\n\n @property({ converter: stringConverter })\n placeholder?: string;\n\n /**\n * Autofocus the input field on page load\n */\n @property({ type: Boolean })\n autofocus = false;\n\n /**\n * User agent autocomplete hint\n */\n @property()\n autocomplete?: AutoFill;\n\n /**\n * The minimum length of input that will be considered valid.\n */\n @property({ type: Number })\n minlength?: number;\n\n /**\n * The maximum length of input that will be considered valid.\n */\n @property({ type: Number })\n maxlength?: number;\n\n /**\n * The input's minimum value. Only applies to date and number input types.\n */\n @property()\n min?: number | string;\n\n /**\n * The input's maximum value. Only applies to date and number input types.\n */\n @property()\n max?: number | string;\n\n /**\n * Error message to display when the input is invalid, also activates invalid styling\n */\n @property()\n invalidmessage = '';\n\n @property()\n type:\n | 'date'\n | 'datetime-local'\n | 'email'\n | 'file'\n | 'month'\n | 'number'\n | 'password'\n | 'search'\n | 'tel'\n | 'text'\n | 'time'\n | 'url'\n | 'week' = 'text';\n\n /**\n * For displaying appropriate virtual keyboard\n */\n @property()\n inputmode:\n | 'none'\n | 'text'\n | 'tel'\n | 'url'\n | 'email'\n | 'numeric'\n | 'decimal' = 'text';\n\n /**\n * Adds a clear button when the input is not empty.\n */\n @property({ type: Boolean })\n clearable = false;\n\n /**\n * Adds a button to toggle the password's visibility.\n * Only applies if type is password\n */\n @property({ type: Boolean })\n passwordtoggle = false;\n\n /**\n * Determines wether the password is currently visible.\n * Only applies if type is password\n */\n @property({ type: Boolean })\n passwordvisible = false;\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: Boolean, reflect: true })\n readonly = false;\n\n /**\n * A regular expression pattern to validate input against.\n */\n @property()\n pattern?: string;\n\n /**\n * Makes the input required\n */\n @property({ type: Boolean })\n required = false;\n\n /**\n * Visually hides `label` and `description` (still available for screen readers)\n */\n @property({ type: Boolean })\n hidelabel = false;\n\n /**\n * Modify input value based on mask e.g: `\"##:##\"` = 12:34.\n * `#`: /[0-9]/\n * `@`: /[a-zA-Z]/\n * `*`: /[a-zA-Z0-9]/\n * For more information go to https://beholdr.github.io/maska\n */\n @property()\n mask?: MaskType;\n\n @state()\n hasFocus = false;\n\n static get formControlValidators() {\n return [\n requiredValidator,\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n typeMismatchValidator,\n ];\n }\n\n constructor() {\n super();\n new LangController(this);\n nextUniqueId++;\n this.inputId = `mid-textfield-input-${nextUniqueId}`;\n this.descriptionId = `mid-textfield-description-${nextUniqueId}`;\n this.validationId = `mid-textfield-validation-${nextUniqueId}`;\n this.setValue(this.value);\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.initialValue = this.value;\n }\n\n get validationTarget() {\n return this.input;\n }\n\n protected firstUpdated(_changedProperties: PropertyValues): void {\n super.firstUpdated(_changedProperties);\n this.setValue(this.value);\n }\n\n disconnectedCallback(): void {\n this.inputMask?.destroy();\n }\n\n private handleKeydown(event: KeyboardEvent) {\n const hasModifier =\n event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;\n\n if (event.key === 'Enter' && !hasModifier) {\n setTimeout(() => {\n if (!event.defaultPrevented && !event.isComposing) {\n this.form.requestSubmit();\n }\n });\n }\n }\n\n private handleBlur() {\n this.hasFocus = false;\n this.dispatchEvent(\n new Event('mid-blur', { bubbles: true, composed: true })\n );\n }\n\n private handleChange() {\n this.value = this.input.value;\n this.dispatchEvent(\n new Event('mid-change', { bubbles: true, composed: true })\n );\n }\n\n private handleInput() {\n let tmp_value = this.input.value;\n\n if (this.type === 'number') {\n tmp_value = tmp_value.replace(/[^0-9]/g, '');\n }\n\n this.value = tmp_value;\n this.setValue(this.value);\n this.dispatchEvent(\n new Event('mid-input', { bubbles: true, composed: true })\n );\n }\n\n private handleFocus() {\n this.hasFocus = true;\n this.dispatchEvent(\n new Event('mid-focus', { composed: true, bubbles: true })\n );\n }\n\n private handlePasswordToggle() {\n this.passwordvisible = !this.passwordvisible;\n }\n\n private handleInFieldButtonMousedown(event: MouseEvent) {\n event.preventDefault();\n }\n\n private handleClearClick(event: MouseEvent) {\n event.preventDefault();\n\n if (this.value !== '') {\n this.value = '';\n this.dispatchEvent(\n new Event('mid-clear', { composed: true, bubbles: true })\n );\n this.dispatchEvent(\n new Event('mid-input', { composed: true, bubbles: true })\n );\n this.dispatchEvent(\n new Event('mid-change', { composed: true, bubbles: true })\n );\n }\n\n this.input.focus();\n }\n\n focus() {\n this.hasFocus = true;\n this.input.focus();\n }\n\n resetFormControl() {\n this.invalidmessage = '';\n this.value = this.initialValue;\n }\n\n forceError(message?: string): void {\n super.forceError(message);\n }\n\n @watch('value')\n handleValueUpdate() {\n this.setValue(this.value);\n }\n\n @watch('mask')\n async handleMaskUpdate() {\n if (!this.mask) return;\n await this.updateComplete;\n this.inputMask?.destroy();\n this.inputMask = new MaskInput(this.input, {\n mask: this.mask,\n eager: true,\n });\n }\n\n override render() {\n const lang = getLang(this);\n const t = getTranslations(lang);\n const hasLabelSlot = this.hasSlotControler.test('label');\n const hasLabel = !!this.label || !!hasLabelSlot;\n const hasPrefix = this.hasSlotControler.test('prefix');\n const hasSuffix = this.hasSlotControler.test('suffix');\n const hasClearIcon = this.clearable && !this.disabled && !this.readonly;\n const hasPasswordToggle = this.passwordtoggle && !this.disabled;\n const overlayFieldButtons =\n (hasClearIcon || hasPasswordToggle) && !hasPrefix && !hasSuffix;\n const hasAffixes = hasPrefix || hasSuffix;\n const isClearIconVisible =\n hasClearIcon && (typeof this.value === 'number' || this.value.length > 0);\n const describedBy = [\n this.description ? this.descriptionId : undefined,\n this.invalidmessage ? this.validationId : undefined,\n ]\n .filter(Boolean)\n .join(' ');\n\n const passwordToggleButton = html`\n <button\n type=\"button\"\n part=\"password-toggle-button\"\n class=\"field-button\"\n aria-label=${this.passwordvisible ? t.hidePassword : t.showPassword}\n aria-controls=${this.inputId}\n @mousedown=${this.handleInFieldButtonMousedown}\n @click=${this.handlePasswordToggle}\n >\n <span>\n <mid-icon\n library=\"system\"\n name=${this.passwordvisible ? 'eye-slash' : 'eye'}\n ></mid-icon>\n </span>\n </button>\n `;\n\n const clearButton = html`\n <button\n type=\"button\"\n part=\"clear-button\"\n class=\"field-button\"\n aria-label=${t.clear}\n @mousedown=${this.handleInFieldButtonMousedown}\n @click=${this.handleClearClick}\n >\n <span>\n <mid-icon library=\"nav-aksel\" name=\"trash\"></mid-icon>\n </span>\n </button>\n `;\n\n return html`\n <ds-field\n part=\"field\"\n class=\"ds-field\"\n data-size=${this.size}\n >\n <label\n for=\"${this.inputId}\"\n class=\"${classMap({\n 'sr-only': this.hidelabel || !hasLabel,\n })} ds-label\"\n >\n <slot name=\"label\"> ${this.label} </slot>\n </label>\n ${this.description\n ? html`\n <div\n id=\"${this.descriptionId}\"\n part=\"description\"\n aria-hidden=\"true\"\n class=\"${classMap({\n 'sr-only': this.hidelabel,\n })}\"\n >\n ${this.description}\n </div>\n `\n : nothing}\n <div\n part=\"base\"\n class=\"${classMap({\n 'ds-field-affixes': hasAffixes,\n 'has-field-buttons': overlayFieldButtons,\n 'has-field-buttons--two':\n overlayFieldButtons && hasClearIcon && hasPasswordToggle,\n })}\"\n >\n ${hasPrefix ? html`<span class=\"ds-field-affix\"><slot name=\"prefix\"></slot></span>` : html`<slot name=\"prefix\"></slot>`}\n <input\n id=\"${this.inputId}\"\n class=\"${classMap({\n 'ds-input': true,\n 'password-toggle-input': hasPasswordToggle,\n })}\"\n part=\"input\"\n lang=${lang}\n .value=${live(this.value)}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n ?autofocus=${this.autofocus}\n autocomplete=${ifDefined(this.autocomplete as any)}\n type=${this.type === 'password' && this.passwordvisible\n ? 'text'\n : this.type}\n aria-describedby=${ifDefined(describedBy || undefined)}\n aria-invalid=${this.invalidmessage ? 'true' : 'false'}\n aria-errormessage=${ifDefined(\n this.invalidmessage ? this.validationId : undefined\n )}\n placeholder=${ifDefined(this.placeholder)}\n minlength=${ifDefined(this.minlength)}\n maxlength=${ifDefined(this.maxlength)}\n min=${ifDefined(this.min)}\n max=${ifDefined(this.max)}\n pattern=${ifDefined(this.pattern)}\n inputmode=${this.inputmode}\n @input=${this.handleInput}\n @change=${this.handleChange}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n @keydown=${this.handleKeydown}\n />\n ${overlayFieldButtons\n ? html`\n <div class=\"field-buttons\">\n ${isClearIconVisible ? clearButton : nothing}\n ${hasPasswordToggle ? passwordToggleButton : nothing}\n </div>\n `\n : nothing}\n ${!overlayFieldButtons && isClearIconVisible\n ? html`<span class=\"ds-field-affix\">${clearButton}</span>`\n : nothing}\n ${!overlayFieldButtons && hasPasswordToggle\n ? html`<span class=\"ds-field-affix\">${passwordToggleButton}</span>`\n : nothing}\n ${hasSuffix ? html`<span part=\"suffix\" class=\"ds-field-affix\"><slot name=\"suffix\"></slot></span>` : html`<slot name=\"suffix\"></slot>`}\n </div>\n <p\n class=\"${classMap({\n 'ds-validation-message': !!this.invalidmessage,\n 'validation-message--empty': !this.invalidmessage,\n })}\"\n part=\"validation-message\"\n id=\"${this.validationId}\"\n aria-live=\"polite\"\n >\n ${this.invalidmessage}\n </p>\n </ds-field>\n `;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-control.mixin.d.ts","sourceRoot":"","sources":["../../src/mixins/form-control.mixin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAO9D;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,SAAS,WAAW,CAAC,UAAU,GAAG,YAAY,CAAC,GAAG;IACrD,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B,EACD,UAAU,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"form-control.mixin.d.ts","sourceRoot":"","sources":["../../src/mixins/form-control.mixin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAO9D;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,SAAS,WAAW,CAAC,UAAU,GAAG,YAAY,CAAC,GAAG;IACrD,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B,EACD,UAAU,EAAE,KAAK,GA4nBgB,WAAW,CAAC,oBAAoB,CAAC,GAAG,KAAK,CAC3E"}
|
|
@@ -204,6 +204,25 @@ function FormControlMixin(SuperClass) {
|
|
|
204
204
|
const showError = __privateMethod(this, _FormControl_instances, shouldShowError_fn).call(this);
|
|
205
205
|
__privateMethod(this, _FormControl_instances, dispatchInvalidEvent_fn).call(this, showError);
|
|
206
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Updates the form value and re-runs validators without touching the
|
|
209
|
+
* error-display state: `#forceError` is left alone, no
|
|
210
|
+
* `validationMessageCallback('')`, no `mid-invalid-show`/`-hide` is
|
|
211
|
+
* dispatched, and the control is not marked touched (a programmatic set
|
|
212
|
+
* is not user interaction). For programmatic value changes where the host
|
|
213
|
+
* page owns the error presentation and a `setValue` would wipe it
|
|
214
|
+
* mid-flow.
|
|
215
|
+
* @param value {FormValue} - The value to pass to the form
|
|
216
|
+
*/
|
|
217
|
+
syncFormValue(value) {
|
|
218
|
+
__privateSet(this, _value, value);
|
|
219
|
+
const valueToUpdate = this.shouldFormValueUpdate() ? value : null;
|
|
220
|
+
this.internals.setFormValue(valueToUpdate);
|
|
221
|
+
__privateMethod(this, _FormControl_instances, runValidators_fn).call(this, valueToUpdate);
|
|
222
|
+
if (this.valueChangedCallback) {
|
|
223
|
+
this.valueChangedCallback(valueToUpdate);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
207
226
|
/**
|
|
208
227
|
* Forces the control to show an error state. If a message is passed in,
|
|
209
228
|
* it will be set as the control's internal validity state message.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-control.mixin.js","sources":["../../src/mixins/form-control.mixin.ts"],"sourcesContent":["import { LitElement } from 'lit';\nimport type { IControlHost } from '../types/control-host';\nimport type { FormControlInterface } from '../types/form-control';\nimport type { FormValue } from '../types/form-value';\nimport type { Constructor } from '../types/mixin-constructor';\nimport type {\n CustomValidityState,\n validationMessageCallback,\n Validator,\n} from '../types/validator.type';\n\n/**\n *\n * https://github.com/open-wc/form-participation/tree/main/packages/form-control\n */\nexport function FormControlMixin<\n TBase extends Constructor<LitElement & IControlHost> & {\n observedAttributes?: string[];\n },\n>(SuperClass: TBase) {\n class FormControl extends SuperClass {\n /**\n * Wires up control instances to be form associated\n * @ignore\n */\n static get formAssociated(): boolean {\n return true;\n }\n\n /**\n * A list of Validator objects that will be evaluated when a control's form\n * value is modified or optionally when a given attribute changes.\n *\n * When a Validator's callback returns false, the entire form control will\n * be set to an invalid state.\n * @ignore\n */\n declare static formControlValidators: Validator[];\n\n /**\n * If set to true the control described should be evaluated and validated\n * as part of a group. Like a radio, if any member of the group's validity\n * changes the the other members should update as well.\n * @ignore\n */\n declare static formControlValidationGroup: boolean;\n\n /**\n * @ignore\n */\n private static get validators(): Validator[] {\n return this.formControlValidators || [];\n }\n\n /**\n * Allows the FormControl instance to respond to Validator attributes.\n * For instance, if a given Validator has a `required` attribute, that\n * validator will be evaluated whenever the host's required attribute\n * is updated.\n * @ignore\n */\n static get observedAttributes(): string[] {\n const validatorAttributes = this.validators\n .map((validator) => validator.attribute)\n .flat();\n\n const observedAttributes = super.observedAttributes || [];\n\n /** Make sure there are no duplicates inside the attributes list */\n const attributeSet = new Set([\n ...observedAttributes,\n ...validatorAttributes,\n ]);\n return [...attributeSet] as string[];\n }\n\n /**\n * Return the validator associated with a given attribute. If no\n * Validator is associated with the attribute, it will return null.\n * @ignore\n */\n static getValidator(attribute: string): Validator | null {\n return (\n this.validators.find(\n (validator) => validator.attribute === attribute\n ) || null\n );\n }\n\n /**\n * Get all validators that are set to react to a given attribute\n * @param {string} attribute - The attribute that has changed\n * @returns {Validator[]}\n * @ignore\n */\n static getValidators(attribute: string): Validator[] | null {\n return this.validators.filter((validator) => {\n if (\n validator.attribute === attribute ||\n validator.attribute?.includes(attribute)\n ) {\n return true;\n }\n });\n }\n\n /**\n * The ElementInternals instance for the control.\n * @ignore\n */\n internals = this.attachInternals();\n\n /**\n * Keep track of if the control has focus\n * @private\n * @ignore\n */\n #focused = false;\n\n /**\n * Exists to control when an error should be displayed\n * @private\n * @ignore\n */\n #forceError = false;\n\n /**\n * Toggles to true whenever the element has been altered. This property\n * will reset whenever the control's formResetCallback is called.\n * @private\n * @ignore\n */\n #touched = false;\n\n /**\n * An internal abort controller for cancelling pending async validation\n * @ignore\n */\n #abortController?: AbortController;\n\n /**\n * Used for tracking if a validation target has been set to manage focus\n * when the control's validity is reported\n * @ignore\n */\n #awaitingValidationTarget = true;\n\n /**\n * Acts as a cache for the current value so the value can be re-evaluated\n * whenever an attribute changes or on some other event.\n * @ignore\n */\n #value: FormValue = '';\n\n /**\n * Set this[focused]\n * to true when the element is focused\n * @private\n * @ignore\n */\n #onFocus = (): void => {\n this.#focused = true;\n this.#shouldShowError();\n };\n\n /**\n * Reset this[focused] on blur\n * @private\n * @ignore\n */\n #onBlur = (): void => {\n this.#focused = false;\n\n this.#runValidators(this.shouldFormValueUpdate() ? this.#value : '');\n\n /**\n * Set forceError to ensure error messages persist until\n * the value is changed.\n */\n if (!this.validity.valid && this.#touched) {\n this.#forceError = true;\n }\n const showError = this.#shouldShowError();\n\n if (this.validationMessageCallback) {\n this.validationMessageCallback(showError ? this.validationMessage : '');\n }\n this.#dispatchInvalidEvent(showError);\n };\n\n /**\n * For the show error state on invalid\n * @private\n * @ignore\n */\n #onInvalid = (event?: Event): void => {\n event?.preventDefault();\n event?.stopImmediatePropagation();\n\n if (this.#awaitingValidationTarget && this.validationTarget) {\n this.internals.setValidity(\n this.validity,\n this.validationMessage,\n this.validationTarget\n );\n this.#awaitingValidationTarget = false;\n }\n this.#touched = true;\n this.#forceError = true;\n const showError = this.#shouldShowError();\n this?.validationMessageCallback?.(\n showError ? this.validationMessage : ''\n );\n this.#dispatchInvalidEvent(showError);\n };\n\n /**\n * Return a reference to the control's form\n * @ignore\n */\n get form(): HTMLFormElement {\n return this.internals.form as HTMLFormElement;\n }\n\n /**\n * Will return true if it is recommended that the control shows an internal\n * error. If using this property, it is wise to listen for 'invalid' events\n * on the element host and call preventDefault on the event. Doing this will\n * prevent browsers from showing a validation popup.\n * @ignore\n */\n get showError(): boolean {\n return this.#shouldShowError();\n }\n\n /**\n * Forward the internals checkValidity method\n * will return the valid state of the control.\n * @ignore\n */\n checkValidity(): boolean {\n return this.internals.checkValidity();\n }\n\n /**\n * The element's validity state\n * @ignore\n */\n get validity(): ValidityState {\n return this.internals.validity;\n }\n\n /**\n * The validation message shown by a given Validator object. If the control\n * is in a valid state this should be falsy.\n * @ignore\n */\n get validationMessage(): string {\n return this.internals.validationMessage;\n }\n\n constructor(...args: any[]) {\n super(...args);\n this.addEventListener?.('focus', this.#onFocus);\n this.addEventListener?.('blur', this.#onBlur);\n this.addEventListener?.('invalid', this.#onInvalid);\n this.setValue(null);\n }\n\n attributeChangedCallback(\n name: string,\n oldValue: string,\n newValue: string\n ): void {\n super.attributeChangedCallback?.(name, oldValue, newValue);\n\n /**\n * Check to see if a Validator is associated with the changed attribute.\n * If one exists, call control's validate function which will perform\n * control validation.\n * @ignore\n */\n const proto = this.constructor as typeof FormControl;\n const validators = proto.getValidators(name);\n\n if (validators?.length && this.validationTarget) {\n this.setValue(this.#value);\n }\n }\n\n /** PUBLIC LIFECYCLE METHODS */\n\n /**\n * Sets the control's form value if the call to `shouldFormValueUpdate`\n * returns `true`. Set this[touch] if connected and value changed.\n * @param value {FormValue} - The value to pass to the form\n * @ignore\n */\n setValue(value: FormValue): void {\n if (this.isConnected && this.#value !== value) {\n this.#touched = true;\n }\n this.#forceError = false;\n this.validationMessageCallback?.('');\n this.#value = value;\n const valueShouldUpdate = this.shouldFormValueUpdate();\n const valueToUpdate = valueShouldUpdate ? value : null;\n this.internals.setFormValue(valueToUpdate as string);\n this.#runValidators(valueToUpdate);\n if (this.valueChangedCallback) {\n this.valueChangedCallback(valueToUpdate);\n }\n const showError = this.#shouldShowError();\n this.#dispatchInvalidEvent(showError);\n }\n\n /**\n * Forces the control to show an error state. If a message is passed in,\n * it will be set as the control's internal validity state message.\n * @param message { string | undefined } - The message for internals validity state\n */\n forceError(message?: string) {\n if (message) {\n this.#setValidityWithOptionalTarget({ customError: true }, message);\n }\n this.#forceError = true;\n this.#shouldShowError();\n }\n\n /**\n * This method can be overridden to determine if the control's form value\n * should be set on a call to `setValue`. An example of when a user might want\n * to skip this step is when implementing checkbox-like behavior, first checking\n * to see if `this.checked` is set to a truthy value. By default this returns\n * `true`.\n * @ignore\n */\n shouldFormValueUpdate(): boolean {\n return true;\n }\n\n /**\n * Save a reference to the validation complete resolver\n * @ignore\n */\n #validationCompleteResolver?: (value: void | PromiseLike<void>) => void;\n\n /**\n * When true validation will be pending\n * @ignore\n */\n #isValidationPending = false;\n\n /**\n * @ignore\n */\n #validationComplete = Promise.resolve();\n\n /**\n * A promise that will resolve when all pending validations are complete\n * @ignore\n */\n get validationComplete(): Promise<void> {\n return new Promise((resolve) => resolve(this.#validationComplete));\n }\n\n /** DECLARED INSTANCE METHODS AND PROPERTIES*/\n\n /**\n * Resets a form control to its initial state\n * @ignore\n */\n declare resetFormControl: () => void;\n\n /**\n * This method is used to override the controls' validity message\n * for a given Validator key. This has the highest level of priority when\n * setting a validationMessage, so use this method wisely.\n *\n * The returned value will be used as the validationMessage for the given key.\n * @param validationKey {string} - The key that has returned invalid\n * @ignore\n */\n declare validityCallback: (validationKey: string) => string | void;\n\n /**\n * Called when the control's validationMessage should be changed\n * @param message { string } - The new validation message\n * @ignore\n */\n declare validationMessageCallback: (message: string) => void;\n\n /**\n * A callback for when the controls' form value changes. The value\n * passed to this function should not be confused with the control's\n * value property, this is the value that will appear on the form.\n *\n * In cases where `checked` did not exist on the control's prototype\n * upon initialization, this value and the value property will be identical;\n * in cases where `checked` is present upon initialization, this will be\n * effectively `this.checked && this.value`.\n * @ignore\n */\n declare valueChangedCallback: (value: FormValue) => void;\n\n /**\n * The element that will receive focus when the control's validity\n * state is reported either by a form submission or via API\n *\n * We use declare since this is optional and we don't particularly\n * care how the consuming component implements this (as a field, member\n * or getter/setter)\n * @ignore\n */\n declare validationTarget: HTMLElement | null;\n\n /** PRIVATE LIFECYCLE METHODS */\n\n /**\n * Check to see if an error should be shown. This method will also\n * update the internals state object with the --show-error state\n * if necessary.\n * @private\n * @ignore\n */\n #shouldShowError(): boolean {\n if (this.hasAttribute('disabled')) {\n return false;\n }\n\n const showError =\n this.#forceError ||\n (this.#touched && !this.validity.valid && !this.#focused);\n\n if (showError && this.internals.states) {\n this.internals.states.add('--show-error');\n this.internals.states.add('--invalid');\n } else if (this.internals.states) {\n this.internals.states.delete('--show-error');\n this.internals.states.delete('--invalid');\n }\n\n return showError;\n }\n\n #runValidators(value: FormValue): void {\n const proto = this.constructor as typeof FormControl;\n const validity: CustomValidityState = {};\n const validators = proto.validators;\n const asyncValidators: Promise<boolean | void>[] = [];\n const hasAsyncValidators = validators.some(\n (validator) => validator.isValid instanceof Promise\n );\n\n if (!this.#isValidationPending) {\n this.#validationComplete = new Promise((resolve) => {\n this.#validationCompleteResolver = resolve;\n });\n this.#isValidationPending = true;\n }\n\n /**\n * If an abort controller exists from a previous validation step\n * notify still-running async validators that we are requesting they\n * discontinue any work.\n */\n if (this.#abortController) {\n this.#abortController.abort();\n }\n\n /**\n * Create a new abort controller and replace the instance reference\n * so we can clean it up for next time\n */\n const abortController = new AbortController();\n this.#abortController = abortController;\n let validationMessage: string | undefined = undefined;\n\n /** Track to see if any validity key has changed */\n let hasChange = false;\n\n if (!validators.length) {\n return;\n }\n\n validators.forEach((validator) => {\n const key = validator.key || 'customError';\n const isValid = validator.isValid(this, value, abortController.signal);\n const isAsyncValidator = isValid instanceof Promise;\n\n if (isAsyncValidator) {\n asyncValidators.push(isValid);\n\n isValid.then((isValidatorValid) => {\n if (isValidatorValid === undefined || isValidatorValid === null) {\n return;\n }\n /** Invert the validity state to correspond to the ValidityState API */\n validity[key] = !isValidatorValid;\n\n validationMessage = this.#getValidatorMessageForValue(\n validator,\n value\n );\n this.#setValidityWithOptionalTarget(validity, validationMessage);\n });\n } else {\n /** Invert the validity state to correspond to the ValidityState API */\n validity[key] = !isValid;\n\n if (this.validity[key] !== !isValid) {\n hasChange = true;\n }\n\n // only update the validationMessage for the first invalid scenario\n // so that earlier invalid validators dont get their messages overwritten by later ones\n // in the validators array\n if (!isValid && !validationMessage) {\n validationMessage = this.#getValidatorMessageForValue(\n validator,\n value\n );\n }\n }\n });\n\n /** Once all the async validators have settled, resolve validationComplete */\n Promise.allSettled(asyncValidators).then(() => {\n /** Don't resolve validations if the signal is aborted */\n if (!abortController?.signal.aborted) {\n this.#isValidationPending = false;\n this.#validationCompleteResolver?.();\n }\n });\n\n /**\n * If async validators are present:\n * Only run updates when a sync validator has a change. This is to prevent\n * situations where running sync validators can override async validators\n * that are still in progress\n *\n * If async validators are not present, always update validity\n */\n if (hasChange || !hasAsyncValidators) {\n this.#setValidityWithOptionalTarget(validity, validationMessage);\n }\n }\n\n /**\n * If the validationTarget is not set, the user can decide how they would\n * prefer to handle focus when the field is validated.\n * @ignore\n */\n #setValidityWithOptionalTarget(\n validity: Partial<ValidityState>,\n validationMessage: string | undefined\n ): void {\n if (this.validationTarget) {\n this.internals.setValidity(\n validity,\n validationMessage,\n this.validationTarget\n );\n this.#awaitingValidationTarget = false;\n } else {\n this.internals.setValidity(validity, validationMessage);\n\n if (this.internals.validity.valid) {\n return;\n }\n\n /**\n * Sets mark the component as awaiting a validation target\n * if the element dispatches an invalid event, the #onInvalid listener\n * will check to see if the validation target has been set since this call\n * has run. This useful in cases like Lit's use of the query\n * decorator for setting the validationTarget or any scenario\n * where the validationTarget isn't available upon construction\n */\n this.#awaitingValidationTarget = true;\n }\n }\n\n /**\n * Process the validator message attribute\n * @ignore\n */\n #getValidatorMessageForValue(\n validator: Validator,\n value: FormValue\n ): string {\n /** If the validity callback exists and returns, use that as the result */\n\n if (this.validityCallback) {\n const message = this.validityCallback(validator.key || 'customError');\n\n if (message) {\n return message;\n }\n }\n\n if (validator.message instanceof Function) {\n return (validator.message as validationMessageCallback)(this, value);\n } else {\n return validator.message as string;\n }\n }\n\n /**\n * Reset control state when the form is reset\n */\n formResetCallback() {\n this.#touched = false;\n this.#forceError = false;\n this.#shouldShowError();\n this.resetFormControl?.();\n const showError = this.#shouldShowError();\n this.validationMessageCallback?.(showError ? this.validationMessage : '');\n this.#dispatchInvalidEvent(showError);\n }\n\n #dispatchInvalidEvent(showError: boolean) {\n const event = showError ? 'mid-invalid-show' : 'mid-invalid-hide';\n this.dispatchEvent(\n new CustomEvent(event, {\n bubbles: true,\n composed: true,\n detail: {\n validity: this.validity,\n },\n })\n );\n }\n }\n\n return FormControl as unknown as Constructor<FormControlInterface> & TBase;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"form-control.mixin.js","sources":["../../src/mixins/form-control.mixin.ts"],"sourcesContent":["import { LitElement } from 'lit';\nimport type { IControlHost } from '../types/control-host';\nimport type { FormControlInterface } from '../types/form-control';\nimport type { FormValue } from '../types/form-value';\nimport type { Constructor } from '../types/mixin-constructor';\nimport type {\n CustomValidityState,\n validationMessageCallback,\n Validator,\n} from '../types/validator.type';\n\n/**\n *\n * https://github.com/open-wc/form-participation/tree/main/packages/form-control\n */\nexport function FormControlMixin<\n TBase extends Constructor<LitElement & IControlHost> & {\n observedAttributes?: string[];\n },\n>(SuperClass: TBase) {\n class FormControl extends SuperClass {\n /**\n * Wires up control instances to be form associated\n * @ignore\n */\n static get formAssociated(): boolean {\n return true;\n }\n\n /**\n * A list of Validator objects that will be evaluated when a control's form\n * value is modified or optionally when a given attribute changes.\n *\n * When a Validator's callback returns false, the entire form control will\n * be set to an invalid state.\n * @ignore\n */\n declare static formControlValidators: Validator[];\n\n /**\n * If set to true the control described should be evaluated and validated\n * as part of a group. Like a radio, if any member of the group's validity\n * changes the the other members should update as well.\n * @ignore\n */\n declare static formControlValidationGroup: boolean;\n\n /**\n * @ignore\n */\n private static get validators(): Validator[] {\n return this.formControlValidators || [];\n }\n\n /**\n * Allows the FormControl instance to respond to Validator attributes.\n * For instance, if a given Validator has a `required` attribute, that\n * validator will be evaluated whenever the host's required attribute\n * is updated.\n * @ignore\n */\n static get observedAttributes(): string[] {\n const validatorAttributes = this.validators\n .map((validator) => validator.attribute)\n .flat();\n\n const observedAttributes = super.observedAttributes || [];\n\n /** Make sure there are no duplicates inside the attributes list */\n const attributeSet = new Set([\n ...observedAttributes,\n ...validatorAttributes,\n ]);\n return [...attributeSet] as string[];\n }\n\n /**\n * Return the validator associated with a given attribute. If no\n * Validator is associated with the attribute, it will return null.\n * @ignore\n */\n static getValidator(attribute: string): Validator | null {\n return (\n this.validators.find(\n (validator) => validator.attribute === attribute\n ) || null\n );\n }\n\n /**\n * Get all validators that are set to react to a given attribute\n * @param {string} attribute - The attribute that has changed\n * @returns {Validator[]}\n * @ignore\n */\n static getValidators(attribute: string): Validator[] | null {\n return this.validators.filter((validator) => {\n if (\n validator.attribute === attribute ||\n validator.attribute?.includes(attribute)\n ) {\n return true;\n }\n });\n }\n\n /**\n * The ElementInternals instance for the control.\n * @ignore\n */\n internals = this.attachInternals();\n\n /**\n * Keep track of if the control has focus\n * @private\n * @ignore\n */\n #focused = false;\n\n /**\n * Exists to control when an error should be displayed\n * @private\n * @ignore\n */\n #forceError = false;\n\n /**\n * Toggles to true whenever the element has been altered. This property\n * will reset whenever the control's formResetCallback is called.\n * @private\n * @ignore\n */\n #touched = false;\n\n /**\n * An internal abort controller for cancelling pending async validation\n * @ignore\n */\n #abortController?: AbortController;\n\n /**\n * Used for tracking if a validation target has been set to manage focus\n * when the control's validity is reported\n * @ignore\n */\n #awaitingValidationTarget = true;\n\n /**\n * Acts as a cache for the current value so the value can be re-evaluated\n * whenever an attribute changes or on some other event.\n * @ignore\n */\n #value: FormValue = '';\n\n /**\n * Set this[focused]\n * to true when the element is focused\n * @private\n * @ignore\n */\n #onFocus = (): void => {\n this.#focused = true;\n this.#shouldShowError();\n };\n\n /**\n * Reset this[focused] on blur\n * @private\n * @ignore\n */\n #onBlur = (): void => {\n this.#focused = false;\n\n this.#runValidators(this.shouldFormValueUpdate() ? this.#value : '');\n\n /**\n * Set forceError to ensure error messages persist until\n * the value is changed.\n */\n if (!this.validity.valid && this.#touched) {\n this.#forceError = true;\n }\n const showError = this.#shouldShowError();\n\n if (this.validationMessageCallback) {\n this.validationMessageCallback(showError ? this.validationMessage : '');\n }\n this.#dispatchInvalidEvent(showError);\n };\n\n /**\n * For the show error state on invalid\n * @private\n * @ignore\n */\n #onInvalid = (event?: Event): void => {\n event?.preventDefault();\n event?.stopImmediatePropagation();\n\n if (this.#awaitingValidationTarget && this.validationTarget) {\n this.internals.setValidity(\n this.validity,\n this.validationMessage,\n this.validationTarget\n );\n this.#awaitingValidationTarget = false;\n }\n this.#touched = true;\n this.#forceError = true;\n const showError = this.#shouldShowError();\n this?.validationMessageCallback?.(\n showError ? this.validationMessage : ''\n );\n this.#dispatchInvalidEvent(showError);\n };\n\n /**\n * Return a reference to the control's form\n * @ignore\n */\n get form(): HTMLFormElement {\n return this.internals.form as HTMLFormElement;\n }\n\n /**\n * Will return true if it is recommended that the control shows an internal\n * error. If using this property, it is wise to listen for 'invalid' events\n * on the element host and call preventDefault on the event. Doing this will\n * prevent browsers from showing a validation popup.\n * @ignore\n */\n get showError(): boolean {\n return this.#shouldShowError();\n }\n\n /**\n * Forward the internals checkValidity method\n * will return the valid state of the control.\n * @ignore\n */\n checkValidity(): boolean {\n return this.internals.checkValidity();\n }\n\n /**\n * The element's validity state\n * @ignore\n */\n get validity(): ValidityState {\n return this.internals.validity;\n }\n\n /**\n * The validation message shown by a given Validator object. If the control\n * is in a valid state this should be falsy.\n * @ignore\n */\n get validationMessage(): string {\n return this.internals.validationMessage;\n }\n\n constructor(...args: any[]) {\n super(...args);\n this.addEventListener?.('focus', this.#onFocus);\n this.addEventListener?.('blur', this.#onBlur);\n this.addEventListener?.('invalid', this.#onInvalid);\n this.setValue(null);\n }\n\n attributeChangedCallback(\n name: string,\n oldValue: string,\n newValue: string\n ): void {\n super.attributeChangedCallback?.(name, oldValue, newValue);\n\n /**\n * Check to see if a Validator is associated with the changed attribute.\n * If one exists, call control's validate function which will perform\n * control validation.\n * @ignore\n */\n const proto = this.constructor as typeof FormControl;\n const validators = proto.getValidators(name);\n\n if (validators?.length && this.validationTarget) {\n this.setValue(this.#value);\n }\n }\n\n /** PUBLIC LIFECYCLE METHODS */\n\n /**\n * Sets the control's form value if the call to `shouldFormValueUpdate`\n * returns `true`. Set this[touch] if connected and value changed.\n * @param value {FormValue} - The value to pass to the form\n * @ignore\n */\n setValue(value: FormValue): void {\n if (this.isConnected && this.#value !== value) {\n this.#touched = true;\n }\n this.#forceError = false;\n this.validationMessageCallback?.('');\n this.#value = value;\n const valueShouldUpdate = this.shouldFormValueUpdate();\n const valueToUpdate = valueShouldUpdate ? value : null;\n this.internals.setFormValue(valueToUpdate as string);\n this.#runValidators(valueToUpdate);\n if (this.valueChangedCallback) {\n this.valueChangedCallback(valueToUpdate);\n }\n const showError = this.#shouldShowError();\n this.#dispatchInvalidEvent(showError);\n }\n\n /**\n * Updates the form value and re-runs validators without touching the\n * error-display state: `#forceError` is left alone, no\n * `validationMessageCallback('')`, no `mid-invalid-show`/`-hide` is\n * dispatched, and the control is not marked touched (a programmatic set\n * is not user interaction). For programmatic value changes where the host\n * page owns the error presentation and a `setValue` would wipe it\n * mid-flow.\n * @param value {FormValue} - The value to pass to the form\n */\n syncFormValue(value: FormValue): void {\n this.#value = value;\n const valueToUpdate = this.shouldFormValueUpdate() ? value : null;\n this.internals.setFormValue(valueToUpdate as string);\n this.#runValidators(valueToUpdate);\n if (this.valueChangedCallback) {\n this.valueChangedCallback(valueToUpdate);\n }\n }\n\n /**\n * Forces the control to show an error state. If a message is passed in,\n * it will be set as the control's internal validity state message.\n * @param message { string | undefined } - The message for internals validity state\n */\n forceError(message?: string) {\n if (message) {\n this.#setValidityWithOptionalTarget({ customError: true }, message);\n }\n this.#forceError = true;\n this.#shouldShowError();\n }\n\n /**\n * This method can be overridden to determine if the control's form value\n * should be set on a call to `setValue`. An example of when a user might want\n * to skip this step is when implementing checkbox-like behavior, first checking\n * to see if `this.checked` is set to a truthy value. By default this returns\n * `true`.\n * @ignore\n */\n shouldFormValueUpdate(): boolean {\n return true;\n }\n\n /**\n * Save a reference to the validation complete resolver\n * @ignore\n */\n #validationCompleteResolver?: (value: void | PromiseLike<void>) => void;\n\n /**\n * When true validation will be pending\n * @ignore\n */\n #isValidationPending = false;\n\n /**\n * @ignore\n */\n #validationComplete = Promise.resolve();\n\n /**\n * A promise that will resolve when all pending validations are complete\n * @ignore\n */\n get validationComplete(): Promise<void> {\n return new Promise((resolve) => resolve(this.#validationComplete));\n }\n\n /** DECLARED INSTANCE METHODS AND PROPERTIES*/\n\n /**\n * Resets a form control to its initial state\n * @ignore\n */\n declare resetFormControl: () => void;\n\n /**\n * This method is used to override the controls' validity message\n * for a given Validator key. This has the highest level of priority when\n * setting a validationMessage, so use this method wisely.\n *\n * The returned value will be used as the validationMessage for the given key.\n * @param validationKey {string} - The key that has returned invalid\n * @ignore\n */\n declare validityCallback: (validationKey: string) => string | void;\n\n /**\n * Called when the control's validationMessage should be changed\n * @param message { string } - The new validation message\n * @ignore\n */\n declare validationMessageCallback: (message: string) => void;\n\n /**\n * A callback for when the controls' form value changes. The value\n * passed to this function should not be confused with the control's\n * value property, this is the value that will appear on the form.\n *\n * In cases where `checked` did not exist on the control's prototype\n * upon initialization, this value and the value property will be identical;\n * in cases where `checked` is present upon initialization, this will be\n * effectively `this.checked && this.value`.\n * @ignore\n */\n declare valueChangedCallback: (value: FormValue) => void;\n\n /**\n * The element that will receive focus when the control's validity\n * state is reported either by a form submission or via API\n *\n * We use declare since this is optional and we don't particularly\n * care how the consuming component implements this (as a field, member\n * or getter/setter)\n * @ignore\n */\n declare validationTarget: HTMLElement | null;\n\n /** PRIVATE LIFECYCLE METHODS */\n\n /**\n * Check to see if an error should be shown. This method will also\n * update the internals state object with the --show-error state\n * if necessary.\n * @private\n * @ignore\n */\n #shouldShowError(): boolean {\n if (this.hasAttribute('disabled')) {\n return false;\n }\n\n const showError =\n this.#forceError ||\n (this.#touched && !this.validity.valid && !this.#focused);\n\n if (showError && this.internals.states) {\n this.internals.states.add('--show-error');\n this.internals.states.add('--invalid');\n } else if (this.internals.states) {\n this.internals.states.delete('--show-error');\n this.internals.states.delete('--invalid');\n }\n\n return showError;\n }\n\n #runValidators(value: FormValue): void {\n const proto = this.constructor as typeof FormControl;\n const validity: CustomValidityState = {};\n const validators = proto.validators;\n const asyncValidators: Promise<boolean | void>[] = [];\n const hasAsyncValidators = validators.some(\n (validator) => validator.isValid instanceof Promise\n );\n\n if (!this.#isValidationPending) {\n this.#validationComplete = new Promise((resolve) => {\n this.#validationCompleteResolver = resolve;\n });\n this.#isValidationPending = true;\n }\n\n /**\n * If an abort controller exists from a previous validation step\n * notify still-running async validators that we are requesting they\n * discontinue any work.\n */\n if (this.#abortController) {\n this.#abortController.abort();\n }\n\n /**\n * Create a new abort controller and replace the instance reference\n * so we can clean it up for next time\n */\n const abortController = new AbortController();\n this.#abortController = abortController;\n let validationMessage: string | undefined = undefined;\n\n /** Track to see if any validity key has changed */\n let hasChange = false;\n\n if (!validators.length) {\n return;\n }\n\n validators.forEach((validator) => {\n const key = validator.key || 'customError';\n const isValid = validator.isValid(this, value, abortController.signal);\n const isAsyncValidator = isValid instanceof Promise;\n\n if (isAsyncValidator) {\n asyncValidators.push(isValid);\n\n isValid.then((isValidatorValid) => {\n if (isValidatorValid === undefined || isValidatorValid === null) {\n return;\n }\n /** Invert the validity state to correspond to the ValidityState API */\n validity[key] = !isValidatorValid;\n\n validationMessage = this.#getValidatorMessageForValue(\n validator,\n value\n );\n this.#setValidityWithOptionalTarget(validity, validationMessage);\n });\n } else {\n /** Invert the validity state to correspond to the ValidityState API */\n validity[key] = !isValid;\n\n if (this.validity[key] !== !isValid) {\n hasChange = true;\n }\n\n // only update the validationMessage for the first invalid scenario\n // so that earlier invalid validators dont get their messages overwritten by later ones\n // in the validators array\n if (!isValid && !validationMessage) {\n validationMessage = this.#getValidatorMessageForValue(\n validator,\n value\n );\n }\n }\n });\n\n /** Once all the async validators have settled, resolve validationComplete */\n Promise.allSettled(asyncValidators).then(() => {\n /** Don't resolve validations if the signal is aborted */\n if (!abortController?.signal.aborted) {\n this.#isValidationPending = false;\n this.#validationCompleteResolver?.();\n }\n });\n\n /**\n * If async validators are present:\n * Only run updates when a sync validator has a change. This is to prevent\n * situations where running sync validators can override async validators\n * that are still in progress\n *\n * If async validators are not present, always update validity\n */\n if (hasChange || !hasAsyncValidators) {\n this.#setValidityWithOptionalTarget(validity, validationMessage);\n }\n }\n\n /**\n * If the validationTarget is not set, the user can decide how they would\n * prefer to handle focus when the field is validated.\n * @ignore\n */\n #setValidityWithOptionalTarget(\n validity: Partial<ValidityState>,\n validationMessage: string | undefined\n ): void {\n if (this.validationTarget) {\n this.internals.setValidity(\n validity,\n validationMessage,\n this.validationTarget\n );\n this.#awaitingValidationTarget = false;\n } else {\n this.internals.setValidity(validity, validationMessage);\n\n if (this.internals.validity.valid) {\n return;\n }\n\n /**\n * Sets mark the component as awaiting a validation target\n * if the element dispatches an invalid event, the #onInvalid listener\n * will check to see if the validation target has been set since this call\n * has run. This useful in cases like Lit's use of the query\n * decorator for setting the validationTarget or any scenario\n * where the validationTarget isn't available upon construction\n */\n this.#awaitingValidationTarget = true;\n }\n }\n\n /**\n * Process the validator message attribute\n * @ignore\n */\n #getValidatorMessageForValue(\n validator: Validator,\n value: FormValue\n ): string {\n /** If the validity callback exists and returns, use that as the result */\n\n if (this.validityCallback) {\n const message = this.validityCallback(validator.key || 'customError');\n\n if (message) {\n return message;\n }\n }\n\n if (validator.message instanceof Function) {\n return (validator.message as validationMessageCallback)(this, value);\n } else {\n return validator.message as string;\n }\n }\n\n /**\n * Reset control state when the form is reset\n */\n formResetCallback() {\n this.#touched = false;\n this.#forceError = false;\n this.#shouldShowError();\n this.resetFormControl?.();\n const showError = this.#shouldShowError();\n this.validationMessageCallback?.(showError ? this.validationMessage : '');\n this.#dispatchInvalidEvent(showError);\n }\n\n #dispatchInvalidEvent(showError: boolean) {\n const event = showError ? 'mid-invalid-show' : 'mid-invalid-hide';\n this.dispatchEvent(\n new CustomEvent(event, {\n bubbles: true,\n composed: true,\n detail: {\n validity: this.validity,\n },\n })\n );\n }\n }\n\n return FormControl as unknown as Constructor<FormControlInterface> & TBase;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@ export interface FormControlInterface {
|
|
|
17
17
|
validityCallback(validationKey: string): string | void;
|
|
18
18
|
validationMessageCallback(message: string): void;
|
|
19
19
|
setValue(value: FormValue): void;
|
|
20
|
+
syncFormValue(value: FormValue): void;
|
|
20
21
|
forceError(message?: string): void;
|
|
21
22
|
shouldFormValueUpdate?(): boolean;
|
|
22
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-control.d.ts","sourceRoot":"","sources":["../../src/types/form-control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,iBAAiB,IAAI,IAAI,CAAC;IAC1B,aAAa,IAAI,OAAO,CAAC;IACzB,iBAAiB,IAAI,IAAI,CAAC;IAC1B,gBAAgB,CAAC,IAAI,IAAI,CAAC;IAE1B,oBAAoB,CAAC,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACvD,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACjC,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,qBAAqB,CAAC,IAAI,OAAO,CAAC;CACnC"}
|
|
1
|
+
{"version":3,"file":"form-control.d.ts","sourceRoot":"","sources":["../../src/types/form-control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,iBAAiB,IAAI,IAAI,CAAC;IAC1B,aAAa,IAAI,OAAO,CAAC;IACzB,iBAAiB,IAAI,IAAI,CAAC;IAC1B,gBAAgB,CAAC,IAAI,IAAI,CAAC;IAE1B,oBAAoB,CAAC,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACvD,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACjC,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,qBAAqB,CAAC,IAAI,OAAO,CAAC;CACnC"}
|