kanto-ds 1.4.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +10 -10
  2. package/dist/chunks/{defaults-BwgjMcww.js → defaults-CFrjqae2.js} +22 -21
  3. package/dist/chunks/{defaults-BwgjMcww.js.map → defaults-CFrjqae2.js.map} +1 -1
  4. package/dist/chunks/events-r51msXNf.js +22 -0
  5. package/dist/chunks/{events-Bjl5Zmmq.js.map → events-r51msXNf.js.map} +1 -1
  6. package/dist/chunks/floating-B7_Dahpn.js +54 -0
  7. package/dist/chunks/floating-B7_Dahpn.js.map +1 -0
  8. package/dist/chunks/{form-control-CxjBTt1c.js → form-control-B74_EHtG.js} +7 -7
  9. package/dist/chunks/form-control-B74_EHtG.js.map +1 -0
  10. package/dist/chunks/{index-DSSLJirw.js → index-STEEvEP7.js} +24 -12
  11. package/dist/chunks/index-STEEvEP7.js.map +1 -0
  12. package/dist/chunks/kt-calendar-B_hFdD9V.js +640 -0
  13. package/dist/chunks/kt-calendar-B_hFdD9V.js.map +1 -0
  14. package/dist/chunks/{kt-element-E-tfJpGQ.js → kt-element-Djx2JcGl.js} +2 -2
  15. package/dist/chunks/{kt-element-E-tfJpGQ.js.map → kt-element-Djx2JcGl.js.map} +1 -1
  16. package/dist/chunks/{listbox-Sm3nvsC6.js → listbox-llcUu_V-.js} +18 -14
  17. package/dist/chunks/{listbox-Sm3nvsC6.js.map → listbox-llcUu_V-.js.map} +1 -1
  18. package/dist/chunks/locale-C5xLkGx5.js +14 -0
  19. package/dist/chunks/locale-C5xLkGx5.js.map +1 -0
  20. package/dist/chunks/position-Cx_ZH5zh.js +39 -0
  21. package/dist/chunks/position-Cx_ZH5zh.js.map +1 -0
  22. package/dist/components/core/kt-avatar/kt-avatar.js +2 -2
  23. package/dist/components/core/kt-badge/kt-badge.js +3 -3
  24. package/dist/components/core/kt-button/kt-button.js +1 -1
  25. package/dist/components/core/kt-card/kt-card.js +2 -2
  26. package/dist/components/core/kt-code/kt-code.js +3 -3
  27. package/dist/components/core/kt-icon/kt-icon.js +2 -2
  28. package/dist/components/core/kt-kbd/kt-kbd.js +1 -1
  29. package/dist/components/core/kt-split-button/kt-split-button.js +4 -4
  30. package/dist/components/data/kt-chart/kt-chart.js +3 -3
  31. package/dist/components/data/kt-meter/kt-meter.js +1 -1
  32. package/dist/components/data/kt-pagination/kt-pagination.js +3 -3
  33. package/dist/components/data/kt-stat/kt-stat.js +1 -1
  34. package/dist/components/data/kt-table/kt-table.d.ts +53 -3
  35. package/dist/components/data/kt-table/kt-table.js +286 -131
  36. package/dist/components/data/kt-table/kt-table.js.map +1 -1
  37. package/dist/components/data/kt-table/window.d.ts +19 -0
  38. package/dist/components/data/kt-timeline/kt-timeline.js +1 -1
  39. package/dist/components/feedback/kt-alert/kt-alert.js +3 -3
  40. package/dist/components/feedback/kt-empty-state/kt-empty-state.js +1 -1
  41. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +10 -10
  42. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js.map +1 -1
  43. package/dist/components/feedback/kt-skeleton/kt-skeleton.js +1 -1
  44. package/dist/components/feedback/kt-toast/kt-toast.js +58 -42
  45. package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -1
  46. package/dist/components/feedback/kt-toast-container/kt-toast-container.js +1 -1
  47. package/dist/components/feedback/kt-tooltip/kt-tooltip.d.ts +20 -0
  48. package/dist/components/feedback/kt-tooltip/kt-tooltip.js +95 -51
  49. package/dist/components/feedback/kt-tooltip/kt-tooltip.js.map +1 -1
  50. package/dist/components/forms/kt-calendar/kt-calendar.d.ts +96 -0
  51. package/dist/components/forms/kt-calendar/kt-calendar.js +13 -0
  52. package/dist/components/forms/kt-calendar/kt-calendar.js.map +1 -0
  53. package/dist/components/forms/kt-checkbox/kt-checkbox.d.ts +9 -0
  54. package/dist/components/forms/kt-checkbox/kt-checkbox.js +34 -20
  55. package/dist/components/forms/kt-checkbox/kt-checkbox.js.map +1 -1
  56. package/dist/components/forms/kt-date-picker/kt-date-picker.d.ts +105 -0
  57. package/dist/components/forms/kt-date-picker/kt-date-picker.js +382 -0
  58. package/dist/components/forms/kt-date-picker/kt-date-picker.js.map +1 -0
  59. package/dist/components/forms/kt-drag-drop/kt-drag-drop.d.ts +9 -0
  60. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +36 -22
  61. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -1
  62. package/dist/components/forms/kt-form/kt-form.js +2 -2
  63. package/dist/components/forms/kt-input/kt-input.d.ts +37 -1
  64. package/dist/components/forms/kt-input/kt-input.js +380 -194
  65. package/dist/components/forms/kt-input/kt-input.js.map +1 -1
  66. package/dist/components/forms/kt-input-menu/kt-input-menu.d.ts +13 -0
  67. package/dist/components/forms/kt-input-menu/kt-input-menu.js +73 -42
  68. package/dist/components/forms/kt-input-menu/kt-input-menu.js.map +1 -1
  69. package/dist/components/forms/kt-label-input/kt-label-input.js +1 -1
  70. package/dist/components/forms/kt-radio-group/kt-radio-group.d.ts +9 -0
  71. package/dist/components/forms/kt-radio-group/kt-radio-group.js +67 -53
  72. package/dist/components/forms/kt-radio-group/kt-radio-group.js.map +1 -1
  73. package/dist/components/forms/kt-select/kt-select.d.ts +13 -0
  74. package/dist/components/forms/kt-select/kt-select.js +87 -56
  75. package/dist/components/forms/kt-select/kt-select.js.map +1 -1
  76. package/dist/components/forms/kt-textarea/kt-textarea.d.ts +9 -0
  77. package/dist/components/forms/kt-textarea/kt-textarea.js +28 -14
  78. package/dist/components/forms/kt-textarea/kt-textarea.js.map +1 -1
  79. package/dist/components/forms/kt-toggle/kt-toggle.d.ts +9 -0
  80. package/dist/components/forms/kt-toggle/kt-toggle.js +43 -29
  81. package/dist/components/forms/kt-toggle/kt-toggle.js.map +1 -1
  82. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +3 -3
  83. package/dist/components/navigation/kt-header/kt-header.js +3 -3
  84. package/dist/components/navigation/kt-page-header/kt-page-header.js +1 -1
  85. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.d.ts +9 -0
  86. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +40 -22
  87. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js.map +1 -1
  88. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +3 -3
  89. package/dist/components/navigation/kt-tabs/kt-tabs.js +2 -2
  90. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +2 -2
  91. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +3 -3
  92. package/dist/components/overlays/kt-collapsible/kt-collapsible.js +2 -2
  93. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +3 -3
  94. package/dist/components/overlays/kt-dropdown/kt-dropdown.d.ts +7 -5
  95. package/dist/components/overlays/kt-dropdown/kt-dropdown.js +67 -57
  96. package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -1
  97. package/dist/components/overlays/kt-modal/kt-modal.js +3 -3
  98. package/dist/components/overlays/kt-side-panel/kt-side-panel.js +3 -3
  99. package/dist/custom-elements.json +2110 -124
  100. package/dist/icons/defaults.d.ts +1 -0
  101. package/dist/icons/index.js +1 -1
  102. package/dist/index.d.ts +4 -0
  103. package/dist/index.js +91 -87
  104. package/dist/index.js.map +1 -1
  105. package/dist/internal/countries.d.ts +24 -9
  106. package/dist/internal/date.d.ts +53 -0
  107. package/dist/internal/events.d.ts +5 -0
  108. package/dist/internal/floating.d.ts +48 -0
  109. package/dist/internal/form-control.d.ts +5 -1
  110. package/dist/internal/locale.d.ts +15 -0
  111. package/dist/internal/position.d.ts +27 -0
  112. package/dist/internal/strings.d.ts +15 -0
  113. package/dist/react/index.d.ts +12 -0
  114. package/dist/react/index.js +180 -166
  115. package/dist/react/index.js.map +1 -1
  116. package/dist/react/jsx.d.ts +11 -1
  117. package/dist/strings/index.js +1 -1
  118. package/dist/tokens/base.css +2 -0
  119. package/dist/tokens/responsive.css +1 -0
  120. package/dist/tokens/spacing.css +1 -0
  121. package/dist/vscode.css-custom-data.json +8 -0
  122. package/dist/vscode.html-custom-data.json +138 -11
  123. package/dist/vue/index.d.ts +4 -0
  124. package/dist/vue/index.js +9 -7
  125. package/dist/vue/index.js.map +1 -1
  126. package/dist/web-types.json +292 -14
  127. package/package.json +10 -1
  128. package/dist/chunks/events-Bjl5Zmmq.js +0 -18
  129. package/dist/chunks/form-control-CxjBTt1c.js.map +0 -1
  130. package/dist/chunks/index-DSSLJirw.js.map +0 -1
@@ -1,20 +1,28 @@
1
- import { css as y, nothing as n, html as d } from "lit";
2
- import { state as m, property as o } from "lit/decorators.js";
3
- import { classMap as h } from "lit/directives/class-map.js";
4
- import { K as v, d as x } from "../../../chunks/kt-element-E-tfJpGQ.js";
5
- import { u as w, e as f } from "../../../chunks/events-Bjl5Zmmq.js";
6
- import { a as k, s as $, b as I } from "../../../chunks/form-control-CxjBTt1c.js";
7
- import { a as D, f as b, l as L, n as S, o as g } from "../../../chunks/listbox-Sm3nvsC6.js";
8
- import { s as l } from "../../../chunks/index-DSSLJirw.js";
1
+ import { css as x, nothing as n, html as h } from "lit";
2
+ import { state as p, property as s } from "lit/decorators.js";
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";
5
+ import { u as k, t as g, e as m } from "../../../chunks/events-r51msXNf.js";
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";
9
10
  import "../../core/kt-icon/kt-icon.js";
10
- var E = Object.defineProperty, i = (c, e, s, a) => {
11
- for (var r = void 0, p = c.length - 1, u; p >= 0; p--)
12
- (u = c[p]) && (r = u(e, s, r) || r);
13
- return r && E(e, s, r), r;
11
+ var q = Object.defineProperty, i = (c, e, o, a) => {
12
+ for (var r = void 0, u = c.length - 1, f; u >= 0; u--)
13
+ (f = c[u]) && (r = f(e, o, r) || r);
14
+ return r && q(e, o, r), r;
14
15
  };
15
16
  class t extends v {
16
17
  constructor() {
17
- super(...arguments), this.internals = null, this.defaultValue = null, this.listId = w("kt-select-list"), this.open = !1, this.activeIndex = -1, this.options = [], this.value = null, this.placeholder = void 0, this.name = "", this.size = "medium", this.disabled = !1, this.required = !1, this.error = "", this.clearable = !0, this.label = "", this.emptyText = void 0, this.onDocumentPointerDown = (e) => {
18
+ super(...arguments), this.internals = null, this.defaultValue = null, this.listId = k("kt-select-list"), this.open = !1, this.placement = "bottom", this.floating = new E(this, {
19
+ panel: () => this.shadowRoot?.querySelector(".popup"),
20
+ anchor: () => this.shadowRoot?.querySelector(".trigger"),
21
+ matchWidth: !0,
22
+ onPlace: (e) => {
23
+ this.placement = e;
24
+ }
25
+ }), this.activeIndex = -1, this.options = [], this.value = null, this.placeholder = void 0, this.name = "", this.size = "medium", this.disabled = !1, this.formDisabled = !1, this.required = !1, this.error = "", this.clearable = !0, this.label = "", this.emptyText = void 0, this.onDocumentPointerDown = (e) => {
18
26
  e.composedPath().includes(this) || (this.open = !1);
19
27
  };
20
28
  }
@@ -24,8 +32,9 @@ class t extends v {
24
32
  static {
25
33
  this.styles = [
26
34
  v.styles,
27
- D,
28
- y`
35
+ P,
36
+ S,
37
+ x`
29
38
  :host {
30
39
  position: relative;
31
40
  display: block;
@@ -89,10 +98,10 @@ class t extends v {
89
98
  outline: var(--outline-width) solid var(--color-danger-base);
90
99
  }
91
100
 
92
- :host([disabled]) {
101
+ :host(:disabled) {
93
102
  pointer-events: none;
94
103
  }
95
- :host([disabled]) .trigger {
104
+ :host(:disabled) .trigger {
96
105
  color: var(--text-disabled);
97
106
  background-color: var(--color-dark-14);
98
107
  }
@@ -137,26 +146,41 @@ class t extends v {
137
146
  `
138
147
  ];
139
148
  }
149
+ /** Whether the control is off, by its own `disabled` or by its form. */
150
+ get inactive() {
151
+ return this.disabled || this.formDisabled;
152
+ }
140
153
  connectedCallback() {
141
- super.connectedCallback(), this.internals ??= k(this), this.defaultValue = this.value, document.addEventListener("pointerdown", this.onDocumentPointerDown);
154
+ super.connectedCallback(), this.internals ??= $(this), this.defaultValue = this.value, g(this.open, document, "pointerdown", this.onDocumentPointerDown);
142
155
  }
143
156
  disconnectedCallback() {
144
157
  super.disconnectedCallback(), document.removeEventListener("pointerdown", this.onDocumentPointerDown);
145
158
  }
159
+ // Untyped: `open` is private, so not among the keys PropertyValues<this> knows.
160
+ updated(e) {
161
+ e.has("open") && g(this.open, document, "pointerdown", this.onDocumentPointerDown), this.floating.sync(this.open);
162
+ }
146
163
  willUpdate(e) {
147
164
  if (e.has("value") || e.has("required") || e.has("error") || this.stringsChanged(e)) {
148
- $(this.internals, this.value === null ? null : String(this.value));
149
- const s = this.required && this.value === null;
150
- I(
165
+ I(this.internals, this.value === null ? null : String(this.value));
166
+ const o = this.required && this.value === null;
167
+ D(
151
168
  this.internals,
152
- { valueMissing: s, customError: !!this.error },
153
- this.error || (s ? l().selectOption : "")
169
+ { valueMissing: o, customError: !!this.error },
170
+ this.error || (o ? l().selectOption : "")
154
171
  );
155
172
  }
156
173
  }
157
174
  formResetCallback() {
158
175
  this.value = this.defaultValue, this.open = !1;
159
176
  }
177
+ /**
178
+ * Called by the platform when the control's disabled state changes — its
179
+ * own `disabled`, or an ancestor `<fieldset disabled>` it cannot see.
180
+ */
181
+ formDisabledCallback(e) {
182
+ this.formDisabled = e;
183
+ }
160
184
  formStateRestoreCallback(e) {
161
185
  this.value = e;
162
186
  }
@@ -168,9 +192,9 @@ class t extends v {
168
192
  return this.options.find((e) => e.id === this.value);
169
193
  }
170
194
  openList() {
171
- if (this.disabled) return;
195
+ if (this.inactive) return;
172
196
  this.open = !0;
173
- const e = this.options.findIndex((s) => s.id === this.value);
197
+ const e = this.options.findIndex((o) => o.id === this.value);
174
198
  this.activeIndex = e >= 0 ? e : b(this.options);
175
199
  }
176
200
  closeList() {
@@ -180,17 +204,17 @@ class t extends v {
180
204
  this.open ? this.closeList() : this.openList();
181
205
  }
182
206
  choose(e) {
183
- e.disabled || (this.value = e.id, this.closeList(), this.focus(), f(this, "kt-change", { value: e.id, option: e }));
207
+ e.disabled || (this.value = e.id, this.closeList(), this.focus(), m(this, "kt-change", { value: e.id, option: e }));
184
208
  }
185
209
  clear(e) {
186
- e.stopPropagation(), this.value = null, f(this, "kt-change", { value: null, option: null });
210
+ e.stopPropagation(), this.value = null, m(this, "kt-change", { value: null, option: null });
187
211
  }
188
212
  onKeyDown(e) {
189
213
  switch (e.key) {
190
214
  case "ArrowDown":
191
215
  case "ArrowUp": {
192
216
  if (e.preventDefault(), !this.open) return this.openList();
193
- this.activeIndex = S(
217
+ this.activeIndex = C(
194
218
  this.options,
195
219
  this.activeIndex,
196
220
  e.key === "ArrowDown" ? 1 : -1
@@ -208,8 +232,8 @@ class t extends v {
208
232
  case "Enter":
209
233
  case " ": {
210
234
  if (e.preventDefault(), !this.open) return this.openList();
211
- const s = this.options[this.activeIndex];
212
- s && this.choose(s);
235
+ const o = this.options[this.activeIndex];
236
+ o && this.choose(o);
213
237
  return;
214
238
  }
215
239
  case "Escape":
@@ -224,9 +248,9 @@ class t extends v {
224
248
  return `${this.listId}-option-${e}`;
225
249
  }
226
250
  render() {
227
- const e = this.selectedOption, s = this.clearable && e !== void 0 && !this.disabled;
228
- return d`<div
229
- class=${h({ open: this.open, error: !!this.error })}
251
+ const e = this.selectedOption, o = this.clearable && e !== void 0 && !this.inactive;
252
+ return h`<div
253
+ class=${d({ open: this.open, error: !!this.error })}
230
254
  @keydown=${this.onKeyDown}
231
255
  >
232
256
  <button
@@ -240,14 +264,14 @@ class t extends v {
240
264
  aria-activedescendant=${this.open && this.activeIndex >= 0 ? this.optionId(this.activeIndex) : n}
241
265
  aria-label=${this.label || n}
242
266
  aria-invalid=${this.error ? "true" : n}
243
- ?disabled=${this.disabled}
267
+ ?disabled=${this.inactive}
244
268
  @click=${this.toggleList}
245
269
  >
246
- <span class=${h({ value: !0, placeholder: !e })}>
247
- ${e ? g(e) : this.placeholder ?? l().select}
270
+ <span class=${d({ value: !0, placeholder: !e })}>
271
+ ${e ? y(e) : this.placeholder ?? l().select}
248
272
  </span>
249
273
  <span class="icons">
250
- ${s ? d`<span
274
+ ${o ? h`<span
251
275
  class="clear"
252
276
  role="button"
253
277
  tabindex="-1"
@@ -263,15 +287,16 @@ class t extends v {
263
287
  <ul
264
288
  part="popup"
265
289
  id=${this.listId}
266
- class=${h({ popup: !0, open: this.open })}
290
+ popover="manual"
291
+ class=${d({ popup: !0, floating: !0, open: this.open, top: this.placement === "top" })}
267
292
  role="listbox"
268
293
  aria-label=${this.label || (this.placeholder ?? l().select)}
269
294
  >
270
- ${this.options.length === 0 ? d`<li class="empty">${this.emptyText ?? l().noOptions}</li>` : this.options.map(
271
- (a, r) => d`<li
295
+ ${this.options.length === 0 ? h`<li class="empty">${this.emptyText ?? l().noOptions}</li>` : this.options.map(
296
+ (a, r) => h`<li
272
297
  part="option"
273
298
  id=${this.optionId(r)}
274
- class=${h({
299
+ class=${d({
275
300
  option: !0,
276
301
  selected: a.id === this.value,
277
302
  active: r === this.activeIndex,
@@ -282,7 +307,7 @@ class t extends v {
282
307
  aria-disabled=${a.disabled ? "true" : n}
283
308
  @click=${() => this.choose(a)}
284
309
  >
285
- ${g(a)}
310
+ ${y(a)}
286
311
  </li>`
287
312
  )}
288
313
  </ul>
@@ -290,45 +315,51 @@ class t extends v {
290
315
  }
291
316
  }
292
317
  i([
293
- m()
318
+ p()
294
319
  ], t.prototype, "open");
295
320
  i([
296
- m()
321
+ p()
322
+ ], t.prototype, "placement");
323
+ i([
324
+ p()
297
325
  ], t.prototype, "activeIndex");
298
326
  i([
299
- o({ attribute: !1 })
327
+ s({ attribute: !1 })
300
328
  ], t.prototype, "options");
301
329
  i([
302
- o({ type: String })
330
+ s({ type: String })
303
331
  ], t.prototype, "value");
304
332
  i([
305
- o({ type: String })
333
+ s({ type: String })
306
334
  ], t.prototype, "placeholder");
307
335
  i([
308
- o({ type: String })
336
+ s({ type: String })
309
337
  ], t.prototype, "name");
310
338
  i([
311
- o({ type: String, reflect: !0 })
339
+ s({ type: String, reflect: !0 })
312
340
  ], t.prototype, "size");
313
341
  i([
314
- o({ type: Boolean, reflect: !0 })
342
+ s({ type: Boolean, reflect: !0 })
315
343
  ], t.prototype, "disabled");
316
344
  i([
317
- o({ type: Boolean, reflect: !0 })
345
+ p()
346
+ ], t.prototype, "formDisabled");
347
+ i([
348
+ s({ type: Boolean, reflect: !0 })
318
349
  ], t.prototype, "required");
319
350
  i([
320
- o({ type: String, reflect: !0 })
351
+ s({ type: String, reflect: !0 })
321
352
  ], t.prototype, "error");
322
353
  i([
323
- o({ type: Boolean })
354
+ s({ type: Boolean })
324
355
  ], t.prototype, "clearable");
325
356
  i([
326
- o({ type: String })
357
+ s({ type: String })
327
358
  ], t.prototype, "label");
328
359
  i([
329
- o({ type: String, attribute: "empty-text" })
360
+ s({ type: String, attribute: "empty-text" })
330
361
  ], t.prototype, "emptyText");
331
- x("kt-select", t);
362
+ w("kt-select", t);
332
363
  export {
333
364
  t as KtSelect
334
365
  };
@@ -1 +1 @@
1
- {"version":3,"file":"kt-select.js","sources":["../../../../src/components/forms/kt-select/kt-select.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit, uniqueId } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport {\n firstEnabledIndex,\n lastEnabledIndex,\n listboxStyles,\n nextEnabledIndex,\n optionLabel,\n type KtOption,\n} from '#internal/listbox';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport type KtSelectSize = 'small' | 'medium' | 'large';\nexport type { KtOption };\n\n/**\n * A single-choice dropdown.\n *\n * Unlike the trigger-plus-div it replaces, this is a real listbox: arrow keys\n * move an active descendant, Home and End jump to the ends, Enter commits,\n * Escape closes without changing anything, and disabled options are skipped\n * rather than merely unclickable.\n *\n * @element kt-select\n *\n * @csspart trigger - The button that opens the list.\n * @csspart popup - The option list.\n * @csspart option - An option row.\n *\n * @fires kt-change - An option was chosen or cleared.\n * `detail: { value, option }`.\n *\n * @example\n * ```html\n * <kt-select placeholder=\"Select a region\"></kt-select>\n * ```\n * ```js\n * select.options = [{ id: 'ne', label: 'North East' }, { id: 'sw', label: 'South West' }];\n * ```\n */\nexport class KtSelect extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n listboxStyles,\n css`\n :host {\n position: relative;\n display: block;\n --field-height: var(--button-height);\n }\n\n :host([size='small']) {\n --field-height: var(--button-height-small);\n }\n :host([size='large']) {\n --field-height: var(--button-height-large);\n }\n\n .trigger {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: center;\n gap: var(--gap-element);\n width: 100%;\n height: var(--field-height);\n padding: 0 var(--button-padding-x);\n color: var(--text-body);\n font: var(--font-input);\n text-align: left;\n background-color: var(--color-dark-20);\n border: none;\n border-radius: var(--radius-input);\n /* A resting hairline. A field is a fill on --surface-field, which is\n one ramp step from the page in dark and almost the same colour in\n light — so on a card or inside a modal it simply disappeared and\n read as a bare native control.\n\n A border rather than an outline, because the control inside fills\n the field exactly and a coincident outline is painted over by the\n native widget. A border insets the control by its own width, so it\n cannot be covered. box-sizing: border-box keeps the outer size.\n\n The hover and focus rings stay outlines on top of it, and the\n transparent resting outline is what they animate from: without it\n outline-color starts at the initial value, which resolves to the\n text colour, and hover flashed near-white before settling. */\n border: var(--border-width) solid var(--border-field);\n outline: var(--outline-width) solid transparent;\n cursor: pointer;\n transition:\n background-color var(--duration-instant),\n outline-color var(--duration-instant);\n }\n\n .trigger:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .trigger:focus-visible,\n .open .trigger {\n background-color: var(--color-dark-12);\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error .trigger,\n .error .trigger:hover {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n\n :host([disabled]) {\n pointer-events: none;\n }\n :host([disabled]) .trigger {\n color: var(--text-disabled);\n background-color: var(--color-dark-14);\n }\n\n .value {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n .placeholder {\n color: var(--text-muted);\n }\n\n .icons {\n display: inline-flex;\n align-items: center;\n gap: var(--gap-element);\n }\n\n .clear {\n display: inline-flex;\n padding: 0;\n color: inherit;\n background: none;\n border: none;\n cursor: pointer;\n transition: transform var(--duration-instant) ease-in-out;\n }\n .clear:hover {\n transform: rotate(90deg);\n }\n\n .chevron {\n display: inline-flex;\n align-items: center;\n transition: transform var(--duration-fast) ease-in-out;\n }\n .open .chevron {\n transform: scaleY(-1);\n }\n `,\n ];\n\n private internals: UsableInternals | null = null;\n private defaultValue: string | number | null = null;\n private readonly listId = uniqueId('kt-select-list');\n\n @state()\n private open = false;\n\n /** Index of the active descendant while the list is open; -1 for none. */\n @state()\n private activeIndex = -1;\n\n /** The options to choose from. A property: this is data, not an attribute. */\n @property({ attribute: false })\n options: readonly KtOption[] = [];\n\n /** The selected option's id, or `null`. */\n @property({ type: String })\n value: string | number | null = null;\n\n @property({ type: String })\n placeholder: string | undefined = undefined;\n\n @property({ type: String })\n name = '';\n\n @property({ type: String, reflect: true })\n size: KtSelectSize = 'medium';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Error message. A non-empty value puts the control in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n /** Shows the clear button once something is selected. */\n @property({ type: Boolean })\n clearable = true;\n\n /** Accessible name, when no `<kt-label-input>` wraps the control. */\n @property({ type: String })\n label = '';\n\n /** Shown when `options` is empty. */\n @property({ type: String, attribute: 'empty-text' })\n emptyText: string | undefined = undefined;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n document.addEventListener('pointerdown', this.onDocumentPointerDown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('pointerdown', this.onDocumentPointerDown);\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 === null ? null : String(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 formResetCallback(): void {\n this.value = this.defaultValue;\n this.open = false;\n }\n\n formStateRestoreCallback(state: string): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.shadowRoot?.querySelector<HTMLButtonElement>('.trigger')?.focus(options);\n }\n\n /** The currently selected option, if the id still matches one. */\n get selectedOption(): KtOption | undefined {\n return this.options.find((option) => option.id === this.value);\n }\n\n private onDocumentPointerDown = (event: Event): void => {\n if (event.composedPath().includes(this)) return;\n this.open = false;\n };\n\n private openList(): void {\n if (this.disabled) return;\n this.open = true;\n const selected = this.options.findIndex((option) => option.id === this.value);\n this.activeIndex = selected >= 0 ? selected : firstEnabledIndex(this.options);\n }\n\n private closeList(): void {\n this.open = false;\n this.activeIndex = -1;\n }\n\n private toggleList(): void {\n if (this.open) this.closeList();\n else this.openList();\n }\n\n private choose(option: KtOption): void {\n if (option.disabled) return;\n this.value = option.id;\n this.closeList();\n this.focus();\n emit(this, 'kt-change', { value: option.id, option });\n }\n\n private clear(event: Event): void {\n event.stopPropagation();\n this.value = null;\n emit(this, 'kt-change', { value: null, option: null });\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n event.preventDefault();\n if (!this.open) return this.openList();\n this.activeIndex = nextEnabledIndex(\n this.options,\n this.activeIndex,\n event.key === 'ArrowDown' ? 1 : -1,\n );\n return;\n }\n case 'Home':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = firstEnabledIndex(this.options);\n return;\n case 'End':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = lastEnabledIndex(this.options);\n return;\n case 'Enter':\n case ' ': {\n event.preventDefault();\n if (!this.open) return this.openList();\n const option = this.options[this.activeIndex];\n if (option) this.choose(option);\n return;\n }\n case 'Escape':\n if (!this.open) return;\n event.stopPropagation();\n this.closeList();\n return;\n case 'Tab':\n this.closeList();\n }\n }\n\n private optionId(index: number): string {\n return `${this.listId}-option-${index}`;\n }\n\n override render(): TemplateResult {\n const selected = this.selectedOption;\n const showClear = this.clearable && selected !== undefined && !this.disabled;\n\n return html`<div\n class=${classMap({ open: this.open, error: Boolean(this.error) })}\n @keydown=${this.onKeyDown}\n >\n <button\n part=\"trigger\"\n type=\"button\"\n class=\"trigger\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-controls=${this.listId}\n aria-activedescendant=${\n this.open && this.activeIndex >= 0 ? this.optionId(this.activeIndex) : nothing\n }\n aria-label=${this.label || nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n ?disabled=${this.disabled}\n @click=${this.toggleList}\n >\n <span class=${classMap({ value: true, placeholder: !selected })}>\n ${selected ? optionLabel(selected) : (this.placeholder ?? strings().select)}\n </span>\n <span class=\"icons\">\n ${\n showClear\n ? html`<span\n class=\"clear\"\n role=\"button\"\n tabindex=\"-1\"\n aria-label=${strings().clear}\n @click=${this.clear}\n >\n <kt-icon name=\"x\" size=\"18\"></kt-icon>\n </span>`\n : nothing\n }\n <span class=\"chevron\"><kt-icon name=\"chevron-down\" size=\"18\"></kt-icon></span>\n </span>\n </button>\n\n <ul\n part=\"popup\"\n id=${this.listId}\n class=${classMap({ popup: true, open: this.open })}\n role=\"listbox\"\n aria-label=${this.label || (this.placeholder ?? strings().select)}\n >\n ${\n this.options.length === 0\n ? html`<li class=\"empty\">${this.emptyText ?? strings().noOptions}</li>`\n : this.options.map(\n (option, index) =>\n html`<li\n part=\"option\"\n id=${this.optionId(index)}\n class=${classMap({\n option: true,\n selected: option.id === this.value,\n active: index === this.activeIndex,\n disabled: Boolean(option.disabled),\n })}\n role=\"option\"\n aria-selected=${option.id === this.value ? 'true' : 'false'}\n aria-disabled=${option.disabled ? 'true' : nothing}\n @click=${() => this.choose(option)}\n >\n ${optionLabel(option)}\n </li>`,\n )\n }\n </ul>\n </div>`;\n }\n}\n\ndefineElement('kt-select', KtSelect);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-select': KtSelect;\n }\n}\n"],"names":["KtSelect","KtElement","uniqueId","event","listboxStyles","css","attachFormInternals","changed","setFormValue","missing","setValidity","strings","state","options","option","selected","firstEnabledIndex","emit","nextEnabledIndex","lastEnabledIndex","index","showClear","html","classMap","nothing","optionLabel","__decorateClass","property","defineElement"],"mappings":"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"}
1
+ {"version":3,"file":"kt-select.js","sources":["../../../../src/components/forms/kt-select/kt-select.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit, toggleListener, uniqueId } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport {\n firstEnabledIndex,\n lastEnabledIndex,\n listboxStyles,\n nextEnabledIndex,\n optionLabel,\n type KtOption,\n} from '#internal/listbox';\nimport { FloatingController, floatingStyles } from '#internal/floating';\nimport type { Side } from '#internal/position';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport type KtSelectSize = 'small' | 'medium' | 'large';\nexport type { KtOption };\n\n/**\n * A single-choice dropdown.\n *\n * Unlike the trigger-plus-div it replaces, this is a real listbox: arrow keys\n * move an active descendant, Home and End jump to the ends, Enter commits,\n * Escape closes without changing anything, and disabled options are skipped\n * rather than merely unclickable.\n *\n * @element kt-select\n *\n * @csspart trigger - The button that opens the list.\n * @csspart popup - The option list.\n * @csspart option - An option row.\n *\n * @fires kt-change - An option was chosen or cleared.\n * `detail: { value, option }`.\n *\n * @example\n * ```html\n * <kt-select placeholder=\"Select a region\"></kt-select>\n * ```\n * ```js\n * select.options = [{ id: 'ne', label: 'North East' }, { id: 'sw', label: 'South West' }];\n * ```\n */\nexport class KtSelect extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n floatingStyles,\n listboxStyles,\n css`\n :host {\n position: relative;\n display: block;\n --field-height: var(--button-height);\n }\n\n :host([size='small']) {\n --field-height: var(--button-height-small);\n }\n :host([size='large']) {\n --field-height: var(--button-height-large);\n }\n\n .trigger {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: center;\n gap: var(--gap-element);\n width: 100%;\n height: var(--field-height);\n padding: 0 var(--button-padding-x);\n color: var(--text-body);\n font: var(--font-input);\n text-align: left;\n background-color: var(--color-dark-20);\n border: none;\n border-radius: var(--radius-input);\n /* A resting hairline. A field is a fill on --surface-field, which is\n one ramp step from the page in dark and almost the same colour in\n light — so on a card or inside a modal it simply disappeared and\n read as a bare native control.\n\n A border rather than an outline, because the control inside fills\n the field exactly and a coincident outline is painted over by the\n native widget. A border insets the control by its own width, so it\n cannot be covered. box-sizing: border-box keeps the outer size.\n\n The hover and focus rings stay outlines on top of it, and the\n transparent resting outline is what they animate from: without it\n outline-color starts at the initial value, which resolves to the\n text colour, and hover flashed near-white before settling. */\n border: var(--border-width) solid var(--border-field);\n outline: var(--outline-width) solid transparent;\n cursor: pointer;\n transition:\n background-color var(--duration-instant),\n outline-color var(--duration-instant);\n }\n\n .trigger:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .trigger:focus-visible,\n .open .trigger {\n background-color: var(--color-dark-12);\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error .trigger,\n .error .trigger:hover {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n\n :host(:disabled) {\n pointer-events: none;\n }\n :host(:disabled) .trigger {\n color: var(--text-disabled);\n background-color: var(--color-dark-14);\n }\n\n .value {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n .placeholder {\n color: var(--text-muted);\n }\n\n .icons {\n display: inline-flex;\n align-items: center;\n gap: var(--gap-element);\n }\n\n .clear {\n display: inline-flex;\n padding: 0;\n color: inherit;\n background: none;\n border: none;\n cursor: pointer;\n transition: transform var(--duration-instant) ease-in-out;\n }\n .clear:hover {\n transform: rotate(90deg);\n }\n\n .chevron {\n display: inline-flex;\n align-items: center;\n transition: transform var(--duration-fast) ease-in-out;\n }\n .open .chevron {\n transform: scaleY(-1);\n }\n `,\n ];\n\n private internals: UsableInternals | null = null;\n private defaultValue: string | number | null = null;\n private readonly listId = uniqueId('kt-select-list');\n\n @state()\n private open = false;\n\n /** The side the list opened on, for the direction of its entrance. */\n @state()\n private placement: Side = 'bottom';\n\n private floating = new FloatingController(this, {\n panel: () => this.shadowRoot?.querySelector<HTMLElement>('.popup'),\n anchor: () => this.shadowRoot?.querySelector('.trigger'),\n matchWidth: true,\n onPlace: (side) => {\n this.placement = side;\n },\n });\n\n /** Index of the active descendant while the list is open; -1 for none. */\n @state()\n private activeIndex = -1;\n\n /** The options to choose from. A property: this is data, not an attribute. */\n @property({ attribute: false })\n options: readonly KtOption[] = [];\n\n /** The selected option's id, or `null`. */\n @property({ type: String })\n value: string | number | null = null;\n\n @property({ type: String })\n placeholder: string | undefined = undefined;\n\n @property({ type: String })\n name = '';\n\n @property({ type: String, reflect: true })\n size: KtSelectSize = 'medium';\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 /** Error message. A non-empty value puts the control in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n /** Shows the clear button once something is selected. */\n @property({ type: Boolean })\n clearable = true;\n\n /** Accessible name, when no `<kt-label-input>` wraps the control. */\n @property({ type: String })\n label = '';\n\n /** Shown when `options` is empty. */\n @property({ type: String, attribute: 'empty-text' })\n emptyText: string | undefined = undefined;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n // Back on the document if it was reconnected while open.\n toggleListener(this.open, document, 'pointerdown', this.onDocumentPointerDown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('pointerdown', this.onDocumentPointerDown);\n }\n\n // Untyped: `open` is private, so not among the keys PropertyValues<this> knows.\n override updated(changed: PropertyValues): void {\n // Only an open list closes on an outside click, so only an open one listens.\n if (changed.has('open')) {\n toggleListener(this.open, document, 'pointerdown', this.onDocumentPointerDown);\n }\n this.floating.sync(this.open);\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 === null ? null : String(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 formResetCallback(): void {\n this.value = this.defaultValue;\n this.open = false;\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): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.shadowRoot?.querySelector<HTMLButtonElement>('.trigger')?.focus(options);\n }\n\n /** The currently selected option, if the id still matches one. */\n get selectedOption(): KtOption | undefined {\n return this.options.find((option) => option.id === this.value);\n }\n\n private onDocumentPointerDown = (event: Event): void => {\n if (event.composedPath().includes(this)) return;\n this.open = false;\n };\n\n private openList(): void {\n if (this.inactive) return;\n this.open = true;\n const selected = this.options.findIndex((option) => option.id === this.value);\n this.activeIndex = selected >= 0 ? selected : firstEnabledIndex(this.options);\n }\n\n private closeList(): void {\n this.open = false;\n this.activeIndex = -1;\n }\n\n private toggleList(): void {\n if (this.open) this.closeList();\n else this.openList();\n }\n\n private choose(option: KtOption): void {\n if (option.disabled) return;\n this.value = option.id;\n this.closeList();\n this.focus();\n emit(this, 'kt-change', { value: option.id, option });\n }\n\n private clear(event: Event): void {\n event.stopPropagation();\n this.value = null;\n emit(this, 'kt-change', { value: null, option: null });\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n event.preventDefault();\n if (!this.open) return this.openList();\n this.activeIndex = nextEnabledIndex(\n this.options,\n this.activeIndex,\n event.key === 'ArrowDown' ? 1 : -1,\n );\n return;\n }\n case 'Home':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = firstEnabledIndex(this.options);\n return;\n case 'End':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = lastEnabledIndex(this.options);\n return;\n case 'Enter':\n case ' ': {\n event.preventDefault();\n if (!this.open) return this.openList();\n const option = this.options[this.activeIndex];\n if (option) this.choose(option);\n return;\n }\n case 'Escape':\n if (!this.open) return;\n event.stopPropagation();\n this.closeList();\n return;\n case 'Tab':\n this.closeList();\n }\n }\n\n private optionId(index: number): string {\n return `${this.listId}-option-${index}`;\n }\n\n override render(): TemplateResult {\n const selected = this.selectedOption;\n const showClear = this.clearable && selected !== undefined && !this.inactive;\n\n return html`<div\n class=${classMap({ open: this.open, error: Boolean(this.error) })}\n @keydown=${this.onKeyDown}\n >\n <button\n part=\"trigger\"\n type=\"button\"\n class=\"trigger\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-controls=${this.listId}\n aria-activedescendant=${\n this.open && this.activeIndex >= 0 ? this.optionId(this.activeIndex) : nothing\n }\n aria-label=${this.label || nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n ?disabled=${this.inactive}\n @click=${this.toggleList}\n >\n <span class=${classMap({ value: true, placeholder: !selected })}>\n ${selected ? optionLabel(selected) : (this.placeholder ?? strings().select)}\n </span>\n <span class=\"icons\">\n ${\n showClear\n ? html`<span\n class=\"clear\"\n role=\"button\"\n tabindex=\"-1\"\n aria-label=${strings().clear}\n @click=${this.clear}\n >\n <kt-icon name=\"x\" size=\"18\"></kt-icon>\n </span>`\n : nothing\n }\n <span class=\"chevron\"><kt-icon name=\"chevron-down\" size=\"18\"></kt-icon></span>\n </span>\n </button>\n\n <ul\n part=\"popup\"\n id=${this.listId}\n popover=\"manual\"\n class=${classMap({ popup: true, floating: true, open: this.open, top: this.placement === 'top' })}\n role=\"listbox\"\n aria-label=${this.label || (this.placeholder ?? strings().select)}\n >\n ${\n this.options.length === 0\n ? html`<li class=\"empty\">${this.emptyText ?? strings().noOptions}</li>`\n : this.options.map(\n (option, index) =>\n html`<li\n part=\"option\"\n id=${this.optionId(index)}\n class=${classMap({\n option: true,\n selected: option.id === this.value,\n active: index === this.activeIndex,\n disabled: Boolean(option.disabled),\n })}\n role=\"option\"\n aria-selected=${option.id === this.value ? 'true' : 'false'}\n aria-disabled=${option.disabled ? 'true' : nothing}\n @click=${() => this.choose(option)}\n >\n ${optionLabel(option)}\n </li>`,\n )\n }\n </ul>\n </div>`;\n }\n}\n\ndefineElement('kt-select', KtSelect);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-select': KtSelect;\n }\n}\n"],"names":["KtSelect","KtElement","uniqueId","FloatingController","side","event","floatingStyles","listboxStyles","css","attachFormInternals","toggleListener","changed","setFormValue","missing","setValidity","strings","disabled","state","options","option","selected","firstEnabledIndex","emit","nextEnabledIndex","lastEnabledIndex","index","showClear","html","classMap","nothing","optionLabel","__decorateClass","property","defineElement"],"mappings":";;;;;;;;;;;;;;;AAoDO,MAAMA,UAAiBC,EAAU;AAAA,EAAjC,cAAA;AAAA,UAAA,GAAA,SAAA,GAuHL,KAAQ,YAAoC,MAC5C,KAAQ,eAAuC,MAC/C,KAAiB,SAASC,EAAS,gBAAgB,GAGnD,KAAQ,OAAO,IAIf,KAAQ,YAAkB,UAE1B,KAAQ,WAAW,IAAIC,EAAmB,MAAM;AAAA,MAC9C,OAAO,MAAM,KAAK,YAAY,cAA2B,QAAQ;AAAA,MACjE,QAAQ,MAAM,KAAK,YAAY,cAAc,UAAU;AAAA,MACvD,YAAY;AAAA,MACZ,SAAS,CAACC,MAAS;AACjB,aAAK,YAAYA;AAAA,MACnB;AAAA,IAAA,CACD,GAID,KAAQ,cAAc,IAItB,KAAA,UAA+B,CAAA,GAI/B,KAAA,QAAgC,MAGhC,KAAA,cAAkC,QAGlC,KAAA,OAAO,IAGP,KAAA,OAAqB,UAGrB,KAAA,WAAW,IAIX,KAAQ,eAAe,IAQvB,KAAA,WAAW,IAIX,KAAA,QAAQ,IAIR,KAAA,YAAY,IAIZ,KAAA,QAAQ,IAIR,KAAA,YAAgC,QAoEhC,KAAQ,wBAAwB,CAACC,MAAuB;AACtD,MAAIA,EAAM,aAAA,EAAe,SAAS,IAAI,MACtC,KAAK,OAAO;AAAA,IACd;AAAA,EAAA;AAAA,EAnQA,OAAA;AAAA,SAAgB,iBAAiB;AAAA,EAAA;AAAA,EAEjC,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBJ,EAAU;AAAA,MACVK;AAAA,MACAC;AAAA,MACAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,EA8GF;AAAA;AAAA,EAmDA,IAAY,WAAoB;AAC9B,WAAO,KAAK,YAAY,KAAK;AAAA,EAC/B;AAAA,EAqBS,oBAA0B;AACjC,UAAM,kBAAA,GACN,KAAK,cAAcC,EAAoB,IAAI,GAC3C,KAAK,eAAe,KAAK,OAEzBC,EAAe,KAAK,MAAM,UAAU,eAAe,KAAK,qBAAqB;AAAA,EAC/E;AAAA,EAES,uBAA6B;AACpC,UAAM,qBAAA,GACN,SAAS,oBAAoB,eAAe,KAAK,qBAAqB;AAAA,EACxE;AAAA;AAAA,EAGS,QAAQC,GAA+B;AAE9C,IAAIA,EAAQ,IAAI,MAAM,KACpBD,EAAe,KAAK,MAAM,UAAU,eAAe,KAAK,qBAAqB,GAE/E,KAAK,SAAS,KAAK,KAAK,IAAI;AAAA,EAC9B;AAAA,EAES,WAAWC,GAAqC;AACvD,QACEA,EAAQ,IAAI,OAAO,KACnBA,EAAQ,IAAI,UAAU,KACtBA,EAAQ,IAAI,OAAO,KACnB,KAAK,eAAeA,CAAO,GAC3B;AACA,MAAAC,EAAa,KAAK,WAAW,KAAK,UAAU,OAAO,OAAO,OAAO,KAAK,KAAK,CAAC;AAE5E,YAAMC,IAAU,KAAK,YAAY,KAAK,UAAU;AAChD,MAAAC;AAAA,QACE,KAAK;AAAA,QACL,EAAE,cAAcD,GAAS,aAAa,EAAQ,KAAK,MAAK;AAAA,QACxD,KAAK,UAAUA,IAAUE,EAAA,EAAU,eAAe;AAAA,MAAA;AAAA,IAEtD;AAAA,EACF;AAAA,EAEA,oBAA0B;AACxB,SAAK,QAAQ,KAAK,cAClB,KAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqBC,GAAyB;AAC5C,SAAK,eAAeA;AAAA,EACtB;AAAA,EAEA,yBAAyBC,GAAqB;AAC5C,SAAK,QAAQA;AAAAA,EACf;AAAA,EAES,MAAMC,GAA8B;AAC3C,SAAK,YAAY,cAAiC,UAAU,GAAG,MAAMA,CAAO;AAAA,EAC9E;AAAA;AAAA,EAGA,IAAI,iBAAuC;AACzC,WAAO,KAAK,QAAQ,KAAK,CAACC,MAAWA,EAAO,OAAO,KAAK,KAAK;AAAA,EAC/D;AAAA,EAOQ,WAAiB;AACvB,QAAI,KAAK,SAAU;AACnB,SAAK,OAAO;AACZ,UAAMC,IAAW,KAAK,QAAQ,UAAU,CAACD,MAAWA,EAAO,OAAO,KAAK,KAAK;AAC5E,SAAK,cAAcC,KAAY,IAAIA,IAAWC,EAAkB,KAAK,OAAO;AAAA,EAC9E;AAAA,EAEQ,YAAkB;AACxB,SAAK,OAAO,IACZ,KAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,aAAmB;AACzB,IAAI,KAAK,OAAM,KAAK,UAAA,SACV,SAAA;AAAA,EACZ;AAAA,EAEQ,OAAOF,GAAwB;AACrC,IAAIA,EAAO,aACX,KAAK,QAAQA,EAAO,IACpB,KAAK,UAAA,GACL,KAAK,MAAA,GACLG,EAAK,MAAM,aAAa,EAAE,OAAOH,EAAO,IAAI,QAAAA,GAAQ;AAAA,EACtD;AAAA,EAEQ,MAAMd,GAAoB;AAChC,IAAAA,EAAM,gBAAA,GACN,KAAK,QAAQ,MACbiB,EAAK,MAAM,aAAa,EAAE,OAAO,MAAM,QAAQ,MAAM;AAAA,EACvD;AAAA,EAEQ,UAAUjB,GAA4B;AAC5C,YAAQA,EAAM,KAAA;AAAA,MACZ,KAAK;AAAA,MACL,KAAK,WAAW;AAEd,YADAA,EAAM,eAAA,GACF,CAAC,KAAK,KAAM,QAAO,KAAK,SAAA;AAC5B,aAAK,cAAckB;AAAA,UACjB,KAAK;AAAA,UACL,KAAK;AAAA,UACLlB,EAAM,QAAQ,cAAc,IAAI;AAAA,QAAA;AAElC;AAAA,MACF;AAAA,MACA,KAAK;AACH,YAAI,CAAC,KAAK,KAAM;AAChB,QAAAA,EAAM,eAAA,GACN,KAAK,cAAcgB,EAAkB,KAAK,OAAO;AACjD;AAAA,MACF,KAAK;AACH,YAAI,CAAC,KAAK,KAAM;AAChB,QAAAhB,EAAM,eAAA,GACN,KAAK,cAAcmB,EAAiB,KAAK,OAAO;AAChD;AAAA,MACF,KAAK;AAAA,MACL,KAAK,KAAK;AAER,YADAnB,EAAM,eAAA,GACF,CAAC,KAAK,KAAM,QAAO,KAAK,SAAA;AAC5B,cAAMc,IAAS,KAAK,QAAQ,KAAK,WAAW;AAC5C,QAAIA,KAAQ,KAAK,OAAOA,CAAM;AAC9B;AAAA,MACF;AAAA,MACA,KAAK;AACH,YAAI,CAAC,KAAK,KAAM;AAChB,QAAAd,EAAM,gBAAA,GACN,KAAK,UAAA;AACL;AAAA,MACF,KAAK;AACH,aAAK,UAAA;AAAA,IAAU;AAAA,EAErB;AAAA,EAEQ,SAASoB,GAAuB;AACtC,WAAO,GAAG,KAAK,MAAM,WAAWA,CAAK;AAAA,EACvC;AAAA,EAES,SAAyB;AAChC,UAAML,IAAW,KAAK,gBAChBM,IAAY,KAAK,aAAaN,MAAa,UAAa,CAAC,KAAK;AAEpE,WAAOO;AAAA,cACGC,EAAS,EAAE,MAAM,KAAK,MAAM,OAAO,EAAQ,KAAK,OAAQ,CAAC;AAAA,iBACtD,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQP,KAAK,OAAO,SAAS,OAAO;AAAA,wBAC5B,KAAK,MAAM;AAAA,gCAEzB,KAAK,QAAQ,KAAK,eAAe,IAAI,KAAK,SAAS,KAAK,WAAW,IAAIC,CACzE;AAAA,qBACa,KAAK,SAASA,CAAO;AAAA,uBACnB,KAAK,QAAQ,SAASA,CAAO;AAAA,oBAChC,KAAK,QAAQ;AAAA,iBAChB,KAAK,UAAU;AAAA;AAAA,sBAEVD,EAAS,EAAE,OAAO,IAAM,aAAa,CAACR,EAAA,CAAU,CAAC;AAAA,YAC3DA,IAAWU,EAAYV,CAAQ,IAAK,KAAK,eAAeL,EAAA,EAAU,MAAO;AAAA;AAAA;AAAA,YAIzEW,IACIC;AAAA;AAAA;AAAA;AAAA,+BAIeZ,EAAA,EAAU,KAAK;AAAA,2BACnB,KAAK,KAAK;AAAA;AAAA;AAAA,2BAIrBc,CACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAOG,KAAK,MAAM;AAAA;AAAA,gBAERD,EAAS,EAAE,OAAO,IAAM,UAAU,IAAM,MAAM,KAAK,MAAM,KAAK,KAAK,cAAc,MAAA,CAAO,CAAC;AAAA;AAAA,qBAEpF,KAAK,UAAU,KAAK,eAAeb,EAAA,EAAU,OAAO;AAAA;AAAA,UAG/D,KAAK,QAAQ,WAAW,IACpBY,sBAAyB,KAAK,aAAaZ,EAAA,EAAU,SAAS,UAC9D,KAAK,QAAQ;AAAA,MACX,CAACI,GAAQM,MACPE;AAAA;AAAA,yBAEO,KAAK,SAASF,CAAK,CAAC;AAAA,4BACjBG,EAAS;AAAA,QACf,QAAQ;AAAA,QACR,UAAUT,EAAO,OAAO,KAAK;AAAA,QAC7B,QAAQM,MAAU,KAAK;AAAA,QACvB,UAAU,EAAQN,EAAO;AAAA,MAAQ,CAClC,CAAC;AAAA;AAAA,oCAEcA,EAAO,OAAO,KAAK,QAAQ,SAAS,OAAO;AAAA,oCAC3CA,EAAO,WAAW,SAASU,CAAO;AAAA,6BACzC,MAAM,KAAK,OAAOV,CAAM,CAAC;AAAA;AAAA,sBAEhCW,EAAYX,CAAM,CAAC;AAAA;AAAA,IAAA,CAGjC;AAAA;AAAA;AAAA,EAGN;AACF;AArSUY,EAAA;AAAA,EADPd,EAAA;AAAM,GA3HIjB,EA4HH,WAAA,MAAA;AAIA+B,EAAA;AAAA,EADPd,EAAA;AAAM,GA/HIjB,EAgIH,WAAA,WAAA;AAaA+B,EAAA;AAAA,EADPd,EAAA;AAAM,GA5IIjB,EA6IH,WAAA,aAAA;AAIR+B,EAAA;AAAA,EADCC,EAAS,EAAE,WAAW,GAAA,CAAO;AAAA,GAhJnBhC,EAiJX,WAAA,SAAA;AAIA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GApJfhC,EAqJX,WAAA,OAAA;AAGA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAvJfhC,EAwJX,WAAA,aAAA;AAGA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA1JfhC,EA2JX,WAAA,MAAA;AAGA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GA7J9BhC,EA8JX,WAAA,MAAA;AAGA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAhK/BhC,EAiKX,WAAA,UAAA;AAIQ+B,EAAA;AAAA,EADPd,EAAA;AAAM,GApKIjB,EAqKH,WAAA,cAAA;AAQR+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA5K/BhC,EA6KX,WAAA,UAAA;AAIA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAhL9BhC,EAiLX,WAAA,OAAA;AAIA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GApLhBhC,EAqLX,WAAA,WAAA;AAIA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAxLfhC,EAyLX,WAAA,OAAA;AAIA+B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,cAAc;AAAA,GA5LxChC,EA6LX,WAAA,WAAA;AAsOFiC,EAAc,aAAajC,CAAQ;"}
@@ -30,6 +30,10 @@ export declare class KtTextarea extends KtElement {
30
30
  rows: number;
31
31
  maxlength?: number;
32
32
  disabled: boolean;
33
+ /** Disabled by an enclosing `<fieldset>`, which leaves `disabled` alone. */
34
+ private formDisabled;
35
+ /** Whether the control is off, by its own `disabled` or by its form. */
36
+ private get inactive();
33
37
  readonly: boolean;
34
38
  required: boolean;
35
39
  /** Error message. A non-empty value puts the field in its error state. */
@@ -48,6 +52,11 @@ export declare class KtTextarea extends KtElement {
48
52
  connectedCallback(): void;
49
53
  willUpdate(changed: PropertyValues<this>): void;
50
54
  formResetCallback(): void;
55
+ /**
56
+ * Called by the platform when the control's disabled state changes — its
57
+ * own `disabled`, or an ancestor `<fieldset disabled>` it cannot see.
58
+ */
59
+ formDisabledCallback(disabled: boolean): void;
51
60
  formStateRestoreCallback(state: string): void;
52
61
  focus(options?: FocusOptions): void;
53
62
  blur(): void;
@@ -1,20 +1,20 @@
1
1
  import { css as m, nothing as i, html as l } from "lit";
2
- import { query as f, property as a } from "lit/decorators.js";
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 b } from "../../../chunks/kt-element-E-tfJpGQ.js";
6
- import { e as p } from "../../../chunks/events-Bjl5Zmmq.js";
7
- import { a as y, s as v, b as x } from "../../../chunks/form-control-CxjBTt1c.js";
8
- import { s as w } from "../../../chunks/index-DSSLJirw.js";
5
+ import { K as c, d as y } from "../../../chunks/kt-element-Djx2JcGl.js";
6
+ import { e as p } from "../../../chunks/events-r51msXNf.js";
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";
9
9
  import "../../core/kt-icon/kt-icon.js";
10
- var $ = Object.defineProperty, r = (n, e, o, k) => {
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--)
12
12
  (d = n[h]) && (s = d(e, o, s) || s);
13
- return s && $(e, o, s), s;
13
+ return s && k(e, o, s), s;
14
14
  };
15
15
  class t extends c {
16
16
  constructor() {
17
- super(...arguments), this.internals = null, this.defaultValue = "", this.value = "", this.name = "", this.placeholder = "", this.rows = 3, this.disabled = !1, this.readonly = !1, this.required = !1, this.error = "", this.label = "", this.resize = "none";
17
+ super(...arguments), this.internals = null, this.defaultValue = "", this.value = "", this.name = "", this.placeholder = "", this.rows = 3, this.disabled = !1, this.formDisabled = !1, this.readonly = !1, this.required = !1, this.error = "", this.label = "", this.resize = "none";
18
18
  }
19
19
  static {
20
20
  this.formAssociated = !0;
@@ -124,23 +124,34 @@ class t extends c {
124
124
  `
125
125
  ];
126
126
  }
127
+ /** Whether the control is off, by its own `disabled` or by its form. */
128
+ get inactive() {
129
+ return this.disabled || this.formDisabled;
130
+ }
127
131
  connectedCallback() {
128
- super.connectedCallback(), this.internals ??= y(this), this.defaultValue = this.value, v(this.internals, this.value);
132
+ super.connectedCallback(), this.internals ??= x(this), this.defaultValue = this.value, v(this.internals, this.value);
129
133
  }
130
134
  willUpdate(e) {
131
135
  if (e.has("value") || e.has("required") || e.has("error") || this.stringsChanged(e)) {
132
136
  v(this.internals, this.value);
133
137
  const o = this.required && this.value.length === 0;
134
- x(
138
+ w(
135
139
  this.internals,
136
140
  { valueMissing: o, customError: !!this.error },
137
- this.error || (o ? w().required : "")
141
+ this.error || (o ? $().required : "")
138
142
  );
139
143
  }
140
144
  }
141
145
  formResetCallback() {
142
146
  this.value = this.defaultValue;
143
147
  }
148
+ /**
149
+ * Called by the platform when the control's disabled state changes — its
150
+ * own `disabled`, or an ancestor `<fieldset disabled>` it cannot see.
151
+ */
152
+ formDisabledCallback(e) {
153
+ this.formDisabled = e;
154
+ }
144
155
  formStateRestoreCallback(e) {
145
156
  this.value = e;
146
157
  }
@@ -163,7 +174,7 @@ class t extends c {
163
174
  class=${u({
164
175
  field: !0,
165
176
  error: !!this.error,
166
- disabled: this.disabled
177
+ disabled: this.inactive
167
178
  })}
168
179
  >
169
180
  ${this.error ? l`<span id="error-message" class="visually-hidden">${this.error}</span>` : i}
@@ -177,7 +188,7 @@ class t extends c {
177
188
  aria-invalid=${this.error ? "true" : i}
178
189
  aria-describedby=${this.error ? "error-message" : i}
179
190
  .value=${g(this.value)}
180
- ?disabled=${this.disabled}
191
+ ?disabled=${this.inactive}
181
192
  ?readonly=${this.readonly}
182
193
  ?required=${this.required}
183
194
  @input=${this.onInput}
@@ -220,6 +231,9 @@ r([
220
231
  r([
221
232
  a({ type: Boolean, reflect: !0 })
222
233
  ], t.prototype, "disabled");
234
+ r([
235
+ b()
236
+ ], t.prototype, "formDisabled");
223
237
  r([
224
238
  a({ type: Boolean, reflect: !0 })
225
239
  ], t.prototype, "readonly");
@@ -235,7 +249,7 @@ r([
235
249
  r([
236
250
  a({ type: String, reflect: !0 })
237
251
  ], t.prototype, "resize");
238
- b("kt-textarea", t);
252
+ y("kt-textarea", t);
239
253
  export {
240
254
  t as KtTextarea
241
255
  };
@@ -1 +1 @@
1
- {"version":3,"file":"kt-textarea.js","sources":["../../../../src/components/forms/kt-textarea/kt-textarea.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, query } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { live } from 'lit/directives/live.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';\nimport '../../core/kt-icon/kt-icon.js';\n\n/**\n * A multi-line text field, with the same borderless fill and outline states as\n * `<kt-input>`.\n *\n * A character counter appears whenever `maxlength` is set — the field tells\n * the user where the limit is before the browser silently stops accepting\n * keystrokes.\n *\n * @element kt-textarea\n *\n * @csspart base - The field container.\n * @csspart control - The native `<textarea>`.\n * @csspart counter - The character counter.\n *\n * @fires kt-input - On every keystroke. `detail: { value }`.\n * @fires kt-change - When the value is committed. `detail: { value }`.\n */\nexport class KtTextarea 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 .field {\n display: flex;\n align-items: flex-start;\n width: 100%;\n min-height: var(--button-height);\n background-color: var(--surface-field);\n border-radius: var(--radius-input);\n /* A resting hairline. A field is a fill on --surface-field, which is\n one ramp step from the page in dark and almost the same colour in\n light — so on a card or inside a modal it simply disappeared and\n read as a bare native control.\n\n A border rather than an outline, because the control inside fills\n the field exactly and a coincident outline is painted over by the\n native widget. A border insets the control by its own width, so it\n cannot be covered. box-sizing: border-box keeps the outer size.\n\n The hover and focus rings stay outlines on top of it, and the\n transparent resting outline is what they animate from: without it\n outline-color starts at the initial value, which resolves to the\n text colour, and hover flashed near-white before settling. */\n border: var(--border-width) solid var(--border-field);\n outline: var(--outline-width) solid transparent;\n transition: outline-color var(--duration-instant);\n }\n\n .field:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .field:focus-within {\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error,\n .error:hover,\n .error:focus-within {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n .error textarea {\n color: var(--color-danger-text);\n }\n\n .disabled {\n background-color: var(--color-dark-14);\n pointer-events: none;\n }\n .disabled textarea {\n color: var(--text-disabled);\n }\n\n textarea {\n width: 100%;\n min-height: calc(var(--button-height) - var(--gap-element) * 2);\n padding: var(--text-area-padding);\n color: var(--text-body);\n font: var(--font-input);\n background: transparent;\n border: none;\n outline: none;\n resize: none;\n }\n\n :host([resize='vertical']) textarea {\n resize: vertical;\n }\n\n textarea::placeholder {\n color: var(--text-muted);\n }\n\n .meta {\n display: flex;\n flex: none;\n flex-direction: column;\n align-items: center;\n gap: var(--gap-element);\n margin: 10px var(--button-padding-x) 0 0;\n }\n\n .counter {\n color: var(--color-text-700);\n font: var(--font-normal-small);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n }\n\n .counter.at-limit {\n color: var(--color-danger-text);\n }\n\n .error-icon {\n display: flex;\n color: var(--color-danger-text);\n }\n `,\n ];\n\n @query('textarea')\n private control!: HTMLTextAreaElement;\n\n private internals: UsableInternals | null = null;\n private defaultValue = '';\n\n @property({ type: String })\n value = '';\n\n @property({ type: String })\n name = '';\n\n @property({ type: String })\n placeholder = '';\n\n @property({ type: Number })\n rows = 3;\n\n @property({ type: Number })\n maxlength?: number;\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: Boolean, reflect: true })\n readonly = false;\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Error message. A non-empty value puts the field in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n /** Accessible name, when no `<kt-label-input>` wraps the field. */\n @property({ type: String })\n label = '';\n\n /**\n * Whether the reader may drag the field taller.\n *\n * Off by default, as in the rest of Kanto: the grip is drawn by the operating\n * system, lands on the field's rounded corner and belongs to no design\n * system — and a field the layout sized is not usually the reader's to\n * resize. Turn it on where the content genuinely varies.\n */\n @property({ type: String, reflect: true })\n resize: 'vertical' | 'none' = 'none';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n setFormValue(this.internals, this.value);\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.length === 0;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? strings().required : ''),\n );\n }\n }\n\n formResetCallback(): void {\n this.value = this.defaultValue;\n }\n\n formStateRestoreCallback(state: string): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.control?.focus(options);\n }\n\n override blur(): void {\n this.control?.blur();\n }\n\n private onInput(event: Event): void {\n this.value = (event.target as HTMLTextAreaElement).value;\n emit(this, 'kt-input', { value: this.value });\n }\n\n private onChange(event: Event): void {\n event.stopPropagation();\n emit(this, 'kt-change', { value: this.value });\n }\n\n override render(): TemplateResult {\n const showCounter = this.maxlength !== undefined;\n const atLimit = this.maxlength !== undefined && this.value.length >= this.maxlength;\n\n return html`<div\n part=\"base\"\n class=${classMap({\n field: true,\n error: Boolean(this.error),\n disabled: this.disabled,\n })}\n >\n ${\n this.error\n ? html`<span id=\"error-message\" class=\"visually-hidden\">${this.error}</span>`\n : nothing\n }\n <textarea\n part=\"control\"\n name=${this.name || nothing}\n rows=${this.rows}\n maxlength=${this.maxlength ?? nothing}\n placeholder=${this.placeholder || nothing}\n aria-label=${this.label || nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n aria-describedby=${this.error ? 'error-message' : nothing}\n .value=${live(this.value)}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n @input=${this.onInput}\n @change=${this.onChange}\n ></textarea>\n\n ${\n this.error || showCounter\n ? html`<div class=\"meta\">\n ${\n this.error\n ? html`<span class=\"error-icon\" title=${this.error}>\n <kt-icon name=\"circle-alert\" size=\"18\" label=${this.error}></kt-icon>\n </span>`\n : nothing\n }\n ${\n showCounter\n ? html`<span\n part=\"counter\"\n class=${classMap({ counter: true, 'at-limit': atLimit })}\n aria-live=\"polite\"\n >\n ${this.value.length} / ${this.maxlength}\n </span>`\n : nothing\n }\n </div>`\n : nothing\n }\n </div>`;\n }\n}\n\ndefineElement('kt-textarea', KtTextarea);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-textarea': KtTextarea;\n }\n}\n"],"names":["KtTextarea","KtElement","css","attachFormInternals","setFormValue","changed","missing","setValidity","strings","state","options","event","emit","showCounter","atLimit","html","classMap","nothing","live","__decorateClass","query","property","defineElement"],"mappings":"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"}
1
+ {"version":3,"file":"kt-textarea.js","sources":["../../../../src/components/forms/kt-textarea/kt-textarea.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { live } from 'lit/directives/live.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';\nimport '../../core/kt-icon/kt-icon.js';\n\n/**\n * A multi-line text field, with the same borderless fill and outline states as\n * `<kt-input>`.\n *\n * A character counter appears whenever `maxlength` is set — the field tells\n * the user where the limit is before the browser silently stops accepting\n * keystrokes.\n *\n * @element kt-textarea\n *\n * @csspart base - The field container.\n * @csspart control - The native `<textarea>`.\n * @csspart counter - The character counter.\n *\n * @fires kt-input - On every keystroke. `detail: { value }`.\n * @fires kt-change - When the value is committed. `detail: { value }`.\n */\nexport class KtTextarea 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 .field {\n display: flex;\n align-items: flex-start;\n width: 100%;\n min-height: var(--button-height);\n background-color: var(--surface-field);\n border-radius: var(--radius-input);\n /* A resting hairline. A field is a fill on --surface-field, which is\n one ramp step from the page in dark and almost the same colour in\n light — so on a card or inside a modal it simply disappeared and\n read as a bare native control.\n\n A border rather than an outline, because the control inside fills\n the field exactly and a coincident outline is painted over by the\n native widget. A border insets the control by its own width, so it\n cannot be covered. box-sizing: border-box keeps the outer size.\n\n The hover and focus rings stay outlines on top of it, and the\n transparent resting outline is what they animate from: without it\n outline-color starts at the initial value, which resolves to the\n text colour, and hover flashed near-white before settling. */\n border: var(--border-width) solid var(--border-field);\n outline: var(--outline-width) solid transparent;\n transition: outline-color var(--duration-instant);\n }\n\n .field:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .field:focus-within {\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error,\n .error:hover,\n .error:focus-within {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n .error textarea {\n color: var(--color-danger-text);\n }\n\n .disabled {\n background-color: var(--color-dark-14);\n pointer-events: none;\n }\n .disabled textarea {\n color: var(--text-disabled);\n }\n\n textarea {\n width: 100%;\n min-height: calc(var(--button-height) - var(--gap-element) * 2);\n padding: var(--text-area-padding);\n color: var(--text-body);\n font: var(--font-input);\n background: transparent;\n border: none;\n outline: none;\n resize: none;\n }\n\n :host([resize='vertical']) textarea {\n resize: vertical;\n }\n\n textarea::placeholder {\n color: var(--text-muted);\n }\n\n .meta {\n display: flex;\n flex: none;\n flex-direction: column;\n align-items: center;\n gap: var(--gap-element);\n margin: 10px var(--button-padding-x) 0 0;\n }\n\n .counter {\n color: var(--color-text-700);\n font: var(--font-normal-small);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n }\n\n .counter.at-limit {\n color: var(--color-danger-text);\n }\n\n .error-icon {\n display: flex;\n color: var(--color-danger-text);\n }\n `,\n ];\n\n @query('textarea')\n private control!: HTMLTextAreaElement;\n\n private internals: UsableInternals | null = null;\n private defaultValue = '';\n\n @property({ type: String })\n value = '';\n\n @property({ type: String })\n name = '';\n\n @property({ type: String })\n placeholder = '';\n\n @property({ type: Number })\n rows = 3;\n\n @property({ type: Number })\n maxlength?: number;\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 readonly = false;\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Error message. A non-empty value puts the field in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n /** Accessible name, when no `<kt-label-input>` wraps the field. */\n @property({ type: String })\n label = '';\n\n /**\n * Whether the reader may drag the field taller.\n *\n * Off by default, as in the rest of Kanto: the grip is drawn by the operating\n * system, lands on the field's rounded corner and belongs to no design\n * system — and a field the layout sized is not usually the reader's to\n * resize. Turn it on where the content genuinely varies.\n */\n @property({ type: String, reflect: true })\n resize: 'vertical' | 'none' = 'none';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n setFormValue(this.internals, this.value);\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.length === 0;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? strings().required : ''),\n );\n }\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): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.control?.focus(options);\n }\n\n override blur(): void {\n this.control?.blur();\n }\n\n private onInput(event: Event): void {\n this.value = (event.target as HTMLTextAreaElement).value;\n emit(this, 'kt-input', { value: this.value });\n }\n\n private onChange(event: Event): void {\n event.stopPropagation();\n emit(this, 'kt-change', { value: this.value });\n }\n\n override render(): TemplateResult {\n const showCounter = this.maxlength !== undefined;\n const atLimit = this.maxlength !== undefined && this.value.length >= this.maxlength;\n\n return html`<div\n part=\"base\"\n class=${classMap({\n field: true,\n error: Boolean(this.error),\n disabled: this.inactive,\n })}\n >\n ${\n this.error\n ? html`<span id=\"error-message\" class=\"visually-hidden\">${this.error}</span>`\n : nothing\n }\n <textarea\n part=\"control\"\n name=${this.name || nothing}\n rows=${this.rows}\n maxlength=${this.maxlength ?? nothing}\n placeholder=${this.placeholder || nothing}\n aria-label=${this.label || nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n aria-describedby=${this.error ? 'error-message' : nothing}\n .value=${live(this.value)}\n ?disabled=${this.inactive}\n ?readonly=${this.readonly}\n ?required=${this.required}\n @input=${this.onInput}\n @change=${this.onChange}\n ></textarea>\n\n ${\n this.error || showCounter\n ? html`<div class=\"meta\">\n ${\n this.error\n ? html`<span class=\"error-icon\" title=${this.error}>\n <kt-icon name=\"circle-alert\" size=\"18\" label=${this.error}></kt-icon>\n </span>`\n : nothing\n }\n ${\n showCounter\n ? html`<span\n part=\"counter\"\n class=${classMap({ counter: true, 'at-limit': atLimit })}\n aria-live=\"polite\"\n >\n ${this.value.length} / ${this.maxlength}\n </span>`\n : nothing\n }\n </div>`\n : nothing\n }\n </div>`;\n }\n}\n\ndefineElement('kt-textarea', KtTextarea);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-textarea': KtTextarea;\n }\n}\n"],"names":["KtTextarea","KtElement","css","attachFormInternals","setFormValue","changed","missing","setValidity","strings","disabled","state","options","event","emit","showCounter","atLimit","html","classMap","nothing","live","__decorateClass","query","property","defineElement"],"mappings":"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"}
@@ -31,6 +31,10 @@ export declare class KtToggle extends KtElement {
31
31
  private defaultChecked;
32
32
  checked: boolean;
33
33
  disabled: boolean;
34
+ /** Disabled by an enclosing `<fieldset>`, which leaves `disabled` alone. */
35
+ private formDisabled;
36
+ /** Whether the control is off, by its own `disabled` or by its form. */
37
+ private get inactive();
34
38
  size: KtToggleSize;
35
39
  name: string;
36
40
  /** Submitted when checked, as for a native checkbox. */
@@ -41,6 +45,11 @@ export declare class KtToggle extends KtElement {
41
45
  willUpdate(changed: PropertyValues<this>): void;
42
46
  private syncFormValue;
43
47
  formResetCallback(): void;
48
+ /**
49
+ * Called by the platform when the control's disabled state changes — its
50
+ * own `disabled`, or an ancestor `<fieldset disabled>` it cannot see.
51
+ */
52
+ formDisabledCallback(disabled: boolean): void;
44
53
  formStateRestoreCallback(state: string): void;
45
54
  focus(options?: FocusOptions): void;
46
55
  private toggle;