@felleslosninger/minid-elements 0.0.140 → 0.1.1

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.
Files changed (89) hide show
  1. package/README.md +69 -4
  2. package/dist/components/alert.component.d.ts +6 -4
  3. package/dist/components/alert.component.d.ts.map +1 -1
  4. package/dist/components/alert.js +33 -61
  5. package/dist/components/alert.js.map +1 -1
  6. package/dist/components/button.component.d.ts +1 -1
  7. package/dist/components/checkbox.component.d.ts +1 -2
  8. package/dist/components/checkbox.component.d.ts.map +1 -1
  9. package/dist/components/checkbox.js +25 -55
  10. package/dist/components/checkbox.js.map +1 -1
  11. package/dist/components/code-input-old.component.d.ts +1 -1
  12. package/dist/components/code-input-old.js +1 -1
  13. package/dist/components/code-input.component.d.ts +1 -1
  14. package/dist/components/code-input.component.d.ts.map +1 -1
  15. package/dist/components/code-input.js +232 -94
  16. package/dist/components/code-input.js.map +1 -1
  17. package/dist/components/combobox.component.d.ts +1 -1
  18. package/dist/components/countdown.component.d.ts +1 -1
  19. package/dist/components/dialog.component.d.ts +7 -1
  20. package/dist/components/dialog.component.d.ts.map +1 -1
  21. package/dist/components/dialog.js +19 -2
  22. package/dist/components/dialog.js.map +1 -1
  23. package/dist/components/dropdown.component.d.ts +1 -1
  24. package/dist/components/heading.component.d.ts +1 -1
  25. package/dist/components/heading.component.d.ts.map +1 -1
  26. package/dist/components/heading.js +1 -11
  27. package/dist/components/heading.js.map +1 -1
  28. package/dist/components/helptext.component.d.ts +1 -1
  29. package/dist/components/label.component.d.ts +1 -1
  30. package/dist/components/label.component.d.ts.map +1 -1
  31. package/dist/components/label.js +3 -12
  32. package/dist/components/label.js.map +1 -1
  33. package/dist/components/link.component.d.ts +1 -1
  34. package/dist/components/link.js +1 -1
  35. package/dist/components/link.js.map +1 -1
  36. package/dist/components/menu-item.component.d.ts +1 -1
  37. package/dist/components/menu.component.d.ts +1 -1
  38. package/dist/components/paragraph.component.d.ts +1 -1
  39. package/dist/components/paragraph.component.d.ts.map +1 -1
  40. package/dist/components/paragraph.js +2 -8
  41. package/dist/components/paragraph.js.map +1 -1
  42. package/dist/components/phone-input.component.d.ts +15 -3
  43. package/dist/components/phone-input.component.d.ts.map +1 -1
  44. package/dist/components/phone-input.js +37 -6
  45. package/dist/components/phone-input.js.map +1 -1
  46. package/dist/components/popup.component.d.ts +1 -1
  47. package/dist/components/qr-code.component.d.ts +1 -1
  48. package/dist/components/radio-button.component.d.ts +1 -1
  49. package/dist/components/radio-group.component.d.ts +1 -1
  50. package/dist/components/radio.component.d.ts +1 -1
  51. package/dist/components/radio.component.d.ts.map +1 -1
  52. package/dist/components/radio.js +12 -16
  53. package/dist/components/radio.js.map +1 -1
  54. package/dist/components/search.component.d.ts +11 -4
  55. package/dist/components/search.component.d.ts.map +1 -1
  56. package/dist/components/search.js +75 -31
  57. package/dist/components/search.js.map +1 -1
  58. package/dist/components/spinner.component.d.ts +1 -1
  59. package/dist/components/step-indicator.component.d.ts +1 -1
  60. package/dist/components/textfield.component.d.ts +5 -3
  61. package/dist/components/textfield.component.d.ts.map +1 -1
  62. package/dist/components/textfield.js +76 -84
  63. package/dist/components/textfield.js.map +1 -1
  64. package/dist/components/tooltip.component.d.ts +1 -1
  65. package/dist/components/validation-message.component.d.ts +1 -1
  66. package/dist/controllers/lang.controller.d.ts +14 -0
  67. package/dist/controllers/lang.controller.d.ts.map +1 -0
  68. package/dist/designsystemet-tailwind.css +355 -297
  69. package/dist/index.d.ts +2 -0
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +4 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/lang.controller-P4W-9ipy.js +32 -0
  74. package/dist/lang.controller-P4W-9ipy.js.map +1 -0
  75. package/dist/mixins/validators.d.ts +1 -0
  76. package/dist/mixins/validators.d.ts.map +1 -1
  77. package/dist/mixins/validators.js +18 -1
  78. package/dist/mixins/validators.js.map +1 -1
  79. package/dist/styles.css +5 -0
  80. package/dist/theme.css +1155 -0
  81. package/dist/utilities/lang.d.ts +6 -0
  82. package/dist/utilities/lang.d.ts.map +1 -0
  83. package/dist/utilities/lang.js +18 -0
  84. package/dist/utilities/lang.js.map +1 -0
  85. package/dist/utilities/translations.d.ts +43 -0
  86. package/dist/utilities/translations.d.ts.map +1 -0
  87. package/dist/utilities/translations.js +49 -0
  88. package/dist/utilities/translations.js.map +1 -0
  89. package/package.json +34 -16
@@ -23,86 +23,224 @@ var __decorateClass = (decorators, target, key, kind) => {
23
23
  let nextUniqueId = 0;
24
24
  const styles = [
25
25
  css`
26
- :host {
27
- display: block;
28
- }
26
+ :host {
27
+ display: block;
28
+ }
29
29
 
30
- .input-wrapper {
31
- position: relative;
32
- cursor: text;
33
- }
30
+ .code-input-label {
31
+ display: inline-flex;
32
+ align-items: center;
33
+ gap: 0.25rem;
34
+ margin-block-end: 0.5rem;
35
+ font-weight: 500;
36
+ }
34
37
 
35
- .character-boxes {
36
- display: inline-flex;
37
- gap: 0.5rem; /* Corresponds to gap-2 in tailwind */
38
- }
38
+ .code-input-label--hidden {
39
+ position: absolute;
40
+ width: 1px;
41
+ height: 1px;
42
+ padding: 0;
43
+ margin: -1px;
44
+ overflow: hidden;
45
+ clip: rect(0, 0, 0, 0);
46
+ white-space: nowrap;
47
+ border: 0;
48
+ }
39
49
 
40
- .character-box {
41
- display: inline-flex;
42
- align-items: center;
43
- justify-content: center;
44
- position: relative;
45
- }
50
+ .code-input-label--disabled,
51
+ .input-wrapper--disabled {
52
+ opacity: var(--ds-opacity-disabled, 0.38);
53
+ }
46
54
 
47
- .hidden-input {
48
- position: absolute;
49
- top: 0;
50
- left: 0;
51
- width: 100%;
52
- height: 100%;
53
- padding: 0;
54
- margin: 0;
55
- background: transparent;
56
- border: none;
57
- color: transparent;
58
- /* Hide the real caret */
59
- caret-color: transparent;
60
- font-size: 16px; /* Must be at least 16px to prevent ios from zooming in */
61
- /* Allow clicks to pass through to elements underneath */
62
- pointer-events: none;
63
- }
55
+ .input-wrapper {
56
+ position: relative;
57
+ cursor: text;
58
+ width: fit-content;
59
+ font-size: 1rem;
60
+ line-height: 1.3;
61
+ font-weight: 500;
62
+ }
64
63
 
65
- .hidden-input:focus {
66
- outline: none;
67
- }
64
+ .input-wrapper--sm {
65
+ font-size: var(--ds-heading-sm-font-size, 1.125rem);
66
+ line-height: var(--ds-heading-sm-line-height, 1.3);
67
+ font-weight: var(--ds-heading-sm-font-weight, 500);
68
+ }
68
69
 
69
- .hidden-input:disabled {
70
- cursor: not-allowed;
71
- }
70
+ .input-wrapper--md {
71
+ font-size: var(--ds-heading-md-font-size, 1.25rem);
72
+ line-height: var(--ds-heading-md-line-height, 1.3);
73
+ font-weight: var(--ds-heading-md-font-weight, 500);
74
+ }
72
75
 
73
- /* Fake caret using a CSS animation */
74
- @keyframes blink {
75
- 0%,
76
- 100% {
77
- opacity: 1;
78
- }
79
- 50% {
80
- opacity: 0;
81
- }
82
- }
76
+ .input-wrapper--lg {
77
+ font-size: var(--ds-heading-lg-font-size, 1.5rem);
78
+ line-height: var(--ds-heading-lg-line-height, 1.3);
79
+ font-weight: var(--ds-heading-lg-font-weight, 500);
80
+ }
83
81
 
84
- .character-box--caret::after {
85
- content: '';
86
- position: absolute;
87
- width: 2px;
88
- height: 60%;
89
- background-color: var(--color-accent-base, blue);
90
- animation: blink 1s step-end infinite;
91
- }
82
+ .input-wrapper--disabled {
83
+ cursor: not-allowed;
84
+ }
92
85
 
93
- /* Hide placeholder circle when the caret is present */
94
- .character-box--caret.character-box--empty {
95
- color: transparent;
96
- }
86
+ .character-boxes {
87
+ display: inline-flex;
88
+ gap: var(--mid-code-input-gap, 0.5rem);
89
+ }
90
+
91
+ .character-box {
92
+ display: inline-flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ position: relative;
96
+ box-sizing: border-box;
97
+ width: var(--mid-code-input-box-size, var(--ds-size-13, 3.25rem));
98
+ height: var(--mid-code-input-box-size, var(--ds-size-13, 3.25rem));
99
+ padding-inline: 0.25rem;
100
+ user-select: none;
101
+ text-align: center;
102
+ font-family:
103
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
104
+ 'Liberation Mono', 'Courier New', monospace;
105
+ line-height: 1;
106
+ border: var(--ds-border-width-default, 1px) solid
107
+ var(
108
+ --mid-code-input-border-color,
109
+ var(--ds-color-neutral-border-default, #717a84)
110
+ );
111
+ border-radius: var(
112
+ --mid-code-input-border-radius,
113
+ var(--ds-border-radius-md, 0.25rem)
114
+ );
115
+ background-color: var(
116
+ --mid-code-input-background,
117
+ var(--ds-color-neutral-background-default, #ffffff)
118
+ );
119
+ color: var(--mid-code-input-text-color, inherit);
120
+ }
121
+
122
+ .character-box--empty {
123
+ color: var(
124
+ --mid-code-input-placeholder-color,
125
+ var(--ds-color-neutral-surface-active, #c7cacf)
126
+ );
127
+ }
128
+
129
+ .character-box--empty::before {
130
+ content: '';
131
+ box-sizing: border-box;
132
+ width: 0.55em;
133
+ height: 0.55em;
134
+ border: 2px solid currentColor;
135
+ border-radius: 50%;
136
+ }
137
+
138
+ .character-box--invalid {
139
+ border-width: 2px;
140
+ border-color: var(
141
+ --mid-code-input-danger-border-color,
142
+ var(--ds-color-danger-border-default, #ce4d4d)
143
+ );
144
+ background-color: var(
145
+ --mid-code-input-danger-background,
146
+ var(--ds-color-danger-surface-tinted, #f8e4e4)
147
+ );
148
+ }
149
+
150
+ .character-box--invalid.character-box--empty {
151
+ color: var(
152
+ --mid-code-input-danger-placeholder-color,
153
+ var(--ds-color-danger-surface-active, #edbfbf)
154
+ );
155
+ }
156
+
157
+ .focus-ring-sm {
158
+ outline: 2px solid var(--ds-color-focus-outer, #1f2c3d);
159
+ outline-offset: 2px;
160
+ box-shadow: 0 0 0 2px var(--ds-color-focus-inner, #ffffff);
161
+ }
162
+
163
+ /* Ensure hidden attribute always hides elements even when Tailwind's
164
+ @layer base [hidden] rule is not available in the shadow DOM */
165
+ [hidden] {
166
+ display: none !important;
167
+ }
168
+
169
+ .hidden-input {
170
+ position: absolute;
171
+ top: 0;
172
+ left: 0;
173
+ width: 100%;
174
+ height: 100%;
175
+ padding: 0;
176
+ margin: 0;
177
+ background: transparent;
178
+ border: none;
179
+ outline: none;
180
+ color: transparent;
181
+ caret-color: transparent;
182
+ font-size: 16px; /* Minimum 16px prevents iOS zoom on focus */
183
+ pointer-events: none;
184
+ -webkit-appearance: none;
185
+ appearance: none;
186
+ }
187
+
188
+ .hidden-input:focus {
189
+ outline: none;
190
+ }
191
+
192
+ .hidden-input:disabled {
193
+ cursor: not-allowed;
194
+ }
97
195
 
98
- /* Hide increment/decrement buttons on inputs */
99
- input[type='number']::-webkit-outer-spin-button,
100
- input[type='number']::-webkit-inner-spin-button,
101
- input[type='number'] {
102
- -webkit-appearance: none;
103
- margin: 0;
104
- -moz-appearance: textfield !important;
196
+ @keyframes blink {
197
+ 0%,
198
+ 100% {
199
+ opacity: 1;
200
+ }
201
+ 50% {
202
+ opacity: 0;
105
203
  }
204
+ }
205
+
206
+ .character-box--caret::after {
207
+ content: '';
208
+ position: absolute;
209
+ width: 2px;
210
+ height: 60%;
211
+ background-color: var(
212
+ --color-accent-base,
213
+ var(--ds-color-accent-base-default, blue)
214
+ );
215
+ animation: blink 1s step-end infinite;
216
+ }
217
+
218
+ /* Hide placeholder circle when the caret is at this position */
219
+ .character-box--caret.character-box--empty {
220
+ color: transparent;
221
+ }
222
+
223
+ /* Hide increment/decrement buttons on number inputs */
224
+ input[type='number']::-webkit-outer-spin-button,
225
+ input[type='number']::-webkit-inner-spin-button,
226
+ input[type='number'] {
227
+ -webkit-appearance: none;
228
+ margin: 0;
229
+ -moz-appearance: textfield !important;
230
+ }
231
+
232
+ .validation-message {
233
+ display: flex;
234
+ gap: 0.25rem;
235
+ margin-block-start: 0.5rem;
236
+ color: var(--ds-color-danger-text-subtle, #a22e2e);
237
+ }
238
+
239
+ .validation-icon {
240
+ margin-block-start: 0.25rem;
241
+ min-width: 1.25rem;
242
+ min-height: 1.25rem;
243
+ }
106
244
  `
107
245
  ];
108
246
  let MinidCodeInput = class extends FormControlMixin(
@@ -115,7 +253,7 @@ let MinidCodeInput = class extends FormControlMixin(
115
253
  this.validationId = `mid-code-input-validation-${nextUniqueId++}`;
116
254
  this.value = "";
117
255
  this.label = "";
118
- this.type = "number";
256
+ this.type = "text";
119
257
  this.inputmode = "numeric";
120
258
  this.size = "sm";
121
259
  this.length = 5;
@@ -149,6 +287,10 @@ let MinidCodeInput = class extends FormControlMixin(
149
287
  }
150
288
  handleFocus() {
151
289
  this.isFocused = true;
290
+ if (this.value.length > 0) {
291
+ const length = this.value.length;
292
+ this.inputElement.setSelectionRange(length, length);
293
+ }
152
294
  }
153
295
  handleBlur() {
154
296
  this.isFocused = false;
@@ -208,6 +350,10 @@ let MinidCodeInput = class extends FormControlMixin(
208
350
  }
209
351
  focus(options) {
210
352
  this.inputElement?.focus(options);
353
+ if (this.value.length > 0) {
354
+ const length = this.value.length;
355
+ this.inputElement.setSelectionRange(length, length);
356
+ }
211
357
  }
212
358
  handleLengthChange() {
213
359
  if (this.value.length > this.length) {
@@ -228,20 +374,21 @@ let MinidCodeInput = class extends FormControlMixin(
228
374
  return html`
229
375
  <label
230
376
  id="${this.labelId}"
231
- class="${classMap({
232
- "sr-only": this.hidelabel || !hasLabel,
233
- "opacity-disabled": this.disabled
234
- })} mb-2 block items-center gap-1 font-medium"
377
+ for="mid-code-input-hidden"
378
+ class="code-input-label ${classMap({
379
+ "code-input-label--hidden": this.hidelabel || !hasLabel,
380
+ "code-input-label--disabled": this.disabled
381
+ })}"
235
382
  >
236
383
  <slot name="label"> ${this.label} </slot>
237
384
  </label>
238
385
  <div
239
386
  part="input-container"
240
387
  class="input-wrapper ${classMap({
241
- "text-heading-sm": this.size === "sm",
242
- "text-heading-md": this.size === "md",
243
- "text-heading-lg": this.size === "lg",
244
- "opacity-disabled": this.disabled
388
+ "input-wrapper--sm": this.size === "sm",
389
+ "input-wrapper--md": this.size === "md",
390
+ "input-wrapper--lg": this.size === "lg",
391
+ "input-wrapper--disabled": this.disabled
245
392
  })}"
246
393
  @click=${() => this.focus()}
247
394
  >
@@ -252,25 +399,19 @@ let MinidCodeInput = class extends FormControlMixin(
252
399
  return html`
253
400
  <div
254
401
  part="character-box"
402
+ aria-hidden="true"
255
403
  class="character-box ${classMap({
256
- "border": !this.invalidmessage,
257
- "border-2": this.invalidmessage,
258
- "border-neutral": !this.invalidmessage,
259
- "border-danger": this.invalidmessage,
260
- "bg-neutral": !this.invalidmessage,
261
- "bg-danger-tinted": this.invalidmessage,
262
- "text-neutral-surface-active": !char && !this.invalidmessage,
263
- "text-danger-surface-active": !char && this.invalidmessage,
404
+ "character-box--invalid": !!this.invalidmessage,
264
405
  "character-box--caret": hasCaret,
265
406
  "character-box--empty": !char,
266
407
  "focus-ring-sm": isFocusTarget
267
- })} size-9 rounded-md text-center font-mono"
408
+ })}"
268
409
  @click=${(e) => {
269
410
  e.stopPropagation();
270
411
  this.handleBoxClick(index);
271
412
  }}
272
413
  >
273
- ${char || "○"}
414
+ ${char}
274
415
  </div>
275
416
  `;
276
417
  })}
@@ -290,7 +431,7 @@ let MinidCodeInput = class extends FormControlMixin(
290
431
  ?autofocus="${this.autofocus}"
291
432
  ?disabled="${this.disabled}"
292
433
  ?required="${this.required}"
293
- .pattern="${this.pattern}"
434
+ pattern=${ifDefined(this.pattern)}
294
435
  inputmode="${this.inputmode}"
295
436
  autocomplete="one-time-code"
296
437
  @beforeinput="${this.handleBeforeInput}"
@@ -302,15 +443,12 @@ let MinidCodeInput = class extends FormControlMixin(
302
443
  />
303
444
  </div>
304
445
  <div
305
- class="text-danger-subtle mt-2 flex gap-1"
446
+ class="validation-message"
306
447
  id="${this.validationId}"
307
448
  aria-live="polite"
308
449
  ?hidden=${!this.invalidmessage}
309
450
  >
310
- <mid-icon
311
- name="xmark-octagon-fill"
312
- class="mt-1 min-h-5 min-w-5"
313
- ></mid-icon>
451
+ <mid-icon name="xmark-octagon-fill" class="validation-icon"></mid-icon>
314
452
  ${this.invalidmessage}
315
453
  </div>
316
454
  `;
@@ -1 +1 @@
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, 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 .input-wrapper {\n position: relative;\n cursor: text;\n }\n\n .character-boxes {\n display: inline-flex;\n gap: 0.5rem; /* Corresponds to gap-2 in tailwind */\n }\n\n .character-box {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\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 color: transparent;\n /* Hide the real caret */\n caret-color: transparent;\n font-size: 16px; /* Must be at least 16px to prevent ios from zooming in */\n /* Allow clicks to pass through to elements underneath */\n pointer-events: none;\n }\n\n .hidden-input:focus {\n outline: none;\n }\n\n .hidden-input:disabled {\n cursor: not-allowed;\n }\n\n /* Fake caret using a CSS animation */\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(--color-accent-base, blue);\n animation: blink 1s step-end infinite;\n }\n\n /* Hide placeholder circle when the caret is present */\n .character-box--caret.character-box--empty {\n color: transparent;\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 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 *\n * @csspart input-container - The wrapper around the input elements. This can be used to adjust font-size.\n * @csspart character-boxes - The container for the visual character boxes.\n * @csspart character-box - An individual character box.\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(this, 'label');\n private readonly labelId = `mid-code-input-label-${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 type: 'number' | 'text' = 'number';\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 /**\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 isFocused = false;\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 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 private handleFocus() {\n this.isFocused = true;\n }\n\n private handleBlur() {\n this.isFocused = false;\n }\n\n private handleBeforeInput(e: InputEvent) {\n if (e.inputType === 'insertText' && e.data) {\n if(this.type == \"number\" && e.data.replace(/\\D/g, '') == ''){\n e.preventDefault();\n }\n }\n }\n\n private handleInput(event: InputEvent) {\n const input = event.target as HTMLInputElement;\n let value = input.value;\n\n value = value.substring(0, this.length);\n\n if (input.value !== value) {\n input.value = value;\n }\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\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 }\n\n resetFormControl() {\n this.clear();\n }\n\n\n focus(options?: FocusOptions): void {\n this.inputElement?.focus(options);\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\n override render() {\n const hasLabelSlot = this.hasSlotControler.test('label');\n const hasLabel = !!this.label || !!hasLabelSlot;\n const describedBy = this.invalidmessage ? this.validationId : undefined;\n\n const chars = this.value.split('');\n const displayValues = Array.from(\n { length: this.length },\n (_, i) => chars[i] || '',\n );\n const isComplete = this.value.length >= this.length;\n const caretIndex =\n this.disabled || this.length === 0\n ? -1\n : Math.min(this.value.length, this.length - 1);\n\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=\"input-wrapper ${classMap({\n 'text-heading-sm': this.size === 'sm',\n 'text-heading-md': this.size === 'md',\n 'text-heading-lg': this.size === 'lg',\n 'opacity-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 && !isComplete;\n return html`\n <div\n part=\"character-box\"\n class=\"character-box ${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 'text-neutral-surface-active':\n !char && !this.invalidmessage,\n 'text-danger-surface-active': !char && this.invalidmessage,\n 'character-box--caret': hasCaret,\n 'character-box--empty': !char,\n 'focus-ring-sm': isFocusTarget,\n })} size-9 rounded-md text-center font-mono\"\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=\"${this.type}\"\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=\"${this.pattern}\"\n inputmode=\"${this.inputmode}\"\n autocomplete=\"one-time-code\"\n @beforeinput=\"${this.handleBeforeInput}\"\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=\"text-danger-subtle mt-2 flex gap-1\"\n id=\"${this.validationId}\"\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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"}
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, 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--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 .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 /* Hide placeholder circle when the caret is at this position */\n .character-box--caret.character-box--empty {\n color: transparent;\n }\n\n /* Hide increment/decrement buttons on number 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 .validation-message {\n display: flex;\n gap: 0.25rem;\n margin-block-start: 0.5rem;\n color: var(--ds-color-danger-text-subtle, #a22e2e);\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 *\n * @csspart input-container - The wrapper around the input elements. This can be used to adjust font-size.\n * @csspart character-boxes - The container for the visual character boxes.\n * @csspart character-box - An individual character box.\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(this, 'label');\n private readonly labelId = `mid-code-input-label-${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 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 /**\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 isFocused = false;\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 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 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 }\n\n private handleBlur() {\n this.isFocused = false;\n }\n\n private handleBeforeInput(e: InputEvent) {\n if (e.inputType === 'insertText' && e.data) {\n if (this.type == 'number' && e.data.replace(/\\D/g, '') == '') {\n e.preventDefault();\n }\n }\n }\n\n private handleInput(event: InputEvent) {\n const input = event.target as HTMLInputElement;\n let value = input.value;\n\n value = value.substring(0, this.length);\n\n if (input.value !== value) {\n input.value = value;\n }\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 }\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 }\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 override render() {\n const hasLabelSlot = this.hasSlotControler.test('label');\n const hasLabel = !!this.label || !!hasLabelSlot;\n const describedBy = this.invalidmessage ? this.validationId : undefined;\n\n const chars = this.value.split('');\n const displayValues = Array.from(\n { length: this.length },\n (_, i) => chars[i] || ''\n );\n const isComplete = this.value.length >= this.length;\n const caretIndex =\n this.disabled || this.length === 0\n ? -1\n : Math.min(this.value.length, this.length - 1);\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--hidden': this.hidelabel || !hasLabel,\n 'code-input-label--disabled': this.disabled,\n })}\"\n >\n <slot name=\"label\"> ${this.label} </slot>\n </label>\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 && !isComplete;\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--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=\"${this.type}\"\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 @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\"\n id=\"${this.validationId}\"\n aria-live=\"polite\"\n ?hidden=${!this.invalidmessage}\n >\n <mid-icon name=\"xmark-octagon-fill\" class=\"validation-icon\"></mid-icon>\n ${this.invalidmessage}\n </div>\n `;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -78,7 +78,7 @@ export declare class MinidCombobox extends MinidCombobox_base {
78
78
  addOpenListeners(): void;
79
79
  removeOpenListeners(): void;
80
80
  handleOpenChange(): Promise<void>;
81
- render(): import('lit-html').TemplateResult<1>;
81
+ render(): import('lit').TemplateResult<1>;
82
82
  }
83
83
  export {};
84
84
  //# sourceMappingURL=combobox.component.d.ts.map
@@ -18,7 +18,7 @@ export declare class MinidCountdown extends MinidCountdown_base {
18
18
  private expired;
19
19
  callback?: () => void;
20
20
  firstUpdated(): void;
21
- render(): import('lit-html').TemplateResult<1>;
21
+ render(): import('lit').TemplateResult<1>;
22
22
  }
23
23
  export {};
24
24
  //# sourceMappingURL=countdown.component.d.ts.map
@@ -42,6 +42,11 @@ export declare class MinidDialog extends MinidDialog_base {
42
42
  * `no-header`, as it is required for proper accessibility. If you need to display HTML, use the `label` slot instead.
43
43
  */
44
44
  heading: string;
45
+ /**
46
+ * When set, the dialog uses `role="alertdialog"` instead of `role="dialog"`, signalling urgency to screen readers.
47
+ * Use this for blocking dialogs that require immediate user attention.
48
+ */
49
+ alertdialog: boolean;
45
50
  private requestClose;
46
51
  handleDialogCancel: (event: Event) => void;
47
52
  private handleBackdropClick;
@@ -54,7 +59,8 @@ export declare class MinidDialog extends MinidDialog_base {
54
59
  * Hides the dialog
55
60
  */
56
61
  hide(): Promise<void>;
57
- render(): import('lit-html').TemplateResult<1>;
62
+ constructor();
63
+ render(): import('lit').TemplateResult<1>;
58
64
  }
59
65
  export {};
60
66
  //# sourceMappingURL=dialog.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.component.d.ts","sourceRoot":"","sources":["../../src/components/dialog.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAE,MAAM,KAAK,CAAC;AAK5C,OAAO,uBAAuB,CAAC;AAQ/B,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,WAAW,CAAC;KAC3B;CACF;;AAWD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBACa,WAAY,SAAQ,gBAA0B;IAEzD,MAAM,EAAG,iBAAiB,CAAC;IAE3B;;;OAGG;IAEH,IAAI,UAAS;IAEb;;;OAGG;IAEH,OAAO,SAAM;IAEb,OAAO,CAAC,YAAY;IAkBpB,kBAAkB,GAAI,OAAO,KAAK,UAQhC;IAEF,OAAO,CAAC,mBAAmB;IAQrB,gBAAgB;IA+CtB;;OAEG;IACG,IAAI;IASV;;OAEG;IACG,IAAI;IASD,MAAM;CA8BhB"}
1
+ {"version":3,"file":"dialog.component.d.ts","sourceRoot":"","sources":["../../src/components/dialog.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAQrD,OAAO,uBAAuB,CAAC;AAQ/B,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,WAAW,CAAC;KAC3B;CACF;;AAWD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBACa,WAAY,SAAQ,gBAA0B;IAEzD,MAAM,EAAG,iBAAiB,CAAC;IAE3B;;;OAGG;IAEH,IAAI,UAAS;IAEb;;;OAGG;IAEH,OAAO,SAAM;IAEb;;;OAGG;IAEH,WAAW,UAAS;IAEpB,OAAO,CAAC,YAAY;IAkBpB,kBAAkB,GAAI,OAAO,KAAK,UAQhC;IAEF,OAAO,CAAC,mBAAmB;IAQrB,gBAAgB;IAmDtB;;OAEG;IACG,IAAI;IASV;;OAEG;IACG,IAAI;;IAcD,MAAM;CAqChB"}
@@ -1,5 +1,8 @@
1
- import { css, LitElement, html } from "lit";
1
+ import { css, LitElement, nothing, html } from "lit";
2
2
  import { query, property, customElement } from "lit/decorators.js";
3
+ import { getLang } from "../utilities/lang.js";
4
+ import { getTranslations } from "../utilities/translations.js";
5
+ import { L as LangController } from "../lang.controller-P4W-9ipy.js";
3
6
  import { waitForEvent } from "../internal/event.js";
4
7
  import { watch } from "../internal/watch.js";
5
8
  import { styled } from "../mixins/tailwind.mixin.js";
@@ -27,9 +30,10 @@ const styles = [
27
30
  ];
28
31
  let MinidDialog = class extends styled(LitElement, styles) {
29
32
  constructor() {
30
- super(...arguments);
33
+ super();
31
34
  this.open = false;
32
35
  this.heading = "";
36
+ this.alertdialog = false;
33
37
  this.handleDialogCancel = (event) => {
34
38
  event.preventDefault();
35
39
  if (event.defaultPrevented) {
@@ -38,6 +42,7 @@ let MinidDialog = class extends styled(LitElement, styles) {
38
42
  this.hide();
39
43
  }
40
44
  };
45
+ new LangController(this);
41
46
  }
42
47
  requestClose(source) {
43
48
  const requestCloseEvent = new CustomEvent("mid-request-close", {
@@ -65,6 +70,9 @@ let MinidDialog = class extends styled(LitElement, styles) {
65
70
  new Event("mid-show", { composed: true, bubbles: true })
66
71
  );
67
72
  this.dialog.showModal();
73
+ if (this.alertdialog) {
74
+ this.dialog.focus();
75
+ }
68
76
  lockBodyScrolling(this);
69
77
  const panelAnimation = getAnimation(this, "dialog.show");
70
78
  await animateTo(
@@ -116,10 +124,15 @@ let MinidDialog = class extends styled(LitElement, styles) {
116
124
  return waitForEvent(this, "mid-after-hide");
117
125
  }
118
126
  render() {
127
+ const t = getTranslations(getLang(this));
119
128
  return html`
120
129
  <dialog
121
130
  part="base"
122
131
  id="dialog"
132
+ tabindex="-1"
133
+ role=${this.alertdialog ? "alertdialog" : "dialog"}
134
+ aria-label=${this.heading || nothing}
135
+ aria-modal="true"
123
136
  class="text-neutral m-auto max-h-[calc(100%---spacing(8))] w-(--width) max-w-[calc(100%---spacing(8))] flex-col rounded-lg p-6 shadow-xl backdrop:bg-black/50 open:flex open:animate-none"
124
137
  @cancel=${this.handleDialogCancel}
125
138
  @click=${this.handleBackdropClick}
@@ -129,6 +142,7 @@ let MinidDialog = class extends styled(LitElement, styles) {
129
142
  <div class="h-0">
130
143
  <button
131
144
  autofocus
145
+ aria-label=${t.close}
132
146
  @click="${() => this.requestClose("close-button")}"
133
147
  class="text-body-md focus-visible:focus-ring text-neutral hover:bg-neutral-surface-hover float-right flex size-12 translate-x-3 -translate-y-3 items-center justify-center rounded"
134
148
  >
@@ -155,6 +169,9 @@ __decorateClass([
155
169
  __decorateClass([
156
170
  property({ reflect: true })
157
171
  ], MinidDialog.prototype, "heading", 2);
172
+ __decorateClass([
173
+ property({ type: Boolean, reflect: true })
174
+ ], MinidDialog.prototype, "alertdialog", 2);
158
175
  __decorateClass([
159
176
  watch("open", { waitUntilFirstUpdate: true })
160
177
  ], MinidDialog.prototype, "handleOpenChange", 1);