@felleslosninger/minid-elements 0.0.110 → 0.0.111
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/checkbox.component.d.ts +0 -14
- package/dist/components/checkbox.component.d.ts.map +1 -1
- package/dist/components/checkbox.js +1 -21
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/code-input-old.component.d.ts +55 -0
- package/dist/components/code-input-old.component.d.ts.map +1 -0
- package/dist/components/code-input-old.js +313 -0
- package/dist/components/code-input-old.js.map +1 -0
- package/dist/components/code-input.component.d.ts +59 -33
- package/dist/components/code-input.component.d.ts.map +1 -1
- package/dist/components/code-input.js +244 -230
- package/dist/components/code-input.js.map +1 -1
- package/dist/components/dropdown.js +1 -1
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/menu.component.d.ts.map +1 -1
- package/dist/components/menu.js +1 -3
- package/dist/components/menu.js.map +1 -1
- package/dist/components/textfield.component.d.ts +0 -1
- package/dist/components/textfield.component.d.ts.map +1 -1
- package/dist/components/textfield.js +0 -3
- package/dist/components/textfield.js.map +1 -1
- package/dist/designsystemet-tailwind.css +43 -13
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mixins/validators.js +2 -2
- package/dist/mixins/validators.js.map +1 -1
- package/package.json +2 -1
- package/dist/components/code-input-2.component.d.ts +0 -15
- package/dist/components/code-input-2.component.d.ts.map +0 -1
- package/dist/components/code-input-2.js +0 -82
- package/dist/components/code-input-2.js.map +0 -1
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { css, LitElement, html } from "lit";
|
|
2
|
-
import { property, state, customElement } from "lit/decorators.js";
|
|
3
|
-
import { createRef, ref } from "lit/directives/ref.js";
|
|
2
|
+
import { queryAll, property, state, customElement } from "lit/decorators.js";
|
|
4
3
|
import { classMap } from "lit/directives/class-map.js";
|
|
5
4
|
import { live } from "lit/directives/live.js";
|
|
6
|
-
import {
|
|
5
|
+
import { watch } from "../internal/watch.js";
|
|
6
|
+
import { FormControlMixin } from "../mixins/form-control.mixin.js";
|
|
7
7
|
import { styled } from "../mixins/tailwind.mixin.js";
|
|
8
|
-
import {
|
|
8
|
+
import { HasSlotController } from "../internal/slot.js";
|
|
9
9
|
import "./icon/icon.js";
|
|
10
|
+
import { requiredValidator, maxLengthValidator, minLengthValidator, patternValidator } from "../mixins/validators.js";
|
|
11
|
+
import { webOtpApiInit } from "../utilities/web-otp-api.js";
|
|
10
12
|
var __defProp = Object.defineProperty;
|
|
11
13
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
|
+
var __typeError = (msg) => {
|
|
15
|
+
throw TypeError(msg);
|
|
16
|
+
};
|
|
12
17
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
13
18
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
14
19
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
@@ -17,293 +22,302 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
17
22
|
if (kind && result) __defProp(target, key, result);
|
|
18
23
|
return result;
|
|
19
24
|
};
|
|
25
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
26
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), member.get(obj));
|
|
27
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
28
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
29
|
+
var _skipValueVisualUpdate;
|
|
30
|
+
let nextUniqueId = 0;
|
|
20
31
|
const styles = [
|
|
21
32
|
css`
|
|
22
33
|
:host {
|
|
23
|
-
display:
|
|
24
|
-
flex-direction: column;
|
|
25
|
-
container: otc / inline-size;
|
|
26
|
-
text-align: left;
|
|
27
|
-
--otc-background: white;
|
|
28
|
-
--otc-error-background: white;
|
|
29
|
-
--otc-length: 5;
|
|
30
|
-
--otc-width: 11.45cqw;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
input {
|
|
34
|
-
all: unset;
|
|
35
|
-
background: var(--otc-background);
|
|
36
|
-
caret-color: transparent;
|
|
37
|
-
clip-path: inset(0% 1ch 0% 0%);
|
|
38
|
-
font-family: ui-monospace, monospace;
|
|
39
|
-
font-size: var(--otc-width);
|
|
40
|
-
inline-size: calc(var(--otc-length) * 3ch);
|
|
41
|
-
letter-spacing: 2ch;
|
|
42
|
-
padding-block: 0.25ch;
|
|
43
|
-
padding-inline-start: calc(0.5ch * 1.5);
|
|
44
|
-
flex-grow: 1;
|
|
45
|
-
|
|
46
|
-
&:focus-visible:focus {
|
|
47
|
-
outline-style: none;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
&:-webkit-autofill {
|
|
51
|
-
animation-name: onAutoFillStart;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
@keyframes onAutoFillStart {
|
|
56
|
-
from {
|
|
57
|
-
}
|
|
58
|
-
to {
|
|
59
|
-
}
|
|
34
|
+
display: block;
|
|
60
35
|
}
|
|
61
36
|
|
|
62
|
-
|
|
63
|
-
|
|
37
|
+
/* Hide increment/decrement buttons on inputs */
|
|
38
|
+
input[type='number']::-webkit-outer-spin-button,
|
|
39
|
+
input[type='number']::-webkit-inner-spin-button,
|
|
40
|
+
input[type='number'] {
|
|
41
|
+
-webkit-appearance: none;
|
|
42
|
+
margin: 0;
|
|
43
|
+
-moz-appearance: textfield !important;
|
|
64
44
|
}
|
|
65
45
|
`
|
|
66
46
|
];
|
|
67
|
-
let
|
|
68
|
-
let MinidCodeInput = class extends ConstraintsValidationMixin(
|
|
47
|
+
let MinidCodeInput = class extends FormControlMixin(
|
|
69
48
|
styled(LitElement, styles)
|
|
70
49
|
) {
|
|
71
50
|
constructor() {
|
|
72
|
-
super();
|
|
73
|
-
this.
|
|
74
|
-
this
|
|
75
|
-
this.
|
|
76
|
-
this.inputRef = createRef();
|
|
51
|
+
super(...arguments);
|
|
52
|
+
this.hasSlotControler = new HasSlotController(this, "label");
|
|
53
|
+
__privateAdd(this, _skipValueVisualUpdate, false);
|
|
54
|
+
this.labelId = `mid-code-input-label-${nextUniqueId++}`;
|
|
77
55
|
this.value = "";
|
|
78
56
|
this.label = "";
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
57
|
+
this.type = "text";
|
|
58
|
+
this.inputmode = "text";
|
|
59
|
+
this.size = "sm";
|
|
60
|
+
this.length = 5;
|
|
81
61
|
this.disabled = false;
|
|
82
|
-
this.
|
|
62
|
+
this.autofocus = false;
|
|
83
63
|
this.invalidmessage = "";
|
|
84
|
-
this.
|
|
85
|
-
this.
|
|
86
|
-
this.
|
|
87
|
-
this.localErrorNode = null;
|
|
88
|
-
this.handleFocusIn = () => {
|
|
89
|
-
const currentChar = this.value.length + 1;
|
|
90
|
-
this.inputRef.value?.style.setProperty(
|
|
91
|
-
`--char-${currentChar}-color`,
|
|
92
|
-
this.caretHighlightColor
|
|
93
|
-
);
|
|
94
|
-
};
|
|
95
|
-
this.handleChange = (e) => {
|
|
96
|
-
this.value = e.target.value;
|
|
97
|
-
this.dispatchEvent(
|
|
98
|
-
new Event("input", {
|
|
99
|
-
bubbles: true,
|
|
100
|
-
cancelable: true,
|
|
101
|
-
composed: true
|
|
102
|
-
})
|
|
103
|
-
);
|
|
104
|
-
};
|
|
105
|
-
this.addEventListener("invalid", (e) => {
|
|
106
|
-
this.renderError = true;
|
|
107
|
-
if (this.localErrorNode) {
|
|
108
|
-
e.preventDefault();
|
|
109
|
-
this.localErrorNode.textContent = this.validationMessage || "Error";
|
|
110
|
-
}
|
|
111
|
-
});
|
|
64
|
+
this.hidelabel = false;
|
|
65
|
+
this.required = false;
|
|
66
|
+
this.internalValues = Array(this.length).fill("");
|
|
112
67
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
68
|
+
static get formControlValidators() {
|
|
69
|
+
return [
|
|
70
|
+
requiredValidator,
|
|
71
|
+
maxLengthValidator,
|
|
72
|
+
minLengthValidator,
|
|
73
|
+
patternValidator
|
|
74
|
+
];
|
|
116
75
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.inputRef.value?.addEventListener(
|
|
120
|
-
"animationstart",
|
|
121
|
-
this.autoFillEventHandler.bind(this)
|
|
122
|
-
);
|
|
123
|
-
this.calcInputStyle();
|
|
76
|
+
get validationTarget() {
|
|
77
|
+
return this.inputElements?.length ? this.inputElements[0] : null;
|
|
124
78
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
this.inputRef.value?.removeEventListener(
|
|
128
|
-
"animationstart",
|
|
129
|
-
this.autoFillEventHandler.bind(this)
|
|
130
|
-
);
|
|
79
|
+
firstUpdated(_changedProperties) {
|
|
80
|
+
webOtpApiInit(this.renderRoot);
|
|
131
81
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
for (let i = 0; i < this.length; i++) {
|
|
137
|
-
gradientStyle += `var(--char-${i + 1}-color) ${i ? i * 3 + "ch" : "0"} ${i * 3 + 2.5}ch, transparent ${i * 3 + 2.5}ch ${i * 3 + 3}ch${i + 1 < this.length ? ", " : ""}`;
|
|
138
|
-
}
|
|
139
|
-
gradientStyle += `) no-repeat 0 0 / ${this.length * 3}ch 100%`;
|
|
140
|
-
inputStyle?.setProperty("--otc-background", gradientStyle);
|
|
141
|
-
const gradientErrorStyle = `linear-gradient(90deg, var(--color-danger-surface-active) calc(${this.length}ch / 2), transparent 0) 0 0 / 3ch 100%`;
|
|
142
|
-
inputStyle?.setProperty("--otc-error-background", gradientErrorStyle);
|
|
143
|
-
inputStyle?.setProperty("--otc-width", this.fontsize);
|
|
82
|
+
handleFocus(index) {
|
|
83
|
+
return () => {
|
|
84
|
+
this.inputElements[index].setAttribute("placeholder", "");
|
|
85
|
+
};
|
|
144
86
|
}
|
|
145
|
-
|
|
146
|
-
|
|
87
|
+
handleBlur(index) {
|
|
88
|
+
return () => {
|
|
89
|
+
this.inputElements[index].setAttribute("placeholder", "○");
|
|
90
|
+
};
|
|
147
91
|
}
|
|
148
|
-
|
|
149
|
-
return
|
|
92
|
+
handleKeydown(index) {
|
|
93
|
+
return (event) => {
|
|
94
|
+
this.internalValues[index] = event.target.value;
|
|
95
|
+
this.value = this.internalValues.join("");
|
|
96
|
+
const input = event.target;
|
|
97
|
+
const hasModifier = event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
|
98
|
+
if (event.key === "Backspace") {
|
|
99
|
+
if (input.value === "" && index > 0) {
|
|
100
|
+
this.inputElements[index - 1].focus();
|
|
101
|
+
this.internalValues[index - 1] = "";
|
|
102
|
+
this.updateValueAndEmit(true);
|
|
103
|
+
} else if (input.value !== "") {
|
|
104
|
+
input.value = "";
|
|
105
|
+
this.internalValues[index] = "";
|
|
106
|
+
this.updateValueAndEmit(true);
|
|
107
|
+
}
|
|
108
|
+
} else if (event.key === "ArrowLeft") {
|
|
109
|
+
if (index > 0) {
|
|
110
|
+
this.inputElements[index - 1].focus();
|
|
111
|
+
}
|
|
112
|
+
} else if (event.key === "ArrowRight") {
|
|
113
|
+
if (index < this.length - 1) {
|
|
114
|
+
this.inputElements[index + 1].focus();
|
|
115
|
+
}
|
|
116
|
+
} else if (event.key === "Delete") {
|
|
117
|
+
input.value = "";
|
|
118
|
+
this.internalValues[index] = "";
|
|
119
|
+
this.updateValueAndEmit(true);
|
|
120
|
+
} else if (event.key === "Enter" && !hasModifier) {
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
if (!event.defaultPrevented && !event.isComposing) {
|
|
123
|
+
this.form?.requestSubmit();
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
};
|
|
150
128
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
129
|
+
handleInput(index) {
|
|
130
|
+
return (event) => {
|
|
131
|
+
const input = event.target;
|
|
132
|
+
let inputValue = input.value;
|
|
133
|
+
if (inputValue.length > 1) {
|
|
134
|
+
inputValue = inputValue.charAt(0);
|
|
135
|
+
input.value = inputValue;
|
|
136
|
+
}
|
|
137
|
+
this.internalValues[index] = inputValue;
|
|
138
|
+
this.updateValueAndEmit(true);
|
|
139
|
+
if (inputValue !== "" && index < this.length - 1) {
|
|
140
|
+
this.inputElements[index + 1].focus();
|
|
141
|
+
}
|
|
142
|
+
this.dispatchEvent(
|
|
143
|
+
new Event("mid-input", { bubbles: true, composed: true })
|
|
156
144
|
);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
handleClick() {
|
|
160
|
-
this.value = this.value.substring(0, this.selectionEnd || 0);
|
|
161
|
-
this.renderError = false;
|
|
162
|
-
this.setCustomValidity("");
|
|
163
|
-
if (this.localErrorNode) {
|
|
164
|
-
this.localErrorNode.textContent = "";
|
|
165
|
-
}
|
|
166
|
-
this.setFormValue(this.value);
|
|
167
|
-
this.setValidity({});
|
|
145
|
+
};
|
|
168
146
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
147
|
+
handlePaste(index) {
|
|
148
|
+
return (event) => {
|
|
149
|
+
event.preventDefault();
|
|
150
|
+
const pasteData = event.clipboardData?.getData("text").trim();
|
|
151
|
+
if (pasteData) {
|
|
152
|
+
const pasteChars = pasteData.split("");
|
|
153
|
+
for (let i = 0; i < this.length; i++) {
|
|
154
|
+
if (index + i < this.length && pasteChars[i]) {
|
|
155
|
+
this.internalValues[index + i] = pasteChars[i];
|
|
156
|
+
}
|
|
175
157
|
}
|
|
176
|
-
|
|
177
|
-
|
|
158
|
+
this.updateValueAndEmit();
|
|
159
|
+
const lastFilledIndex = Math.min(
|
|
160
|
+
index + pasteChars.length - 1,
|
|
161
|
+
this.length - 1
|
|
162
|
+
);
|
|
163
|
+
this.inputElements[lastFilledIndex]?.focus();
|
|
164
|
+
}
|
|
165
|
+
};
|
|
178
166
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
this.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
167
|
+
updateValueAndEmit(skipValueUpdate = false) {
|
|
168
|
+
__privateSet(this, _skipValueVisualUpdate, skipValueUpdate);
|
|
169
|
+
this.value = this.internalValues.join("");
|
|
170
|
+
this.dispatchEvent(
|
|
171
|
+
new Event("mid-change", {
|
|
172
|
+
bubbles: true,
|
|
173
|
+
composed: true
|
|
174
|
+
})
|
|
175
|
+
);
|
|
176
|
+
if (this.value.length === this.length && this.internalValues.every((digit) => digit !== "")) {
|
|
177
|
+
this.dispatchEvent(
|
|
178
|
+
new Event("mid-complete", {
|
|
179
|
+
bubbles: true,
|
|
180
|
+
composed: true
|
|
181
|
+
})
|
|
182
|
+
);
|
|
187
183
|
}
|
|
188
184
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const childNodesArray = Array.from(node.childNodes);
|
|
195
|
-
const foundNode = this.findErrorMessageNode(childNodesArray);
|
|
196
|
-
if (foundNode) {
|
|
197
|
-
return foundNode;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return null;
|
|
185
|
+
valueVisualUpdate(value) {
|
|
186
|
+
const chars = value.split("");
|
|
187
|
+
this.internalValues.forEach((_, index) => {
|
|
188
|
+
this.internalValues[index] = chars[index];
|
|
189
|
+
});
|
|
201
190
|
}
|
|
202
|
-
|
|
203
|
-
this.
|
|
204
|
-
|
|
191
|
+
handleLengthChange() {
|
|
192
|
+
this.internalValues = Array(this.length).fill("");
|
|
193
|
+
this.valueVisualUpdate(this.value);
|
|
205
194
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
this
|
|
210
|
-
|
|
211
|
-
if (_changedProperties.has("_forcedErrorMessage")) {
|
|
212
|
-
this.setCustomValidity(this.invalidmessage);
|
|
195
|
+
handleValueChange() {
|
|
196
|
+
this.setValue(this.value);
|
|
197
|
+
if (__privateGet(this, _skipValueVisualUpdate)) {
|
|
198
|
+
__privateSet(this, _skipValueVisualUpdate, false);
|
|
199
|
+
return;
|
|
213
200
|
}
|
|
214
|
-
this.
|
|
215
|
-
this.setValidity(
|
|
216
|
-
this.inputRef.value.validity,
|
|
217
|
-
this.inputRef.value.validationMessage,
|
|
218
|
-
this.inputRef.value
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
focus(options) {
|
|
222
|
-
const notMobile = !window.matchMedia("only screen and (max-width: 768px)").matches;
|
|
223
|
-
notMobile && this.inputRef.value?.focus(options);
|
|
224
|
-
}
|
|
225
|
-
setCustomValidity(error) {
|
|
226
|
-
this.inputRef.value?.setCustomValidity(error);
|
|
201
|
+
this.valueVisualUpdate(this.value);
|
|
227
202
|
}
|
|
228
203
|
render() {
|
|
204
|
+
const hasLabelSlot = this.hasSlotControler.test("label");
|
|
205
|
+
const hasLabel = !!this.label || !!hasLabelSlot;
|
|
229
206
|
return html`
|
|
230
207
|
<label
|
|
208
|
+
id="${this.labelId}"
|
|
231
209
|
class="${classMap({
|
|
232
|
-
"sr-only": this.hidelabel,
|
|
233
|
-
"
|
|
234
|
-
})} font-medium"
|
|
235
|
-
|
|
236
|
-
|
|
210
|
+
"sr-only": this.hidelabel || !hasLabel,
|
|
211
|
+
"opacity-disabled": this.disabled
|
|
212
|
+
})} mb-2 block items-center gap-1 font-medium"
|
|
213
|
+
>
|
|
214
|
+
<slot name="label"> ${this.label} </slot>
|
|
237
215
|
</label>
|
|
238
|
-
<
|
|
239
|
-
|
|
240
|
-
id=${this.inputId}
|
|
241
|
-
.value="${live(this.value)}"
|
|
216
|
+
<div
|
|
217
|
+
part="input-container"
|
|
242
218
|
class="${classMap({
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
219
|
+
"text-heading-sm": this.size === "sm",
|
|
220
|
+
"text-heading-md": this.size === "md",
|
|
221
|
+
"text-heading-lg": this.size === "lg"
|
|
222
|
+
})} inline-flex gap-2"
|
|
223
|
+
>
|
|
224
|
+
${this.internalValues.map((value, index) => {
|
|
225
|
+
return html`
|
|
226
|
+
<input
|
|
227
|
+
.value="${live(value || "")}"
|
|
228
|
+
id="mid-code-input-${index}"
|
|
229
|
+
class="${classMap({
|
|
230
|
+
border: !this.invalidmessage,
|
|
231
|
+
"border-2": this.invalidmessage,
|
|
232
|
+
"border-neutral": !this.invalidmessage,
|
|
233
|
+
"border-danger": this.invalidmessage,
|
|
234
|
+
"bg-neutral": !this.invalidmessage,
|
|
235
|
+
"bg-danger-tinted": this.invalidmessage,
|
|
236
|
+
"placeholder:text-neutral-surface-active": !this.invalidmessage,
|
|
237
|
+
"placeholder:text-danger-surface-active": this.invalidmessage
|
|
238
|
+
})} focus:focus-ring-sm disabled:opacity-disabled size-9 rounded-md text-center font-mono disabled:cursor-not-allowed"
|
|
239
|
+
type="${this.type}"
|
|
240
|
+
placeholder="○"
|
|
241
|
+
aria-labelledby="${this.labelId}"
|
|
242
|
+
size="1"
|
|
243
|
+
?autofocus="${!index && this.autofocus}"
|
|
244
|
+
?disabled="${this.disabled}"
|
|
245
|
+
inputmode="${this.inputmode}"
|
|
246
|
+
@keydown="${this.handleKeydown(index)}"
|
|
247
|
+
@input="${this.handleInput(index)}"
|
|
248
|
+
@paste="${this.handlePaste(index)}"
|
|
249
|
+
@focus="${this.handleFocus(index)}"
|
|
250
|
+
@blur="${this.handleBlur(index)}"
|
|
251
|
+
/>
|
|
252
|
+
`;
|
|
253
|
+
})}
|
|
254
|
+
</div>
|
|
255
|
+
<div
|
|
256
|
+
class="text-danger-subtle mt-2 flex gap-1"
|
|
257
|
+
aria-live="polite"
|
|
258
|
+
?hidden=${!this.invalidmessage}
|
|
259
|
+
>
|
|
260
|
+
<mid-icon
|
|
261
|
+
name="xmark-octagon-fill"
|
|
262
|
+
class="mt-1 min-h-5 min-w-5"
|
|
263
|
+
></mid-icon>
|
|
264
|
+
${this.invalidmessage}
|
|
265
|
+
</div>
|
|
271
266
|
`;
|
|
272
267
|
}
|
|
273
268
|
};
|
|
269
|
+
_skipValueVisualUpdate = /* @__PURE__ */ new WeakMap();
|
|
270
|
+
__decorateClass([
|
|
271
|
+
queryAll("input")
|
|
272
|
+
], MinidCodeInput.prototype, "inputElements", 2);
|
|
274
273
|
__decorateClass([
|
|
275
|
-
property({
|
|
274
|
+
property({ reflect: true })
|
|
276
275
|
], MinidCodeInput.prototype, "value", 2);
|
|
277
276
|
__decorateClass([
|
|
278
277
|
property()
|
|
279
278
|
], MinidCodeInput.prototype, "label", 2);
|
|
280
279
|
__decorateClass([
|
|
281
|
-
property(
|
|
282
|
-
], MinidCodeInput.prototype, "
|
|
280
|
+
property()
|
|
281
|
+
], MinidCodeInput.prototype, "type", 2);
|
|
283
282
|
__decorateClass([
|
|
284
|
-
property(
|
|
285
|
-
], MinidCodeInput.prototype, "
|
|
283
|
+
property()
|
|
284
|
+
], MinidCodeInput.prototype, "inputmode", 2);
|
|
285
|
+
__decorateClass([
|
|
286
|
+
property()
|
|
287
|
+
], MinidCodeInput.prototype, "size", 2);
|
|
288
|
+
__decorateClass([
|
|
289
|
+
property({ type: Number })
|
|
290
|
+
], MinidCodeInput.prototype, "length", 2);
|
|
286
291
|
__decorateClass([
|
|
287
292
|
property({ type: Boolean })
|
|
288
293
|
], MinidCodeInput.prototype, "disabled", 2);
|
|
289
294
|
__decorateClass([
|
|
290
|
-
property({ type:
|
|
291
|
-
], MinidCodeInput.prototype, "
|
|
295
|
+
property({ type: Boolean })
|
|
296
|
+
], MinidCodeInput.prototype, "autofocus", 2);
|
|
297
|
+
__decorateClass([
|
|
298
|
+
property({ type: Number })
|
|
299
|
+
], MinidCodeInput.prototype, "minlength", 2);
|
|
292
300
|
__decorateClass([
|
|
293
301
|
property()
|
|
294
302
|
], MinidCodeInput.prototype, "invalidmessage", 2);
|
|
295
303
|
__decorateClass([
|
|
296
|
-
property({ type:
|
|
297
|
-
], MinidCodeInput.prototype, "
|
|
304
|
+
property({ type: Boolean })
|
|
305
|
+
], MinidCodeInput.prototype, "hidelabel", 2);
|
|
306
|
+
__decorateClass([
|
|
307
|
+
property({ type: Boolean })
|
|
308
|
+
], MinidCodeInput.prototype, "required", 2);
|
|
298
309
|
__decorateClass([
|
|
299
310
|
property()
|
|
300
|
-
], MinidCodeInput.prototype, "
|
|
311
|
+
], MinidCodeInput.prototype, "pattern", 2);
|
|
301
312
|
__decorateClass([
|
|
302
313
|
state()
|
|
303
|
-
], MinidCodeInput.prototype, "
|
|
314
|
+
], MinidCodeInput.prototype, "internalValues", 2);
|
|
304
315
|
__decorateClass([
|
|
305
|
-
|
|
306
|
-
], MinidCodeInput.prototype, "
|
|
316
|
+
watch("length")
|
|
317
|
+
], MinidCodeInput.prototype, "handleLengthChange", 1);
|
|
318
|
+
__decorateClass([
|
|
319
|
+
watch("value")
|
|
320
|
+
], MinidCodeInput.prototype, "handleValueChange", 1);
|
|
307
321
|
MinidCodeInput = __decorateClass([
|
|
308
322
|
customElement("mid-code-input")
|
|
309
323
|
], MinidCodeInput);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-input.js","sources":["../../src/components/code-input.component.ts"],"sourcesContent":["import { css, html, LitElement, type PropertyValues } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { createRef, ref, type Ref } from 'lit/directives/ref.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { live } from 'lit/directives/live.js';\nimport { webOtpApiClose, webOtpApiInit } from '../utilities/web-otp-api';\nimport { styled } from '../mixins/tailwind.mixin';\nimport { ConstraintsValidationMixin } from '../mixins/form-controller.mixin';\nimport './icon/icon.component';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mid-code-input': MinidCodeInput;\n }\n}\n\nconst styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n container: otc / inline-size;\n text-align: left;\n --otc-background: white;\n --otc-error-background: white;\n --otc-length: 5;\n --otc-width: 11.45cqw;\n }\n\n input {\n all: unset;\n background: var(--otc-background);\n caret-color: transparent;\n clip-path: inset(0% 1ch 0% 0%);\n font-family: ui-monospace, monospace;\n font-size: var(--otc-width);\n inline-size: calc(var(--otc-length) * 3ch);\n letter-spacing: 2ch;\n padding-block: 0.25ch;\n padding-inline-start: calc(0.5ch * 1.5);\n flex-grow: 1;\n\n &:focus-visible:focus {\n outline-style: none;\n }\n\n &:-webkit-autofill {\n animation-name: onAutoFillStart;\n }\n }\n\n @keyframes onAutoFillStart {\n from {\n }\n to {\n }\n }\n\n input.error {\n background: var(--otc-error-background);\n }\n `,\n];\n\nlet nextUniqueId = 0;\n\n@customElement('mid-code-input')\nexport class MinidCodeInput extends ConstraintsValidationMixin(\n styled(LitElement, styles)\n) {\n private readonly caretColor = 'var(--color-neutral-surface-tinted)';\n private readonly caretHighlightColor = 'var(--color-accent-surface-active)';\n private readonly inputId = `mid-code-input-${nextUniqueId++}`;\n\n public inputRef: Ref<HTMLInputElement> = createRef();\n\n @property({ type: String, reflect: true })\n value = '';\n\n @property()\n label = '';\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 required = false;\n\n @property({ type: Boolean })\n disabled = false;\n\n @property({ type: String })\n inputmode = 'numeric';\n\n /**\n * Display custom error message, and force invalid state\n */\n @property()\n invalidmessage = '';\n\n /**\n * The length of the code input\n */\n @property({ type: Number })\n length = 5;\n\n @property()\n fontsize = '11.45cqw';\n\n @state()\n renderError = false;\n\n @state()\n localErrorNode: Node | null = null;\n\n constructor() {\n super();\n this.addEventListener('invalid', (e) => {\n this.renderError = true;\n if (this.localErrorNode) {\n e.preventDefault();\n this.localErrorNode.textContent = this.validationMessage || 'Error';\n }\n });\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this._whenSettled();\n }\n\n async _whenSettled() {\n await this.updateComplete;\n this.inputRef.value?.addEventListener(\n 'animationstart',\n this.autoFillEventHandler.bind(this)\n );\n this.calcInputStyle();\n }\n\n override disconnectedCallback() {\n webOtpApiClose();\n this.inputRef.value?.removeEventListener(\n 'animationstart',\n this.autoFillEventHandler.bind(this)\n );\n }\n\n private calcInputStyle() {\n const inputStyle = this.inputRef.value?.style;\n\n inputStyle?.setProperty('--otc-length', this.length.toString());\n\n let gradientStyle = 'linear-gradient(90deg, ';\n for (let i = 0; i < this.length; i++) {\n gradientStyle += `var(--char-${i + 1}-color) ${i ? i * 3 + 'ch' : '0'} ${i * 3 + 2.5}ch, transparent ${i * 3 + 2.5}ch ${i * 3 + 3}ch${i + 1 < this.length ? ', ' : ''}`;\n }\n gradientStyle += `) no-repeat 0 0 / ${this.length * 3}ch 100%`;\n inputStyle?.setProperty('--otc-background', gradientStyle);\n\n const gradientErrorStyle = `linear-gradient(90deg, var(--color-danger-surface-active) calc(${this.length}ch / 2), transparent 0) 0 0 / 3ch 100%`;\n inputStyle?.setProperty('--otc-error-background', gradientErrorStyle);\n\n inputStyle?.setProperty('--otc-width', this.fontsize);\n }\n\n private autoFillEventHandler(e: AnimationEvent) {\n e.animationName === 'onAutoFillStart' &&\n (this.value = (this.inputRef.value as HTMLInputElement).value);\n }\n\n get selectionEnd() {\n return this.inputRef.value?.selectionEnd;\n }\n\n private handleFocusOut() {\n for (let i = 0; i < this.length; i++) {\n this.inputRef.value?.style.setProperty(\n `--char-${i + 1}-color`,\n this.caretColor\n );\n }\n }\n\n private handleFocusIn = () => {\n const currentChar = this.value.length + 1;\n this.inputRef.value?.style.setProperty(\n `--char-${currentChar}-color`,\n this.caretHighlightColor\n );\n };\n\n private handleClick() {\n this.value = this.value.substring(0, this.selectionEnd || 0);\n\n this.renderError = false;\n this.setCustomValidity('');\n if (this.localErrorNode) {\n this.localErrorNode.textContent = '';\n }\n\n this.setFormValue(this.value);\n this.setValidity({} as ValidityState);\n }\n\n private handleKeydown(event: KeyboardEvent) {\n const hasModifier =\n event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;\n\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 if (event.key === 'Enter' && !hasModifier) {\n setTimeout(() => {\n //\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.internals.form?.requestSubmit();\n }\n });\n }\n }\n\n private handleChange = (e: Event) => {\n this.value = (e.target as HTMLInputElement).value;\n this.dispatchEvent(\n new Event('input', {\n bubbles: true,\n cancelable: true,\n composed: true,\n })\n );\n };\n\n private handleSlotchange(e: Event) {\n const slot = e.target as HTMLSlotElement;\n const childNodes = slot.assignedNodes({ flatten: true });\n\n this.localErrorNode = this.findErrorMessageNode(childNodes);\n if (this.localErrorNode && this.invalidmessage) {\n // display if slot set, and error override in effect\n this.renderError = true;\n this.localErrorNode.textContent = this.invalidmessage;\n this.setValidity({} as ValidityState); // cancel built-in visual feedback\n }\n }\n\n private findErrorMessageNode(nodes: Node[]): Node | null {\n for (const node of nodes) {\n if (node instanceof Element && node.classList.contains('error-message')) {\n return node;\n }\n const childNodesArray = Array.from(node.childNodes);\n const foundNode = this.findErrorMessageNode(childNodesArray);\n if (foundNode) {\n return foundNode;\n }\n }\n return null;\n }\n\n firstUpdated(_changedProperties: PropertyValues) {\n this.focus();\n webOtpApiInit(this.renderRoot);\n }\n\n updated(_changedProperties: PropertyValues): void {\n for (let i = 0; i < this.length; i++) {\n const color =\n i === this.value.length ? this.caretHighlightColor : this.caretColor;\n this.inputRef.value?.style.setProperty(`--char-${i + 1}-color`, color);\n }\n\n if (_changedProperties.has('_forcedErrorMessage')) {\n this.setCustomValidity(this.invalidmessage);\n }\n\n this.setFormValue(this.value);\n this.setValidity(\n this.inputRef.value!.validity,\n this.inputRef.value!.validationMessage,\n this.inputRef!.value\n );\n }\n\n focus(options?: FocusOptions) {\n const notMobile = !window.matchMedia('only screen and (max-width: 768px)')\n .matches;\n notMobile && this.inputRef.value?.focus(options);\n }\n\n setCustomValidity(error: string) {\n this.inputRef!.value?.setCustomValidity(error);\n }\n\n override render() {\n return html`\n <label\n class=\"${classMap({\n 'sr-only': this.hidelabel,\n 'mb-2': !!this.label,\n })} font-medium\"\n for=\"${this.inputId}\"\n >${this.label}\n </label>\n <input\n ${ref(this.inputRef)}\n id=${this.inputId}\n .value=\"${live(this.value)}\"\n class=\"${classMap({\n error: this.invalidmessage,\n })}\"\n autocomplete=\"${'one-time-code' as any}\"\n inputmode=\"${this.inputmode}\"\n @input=\"${this.handleChange}\"\n @change=\"${this.handleChange}\"\n @focusout=\"${this.handleFocusOut}\"\n @focusin=\"${this.handleFocusIn}\"\n @keydown=\"${this.handleKeydown}\"\n @click=\"${this.handleClick}\"\n minlength=\"${this.length}\"\n maxlength=\"${this.length}\"\n ?disabled=\"${this.disabled}\"\n ?required=\"${this.required}\"\n />\n <slot name=\"error-message\" @slotchange=${this.handleSlotchange}>\n <div\n class=\"text-danger-subtle mt-2 flex gap-1\"\n aria-live=\"polite\"\n ?hidden=${!this.invalidmessage}\n >\n <mid-icon\n name=\"xmark-octagon-fill\"\n class=\"mt-1 min-h-5 min-w-5\"\n ></mid-icon>\n ${this.invalidmessage}\n </div>\n </slot>\n `;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"code-input.js","sources":["../../src/components/code-input.component.ts"],"sourcesContent":["import { css, html, LitElement, PropertyValues } from 'lit';\nimport { customElement, property, queryAll, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.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 /* 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];\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 {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 *\n * @csspart input-container - The wrapper around the input elements. This can be used to adjust font-size.\n *\n */\n@customElement('mid-code-input')\nexport class MinidCodeInput extends FormControlMixin(\n styled(LitElement, styles)\n) {\n private readonly hasSlotControler = new HasSlotController(this, 'label');\n #skipValueVisualUpdate = false;\n private readonly labelId = `mid-code-input-label-${nextUniqueId++}`;\n\n @queryAll('input')\n private inputElements!: NodeListOf<HTMLInputElement>;\n\n @property({ reflect: true })\n value = '';\n\n @property()\n label = '';\n\n @property()\n type: 'number' | 'text' = 'text';\n\n /**\n * For displaying appropriate virtual keyboard\n */\n @property()\n inputmode: 'numeric' | 'text' = 'text';\n\n /**\n * Adjusts the font-size of the code inputs\n */\n @property()\n size: 'sm' | 'md' | 'lg' = 'sm';\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 /**\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 internalValues = Array<string>(this.length).fill('');\n\n static get formControlValidators() {\n return [\n requiredValidator,\n maxLengthValidator,\n minLengthValidator,\n patternValidator,\n ];\n }\n\n get validationTarget() {\n return this.inputElements?.length ? this.inputElements[0] : null;\n }\n\n protected firstUpdated(_changedProperties: PropertyValues): void {\n webOtpApiInit(this.renderRoot);\n }\n\n private handleFocus(index: number) {\n return () => {\n this.inputElements[index].setAttribute('placeholder', '');\n };\n }\n\n private handleBlur(index: number) {\n return () => {\n this.inputElements[index].setAttribute('placeholder', '○');\n };\n }\n\n private handleKeydown(index: number) {\n return (event: KeyboardEvent) => {\n this.internalValues[index] = (event.target as HTMLInputElement).value;\n this.value = this.internalValues.join('');\n const input = event.target as HTMLInputElement;\n const hasModifier =\n event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;\n\n if (event.key === 'Backspace') {\n if (input.value === '' && index > 0) {\n // If current input is empty, move to previous and clear it\n this.inputElements[index - 1].focus();\n this.internalValues[index - 1] = '';\n this.updateValueAndEmit(true);\n } else if (input.value !== '') {\n // If current input has a value, clear it\n input.value = '';\n this.internalValues[index] = '';\n this.updateValueAndEmit(true);\n }\n } else if (event.key === 'ArrowLeft') {\n if (index > 0) {\n this.inputElements[index - 1].focus();\n }\n } else if (event.key === 'ArrowRight') {\n if (index < this.length - 1) {\n this.inputElements[index + 1].focus();\n }\n } else if (event.key === 'Delete') {\n // Clear current field without moving\n input.value = '';\n this.internalValues[index] = '';\n this.updateValueAndEmit(true);\n } else 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 //\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\n private handleInput(index: number) {\n return (event: InputEvent) => {\n const input = event.target as HTMLInputElement;\n let inputValue = input.value;\n\n // Only allow single digit input\n if (inputValue.length > 1) {\n inputValue = inputValue.charAt(0);\n input.value = inputValue; // Correct the input value\n }\n\n this.internalValues[index] = inputValue;\n this.updateValueAndEmit(true);\n\n // Auto-focus next input if a digit was entered and it's not the last one\n if (inputValue !== '' && index < this.length - 1) {\n this.inputElements[index + 1].focus();\n }\n\n this.dispatchEvent(\n new Event('mid-input', { bubbles: true, composed: true })\n );\n };\n }\n\n private handlePaste(index: number) {\n return (event: ClipboardEvent) => {\n event.preventDefault(); // Prevent default paste behavior\n const pasteData = event.clipboardData?.getData('text').trim();\n\n if (pasteData) {\n const pasteChars = pasteData.split('');\n for (let i = 0; i < this.length; i++) {\n if (index + i < this.length && pasteChars[i]) {\n this.internalValues[index + i] = pasteChars[i];\n // Update the actual input element's value directly as well\n // if (this.inputElements[index + i]) {\n // this.inputElements[index + i].value = pasteChars[i];\n // }\n }\n }\n this.updateValueAndEmit();\n\n // Focus the last filled input or the last input if all are filled\n const lastFilledIndex = Math.min(\n index + pasteChars.length - 1,\n this.length - 1\n );\n this.inputElements[lastFilledIndex]?.focus();\n }\n };\n }\n\n private updateValueAndEmit(skipValueUpdate = false) {\n this.#skipValueVisualUpdate = skipValueUpdate;\n this.value = this.internalValues.join('');\n this.dispatchEvent(\n new Event('mid-change', {\n bubbles: true,\n composed: true,\n })\n );\n\n if (\n this.value.length === this.length &&\n this.internalValues.every((digit) => digit !== '')\n ) {\n this.dispatchEvent(\n new Event('mid-complete', {\n bubbles: true,\n composed: true,\n })\n );\n }\n }\n\n private valueVisualUpdate(value: string) {\n const chars = value.split('');\n this.internalValues.forEach((_, index) => {\n this.internalValues[index] = chars[index];\n });\n }\n\n @watch('length')\n handleLengthChange() {\n this.internalValues = Array(this.length).fill('');\n this.valueVisualUpdate(this.value);\n }\n\n @watch('value')\n handleValueChange() {\n this.setValue(this.value);\n\n if (this.#skipValueVisualUpdate) {\n this.#skipValueVisualUpdate = false;\n return;\n }\n\n this.valueVisualUpdate(this.value);\n }\n\n override render() {\n const hasLabelSlot = this.hasSlotControler.test('label');\n const hasLabel = !!this.label || !!hasLabelSlot;\n return html`\n <label\n id=\"${this.labelId}\"\n class=\"${classMap({\n 'sr-only': this.hidelabel || !hasLabel,\n 'opacity-disabled': this.disabled,\n })} mb-2 block items-center gap-1 font-medium\"\n >\n <slot name=\"label\"> ${this.label} </slot>\n </label>\n <div\n part=\"input-container\"\n class=\"${classMap({\n 'text-heading-sm': this.size === 'sm',\n 'text-heading-md': this.size === 'md',\n 'text-heading-lg': this.size === 'lg',\n })} inline-flex gap-2\"\n >\n ${this.internalValues.map((value, index) => {\n return html`\n <input\n .value=\"${live(value || '')}\"\n id=\"mid-code-input-${index}\"\n class=\"${classMap({\n border: !this.invalidmessage,\n 'border-2': this.invalidmessage,\n 'border-neutral': !this.invalidmessage,\n 'border-danger': this.invalidmessage,\n 'bg-neutral': !this.invalidmessage,\n 'bg-danger-tinted': this.invalidmessage,\n 'placeholder:text-neutral-surface-active': !this.invalidmessage,\n 'placeholder:text-danger-surface-active': this.invalidmessage,\n })} focus:focus-ring-sm disabled:opacity-disabled size-9 rounded-md text-center font-mono disabled:cursor-not-allowed\"\n type=\"${this.type}\"\n placeholder=\"○\"\n aria-labelledby=\"${this.labelId}\"\n size=\"1\"\n ?autofocus=\"${!index && this.autofocus}\"\n ?disabled=\"${this.disabled}\"\n inputmode=\"${this.inputmode}\"\n @keydown=\"${this.handleKeydown(index)}\"\n @input=\"${this.handleInput(index)}\"\n @paste=\"${this.handlePaste(index)}\"\n @focus=\"${this.handleFocus(index)}\"\n @blur=\"${this.handleBlur(index)}\"\n />\n `;\n })}\n </div>\n <div\n class=\"text-danger-subtle mt-2 flex gap-1\"\n aria-live=\"polite\"\n ?hidden=${!this.invalidmessage}\n >\n <mid-icon\n name=\"xmark-octagon-fill\"\n class=\"mt-1 min-h-5 min-w-5\"\n ></mid-icon>\n ${this.invalidmessage}\n </div>\n `;\n }\n}\n"],"names":[],"mappings":"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"}
|