kanto-ds 1.5.2 → 1.6.0

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 (125) hide show
  1. package/README.md +10 -10
  2. package/dist/chunks/floating-B33g-M_1.js +63 -0
  3. package/dist/chunks/floating-B33g-M_1.js.map +1 -0
  4. package/dist/chunks/{index-STEEvEP7.js → index-TWJzttLX.js} +38 -15
  5. package/dist/chunks/index-TWJzttLX.js.map +1 -0
  6. package/dist/chunks/kt-calendar-CtwOby1R.js +780 -0
  7. package/dist/chunks/kt-calendar-CtwOby1R.js.map +1 -0
  8. package/dist/chunks/{kt-element-Djx2JcGl.js → kt-element-T0VbIBNp.js} +2 -2
  9. package/dist/chunks/{kt-element-Djx2JcGl.js.map → kt-element-T0VbIBNp.js.map} +1 -1
  10. package/dist/chunks/{listbox-llcUu_V-.js → listbox-LsUEyGhQ.js} +2 -2
  11. package/dist/chunks/{listbox-llcUu_V-.js.map → listbox-LsUEyGhQ.js.map} +1 -1
  12. package/dist/chunks/segmented-field-BBXR4XFL.js +384 -0
  13. package/dist/chunks/segmented-field-BBXR4XFL.js.map +1 -0
  14. package/dist/chunks/typed-date-CPAUNHzr.js +103 -0
  15. package/dist/chunks/typed-date-CPAUNHzr.js.map +1 -0
  16. package/dist/components/core/kt-avatar/kt-avatar.js +2 -2
  17. package/dist/components/core/kt-badge/kt-badge.js +2 -2
  18. package/dist/components/core/kt-button/kt-button.js +1 -1
  19. package/dist/components/core/kt-card/kt-card.js +1 -1
  20. package/dist/components/core/kt-code/kt-code.js +13 -13
  21. package/dist/components/core/kt-code/kt-code.js.map +1 -1
  22. package/dist/components/core/kt-icon/kt-icon.js +1 -1
  23. package/dist/components/core/kt-kbd/kt-kbd.js +5 -5
  24. package/dist/components/core/kt-kbd/kt-kbd.js.map +1 -1
  25. package/dist/components/core/kt-split-button/kt-split-button.js +3 -3
  26. package/dist/components/data/kt-chart/kt-chart.js +3 -3
  27. package/dist/components/data/kt-chart/kt-chart.js.map +1 -1
  28. package/dist/components/data/kt-meter/kt-meter.js +1 -1
  29. package/dist/components/data/kt-pagination/kt-pagination.js +2 -2
  30. package/dist/components/data/kt-stat/kt-stat.js +1 -1
  31. package/dist/components/data/kt-table/kt-table.js +85 -85
  32. package/dist/components/data/kt-table/kt-table.js.map +1 -1
  33. package/dist/components/data/kt-timeline/kt-timeline.js +1 -1
  34. package/dist/components/feedback/kt-alert/kt-alert.js +15 -15
  35. package/dist/components/feedback/kt-alert/kt-alert.js.map +1 -1
  36. package/dist/components/feedback/kt-empty-state/kt-empty-state.js +1 -1
  37. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +1 -1
  38. package/dist/components/feedback/kt-skeleton/kt-skeleton.js +13 -13
  39. package/dist/components/feedback/kt-skeleton/kt-skeleton.js.map +1 -1
  40. package/dist/components/feedback/kt-toast/kt-toast.js +3 -3
  41. package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -1
  42. package/dist/components/feedback/kt-toast-container/kt-toast-container.js +1 -1
  43. package/dist/components/feedback/kt-tooltip/kt-tooltip.js +1 -1
  44. package/dist/components/forms/kt-calendar/kt-calendar.d.ts +35 -9
  45. package/dist/components/forms/kt-calendar/kt-calendar.js +3 -3
  46. package/dist/components/forms/kt-checkbox/kt-checkbox.js +2 -2
  47. package/dist/components/forms/kt-date-input/kt-date-input.d.ts +65 -0
  48. package/dist/components/forms/kt-date-input/kt-date-input.js +241 -0
  49. package/dist/components/forms/kt-date-input/kt-date-input.js.map +1 -0
  50. package/dist/components/forms/kt-date-picker/kt-date-picker.d.ts +47 -3
  51. package/dist/components/forms/kt-date-picker/kt-date-picker.js +430 -199
  52. package/dist/components/forms/kt-date-picker/kt-date-picker.js.map +1 -1
  53. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +3 -3
  54. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -1
  55. package/dist/components/forms/kt-form/kt-form.js +2 -2
  56. package/dist/components/forms/kt-input/kt-input.js +10 -10
  57. package/dist/components/forms/kt-input/kt-input.js.map +1 -1
  58. package/dist/components/forms/kt-input-menu/kt-input-menu.js +4 -4
  59. package/dist/components/forms/kt-label-input/kt-label-input.js +1 -1
  60. package/dist/components/forms/kt-multi-select/kt-multi-select.d.ts +113 -0
  61. package/dist/components/forms/kt-multi-select/kt-multi-select.js +532 -0
  62. package/dist/components/forms/kt-multi-select/kt-multi-select.js.map +1 -0
  63. package/dist/components/forms/kt-radio-group/kt-radio-group.js +56 -51
  64. package/dist/components/forms/kt-radio-group/kt-radio-group.js.map +1 -1
  65. package/dist/components/forms/kt-select/kt-select.js +4 -4
  66. package/dist/components/forms/kt-textarea/kt-textarea.js +2 -2
  67. package/dist/components/forms/kt-time-input/kt-time-input.d.ts +48 -0
  68. package/dist/components/forms/kt-time-input/kt-time-input.js +114 -0
  69. package/dist/components/forms/kt-time-input/kt-time-input.js.map +1 -0
  70. package/dist/components/forms/kt-toggle/kt-toggle.js +1 -1
  71. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +6 -6
  72. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js.map +1 -1
  73. package/dist/components/navigation/kt-header/kt-header.js +2 -2
  74. package/dist/components/navigation/kt-page-header/kt-page-header.js +1 -1
  75. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +2 -2
  76. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +2 -2
  77. package/dist/components/navigation/kt-tabs/kt-tabs.js +2 -2
  78. package/dist/components/navigation/kt-tabs/kt-tabs.js.map +1 -1
  79. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +1 -1
  80. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +2 -2
  81. package/dist/components/overlays/kt-collapsible/kt-collapsible.js +3 -3
  82. package/dist/components/overlays/kt-collapsible/kt-collapsible.js.map +1 -1
  83. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +2 -2
  84. package/dist/components/overlays/kt-dropdown/kt-dropdown.js +24 -24
  85. package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -1
  86. package/dist/components/overlays/kt-modal/kt-modal.js +2 -2
  87. package/dist/components/overlays/kt-side-panel/kt-side-panel.js +2 -2
  88. package/dist/custom-elements.json +2230 -842
  89. package/dist/index.d.ts +9 -1
  90. package/dist/index.js +316 -109
  91. package/dist/index.js.map +1 -1
  92. package/dist/internal/floating.d.ts +3 -0
  93. package/dist/internal/segmented-field.d.ts +114 -0
  94. package/dist/internal/segments.d.ts +30 -0
  95. package/dist/internal/strings.d.ts +30 -0
  96. package/dist/internal/typed-date.d.ts +33 -0
  97. package/dist/react/index.d.ts +23 -0
  98. package/dist/react/index.js +193 -169
  99. package/dist/react/index.js.map +1 -1
  100. package/dist/react/jsx.d.ts +20 -1
  101. package/dist/strings/index.js +1 -1
  102. package/dist/theme/accent.d.ts +51 -0
  103. package/dist/theme/appearance.d.ts +37 -0
  104. package/dist/tokens/README.md +100 -1
  105. package/dist/tokens/accents.css +80 -0
  106. package/dist/tokens/appearance.css +65 -0
  107. package/dist/tokens/base.css +3 -0
  108. package/dist/tokens/colors.css +78 -25
  109. package/dist/tokens/index.css +2 -0
  110. package/dist/tokens/responsive.css +160 -75
  111. package/dist/tokens/spacing.css +47 -28
  112. package/dist/tokens/theme-light.css +124 -38
  113. package/dist/tokens/typography.css +20 -13
  114. package/dist/vscode.css-custom-data.json +36 -1
  115. package/dist/vscode.html-custom-data.json +67 -2
  116. package/dist/vue/index.d.ts +6 -0
  117. package/dist/vue/index.js +11 -8
  118. package/dist/vue/index.js.map +1 -1
  119. package/dist/web-types.json +190 -3
  120. package/package.json +13 -1
  121. package/dist/chunks/floating-B7_Dahpn.js +0 -54
  122. package/dist/chunks/floating-B7_Dahpn.js.map +0 -1
  123. package/dist/chunks/index-STEEvEP7.js.map +0 -1
  124. package/dist/chunks/kt-calendar-B_hFdD9V.js +0 -640
  125. package/dist/chunks/kt-calendar-B_hFdD9V.js.map +0 -1
@@ -1,10 +1,10 @@
1
- import { css as b, nothing as d, html as p } from "lit";
2
- import { property as a, queryAssignedElements as y, state as m } from "lit/decorators.js";
3
- import { K as u, d as v } from "../../../chunks/kt-element-Djx2JcGl.js";
4
- import { e as g } from "../../../chunks/events-r51msXNf.js";
1
+ import { css as f, nothing as d, html as p } from "lit";
2
+ import { property as i, queryAssignedElements as y, state as g } from "lit/decorators.js";
3
+ import { K as u, d as v } from "../../../chunks/kt-element-T0VbIBNp.js";
4
+ import { e as m } from "../../../chunks/events-r51msXNf.js";
5
5
  import { a as k, s as w, b as x } from "../../../chunks/form-control-B74_EHtG.js";
6
- import { s as f } from "../../../chunks/index-STEEvEP7.js";
7
- var D = Object.defineProperty, i = (c, e, t, l) => {
6
+ import { s as b } from "../../../chunks/index-TWJzttLX.js";
7
+ var D = Object.defineProperty, a = (c, e, t, l) => {
8
8
  for (var r = void 0, o = c.length - 1, h; o >= 0; o--)
9
9
  (h = c[o]) && (r = h(e, t, r) || r);
10
10
  return r && D(e, t, r), r;
@@ -16,10 +16,14 @@ class n extends u {
16
16
  static {
17
17
  this.styles = [
18
18
  u.styles,
19
- b`
19
+ f`
20
20
  :host {
21
21
  display: block;
22
- --radio-size: calc(var(--button-height) * 0.45);
22
+ /* Whole, even pixels: an even circle around an even dot leaves the
23
+ same whole number of pixels on each side, so no browser has a half
24
+ to round its own way. */
25
+ --radio-size: round(nearest, calc(var(--button-height) * 0.45), 2px);
26
+ --radio-dot: 8px;
23
27
  }
24
28
 
25
29
  .radio {
@@ -33,7 +37,8 @@ class n extends u {
33
37
  }
34
38
 
35
39
  .circle {
36
- position: relative;
40
+ display: grid;
41
+ place-items: center;
37
42
  flex: none;
38
43
  width: var(--radio-size);
39
44
  height: var(--radio-size);
@@ -44,11 +49,11 @@ class n extends u {
44
49
  transition: border-color var(--duration-instant);
45
50
  }
46
51
 
47
- /* The dot: a fill inset by a third of the circle. */
48
- .circle::after {
49
- content: '';
50
- position: absolute;
51
- inset: 22%;
52
+ /* The dot, centred by the circle's grid rather than inset by a
53
+ percentage, which landed it on fractions of a pixel. */
54
+ .dot {
55
+ width: var(--radio-dot);
56
+ height: var(--radio-dot);
52
57
  border-radius: var(--radius-full);
53
58
  background-color: var(--color-primary-base);
54
59
  transform: scale(0);
@@ -67,7 +72,7 @@ class n extends u {
67
72
  .radio[aria-checked='true'] .circle {
68
73
  border-color: var(--color-primary-base);
69
74
  }
70
- .radio[aria-checked='true'] .circle::after {
75
+ .radio[aria-checked='true'] .dot {
71
76
  transform: scale(1);
72
77
  }
73
78
 
@@ -85,8 +90,8 @@ class n extends u {
85
90
  background-color: var(--color-dark-22);
86
91
  border-color: var(--color-dark-24);
87
92
  }
88
- :host([disabled]) .circle::after,
89
- :host([group-disabled]) .circle::after {
93
+ :host([disabled]) .dot,
94
+ :host([group-disabled]) .dot {
90
95
  background-color: var(--text-disabled);
91
96
  }
92
97
  `
@@ -107,28 +112,28 @@ class n extends u {
107
112
  aria-disabled=${this.inactive ? "true" : d}
108
113
  tabindex=${this.tabbable && !this.inactive ? 0 : -1}
109
114
  >
110
- <span part="circle" class="circle"></span>
115
+ <span part="circle" class="circle"><span class="dot"></span></span>
111
116
  <span class="text"><slot></slot></span>
112
117
  </div>`;
113
118
  }
114
119
  }
115
- i([
116
- a({ type: String, reflect: !0 })
120
+ a([
121
+ i({ type: String, reflect: !0 })
117
122
  ], n.prototype, "value");
118
- i([
119
- a({ type: Boolean, reflect: !0 })
123
+ a([
124
+ i({ type: Boolean, reflect: !0 })
120
125
  ], n.prototype, "disabled");
121
- i([
122
- a({ type: Boolean, reflect: !0 })
126
+ a([
127
+ i({ type: Boolean, reflect: !0 })
123
128
  ], n.prototype, "checked");
124
- i([
125
- a({ type: Boolean, attribute: !1 })
129
+ a([
130
+ i({ type: Boolean, attribute: !1 })
126
131
  ], n.prototype, "tabbable");
127
- i([
128
- a({ type: Boolean, reflect: !0 })
132
+ a([
133
+ i({ type: Boolean, reflect: !0 })
129
134
  ], n.prototype, "invalid");
130
- i([
131
- a({ type: Boolean, reflect: !0, attribute: "group-disabled" })
135
+ a([
136
+ i({ type: Boolean, reflect: !0, attribute: "group-disabled" })
132
137
  ], n.prototype, "groupDisabled");
133
138
  class s extends u {
134
139
  constructor() {
@@ -161,7 +166,7 @@ class s extends u {
161
166
  static {
162
167
  this.styles = [
163
168
  u.styles,
164
- b`
169
+ f`
165
170
  :host {
166
171
  display: block;
167
172
  }
@@ -197,7 +202,7 @@ class s extends u {
197
202
  x(
198
203
  this.internals,
199
204
  { valueMissing: t, customError: !!this.error },
200
- this.error || (t ? f().selectOption : "")
205
+ this.error || (t ? b().selectOption : "")
201
206
  );
202
207
  }
203
208
  }
@@ -224,7 +229,7 @@ class s extends u {
224
229
  return this.inactive ? [] : this.radios.filter((e) => !e.disabled);
225
230
  }
226
231
  choose(e) {
227
- e.value !== this.value && (this.value = e.value, g(this, "kt-change", { value: this.value }));
232
+ e.value !== this.value && (this.value = e.value, m(this, "kt-change", { value: this.value }));
228
233
  }
229
234
  render() {
230
235
  return p`${this.error ? p`<span id="error-message" class="visually-hidden">${this.error}</span>` : d}
@@ -232,7 +237,7 @@ class s extends u {
232
237
  part="base"
233
238
  class="group"
234
239
  role="radiogroup"
235
- aria-label=${this.label || f().options}
240
+ aria-label=${this.label || b().options}
236
241
  aria-orientation=${this.orientation}
237
242
  aria-required=${this.required ? "true" : d}
238
243
  aria-invalid=${this.error ? "true" : d}
@@ -243,32 +248,32 @@ class s extends u {
243
248
  </div>`;
244
249
  }
245
250
  }
246
- i([
251
+ a([
247
252
  y({ selector: "kt-radio" })
248
253
  ], s.prototype, "radios");
249
- i([
250
- a({ type: String, reflect: !0 })
254
+ a([
255
+ i({ type: String, reflect: !0 })
251
256
  ], s.prototype, "value");
252
- i([
253
- a({ type: String })
257
+ a([
258
+ i({ type: String })
254
259
  ], s.prototype, "name");
255
- i([
256
- a({ type: String })
260
+ a([
261
+ i({ type: String })
257
262
  ], s.prototype, "label");
258
- i([
259
- a({ type: Boolean, reflect: !0 })
263
+ a([
264
+ i({ type: Boolean, reflect: !0 })
260
265
  ], s.prototype, "disabled");
261
- i([
262
- m()
266
+ a([
267
+ g()
263
268
  ], s.prototype, "formDisabled");
264
- i([
265
- a({ type: Boolean, reflect: !0 })
269
+ a([
270
+ i({ type: Boolean, reflect: !0 })
266
271
  ], s.prototype, "required");
267
- i([
268
- a({ type: String, reflect: !0 })
272
+ a([
273
+ i({ type: String, reflect: !0 })
269
274
  ], s.prototype, "orientation");
270
- i([
271
- a({ type: String, reflect: !0 })
275
+ a([
276
+ i({ type: String, reflect: !0 })
272
277
  ], s.prototype, "error");
273
278
  v("kt-radio", n);
274
279
  v("kt-radio-group", s);
@@ -1 +1 @@
1
- {"version":3,"file":"kt-radio-group.js","sources":["../../../../src/components/forms/kt-radio-group/kt-radio-group.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, queryAssignedElements, state } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport { strings } from '#internal/strings';\n\nexport type KtRadioGroupOrientation = 'vertical' | 'horizontal';\n\n/**\n * One option of a `<kt-radio-group>`.\n *\n * It draws itself and carries `role=\"radio\"`; the group owns the selection,\n * the tab stop and the keyboard. A `<kt-radio>` outside a group does nothing\n * useful.\n *\n * @element kt-radio\n *\n * @slot - The label.\n *\n * @csspart base - The `role=\"radio\"` row.\n * @csspart circle - The drawn circle.\n */\nexport class KtRadio extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n --radio-size: calc(var(--button-height) * 0.45);\n }\n\n .radio {\n display: inline-flex;\n align-items: flex-start;\n gap: var(--gap-button);\n color: var(--text-body);\n font: var(--font-normal-regular);\n outline: none;\n cursor: pointer;\n }\n\n .circle {\n position: relative;\n flex: none;\n width: var(--radio-size);\n height: var(--radio-size);\n margin-top: calc((1lh - var(--radio-size)) / 2);\n background-color: var(--surface-field);\n border: var(--border-width) solid var(--border-field);\n border-radius: var(--radius-full);\n transition: border-color var(--duration-instant);\n }\n\n /* The dot: a fill inset by a third of the circle. */\n .circle::after {\n content: '';\n position: absolute;\n inset: 22%;\n border-radius: var(--radius-full);\n background-color: var(--color-primary-base);\n transform: scale(0);\n transition: transform var(--duration-fast);\n }\n\n .radio:hover .circle {\n border-color: var(--text-muted);\n }\n\n .radio:focus-visible .circle {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 2px;\n }\n\n .radio[aria-checked='true'] .circle {\n border-color: var(--color-primary-base);\n }\n .radio[aria-checked='true'] .circle::after {\n transform: scale(1);\n }\n\n :host([invalid]) .circle {\n border-color: var(--color-danger-base);\n }\n\n :host([disabled]) .radio,\n :host([group-disabled]) .radio {\n color: var(--text-disabled);\n cursor: not-allowed;\n }\n :host([disabled]) .circle,\n :host([group-disabled]) .circle {\n background-color: var(--color-dark-22);\n border-color: var(--color-dark-24);\n }\n :host([disabled]) .circle::after,\n :host([group-disabled]) .circle::after {\n background-color: var(--text-disabled);\n }\n `,\n ];\n\n /** Submitted by the group when this option is chosen. */\n @property({ type: String, reflect: true })\n value = '';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /** Set by the group. */\n @property({ type: Boolean, reflect: true })\n checked = false;\n\n /** Set by the group: whether this option holds the group's one tab stop. */\n @property({ type: Boolean, attribute: false })\n tabbable = false;\n\n /** Set by the group while it reports an error. */\n @property({ type: Boolean, reflect: true })\n invalid = false;\n\n /** Set by the group while the whole group is disabled. */\n @property({ type: Boolean, reflect: true, attribute: 'group-disabled' })\n groupDisabled = false;\n\n private get inactive(): boolean {\n return this.disabled || this.groupDisabled;\n }\n\n override focus(options?: FocusOptions): void {\n this.shadowRoot?.querySelector<HTMLElement>('.radio')?.focus(options);\n }\n\n override render(): TemplateResult {\n return html`<div\n part=\"base\"\n class=\"radio\"\n role=\"radio\"\n aria-checked=${this.checked ? 'true' : 'false'}\n aria-disabled=${this.inactive ? 'true' : nothing}\n tabindex=${this.tabbable && !this.inactive ? 0 : -1}\n >\n <span part=\"circle\" class=\"circle\"></span>\n <span class=\"text\"><slot></slot></span>\n </div>`;\n }\n}\n\n/**\n * One choice among a few, all visible at once.\n *\n * Reach for it over `<kt-select>` when there are few enough options to show\n * them all — seeing every option is the point — and over\n * `<kt-segmented-control>` when the options need a sentence each, or the\n * choice belongs in a form rather than a toolbar.\n *\n * Native radios cannot form a group across shadow roots, so this is the ARIA\n * radio group pattern: one tab stop for the whole group, arrow keys move and\n * select, disabled options are skipped.\n *\n * @element kt-radio-group\n *\n * @slot - The `<kt-radio>` options.\n *\n * @csspart base - The `role=\"radiogroup\"` container.\n *\n * @fires kt-change - An option was chosen. `detail: { value }`.\n *\n * @example\n * ```html\n * <kt-radio-group label=\"Billing\" name=\"billing\" value=\"monthly\">\n * <kt-radio value=\"monthly\">Monthly</kt-radio>\n * <kt-radio value=\"yearly\">Yearly — two months free</kt-radio>\n * </kt-radio-group>\n * ```\n */\nexport class KtRadioGroup extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n .group {\n display: flex;\n flex-direction: column;\n gap: var(--gap-element);\n }\n\n :host([orientation='horizontal']) .group {\n flex-direction: row;\n flex-wrap: wrap;\n column-gap: var(--gap-card);\n }\n `,\n ];\n\n @queryAssignedElements({ selector: 'kt-radio' })\n private radios!: KtRadio[];\n\n private internals: UsableInternals | null = null;\n private defaultValue: string | null = null;\n\n /** The chosen option's value, or `null`. */\n @property({ type: String, reflect: true })\n value: string | null = null;\n\n @property({ type: String })\n name = '';\n\n /** Accessible name of the group. */\n @property({ type: String })\n label = '';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /** Disabled by an enclosing `<fieldset>`, which leaves `disabled` alone. */\n @state()\n private formDisabled = false;\n\n /** Whether the control is off, by its own `disabled` or by its form. */\n private get inactive(): boolean {\n return this.disabled || this.formDisabled;\n }\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n @property({ type: String, reflect: true })\n orientation: KtRadioGroupOrientation = 'vertical';\n\n /** Error message. A non-empty value puts the group in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n // On the host: the radios are slotted light-DOM children.\n this.addEventListener('click', this.onClick);\n this.addEventListener('keydown', this.onKeyDown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('click', this.onClick);\n this.removeEventListener('keydown', this.onKeyDown);\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('value') ||\n changed.has('required') ||\n changed.has('error') ||\n this.stringsChanged(changed)\n ) {\n setFormValue(this.internals, this.value);\n\n const missing = this.required && this.value === null;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? strings().selectOption : ''),\n );\n }\n }\n\n override updated(): void {\n this.syncRadios();\n }\n\n formResetCallback(): void {\n this.value = this.defaultValue;\n }\n\n /**\n * Called by the platform when the control's disabled state changes — its\n * own `disabled`, or an ancestor `<fieldset disabled>` it cannot see.\n */\n formDisabledCallback(disabled: boolean): void {\n this.formDisabled = disabled;\n }\n\n formStateRestoreCallback(state: string | null): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.radios.find((radio) => radio.tabbable)?.focus(options);\n }\n\n private enabled(): KtRadio[] {\n return this.inactive ? [] : this.radios.filter((radio) => !radio.disabled);\n }\n\n /**\n * Pushes the group's state down; the radios are the display, not the truth.\n * The tab stop sits on the chosen option, or the first enabled one.\n */\n private syncRadios = (): void => {\n const enabled = this.enabled();\n const chosen = enabled.find((radio) => radio.value === this.value);\n const tabStop = chosen ?? enabled[0];\n\n for (const radio of this.radios) {\n radio.checked = radio.value === this.value;\n radio.tabbable = radio === tabStop;\n radio.invalid = Boolean(this.error);\n radio.groupDisabled = this.inactive;\n }\n };\n\n private choose(radio: KtRadio): void {\n if (radio.value === this.value) return;\n this.value = radio.value;\n emit(this, 'kt-change', { value: this.value });\n }\n\n private onClick = (event: Event): void => {\n const radio = event.composedPath().find((node): node is KtRadio => node instanceof KtRadio);\n if (!radio || !this.enabled().includes(radio)) return;\n this.choose(radio);\n radio.focus();\n };\n\n /** Arrows move and select, wrapping; Space selects the focused option. */\n private onKeyDown = (event: KeyboardEvent): void => {\n const enabled = this.enabled();\n if (enabled.length === 0) return;\n\n const focused = event.composedPath().find((node): node is KtRadio => node instanceof KtRadio);\n const from = focused ? enabled.indexOf(focused) : -1;\n\n let target: KtRadio | undefined;\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n target = enabled[(from + 1) % enabled.length];\n } else if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n target = enabled[(from - 1 + enabled.length) % enabled.length];\n } else if (event.key === ' ' && focused && from >= 0) {\n target = focused;\n } else {\n return;\n }\n\n event.preventDefault();\n if (!target) return;\n this.choose(target);\n void this.updateComplete.then(() => target.focus());\n };\n\n override render(): TemplateResult {\n return html`${\n this.error\n ? html`<span id=\"error-message\" class=\"visually-hidden\">${this.error}</span>`\n : nothing\n }\n <div\n part=\"base\"\n class=\"group\"\n role=\"radiogroup\"\n aria-label=${this.label || strings().options}\n aria-orientation=${this.orientation}\n aria-required=${this.required ? 'true' : nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n aria-disabled=${this.inactive ? 'true' : nothing}\n aria-describedby=${this.error ? 'error-message' : nothing}\n >\n <slot @slotchange=${this.syncRadios}></slot>\n </div>`;\n }\n}\n\ndefineElement('kt-radio', KtRadio);\ndefineElement('kt-radio-group', KtRadioGroup);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-radio': KtRadio;\n 'kt-radio-group': KtRadioGroup;\n }\n}\n"],"names":["KtRadio","KtElement","css","options","html","nothing","__decorateClass","property","KtRadioGroup","enabled","tabStop","radio","event","node","focused","from","target","attachFormInternals","changed","setFormValue","missing","setValidity","strings","disabled","state","emit","queryAssignedElements","defineElement"],"mappings":"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"}
1
+ {"version":3,"file":"kt-radio-group.js","sources":["../../../../src/components/forms/kt-radio-group/kt-radio-group.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, queryAssignedElements, state } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport { strings } from '#internal/strings';\n\nexport type KtRadioGroupOrientation = 'vertical' | 'horizontal';\n\n/**\n * One option of a `<kt-radio-group>`.\n *\n * It draws itself and carries `role=\"radio\"`; the group owns the selection,\n * the tab stop and the keyboard. A `<kt-radio>` outside a group does nothing\n * useful.\n *\n * @element kt-radio\n *\n * @slot - The label.\n *\n * @csspart base - The `role=\"radio\"` row.\n * @csspart circle - The drawn circle.\n */\nexport class KtRadio extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n /* Whole, even pixels: an even circle around an even dot leaves the\n same whole number of pixels on each side, so no browser has a half\n to round its own way. */\n --radio-size: round(nearest, calc(var(--button-height) * 0.45), 2px);\n --radio-dot: 8px;\n }\n\n .radio {\n display: inline-flex;\n align-items: flex-start;\n gap: var(--gap-button);\n color: var(--text-body);\n font: var(--font-normal-regular);\n outline: none;\n cursor: pointer;\n }\n\n .circle {\n display: grid;\n place-items: center;\n flex: none;\n width: var(--radio-size);\n height: var(--radio-size);\n margin-top: calc((1lh - var(--radio-size)) / 2);\n background-color: var(--surface-field);\n border: var(--border-width) solid var(--border-field);\n border-radius: var(--radius-full);\n transition: border-color var(--duration-instant);\n }\n\n /* The dot, centred by the circle's grid rather than inset by a\n percentage, which landed it on fractions of a pixel. */\n .dot {\n width: var(--radio-dot);\n height: var(--radio-dot);\n border-radius: var(--radius-full);\n background-color: var(--color-primary-base);\n transform: scale(0);\n transition: transform var(--duration-fast);\n }\n\n .radio:hover .circle {\n border-color: var(--text-muted);\n }\n\n .radio:focus-visible .circle {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 2px;\n }\n\n .radio[aria-checked='true'] .circle {\n border-color: var(--color-primary-base);\n }\n .radio[aria-checked='true'] .dot {\n transform: scale(1);\n }\n\n :host([invalid]) .circle {\n border-color: var(--color-danger-base);\n }\n\n :host([disabled]) .radio,\n :host([group-disabled]) .radio {\n color: var(--text-disabled);\n cursor: not-allowed;\n }\n :host([disabled]) .circle,\n :host([group-disabled]) .circle {\n background-color: var(--color-dark-22);\n border-color: var(--color-dark-24);\n }\n :host([disabled]) .dot,\n :host([group-disabled]) .dot {\n background-color: var(--text-disabled);\n }\n `,\n ];\n\n /** Submitted by the group when this option is chosen. */\n @property({ type: String, reflect: true })\n value = '';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /** Set by the group. */\n @property({ type: Boolean, reflect: true })\n checked = false;\n\n /** Set by the group: whether this option holds the group's one tab stop. */\n @property({ type: Boolean, attribute: false })\n tabbable = false;\n\n /** Set by the group while it reports an error. */\n @property({ type: Boolean, reflect: true })\n invalid = false;\n\n /** Set by the group while the whole group is disabled. */\n @property({ type: Boolean, reflect: true, attribute: 'group-disabled' })\n groupDisabled = false;\n\n private get inactive(): boolean {\n return this.disabled || this.groupDisabled;\n }\n\n override focus(options?: FocusOptions): void {\n this.shadowRoot?.querySelector<HTMLElement>('.radio')?.focus(options);\n }\n\n override render(): TemplateResult {\n return html`<div\n part=\"base\"\n class=\"radio\"\n role=\"radio\"\n aria-checked=${this.checked ? 'true' : 'false'}\n aria-disabled=${this.inactive ? 'true' : nothing}\n tabindex=${this.tabbable && !this.inactive ? 0 : -1}\n >\n <span part=\"circle\" class=\"circle\"><span class=\"dot\"></span></span>\n <span class=\"text\"><slot></slot></span>\n </div>`;\n }\n}\n\n/**\n * One choice among a few, all visible at once.\n *\n * Reach for it over `<kt-select>` when there are few enough options to show\n * them all — seeing every option is the point — and over\n * `<kt-segmented-control>` when the options need a sentence each, or the\n * choice belongs in a form rather than a toolbar.\n *\n * Native radios cannot form a group across shadow roots, so this is the ARIA\n * radio group pattern: one tab stop for the whole group, arrow keys move and\n * select, disabled options are skipped.\n *\n * @element kt-radio-group\n *\n * @slot - The `<kt-radio>` options.\n *\n * @csspart base - The `role=\"radiogroup\"` container.\n *\n * @fires kt-change - An option was chosen. `detail: { value }`.\n *\n * @example\n * ```html\n * <kt-radio-group label=\"Billing\" name=\"billing\" value=\"monthly\">\n * <kt-radio value=\"monthly\">Monthly</kt-radio>\n * <kt-radio value=\"yearly\">Yearly — two months free</kt-radio>\n * </kt-radio-group>\n * ```\n */\nexport class KtRadioGroup extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n .group {\n display: flex;\n flex-direction: column;\n gap: var(--gap-element);\n }\n\n :host([orientation='horizontal']) .group {\n flex-direction: row;\n flex-wrap: wrap;\n column-gap: var(--gap-card);\n }\n `,\n ];\n\n @queryAssignedElements({ selector: 'kt-radio' })\n private radios!: KtRadio[];\n\n private internals: UsableInternals | null = null;\n private defaultValue: string | null = null;\n\n /** The chosen option's value, or `null`. */\n @property({ type: String, reflect: true })\n value: string | null = null;\n\n @property({ type: String })\n name = '';\n\n /** Accessible name of the group. */\n @property({ type: String })\n label = '';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /** Disabled by an enclosing `<fieldset>`, which leaves `disabled` alone. */\n @state()\n private formDisabled = false;\n\n /** Whether the control is off, by its own `disabled` or by its form. */\n private get inactive(): boolean {\n return this.disabled || this.formDisabled;\n }\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n @property({ type: String, reflect: true })\n orientation: KtRadioGroupOrientation = 'vertical';\n\n /** Error message. A non-empty value puts the group in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n // On the host: the radios are slotted light-DOM children.\n this.addEventListener('click', this.onClick);\n this.addEventListener('keydown', this.onKeyDown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('click', this.onClick);\n this.removeEventListener('keydown', this.onKeyDown);\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('value') ||\n changed.has('required') ||\n changed.has('error') ||\n this.stringsChanged(changed)\n ) {\n setFormValue(this.internals, this.value);\n\n const missing = this.required && this.value === null;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? strings().selectOption : ''),\n );\n }\n }\n\n override updated(): void {\n this.syncRadios();\n }\n\n formResetCallback(): void {\n this.value = this.defaultValue;\n }\n\n /**\n * Called by the platform when the control's disabled state changes — its\n * own `disabled`, or an ancestor `<fieldset disabled>` it cannot see.\n */\n formDisabledCallback(disabled: boolean): void {\n this.formDisabled = disabled;\n }\n\n formStateRestoreCallback(state: string | null): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.radios.find((radio) => radio.tabbable)?.focus(options);\n }\n\n private enabled(): KtRadio[] {\n return this.inactive ? [] : this.radios.filter((radio) => !radio.disabled);\n }\n\n /**\n * Pushes the group's state down; the radios are the display, not the truth.\n * The tab stop sits on the chosen option, or the first enabled one.\n */\n private syncRadios = (): void => {\n const enabled = this.enabled();\n const chosen = enabled.find((radio) => radio.value === this.value);\n const tabStop = chosen ?? enabled[0];\n\n for (const radio of this.radios) {\n radio.checked = radio.value === this.value;\n radio.tabbable = radio === tabStop;\n radio.invalid = Boolean(this.error);\n radio.groupDisabled = this.inactive;\n }\n };\n\n private choose(radio: KtRadio): void {\n if (radio.value === this.value) return;\n this.value = radio.value;\n emit(this, 'kt-change', { value: this.value });\n }\n\n private onClick = (event: Event): void => {\n const radio = event.composedPath().find((node): node is KtRadio => node instanceof KtRadio);\n if (!radio || !this.enabled().includes(radio)) return;\n this.choose(radio);\n radio.focus();\n };\n\n /** Arrows move and select, wrapping; Space selects the focused option. */\n private onKeyDown = (event: KeyboardEvent): void => {\n const enabled = this.enabled();\n if (enabled.length === 0) return;\n\n const focused = event.composedPath().find((node): node is KtRadio => node instanceof KtRadio);\n const from = focused ? enabled.indexOf(focused) : -1;\n\n let target: KtRadio | undefined;\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n target = enabled[(from + 1) % enabled.length];\n } else if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n target = enabled[(from - 1 + enabled.length) % enabled.length];\n } else if (event.key === ' ' && focused && from >= 0) {\n target = focused;\n } else {\n return;\n }\n\n event.preventDefault();\n if (!target) return;\n this.choose(target);\n void this.updateComplete.then(() => target.focus());\n };\n\n override render(): TemplateResult {\n return html`${\n this.error\n ? html`<span id=\"error-message\" class=\"visually-hidden\">${this.error}</span>`\n : nothing\n }\n <div\n part=\"base\"\n class=\"group\"\n role=\"radiogroup\"\n aria-label=${this.label || strings().options}\n aria-orientation=${this.orientation}\n aria-required=${this.required ? 'true' : nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n aria-disabled=${this.inactive ? 'true' : nothing}\n aria-describedby=${this.error ? 'error-message' : nothing}\n >\n <slot @slotchange=${this.syncRadios}></slot>\n </div>`;\n }\n}\n\ndefineElement('kt-radio', KtRadio);\ndefineElement('kt-radio-group', KtRadioGroup);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-radio': KtRadio;\n 'kt-radio-group': KtRadioGroup;\n }\n}\n"],"names":["KtRadio","KtElement","css","options","html","nothing","__decorateClass","property","KtRadioGroup","enabled","tabStop","radio","event","node","focused","from","target","attachFormInternals","changed","setFormValue","missing","setValidity","strings","disabled","state","emit","queryAssignedElements","defineElement"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import { css as x, nothing as n, html as h } from "lit";
2
2
  import { state as p, property as s } from "lit/decorators.js";
3
3
  import { classMap as d } from "lit/directives/class-map.js";
4
- import { K as v, d as w } from "../../../chunks/kt-element-Djx2JcGl.js";
4
+ import { K as v, d as w } from "../../../chunks/kt-element-T0VbIBNp.js";
5
5
  import { u as k, t as g, e as m } from "../../../chunks/events-r51msXNf.js";
6
6
  import { a as $, s as I, b as D } from "../../../chunks/form-control-B74_EHtG.js";
7
- import { a as S, f as b, l as L, n as C, o as y } from "../../../chunks/listbox-llcUu_V-.js";
8
- import { F as E, f as P } from "../../../chunks/floating-B7_Dahpn.js";
9
- import { s as l } from "../../../chunks/index-STEEvEP7.js";
7
+ import { a as S, f as b, l as L, n as C, o as y } from "../../../chunks/listbox-LsUEyGhQ.js";
8
+ import { F as E, f as P } from "../../../chunks/floating-B33g-M_1.js";
9
+ import { s as l } from "../../../chunks/index-TWJzttLX.js";
10
10
  import "../../core/kt-icon/kt-icon.js";
11
11
  var q = Object.defineProperty, i = (c, e, o, a) => {
12
12
  for (var r = void 0, u = c.length - 1, f; u >= 0; u--)
@@ -2,10 +2,10 @@ import { css as m, nothing as i, html as l } from "lit";
2
2
  import { query as f, property as a, state as b } from "lit/decorators.js";
3
3
  import { classMap as u } from "lit/directives/class-map.js";
4
4
  import { live as g } from "lit/directives/live.js";
5
- import { K as c, d as y } from "../../../chunks/kt-element-Djx2JcGl.js";
5
+ import { K as c, d as y } from "../../../chunks/kt-element-T0VbIBNp.js";
6
6
  import { e as p } from "../../../chunks/events-r51msXNf.js";
7
7
  import { a as x, s as v, b as w } from "../../../chunks/form-control-B74_EHtG.js";
8
- import { s as $ } from "../../../chunks/index-STEEvEP7.js";
8
+ import { s as $ } from "../../../chunks/index-TWJzttLX.js";
9
9
  import "../../core/kt-icon/kt-icon.js";
10
10
  var k = Object.defineProperty, r = (n, e, o, C) => {
11
11
  for (var s = void 0, h = n.length - 1, d; h >= 0; h--)
@@ -0,0 +1,48 @@
1
+ import { type PropertyValues } from 'lit';
2
+ import { KtSegmentedField, type FieldItem, type Segment } from '#internal/segmented-field';
3
+ export type KtHourCycle = 'h12' | 'h23';
4
+ /**
5
+ * A time of day typed into its parts: hours, minutes and, if asked, seconds.
6
+ *
7
+ * The clock is the reader's — `14:30` in London, `2:30 PM` in New York — or
8
+ * the one `hour-cycle` names. Whatever the clock shows, the value is the
9
+ * 24-hour time HTML uses, `14:30` or `14:30:00`, and `null` until complete.
10
+ * The arrows step a segment, the minutes by `step`.
11
+ *
12
+ * @element kt-time-input
13
+ *
14
+ * @csspart field - The field.
15
+ * @csspart segment - An hour, minute, second or AM/PM segment.
16
+ *
17
+ * @fires kt-change - The time became complete, changed, or stopped being one.
18
+ * `detail: { value }` — `HH:MM`, `HH:MM:SS` or `null`.
19
+ *
20
+ * @example
21
+ * ```html
22
+ * <kt-time-input label="Starts at" name="start" step="15" min="08:00" max="20:00"></kt-time-input>
23
+ * ```
24
+ */
25
+ export declare class KtTimeInput extends KtSegmentedField {
26
+ /** Shows a seconds segment, and puts seconds in the value. */
27
+ seconds: boolean;
28
+ /** The clock to show: `h12` with AM/PM, `h23` without. Empty: the language's. */
29
+ hourCycle: KtHourCycle | '';
30
+ /** How many minutes the arrows step by. */
31
+ step: number;
32
+ private get twelve();
33
+ willUpdate(changed: PropertyValues<this>): void;
34
+ protected items(): FieldItem[];
35
+ protected fill(value: string | null): Record<string, string>;
36
+ protected read(texts: Record<string, string>): {
37
+ value: string | null;
38
+ error: string;
39
+ };
40
+ /** A number left at one digit is written out: 9 is 09. */
41
+ protected completeOnBlur(segment: Segment, text: string): string | null;
42
+ protected requiredMessage(): string;
43
+ }
44
+ declare global {
45
+ interface HTMLElementTagNameMap {
46
+ 'kt-time-input': KtTimeInput;
47
+ }
48
+ }
@@ -0,0 +1,114 @@
1
+ import "lit";
2
+ import { property as v } from "lit/decorators.js";
3
+ import { d as x } from "../../../chunks/kt-element-T0VbIBNp.js";
4
+ import { K as O } from "../../../chunks/segmented-field-BBXR4XFL.js";
5
+ import { d as w } from "../../../chunks/locale-C5xLkGx5.js";
6
+ import { s as y } from "../../../chunks/index-TWJzttLX.js";
7
+ var P = Object.defineProperty, g = (u, e, t, r) => {
8
+ for (var o = void 0, n = u.length - 1, s; n >= 0; n--)
9
+ (s = u[n]) && (o = s(e, t, o) || o);
10
+ return o && P(e, t, o), o;
11
+ };
12
+ function b(u, e) {
13
+ const t = w(u, {
14
+ hour: "2-digit",
15
+ minute: "2-digit",
16
+ hourCycle: e ? "h12" : "h23"
17
+ }), r = t.formatToParts(new Date(2026, 0, 1, 1, 5)), o = r.map((i) => i.type), n = r.find((i) => i.type === "literal")?.value.trim() || ":", s = (i) => t.formatToParts(new Date(2026, 0, 1, i)).find((l) => l.type === "dayPeriod")?.value ?? (i < 12 ? "AM" : "PM");
18
+ return {
19
+ separator: n === "." ? "." : ":",
20
+ periodFirst: o.indexOf("dayPeriod") >= 0 && o.indexOf("dayPeriod") < o.indexOf("hour"),
21
+ periods: [s(1), s(13)]
22
+ };
23
+ }
24
+ function m(u) {
25
+ const e = /^(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(u);
26
+ if (!e) return null;
27
+ const [t, r, o = 0] = e.slice(1).map((n) => Number(n ?? 0));
28
+ return t > 23 || r > 59 || o > 59 ? null : t * 3600 + r * 60 + o;
29
+ }
30
+ const c = (u) => String(u).padStart(2, "0");
31
+ class f extends O {
32
+ constructor() {
33
+ super(...arguments), this.seconds = !1, this.hourCycle = "", this.step = 1;
34
+ }
35
+ get twelve() {
36
+ if (this.hourCycle) return this.hourCycle === "h12";
37
+ const e = w(this.resolvedLocale, { hour: "numeric" }).resolvedOptions().hourCycle;
38
+ return e === "h11" || e === "h12";
39
+ }
40
+ willUpdate(e) {
41
+ (e.has("hourCycle") || e.has("seconds")) && (this.texts = this.fill(this.value)), super.willUpdate(e);
42
+ }
43
+ // --- Segments ---
44
+ items() {
45
+ const e = y(), t = this.twelve, { separator: r, periodFirst: o, periods: n } = b(this.resolvedLocale, t), s = (l, p, a, d, h = 1) => ({
46
+ key: l,
47
+ label: p,
48
+ placeholder: e.placeholderTime,
49
+ spec: { min: a, max: d, length: 2 },
50
+ step: h
51
+ }), i = [
52
+ t ? s("hour", e.segmentHour, 1, 12) : s("hour", e.segmentHour, 0, 23),
53
+ { literal: r },
54
+ s("minute", e.segmentMinute, 0, 59, Math.max(1, Math.round(this.step) || 1))
55
+ ];
56
+ if (this.seconds && i.push({ literal: r }, s("second", e.segmentSecond, 0, 59)), t) {
57
+ const l = {
58
+ key: "period",
59
+ label: e.segmentDayPeriod,
60
+ placeholder: e.placeholderTime,
61
+ choices: n
62
+ };
63
+ o ? i.unshift(l, { literal: " " }) : i.push({ literal: " " }, l);
64
+ }
65
+ return i;
66
+ }
67
+ fill(e) {
68
+ const t = e === null ? null : m(e);
69
+ if (t === null) return { hour: "", minute: "", second: "", period: "" };
70
+ const r = Math.floor(t / 3600);
71
+ return {
72
+ hour: c(this.twelve ? r % 12 || 12 : r),
73
+ minute: c(Math.floor(t / 60) % 60),
74
+ second: c(t % 60),
75
+ period: r < 12 ? "0" : "1"
76
+ };
77
+ }
78
+ read(e) {
79
+ const { hour: t = "", minute: r = "", second: o = "", period: n = "" } = e, s = this.twelve;
80
+ if (t.length < 2 || r.length < 2 || this.seconds && o.length < 2 || s && n === "") return { value: null, error: "" };
81
+ let l = Number(t);
82
+ if (s) {
83
+ if (l < 1 || l > 12) return { value: null, error: "" };
84
+ l = l % 12 + (n === "1" ? 12 : 0);
85
+ }
86
+ const p = `${c(l)}:${r}${this.seconds ? `:${o}` : ""}`, a = m(p);
87
+ if (a === null) return { value: null, error: "" };
88
+ const d = m(this.min), h = m(this.max);
89
+ return d !== null && a < d || h !== null && a > h ? { value: null, error: y().timeOutOfRange } : { value: p, error: "" };
90
+ }
91
+ /** A number left at one digit is written out: 9 is 09. */
92
+ completeOnBlur(e, t) {
93
+ if (!e.spec || t.length !== 1) return null;
94
+ const r = Number(t);
95
+ return r < e.spec.min ? null : c(r);
96
+ }
97
+ requiredMessage() {
98
+ return y().timeRequired;
99
+ }
100
+ }
101
+ g([
102
+ v({ type: Boolean, reflect: !0 })
103
+ ], f.prototype, "seconds");
104
+ g([
105
+ v({ type: String, attribute: "hour-cycle" })
106
+ ], f.prototype, "hourCycle");
107
+ g([
108
+ v({ type: Number })
109
+ ], f.prototype, "step");
110
+ x("kt-time-input", f);
111
+ export {
112
+ f as KtTimeInput
113
+ };
114
+ //# sourceMappingURL=kt-time-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kt-time-input.js","sources":["../../../../src/components/forms/kt-time-input/kt-time-input.ts"],"sourcesContent":["import { type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { defineElement } from '#internal/kt-element';\nimport { KtSegmentedField, type FieldItem, type Segment } from '#internal/segmented-field';\nimport { dateFormat } from '#internal/locale';\nimport { strings } from '#internal/strings';\n\nexport type KtHourCycle = 'h12' | 'h23';\n\n/** How the language writes a time on a clock: what goes between the numbers, and where AM/PM sits. */\nfunction timeLayout(\n locale: string,\n twelve: boolean,\n): { separator: string; periodFirst: boolean; periods: [string, string] } {\n const format = dateFormat(locale, {\n hour: '2-digit',\n minute: '2-digit',\n hourCycle: twelve ? 'h12' : 'h23',\n });\n const parts = format.formatToParts(new Date(2026, 0, 1, 1, 5));\n const types = parts.map((part) => part.type);\n const separator = parts.find((part) => part.type === 'literal')?.value.trim() || ':';\n const period = (hour: number) =>\n format.formatToParts(new Date(2026, 0, 1, hour)).find((part) => part.type === 'dayPeriod')\n ?.value ?? (hour < 12 ? 'AM' : 'PM');\n return {\n separator: separator === '.' ? '.' : ':',\n periodFirst:\n types.indexOf('dayPeriod') >= 0 && types.indexOf('dayPeriod') < types.indexOf('hour'),\n periods: [period(1), period(13)],\n };\n}\n\n/** `HH:MM` or `HH:MM:SS` as seconds since midnight, or null when it is not one. */\nfunction secondsOf(time: string): number | null {\n const match = /^(\\d{2}):(\\d{2})(?::(\\d{2}))?$/.exec(time);\n if (!match) return null;\n const [hours, minutes, seconds = 0] = match.slice(1).map((part) => Number(part ?? 0));\n if (hours! > 23 || minutes! > 59 || seconds > 59) return null;\n return hours! * 3600 + minutes! * 60 + seconds;\n}\n\nconst pad = (n: number) => String(n).padStart(2, '0');\n\n/**\n * A time of day typed into its parts: hours, minutes and, if asked, seconds.\n *\n * The clock is the reader's — `14:30` in London, `2:30 PM` in New York — or\n * the one `hour-cycle` names. Whatever the clock shows, the value is the\n * 24-hour time HTML uses, `14:30` or `14:30:00`, and `null` until complete.\n * The arrows step a segment, the minutes by `step`.\n *\n * @element kt-time-input\n *\n * @csspart field - The field.\n * @csspart segment - An hour, minute, second or AM/PM segment.\n *\n * @fires kt-change - The time became complete, changed, or stopped being one.\n * `detail: { value }` — `HH:MM`, `HH:MM:SS` or `null`.\n *\n * @example\n * ```html\n * <kt-time-input label=\"Starts at\" name=\"start\" step=\"15\" min=\"08:00\" max=\"20:00\"></kt-time-input>\n * ```\n */\nexport class KtTimeInput extends KtSegmentedField {\n /** Shows a seconds segment, and puts seconds in the value. */\n @property({ type: Boolean, reflect: true })\n seconds = false;\n\n /** The clock to show: `h12` with AM/PM, `h23` without. Empty: the language's. */\n @property({ type: String, attribute: 'hour-cycle' })\n hourCycle: KtHourCycle | '' = '';\n\n /** How many minutes the arrows step by. */\n @property({ type: Number })\n step = 1;\n\n private get twelve(): boolean {\n if (this.hourCycle) return this.hourCycle === 'h12';\n const cycle = dateFormat(this.resolvedLocale, { hour: 'numeric' }).resolvedOptions().hourCycle;\n return cycle === 'h11' || cycle === 'h12';\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n // Another clock shows the same value in other segments.\n if (changed.has('hourCycle') || changed.has('seconds')) this.texts = this.fill(this.value);\n super.willUpdate(changed);\n }\n\n // --- Segments ---\n\n protected override items(): FieldItem[] {\n const s = strings();\n const twelve = this.twelve;\n const { separator, periodFirst, periods } = timeLayout(this.resolvedLocale, twelve);\n const number = (key: string, label: string, min: number, max: number, step = 1): Segment => ({\n key,\n label,\n placeholder: s.placeholderTime,\n spec: { min, max, length: 2 },\n step,\n });\n\n const items: FieldItem[] = [\n twelve ? number('hour', s.segmentHour, 1, 12) : number('hour', s.segmentHour, 0, 23),\n { literal: separator },\n number('minute', s.segmentMinute, 0, 59, Math.max(1, Math.round(this.step) || 1)),\n ];\n if (this.seconds) items.push({ literal: separator }, number('second', s.segmentSecond, 0, 59));\n if (twelve) {\n const period: Segment = {\n key: 'period',\n label: s.segmentDayPeriod,\n placeholder: s.placeholderTime,\n choices: periods,\n };\n if (periodFirst) items.unshift(period, { literal: ' ' });\n else items.push({ literal: ' ' }, period);\n }\n return items;\n }\n\n protected override fill(value: string | null): Record<string, string> {\n const total = value === null ? null : secondsOf(value);\n if (total === null) return { hour: '', minute: '', second: '', period: '' };\n const hours = Math.floor(total / 3600);\n return {\n hour: pad(this.twelve ? hours % 12 || 12 : hours),\n minute: pad(Math.floor(total / 60) % 60),\n second: pad(total % 60),\n period: hours < 12 ? '0' : '1',\n };\n }\n\n protected override read(texts: Record<string, string>): { value: string | null; error: string } {\n const { hour = '', minute = '', second = '', period = '' } = texts;\n const twelve = this.twelve;\n // A segment still being typed is not a number yet: two digits, or one\n // written out when the focus leaves it.\n const incomplete =\n hour.length < 2 ||\n minute.length < 2 ||\n (this.seconds && second.length < 2) ||\n (twelve && period === '');\n if (incomplete) return { value: null, error: '' };\n\n let hours = Number(hour);\n if (twelve) {\n if (hours < 1 || hours > 12) return { value: null, error: '' };\n hours = (hours % 12) + (period === '1' ? 12 : 0);\n }\n const time = `${pad(hours)}:${minute}${this.seconds ? `:${second}` : ''}`;\n const total = secondsOf(time);\n if (total === null) return { value: null, error: '' };\n\n const min = secondsOf(this.min);\n const max = secondsOf(this.max);\n if ((min !== null && total < min) || (max !== null && total > max)) {\n return { value: null, error: strings().timeOutOfRange };\n }\n return { value: time, error: '' };\n }\n\n /** A number left at one digit is written out: 9 is 09. */\n protected override completeOnBlur(segment: Segment, text: string): string | null {\n if (!segment.spec || text.length !== 1) return null;\n const value = Number(text);\n return value < segment.spec.min ? null : pad(value);\n }\n\n protected override requiredMessage(): string {\n return strings().timeRequired;\n }\n}\n\ndefineElement('kt-time-input', KtTimeInput);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-time-input': KtTimeInput;\n }\n}\n"],"names":["timeLayout","locale","twelve","format","dateFormat","parts","types","part","separator","period","hour","secondsOf","time","match","hours","minutes","seconds","pad","n","KtTimeInput","KtSegmentedField","cycle","changed","s","strings","periodFirst","periods","number","key","label","min","max","step","items","value","total","texts","minute","second","segment","text","__decorateClass","property","defineElement"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { css as d, nothing as h, html as u } from "lit";
2
2
  import { property as i, state as b } from "lit/decorators.js";
3
- import { K as n, d as p } from "../../../chunks/kt-element-Djx2JcGl.js";
3
+ import { K as n, d as p } from "../../../chunks/kt-element-T0VbIBNp.js";
4
4
  import { e as m } from "../../../chunks/events-r51msXNf.js";
5
5
  import { a as f, s as v } from "../../../chunks/form-control-B74_EHtG.js";
6
6
  var g = Object.defineProperty, a = (s, t, l, k) => {
@@ -1,13 +1,13 @@
1
1
  import { css as d, nothing as f, html as s } from "lit";
2
2
  import { property as c } from "lit/decorators.js";
3
- import { K as p, d as u } from "../../../chunks/kt-element-Djx2JcGl.js";
3
+ import { K as p, d as u } from "../../../chunks/kt-element-T0VbIBNp.js";
4
4
  import { e as h } from "../../../chunks/events-r51msXNf.js";
5
- import { s as b } from "../../../chunks/index-STEEvEP7.js";
5
+ import { s as v } from "../../../chunks/index-TWJzttLX.js";
6
6
  import "../../core/kt-icon/kt-icon.js";
7
- var v = Object.defineProperty, m = (o, t, e, a) => {
7
+ var b = Object.defineProperty, m = (o, t, e, a) => {
8
8
  for (var r = void 0, i = o.length - 1, l; i >= 0; i--)
9
9
  (l = o[i]) && (r = l(t, e, r) || r);
10
- return r && v(t, e, r), r;
10
+ return r && b(t, e, r), r;
11
11
  };
12
12
  class n extends p {
13
13
  constructor() {
@@ -32,7 +32,7 @@ class n extends p {
32
32
  padding: 2px 6px;
33
33
  color: var(--text-muted);
34
34
  font: var(--font-normal-regular);
35
- border-radius: 6px;
35
+ border-radius: calc(6px * var(--radius-scale, 1));
36
36
  text-decoration: none;
37
37
  }
38
38
 
@@ -64,7 +64,7 @@ class n extends p {
64
64
  }
65
65
  render() {
66
66
  const t = this.items.length - 1;
67
- return s`<nav part="nav" aria-label=${this.label ?? b().breadcrumb}>
67
+ return s`<nav part="nav" aria-label=${this.label ?? v().breadcrumb}>
68
68
  ${this.items.map(
69
69
  (e, a) => a === t ? s`<span part="item" class="item current" aria-current="page">${e.label}</span>` : s`<a
70
70
  part="item"
@@ -1 +1 @@
1
- {"version":3,"file":"kt-breadcrumb.js","sources":["../../../../src/components/navigation/kt-breadcrumb/kt-breadcrumb.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport interface KtBreadcrumbItem {\n readonly label: string;\n readonly href?: string;\n}\n\n/**\n * A trail showing where the current page sits.\n *\n * The last entry is the current page: rendered as text, not a link, and marked\n * `aria-current=\"page\"`. A breadcrumb whose final item links to the page you\n * are already on is a dead control.\n *\n * @element kt-breadcrumb\n *\n * @csspart nav - The `<nav>`.\n * @csspart item - A trail entry.\n *\n * @fires kt-navigate - An entry was activated. `detail: { item, index }`.\n * Cancel it to keep the browser from following the href.\n *\n * @example\n * ```js\n * trail.items = [\n * { label: 'Home', href: '/' },\n * { label: 'Entities', href: '/entities' },\n * { label: 'Entity 4812' },\n * ];\n * ```\n */\nexport class KtBreadcrumb extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n nav {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n }\n\n .item {\n padding: 2px 6px;\n color: var(--text-muted);\n font: var(--font-normal-regular);\n border-radius: 6px;\n text-decoration: none;\n }\n\n a.item:hover {\n color: var(--text-body);\n background: var(--color-dark-18);\n text-decoration: none;\n }\n\n a.item:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n .current {\n color: var(--text-body);\n font: var(--font-normal-medium);\n }\n\n .separator {\n display: inline-flex;\n color: var(--color-text-600);\n }\n `,\n ];\n\n /** The trail, root first. The last entry is the current page. */\n @property({ attribute: false })\n items: readonly KtBreadcrumbItem[] = [];\n\n /** Accessible name for the navigation landmark. */\n @property({ type: String })\n label: string | undefined = undefined;\n\n private onSelect(event: MouseEvent, item: KtBreadcrumbItem, index: number): void {\n // Let modified clicks through: they open a new tab, which is the user\n // asking the browser for something we should not intercept.\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;\n\n const proceed = emit(this, 'kt-navigate', { item, index });\n if (!proceed.defaultPrevented) return;\n event.preventDefault();\n }\n\n override render(): TemplateResult {\n const lastIndex = this.items.length - 1;\n\n return html`<nav part=\"nav\" aria-label=${this.label ?? strings().breadcrumb}>\n ${this.items.map((item, index) =>\n index === lastIndex\n ? html`<span part=\"item\" class=\"item current\" aria-current=\"page\">${item.label}</span>`\n : html`<a\n part=\"item\"\n class=\"item\"\n href=${item.href ?? '#'}\n @click=${(event: MouseEvent) => this.onSelect(event, item, index)}\n >${item.label}</a\n >\n <span class=\"separator\" aria-hidden=\"true\">\n <kt-icon name=\"chevron-right\" size=\"14\"></kt-icon>\n </span>`,\n )}\n ${this.items.length === 0 ? nothing : ''}\n </nav>`;\n }\n}\n\ndefineElement('kt-breadcrumb', KtBreadcrumb);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-breadcrumb': KtBreadcrumb;\n }\n}\n"],"names":["KtBreadcrumb","KtElement","css","event","item","index","emit","lastIndex","html","strings","nothing","__decorateClass","property","defineElement"],"mappings":";;;;;;;;;;;AAoCO,MAAMA,UAAqBC,EAAU;AAAA,EAArC,cAAA;AAAA,UAAA,GAAA,SAAA,GAgDL,KAAA,QAAqC,CAAA,GAIrC,KAAA,QAA4B;AAAA,EAAA;AAAA,EAnD5B,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBA,EAAU;AAAA,MACVC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EAyCF;AAAA,EAUQ,SAASC,GAAmBC,GAAwBC,GAAqB;AAM/E,IAHIF,EAAM,WAAWA,EAAM,WAAWA,EAAM,YAAYA,EAAM,WAAW,KAGrE,CADYG,EAAK,MAAM,eAAe,EAAE,MAAAF,GAAM,OAAAC,GAAO,EAC5C,oBACbF,EAAM,eAAA;AAAA,EACR;AAAA,EAES,SAAyB;AAChC,UAAMI,IAAY,KAAK,MAAM,SAAS;AAEtC,WAAOC,+BAAkC,KAAK,SAASC,EAAA,EAAU,UAAU;AAAA,QACvE,KAAK,MAAM;AAAA,MAAI,CAACL,GAAMC,MACtBA,MAAUE,IACNC,+DAAkEJ,EAAK,KAAK,YAC5EI;AAAA;AAAA;AAAA,uBAGWJ,EAAK,QAAQ,GAAG;AAAA,yBACd,CAACD,MAAsB,KAAK,SAASA,GAAOC,GAAMC,CAAK,CAAC;AAAA,mBAC9DD,EAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAKtB;AAAA,QACC,KAAK,MAAM,WAAW,IAAIM,IAAU,EAAE;AAAA;AAAA,EAE5C;AACF;AArCEC,EAAA;AAAA,EADCC,EAAS,EAAE,WAAW,GAAA,CAAO;AAAA,GA/CnBZ,EAgDX,WAAA,OAAA;AAIAW,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAnDfZ,EAoDX,WAAA,OAAA;AAmCFa,EAAc,iBAAiBb,CAAY;"}
1
+ {"version":3,"file":"kt-breadcrumb.js","sources":["../../../../src/components/navigation/kt-breadcrumb/kt-breadcrumb.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport interface KtBreadcrumbItem {\n readonly label: string;\n readonly href?: string;\n}\n\n/**\n * A trail showing where the current page sits.\n *\n * The last entry is the current page: rendered as text, not a link, and marked\n * `aria-current=\"page\"`. A breadcrumb whose final item links to the page you\n * are already on is a dead control.\n *\n * @element kt-breadcrumb\n *\n * @csspart nav - The `<nav>`.\n * @csspart item - A trail entry.\n *\n * @fires kt-navigate - An entry was activated. `detail: { item, index }`.\n * Cancel it to keep the browser from following the href.\n *\n * @example\n * ```js\n * trail.items = [\n * { label: 'Home', href: '/' },\n * { label: 'Entities', href: '/entities' },\n * { label: 'Entity 4812' },\n * ];\n * ```\n */\nexport class KtBreadcrumb extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n nav {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n }\n\n .item {\n padding: 2px 6px;\n color: var(--text-muted);\n font: var(--font-normal-regular);\n border-radius: calc(6px * var(--radius-scale, 1));\n text-decoration: none;\n }\n\n a.item:hover {\n color: var(--text-body);\n background: var(--color-dark-18);\n text-decoration: none;\n }\n\n a.item:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n .current {\n color: var(--text-body);\n font: var(--font-normal-medium);\n }\n\n .separator {\n display: inline-flex;\n color: var(--color-text-600);\n }\n `,\n ];\n\n /** The trail, root first. The last entry is the current page. */\n @property({ attribute: false })\n items: readonly KtBreadcrumbItem[] = [];\n\n /** Accessible name for the navigation landmark. */\n @property({ type: String })\n label: string | undefined = undefined;\n\n private onSelect(event: MouseEvent, item: KtBreadcrumbItem, index: number): void {\n // Let modified clicks through: they open a new tab, which is the user\n // asking the browser for something we should not intercept.\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;\n\n const proceed = emit(this, 'kt-navigate', { item, index });\n if (!proceed.defaultPrevented) return;\n event.preventDefault();\n }\n\n override render(): TemplateResult {\n const lastIndex = this.items.length - 1;\n\n return html`<nav part=\"nav\" aria-label=${this.label ?? strings().breadcrumb}>\n ${this.items.map((item, index) =>\n index === lastIndex\n ? html`<span part=\"item\" class=\"item current\" aria-current=\"page\">${item.label}</span>`\n : html`<a\n part=\"item\"\n class=\"item\"\n href=${item.href ?? '#'}\n @click=${(event: MouseEvent) => this.onSelect(event, item, index)}\n >${item.label}</a\n >\n <span class=\"separator\" aria-hidden=\"true\">\n <kt-icon name=\"chevron-right\" size=\"14\"></kt-icon>\n </span>`,\n )}\n ${this.items.length === 0 ? nothing : ''}\n </nav>`;\n }\n}\n\ndefineElement('kt-breadcrumb', KtBreadcrumb);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-breadcrumb': KtBreadcrumb;\n }\n}\n"],"names":["KtBreadcrumb","KtElement","css","event","item","index","emit","lastIndex","html","strings","nothing","__decorateClass","property","defineElement"],"mappings":";;;;;;;;;;;AAoCO,MAAMA,UAAqBC,EAAU;AAAA,EAArC,cAAA;AAAA,UAAA,GAAA,SAAA,GAgDL,KAAA,QAAqC,CAAA,GAIrC,KAAA,QAA4B;AAAA,EAAA;AAAA,EAnD5B,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBA,EAAU;AAAA,MACVC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EAyCF;AAAA,EAUQ,SAASC,GAAmBC,GAAwBC,GAAqB;AAM/E,IAHIF,EAAM,WAAWA,EAAM,WAAWA,EAAM,YAAYA,EAAM,WAAW,KAGrE,CADYG,EAAK,MAAM,eAAe,EAAE,MAAAF,GAAM,OAAAC,GAAO,EAC5C,oBACbF,EAAM,eAAA;AAAA,EACR;AAAA,EAES,SAAyB;AAChC,UAAMI,IAAY,KAAK,MAAM,SAAS;AAEtC,WAAOC,+BAAkC,KAAK,SAASC,EAAA,EAAU,UAAU;AAAA,QACvE,KAAK,MAAM;AAAA,MAAI,CAACL,GAAMC,MACtBA,MAAUE,IACNC,+DAAkEJ,EAAK,KAAK,YAC5EI;AAAA;AAAA;AAAA,uBAGWJ,EAAK,QAAQ,GAAG;AAAA,yBACd,CAACD,MAAsB,KAAK,SAASA,GAAOC,GAAMC,CAAK,CAAC;AAAA,mBAC9DD,EAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAKtB;AAAA,QACC,KAAK,MAAM,WAAW,IAAIM,IAAU,EAAE;AAAA;AAAA,EAE5C;AACF;AArCEC,EAAA;AAAA,EADCC,EAAS,EAAE,WAAW,GAAA,CAAO;AAAA,GA/CnBZ,EAgDX,WAAA,OAAA;AAIAW,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAnDfZ,EAoDX,WAAA,OAAA;AAmCFa,EAAc,iBAAiBb,CAAY;"}
@@ -1,8 +1,8 @@
1
1
  import { css as c, nothing as u, html as m } from "lit";
2
2
  import { state as b, property as n } from "lit/decorators.js";
3
- import { K as d, d as f } from "../../../chunks/kt-element-Djx2JcGl.js";
3
+ import { K as d, d as f } from "../../../chunks/kt-element-T0VbIBNp.js";
4
4
  import { e as p } from "../../../chunks/events-r51msXNf.js";
5
- import { s as h } from "../../../chunks/index-STEEvEP7.js";
5
+ import { s as h } from "../../../chunks/index-TWJzttLX.js";
6
6
  import "../../core/kt-button/kt-button.js";
7
7
  var g = Object.defineProperty, a = (r, o, s, v) => {
8
8
  for (var e = void 0, i = r.length - 1, l; i >= 0; i--)
@@ -1,6 +1,6 @@
1
1
  import { css as c, html as t, nothing as l } from "lit";
2
2
  import { property as s } from "lit/decorators.js";
3
- import { K as h, d as g } from "../../../chunks/kt-element-Djx2JcGl.js";
3
+ import { K as h, d as g } from "../../../chunks/kt-element-T0VbIBNp.js";
4
4
  var f = Object.defineProperty, o = (a, r, p, v) => {
5
5
  for (var e = void 0, n = a.length - 1, d; n >= 0; n--)
6
6
  (d = a[n]) && (e = d(r, p, e) || e);
@@ -1,10 +1,10 @@
1
1
  import { css as b, nothing as c, html as p } from "lit";
2
2
  import { queryAll as v, property as n, state as m } from "lit/decorators.js";
3
3
  import { classMap as u } from "lit/directives/class-map.js";
4
- import { K as f, d as g } from "../../../chunks/kt-element-Djx2JcGl.js";
4
+ import { K as f, d as g } from "../../../chunks/kt-element-T0VbIBNp.js";
5
5
  import { e as x } from "../../../chunks/events-r51msXNf.js";
6
6
  import { a as y, s as k, b as w } from "../../../chunks/form-control-B74_EHtG.js";
7
- import { s as $ } from "../../../chunks/index-STEEvEP7.js";
7
+ import { s as $ } from "../../../chunks/index-TWJzttLX.js";
8
8
  import "../../core/kt-icon/kt-icon.js";
9
9
  var I = Object.defineProperty, s = (h, t, i, o) => {
10
10
  for (var e = void 0, r = h.length - 1, l; r >= 0; r--)