kanto-ds 1.0.1 → 1.2.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 (90) hide show
  1. package/README.md +20 -2
  2. package/dist/chunks/form-control-CxjBTt1c.js.map +1 -1
  3. package/dist/chunks/kt-element-B_jjQDhg.js +38 -0
  4. package/dist/chunks/kt-element-B_jjQDhg.js.map +1 -0
  5. package/dist/components/core/kt-avatar/kt-avatar.js +9 -6
  6. package/dist/components/core/kt-avatar/kt-avatar.js.map +1 -1
  7. package/dist/components/core/kt-badge/kt-badge.js +17 -17
  8. package/dist/components/core/kt-badge/kt-badge.js.map +1 -1
  9. package/dist/components/core/kt-button/kt-button.d.ts +7 -0
  10. package/dist/components/core/kt-button/kt-button.js +68 -60
  11. package/dist/components/core/kt-button/kt-button.js.map +1 -1
  12. package/dist/components/core/kt-card/kt-card.js +1 -1
  13. package/dist/components/core/kt-code/kt-code.js +12 -12
  14. package/dist/components/core/kt-code/kt-code.js.map +1 -1
  15. package/dist/components/core/kt-icon/kt-icon.js +1 -1
  16. package/dist/components/core/kt-kbd/kt-kbd.js +14 -14
  17. package/dist/components/core/kt-kbd/kt-kbd.js.map +1 -1
  18. package/dist/components/core/kt-split-button/kt-split-button.js +3 -3
  19. package/dist/components/core/kt-split-button/kt-split-button.js.map +1 -1
  20. package/dist/components/data/kt-chart/kt-chart.js +1 -1
  21. package/dist/components/data/kt-meter/kt-meter.js +1 -1
  22. package/dist/components/data/kt-pagination/kt-pagination.js +1 -1
  23. package/dist/components/data/kt-stat/kt-stat.js +5 -5
  24. package/dist/components/data/kt-stat/kt-stat.js.map +1 -1
  25. package/dist/components/data/kt-table/kt-table.js +2 -2
  26. package/dist/components/data/kt-table/kt-table.js.map +1 -1
  27. package/dist/components/data/kt-timeline/kt-timeline.js +1 -1
  28. package/dist/components/feedback/kt-alert/kt-alert.js +26 -26
  29. package/dist/components/feedback/kt-alert/kt-alert.js.map +1 -1
  30. package/dist/components/feedback/kt-empty-state/kt-empty-state.js +1 -1
  31. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +2 -2
  32. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js.map +1 -1
  33. package/dist/components/feedback/kt-skeleton/kt-skeleton.js +1 -1
  34. package/dist/components/feedback/kt-toast/kt-toast.js +22 -22
  35. package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -1
  36. package/dist/components/feedback/kt-toast-container/kt-toast-container.js +1 -1
  37. package/dist/components/feedback/kt-tooltip/kt-tooltip.js +1 -1
  38. package/dist/components/forms/kt-drag-drop/kt-drag-drop.d.ts +11 -1
  39. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +69 -36
  40. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -1
  41. package/dist/components/forms/kt-form/kt-form.js +1 -1
  42. package/dist/components/forms/kt-input/kt-input.js +95 -91
  43. package/dist/components/forms/kt-input/kt-input.js.map +1 -1
  44. package/dist/components/forms/kt-input-menu/kt-input-menu.d.ts +10 -1
  45. package/dist/components/forms/kt-input-menu/kt-input-menu.js +83 -53
  46. package/dist/components/forms/kt-input-menu/kt-input-menu.js.map +1 -1
  47. package/dist/components/forms/kt-label-input/kt-label-input.js +2 -2
  48. package/dist/components/forms/kt-label-input/kt-label-input.js.map +1 -1
  49. package/dist/components/forms/kt-select/kt-select.js +2 -2
  50. package/dist/components/forms/kt-select/kt-select.js.map +1 -1
  51. package/dist/components/forms/kt-textarea/kt-textarea.js +15 -13
  52. package/dist/components/forms/kt-textarea/kt-textarea.js.map +1 -1
  53. package/dist/components/forms/kt-toggle/kt-toggle.js +8 -7
  54. package/dist/components/forms/kt-toggle/kt-toggle.js.map +1 -1
  55. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +1 -1
  56. package/dist/components/navigation/kt-header/kt-header.js +1 -1
  57. package/dist/components/navigation/kt-page-header/kt-page-header.js +18 -18
  58. package/dist/components/navigation/kt-page-header/kt-page-header.js.map +1 -1
  59. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.d.ts +10 -1
  60. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +88 -62
  61. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js.map +1 -1
  62. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +5 -5
  63. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js.map +1 -1
  64. package/dist/components/navigation/kt-tabs/kt-tabs.js +1 -1
  65. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +3 -3
  66. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js.map +1 -1
  67. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +1 -1
  68. package/dist/components/overlays/kt-collapsible/kt-collapsible.js +1 -1
  69. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +1 -1
  70. package/dist/components/overlays/kt-dropdown/kt-dropdown.d.ts +13 -0
  71. package/dist/components/overlays/kt-dropdown/kt-dropdown.js +74 -59
  72. package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -1
  73. package/dist/components/overlays/kt-modal/kt-modal.js +1 -1
  74. package/dist/components/overlays/kt-side-panel/kt-side-panel.js +1 -1
  75. package/dist/custom-elements.json +11791 -0
  76. package/dist/index.js +1 -1
  77. package/dist/internal/form-control.d.ts +7 -2
  78. package/dist/react/index.js.map +1 -1
  79. package/dist/react/jsx.d.ts +213 -0
  80. package/dist/react/jsx.js +2 -0
  81. package/dist/react/jsx.js.map +1 -0
  82. package/dist/tokens/README.md +7 -3
  83. package/dist/tokens/colors.css +24 -5
  84. package/dist/tokens/theme-light.css +18 -0
  85. package/dist/vscode.css-custom-data.json +154 -0
  86. package/dist/vscode.html-custom-data.json +1136 -0
  87. package/dist/web-types.json +3186 -0
  88. package/package.json +28 -9
  89. package/dist/chunks/kt-element-CcMLO5e8.js +0 -28
  90. package/dist/chunks/kt-element-CcMLO5e8.js.map +0 -1
@@ -0,0 +1,3186 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
3
+ "name": "kanto-ds",
4
+ "version": "1.2.0",
5
+ "description-markup": "markdown",
6
+ "contributions": {
7
+ "html": {
8
+ "elements": [
9
+ {
10
+ "name": "kt-avatar",
11
+ "description": "A person or an organisation, as a picture or as their initials.\n\nThe fallback is not decoration: most rows in most products have no photo, so\nthe initials path is the one that renders. It picks a colour from the name,\nwhich means the same person is the same colour on every screen and the eye\ncan use it.\n\n---\n\n\n### **CSS Parts:**\n - **base** - The avatar circle.\n- **image** - The `<img>`, when `src` is set and loads.",
12
+ "doc-url": "",
13
+ "attributes": [
14
+ {
15
+ "name": "name",
16
+ "description": "The person's name. Drives the initials, the colour and the label.",
17
+ "value": { "type": "string", "default": "''" }
18
+ },
19
+ {
20
+ "name": "src",
21
+ "description": "Photo. Falls back to initials if it is missing or fails to load.",
22
+ "value": { "type": "string", "default": "''" }
23
+ },
24
+ {
25
+ "name": "size",
26
+ "value": { "type": "KtAvatarSize", "default": "'medium'" }
27
+ },
28
+ {
29
+ "name": "square",
30
+ "description": "Rounds to the card radius instead of a circle — for organisations.",
31
+ "value": { "type": "boolean", "default": "false" }
32
+ },
33
+ {
34
+ "name": "status",
35
+ "description": "Presence dot. Omit for none.",
36
+ "value": { "type": "KtAvatarStatus | undefined" }
37
+ },
38
+ {
39
+ "name": "color",
40
+ "description": "Overrides the colour picked from the name.",
41
+ "value": { "type": "string", "default": "''" }
42
+ }
43
+ ],
44
+ "events": [],
45
+ "js": {
46
+ "properties": [
47
+ {
48
+ "name": "name",
49
+ "description": "The person's name. Drives the initials, the colour and the label.",
50
+ "type": "string"
51
+ },
52
+ {
53
+ "name": "src",
54
+ "description": "Photo. Falls back to initials if it is missing or fails to load.",
55
+ "type": "string"
56
+ },
57
+ { "name": "size", "type": "KtAvatarSize" },
58
+ {
59
+ "name": "square",
60
+ "description": "Rounds to the card radius instead of a circle — for organisations.",
61
+ "type": "boolean"
62
+ },
63
+ {
64
+ "name": "status",
65
+ "description": "Presence dot. Omit for none.",
66
+ "type": "KtAvatarStatus | undefined"
67
+ },
68
+ {
69
+ "name": "color",
70
+ "description": "Overrides the colour picked from the name.",
71
+ "type": "string"
72
+ }
73
+ ],
74
+ "events": []
75
+ }
76
+ },
77
+ {
78
+ "name": "kt-badge",
79
+ "description": "A compact label: a pill `tag`, a monospaced `code` token, a `category`\ntinted with a colour of your choosing, or a `count`.\n\nTwo independent axes, because they answer different questions. `variant` is\nthe **shape** — what kind of thing this is. `tone` is the **colour** — what\nit means. A tag can be neutral or dangerous; so can a count. Folding them\ninto one list would give you nine variants and no way to say \"a tag, but\nthis one is a warning\".\n\n`count` is the exception that carries no border, because a number pinned to\na nav item is not a label with an outline — it is a mark on the thing it\ncounts.\n\n---\n\n\n### **Events:**\n - **kt-badge-click** - A `clickable` badge was activated. Cancelable.\n- **kt-remove** - The remove button was pressed. Cancelable: cancel it and remove the badge yourself once the server agrees.\n\n### **Slots:**\n - _default_ - The text. Falls back to the `label` attribute.\n\n### **CSS Properties:**\n - **--kt-badge-color** - Category hue. The fill is this colour at 20%. _(default: undefined)_\n\n### **CSS Parts:**\n - **base** - The container.\n- **remove** - The remove button, when `removable`.",
80
+ "doc-url": "",
81
+ "attributes": [
82
+ {
83
+ "name": "variant",
84
+ "description": "The shape: what kind of thing this is.",
85
+ "value": { "type": "KtBadgeVariant", "default": "'tag'" }
86
+ },
87
+ {
88
+ "name": "tone",
89
+ "description": "The colour: what it means. Independent of `variant`.",
90
+ "value": { "type": "KtBadgeTone", "default": "'neutral'" }
91
+ },
92
+ {
93
+ "name": "size",
94
+ "value": { "type": "KtBadgeSize", "default": "'medium'" }
95
+ },
96
+ {
97
+ "name": "label",
98
+ "description": "Badge text. The default slot wins when both are present.",
99
+ "value": { "type": "string", "default": "''" }
100
+ },
101
+ {
102
+ "name": "color",
103
+ "description": "Category hue: any CSS colour. The fill is this colour at 20%.",
104
+ "value": { "type": "string", "default": "''" }
105
+ },
106
+ {
107
+ "name": "icon",
108
+ "description": "Lucide icon name, before the text.",
109
+ "value": { "type": "string", "default": "''" }
110
+ },
111
+ {
112
+ "name": "clickable",
113
+ "value": { "type": "boolean", "default": "false" }
114
+ },
115
+ {
116
+ "name": "removable",
117
+ "description": "Adds a remove button. Fires a cancelable `kt-remove`.",
118
+ "value": { "type": "boolean", "default": "false" }
119
+ },
120
+ {
121
+ "name": "max",
122
+ "description": "Caps a numeric label: `max=\"99\"` shows `99+`.\nIgnored when the content is not a number.",
123
+ "value": { "type": "number | undefined" }
124
+ },
125
+ {
126
+ "name": "error",
127
+ "description": "Shorthand for `tone=\"danger\"`, kept from the field components.",
128
+ "value": { "type": "boolean", "default": "false" }
129
+ }
130
+ ],
131
+ "slots": [
132
+ {
133
+ "name": "",
134
+ "description": "The text. Falls back to the `label` attribute."
135
+ }
136
+ ],
137
+ "events": [
138
+ {
139
+ "name": "kt-badge-click",
140
+ "description": "A `clickable` badge was activated. Cancelable."
141
+ },
142
+ {
143
+ "name": "kt-remove",
144
+ "description": "The remove button was pressed. Cancelable: cancel it and remove the badge yourself once the server agrees."
145
+ }
146
+ ],
147
+ "js": {
148
+ "properties": [
149
+ {
150
+ "name": "variant",
151
+ "description": "The shape: what kind of thing this is.",
152
+ "type": "KtBadgeVariant"
153
+ },
154
+ {
155
+ "name": "tone",
156
+ "description": "The colour: what it means. Independent of `variant`.",
157
+ "type": "KtBadgeTone"
158
+ },
159
+ { "name": "size", "type": "KtBadgeSize" },
160
+ {
161
+ "name": "label",
162
+ "description": "Badge text. The default slot wins when both are present.",
163
+ "type": "string"
164
+ },
165
+ {
166
+ "name": "color",
167
+ "description": "Category hue: any CSS colour. The fill is this colour at 20%.",
168
+ "type": "string"
169
+ },
170
+ {
171
+ "name": "icon",
172
+ "description": "Lucide icon name, before the text.",
173
+ "type": "string"
174
+ },
175
+ { "name": "clickable", "type": "boolean" },
176
+ {
177
+ "name": "removable",
178
+ "description": "Adds a remove button. Fires a cancelable `kt-remove`.",
179
+ "type": "boolean"
180
+ },
181
+ {
182
+ "name": "max",
183
+ "description": "Caps a numeric label: `max=\"99\"` shows `99+`.\nIgnored when the content is not a number.",
184
+ "type": "number | undefined"
185
+ },
186
+ {
187
+ "name": "error",
188
+ "description": "Shorthand for `tone=\"danger\"`, kept from the field components.",
189
+ "type": "boolean"
190
+ }
191
+ ],
192
+ "events": [
193
+ {
194
+ "name": "kt-badge-click",
195
+ "description": "A `clickable` badge was activated. Cancelable."
196
+ },
197
+ {
198
+ "name": "kt-remove",
199
+ "description": "The remove button was pressed. Cancelable: cancel it and remove the badge yourself once the server agrees."
200
+ }
201
+ ]
202
+ }
203
+ },
204
+ {
205
+ "name": "kt-button",
206
+ "description": "The Kanto action button.\n\nTen variants; `primary` for the one action a screen is about, `secondary`\n(a soft indigo tint) for everything supporting it. The semantic variants —\n`danger`, `warning`, `info`, `success` — are tinted fills with coloured\ntext; `delete` is the only solid red, reserved for irreversible actions.\n\nSetting `icon` with no slotted text produces a square icon-only button,\nwhich then requires a `label`.\n\n---\n\n\n### **Methods:**\n - **focus(options: _FocusOptions_): _void_** - Moves focus to the button.\n\n### **Slots:**\n - _default_ - The button label.\n\n### **CSS Parts:**\n - **button** - The native `<button>`.\n- **icon** - The icon, when `icon` is set.",
207
+ "doc-url": "",
208
+ "attributes": [
209
+ {
210
+ "name": "variant",
211
+ "description": "Visual variant.",
212
+ "value": { "type": "KtButtonVariant", "default": "'primary'" }
213
+ },
214
+ {
215
+ "name": "size",
216
+ "description": "Height: 32 / 40 / 48px at the desktop scale.",
217
+ "value": { "type": "KtButtonSize", "default": "'medium'" }
218
+ },
219
+ {
220
+ "name": "disabled",
221
+ "value": { "type": "boolean", "default": "false" }
222
+ },
223
+ {
224
+ "name": "type",
225
+ "description": "Native button behaviour. `submit` and `reset` act on the enclosing form.",
226
+ "value": { "type": "KtButtonType", "default": "'button'" }
227
+ },
228
+ {
229
+ "name": "icon",
230
+ "description": "Lucide icon name, kebab-case.",
231
+ "value": { "type": "string", "default": "''" }
232
+ },
233
+ {
234
+ "name": "icon-position",
235
+ "description": "Which side of the label the icon sits on.",
236
+ "value": { "type": "'left' | 'right'", "default": "'left'" }
237
+ },
238
+ {
239
+ "name": "label",
240
+ "description": "Accessible name. Required for an icon-only button.",
241
+ "value": { "type": "string", "default": "''" }
242
+ },
243
+ {
244
+ "name": "full-width",
245
+ "description": "Stretches the button to the width of its container.",
246
+ "value": { "type": "boolean", "default": "false" }
247
+ },
248
+ {
249
+ "name": "name",
250
+ "description": "Submitted with the form, as on a native button.",
251
+ "value": { "type": "string", "default": "''" }
252
+ },
253
+ { "name": "value", "value": { "type": "string", "default": "''" } }
254
+ ],
255
+ "slots": [{ "name": "", "description": "The button label." }],
256
+ "events": [],
257
+ "js": {
258
+ "properties": [
259
+ {
260
+ "name": "variant",
261
+ "description": "Visual variant.",
262
+ "type": "KtButtonVariant"
263
+ },
264
+ {
265
+ "name": "size",
266
+ "description": "Height: 32 / 40 / 48px at the desktop scale.",
267
+ "type": "KtButtonSize"
268
+ },
269
+ { "name": "disabled", "type": "boolean" },
270
+ {
271
+ "name": "type",
272
+ "description": "Native button behaviour. `submit` and `reset` act on the enclosing form.",
273
+ "type": "KtButtonType"
274
+ },
275
+ {
276
+ "name": "icon",
277
+ "description": "Lucide icon name, kebab-case.",
278
+ "type": "string"
279
+ },
280
+ {
281
+ "name": "iconPosition",
282
+ "description": "Which side of the label the icon sits on.",
283
+ "type": "'left' | 'right'"
284
+ },
285
+ {
286
+ "name": "label",
287
+ "description": "Accessible name. Required for an icon-only button.",
288
+ "type": "string"
289
+ },
290
+ {
291
+ "name": "popup",
292
+ "description": "The kind of popup this button opens, as `aria-haspopup` on the inner\nbutton. Set by `<kt-dropdown>` on its trigger; rarely by hand.",
293
+ "type": "'menu' | 'listbox' | 'dialog' | undefined"
294
+ },
295
+ {
296
+ "name": "expanded",
297
+ "description": "Whether the popup or region this button controls is open, as `aria-expanded`.",
298
+ "type": "boolean | undefined"
299
+ },
300
+ {
301
+ "name": "fullWidth",
302
+ "description": "Stretches the button to the width of its container.",
303
+ "type": "boolean"
304
+ },
305
+ {
306
+ "name": "name",
307
+ "description": "Submitted with the form, as on a native button.",
308
+ "type": "string"
309
+ },
310
+ { "name": "value", "type": "string" }
311
+ ],
312
+ "events": []
313
+ }
314
+ },
315
+ {
316
+ "name": "kt-card",
317
+ "description": "A surface for a block of related content: 12px radius, a 1px border, 24px of\npadding and a 20px internal gap.\n\nSet `clickable` to turn the whole card into a control. Unlike the div-with-a\n-click-handler this replaces, a clickable card is reachable by keyboard,\nannounces itself as a button, and responds to Enter and Space.\n\n---\n\n\n### **Events:**\n - **kt-card-click** - The card was activated, by pointer or keyboard. Only fired when `clickable` is set.\n\n### **Slots:**\n - _default_ - The card body.\n- **header** - Above the body.\n- **footer** - Below the body.\n- **media** - Replaces the `image` attribute for anything that is not a plain `<img>` — a chart, a map, a video.\n\n### **CSS Parts:**\n - **base** - The card container.\n- **media** - The image or media well.\n- **body** - The header/content/footer column.",
318
+ "doc-url": "",
319
+ "attributes": [
320
+ {
321
+ "name": "clickable",
322
+ "description": "Makes the card a keyboard-reachable control.",
323
+ "value": { "type": "boolean", "default": "false" }
324
+ },
325
+ {
326
+ "name": "selected",
327
+ "description": "Marks the card as chosen — one of a set of filters, a picked plan.\n\nPairs with `clickable`: a card the user cannot toggle has no business\nlooking toggled.",
328
+ "value": { "type": "boolean", "default": "false" }
329
+ },
330
+ {
331
+ "name": "image",
332
+ "description": "Convenience image. For anything richer, use the `media` slot.",
333
+ "value": { "type": "string", "default": "''" }
334
+ },
335
+ {
336
+ "name": "image-alt",
337
+ "description": "Alternative text for `image`. Empty means decorative.",
338
+ "value": { "type": "string", "default": "''" }
339
+ },
340
+ {
341
+ "name": "image-position",
342
+ "value": { "type": "KtCardImagePosition", "default": "'left'" }
343
+ },
344
+ {
345
+ "name": "image-size",
346
+ "description": "Width (left/right) or height (top/bottom) of the media well.",
347
+ "value": { "type": "string", "default": "'120px'" }
348
+ }
349
+ ],
350
+ "slots": [
351
+ { "name": "", "description": "The card body." },
352
+ { "name": "header", "description": "Above the body." },
353
+ { "name": "footer", "description": "Below the body." },
354
+ {
355
+ "name": "media",
356
+ "description": "Replaces the `image` attribute for anything that is not a plain `<img>` — a chart, a map, a video."
357
+ }
358
+ ],
359
+ "events": [
360
+ {
361
+ "name": "kt-card-click",
362
+ "description": "The card was activated, by pointer or keyboard. Only fired when `clickable` is set."
363
+ }
364
+ ],
365
+ "js": {
366
+ "properties": [
367
+ {
368
+ "name": "clickable",
369
+ "description": "Makes the card a keyboard-reachable control.",
370
+ "type": "boolean"
371
+ },
372
+ {
373
+ "name": "selected",
374
+ "description": "Marks the card as chosen — one of a set of filters, a picked plan.\n\nPairs with `clickable`: a card the user cannot toggle has no business\nlooking toggled.",
375
+ "type": "boolean"
376
+ },
377
+ {
378
+ "name": "image",
379
+ "description": "Convenience image. For anything richer, use the `media` slot.",
380
+ "type": "string"
381
+ },
382
+ {
383
+ "name": "imageAlt",
384
+ "description": "Alternative text for `image`. Empty means decorative.",
385
+ "type": "string"
386
+ },
387
+ { "name": "imagePosition", "type": "KtCardImagePosition" },
388
+ {
389
+ "name": "imageSize",
390
+ "description": "Width (left/right) or height (top/bottom) of the media well.",
391
+ "type": "string"
392
+ }
393
+ ],
394
+ "events": [
395
+ {
396
+ "name": "kt-card-click",
397
+ "description": "The card was activated, by pointer or keyboard. Only fired when `clickable` is set."
398
+ }
399
+ ]
400
+ }
401
+ },
402
+ {
403
+ "name": "kt-code",
404
+ "description": "A block of code on a recessed surface, with its language and a copy button.\n\nThe element owns the chrome — surface, label, scrolling, copy — and nothing\nelse. **Highlighting is the caller's**: slot in whatever markup a highlighter\nproduced, or plain text for none. A design system that bundled a syntax\nhighlighter would be picking your bundle size and your language set for you.\n\n```html\n<kt-code language=\"js\">const total = items.length;</kt-code>\n\n<kt-code language=\"ts\" copy>\n <span class=\"hljs-keyword\">const</span> total = items.length;\n</kt-code>\n```\n\nFor a token or an identifier inside a sentence, reach for\n`<kt-badge variant=\"code\">` instead — this is for blocks.\n\n---\n\n\n### **Events:**\n - **kt-copy** - The copy button was pressed. `detail: { code }`.\n\n### **Slots:**\n - _default_ - The code. Plain text, or a highlighter's markup.\n\n### **CSS Parts:**\n - **base** - The container.\n- **header** - The language row.\n- **pre** - The scrolling `<pre>`.",
405
+ "doc-url": "",
406
+ "attributes": [
407
+ {
408
+ "name": "language",
409
+ "description": "Language label, shown uppercase. Purely informative.",
410
+ "value": { "type": "string", "default": "''" }
411
+ },
412
+ {
413
+ "name": "copy",
414
+ "description": "Shows the copy button.",
415
+ "value": { "type": "boolean", "default": "false" }
416
+ },
417
+ {
418
+ "name": "label",
419
+ "description": "Accessible name for the block, when the language alone is not enough.",
420
+ "value": { "type": "string", "default": "''" }
421
+ }
422
+ ],
423
+ "slots": [
424
+ {
425
+ "name": "",
426
+ "description": "The code. Plain text, or a highlighter's markup."
427
+ }
428
+ ],
429
+ "events": [
430
+ {
431
+ "name": "kt-copy",
432
+ "description": "The copy button was pressed. `detail: { code }`."
433
+ }
434
+ ],
435
+ "js": {
436
+ "properties": [
437
+ {
438
+ "name": "language",
439
+ "description": "Language label, shown uppercase. Purely informative.",
440
+ "type": "string"
441
+ },
442
+ {
443
+ "name": "copy",
444
+ "description": "Shows the copy button.",
445
+ "type": "boolean"
446
+ },
447
+ {
448
+ "name": "label",
449
+ "description": "Accessible name for the block, when the language alone is not enough.",
450
+ "type": "string"
451
+ },
452
+ {
453
+ "name": "code",
454
+ "description": "The code as plain text, whatever markup it is wrapped in.",
455
+ "type": "string"
456
+ }
457
+ ],
458
+ "events": [
459
+ {
460
+ "name": "kt-copy",
461
+ "description": "The copy button was pressed. `detail: { code }`."
462
+ }
463
+ ]
464
+ }
465
+ },
466
+ {
467
+ "name": "kt-icon",
468
+ "description": "A Lucide icon, resolved from the registry by name.\n\nThe icon inherits `currentColor`, so it is coloured by setting `color` on\nthe element or on any ancestor — there is no colour attribute to keep in\nsync with the surrounding text.\n\nUnknown names render nothing but still occupy their box, so a typo shifts no\nlayout while you find it in the console.\n\n---\n\n\n### **CSS Parts:**\n - **svg** - The `<svg>` root.",
469
+ "doc-url": "",
470
+ "attributes": [
471
+ {
472
+ "name": "name",
473
+ "description": "Icon name, kebab-case: `chevron-down`, `circle-alert`.",
474
+ "value": { "type": "string", "default": "''" }
475
+ },
476
+ {
477
+ "name": "size",
478
+ "description": "Width and height in pixels.",
479
+ "value": { "type": "number", "default": "24" }
480
+ },
481
+ {
482
+ "name": "stroke-width",
483
+ "description": "Stroke width passed to the SVG.",
484
+ "value": { "type": "number", "default": "2" }
485
+ },
486
+ {
487
+ "name": "label",
488
+ "description": "Accessible name. Set it when the icon carries meaning on its own; leave it\noff — the default — when adjacent text already says what this is, and the\nicon is hidden from assistive technology.",
489
+ "value": { "type": "string", "default": "''" }
490
+ }
491
+ ],
492
+ "events": [],
493
+ "js": {
494
+ "properties": [
495
+ {
496
+ "name": "name",
497
+ "description": "Icon name, kebab-case: `chevron-down`, `circle-alert`.",
498
+ "type": "string"
499
+ },
500
+ {
501
+ "name": "size",
502
+ "description": "Width and height in pixels.",
503
+ "type": "number"
504
+ },
505
+ {
506
+ "name": "strokeWidth",
507
+ "description": "Stroke width passed to the SVG.",
508
+ "type": "number"
509
+ },
510
+ {
511
+ "name": "label",
512
+ "description": "Accessible name. Set it when the icon carries meaning on its own; leave it\noff — the default — when adjacent text already says what this is, and the\nicon is hidden from assistive technology.",
513
+ "type": "string"
514
+ }
515
+ ],
516
+ "events": []
517
+ }
518
+ },
519
+ {
520
+ "name": "kt-kbd",
521
+ "description": "A keyboard shortcut.\n\nRenders per platform: `⌘ K` on a Mac, `Ctrl K` elsewhere. A shortcut printed\nwith the wrong modifier is worse than none — the reader tries it, it does not\nwork, and they stop trusting the hints.\n\n---\n\n\n### **Slots:**\n - _default_ - The key, when `keys` is not used.\n\n### **CSS Parts:**\n - **base** - The wrapper.\n- **key** - One key.",
522
+ "doc-url": "",
523
+ "attributes": [
524
+ {
525
+ "name": "keys",
526
+ "description": "Space-separated keys: `meta k`, `ctrl shift p`.",
527
+ "value": { "type": "string", "default": "''" }
528
+ },
529
+ {
530
+ "name": "platform",
531
+ "description": "Forces a platform instead of sniffing the current one.",
532
+ "value": {
533
+ "type": "'auto' | 'mac' | 'other'",
534
+ "default": "'auto'"
535
+ }
536
+ }
537
+ ],
538
+ "slots": [
539
+ { "name": "", "description": "The key, when `keys` is not used." }
540
+ ],
541
+ "events": [],
542
+ "js": {
543
+ "properties": [
544
+ {
545
+ "name": "keys",
546
+ "description": "Space-separated keys: `meta k`, `ctrl shift p`.",
547
+ "type": "string"
548
+ },
549
+ {
550
+ "name": "platform",
551
+ "description": "Forces a platform instead of sniffing the current one.",
552
+ "type": "'auto' | 'mac' | 'other'"
553
+ },
554
+ {
555
+ "name": "labels",
556
+ "description": "The keys as they will be shown. Exposed so tests and docs can read them.",
557
+ "type": "string[]"
558
+ }
559
+ ],
560
+ "events": []
561
+ }
562
+ },
563
+ {
564
+ "name": "kt-split-button",
565
+ "description": "One button carrying a menu of related actions.\n\nThe body runs the action a user wants nine times out of ten and emits a\nplain `click`; the caret opens the rest. Reach for it when the alternatives\nare variations on the same action — \"Save and close\", \"Save a copy\" — and\nfor an unrelated set of actions use `<kt-dropdown>` instead, which has no\ndefault action to promote.\n\nA caret press never reads as a `click` on the host, so a single `click`\nlistener means the primary action and nothing else.\n\n---\n\n\n### **Events:**\n - **kt-select** - A menu row was chosen. `detail: { value, item }`.\n- **kt-open** - The menu opened.\n- **kt-close** - The menu closed.\n\n### **Methods:**\n - **show(): _void_** - Opens the menu.\n- **hide(): _void_** - Closes it.\n- **toggle(): _void_** - Either.\n- **focus(options: _FocusOptions_): _void_** - Moves focus to the primary segment.\n\n### **Slots:**\n - _default_ - The primary action's label.\n\n### **CSS Parts:**\n - **action** - The primary `<kt-button>`.\n- **caret** - The `<kt-button>` that opens the menu.\n- **menu** - The list of rows.\n- **item** - A menu row.",
566
+ "doc-url": "",
567
+ "attributes": [
568
+ {
569
+ "name": "variant",
570
+ "description": "Visual variant, forwarded to both segments.",
571
+ "value": { "type": "KtButtonVariant", "default": "'primary'" }
572
+ },
573
+ {
574
+ "name": "size",
575
+ "description": "Height, forwarded to both segments.",
576
+ "value": { "type": "KtButtonSize", "default": "'medium'" }
577
+ },
578
+ {
579
+ "name": "disabled",
580
+ "value": { "type": "boolean", "default": "false" }
581
+ },
582
+ {
583
+ "name": "icon",
584
+ "description": "Lucide icon name for the primary segment.",
585
+ "value": { "type": "string", "default": "''" }
586
+ },
587
+ {
588
+ "name": "menu-label",
589
+ "description": "Accessible name of the caret, which has no text of its own.",
590
+ "value": { "type": "string", "default": "'More actions'" }
591
+ },
592
+ {
593
+ "name": "preferred-placement",
594
+ "description": "Where to put the menu when there is room on both sides.",
595
+ "value": { "type": "KtDropdownPlacement", "default": "'bottom'" }
596
+ },
597
+ {
598
+ "name": "empty-text",
599
+ "value": { "type": "string", "default": "'No actions'" }
600
+ }
601
+ ],
602
+ "slots": [
603
+ { "name": "", "description": "The primary action's label." }
604
+ ],
605
+ "events": [
606
+ {
607
+ "name": "kt-select",
608
+ "description": "A menu row was chosen. `detail: { value, item }`."
609
+ },
610
+ { "name": "kt-open", "description": "The menu opened." },
611
+ { "name": "kt-close", "description": "The menu closed." }
612
+ ],
613
+ "js": {
614
+ "properties": [
615
+ {
616
+ "name": "items",
617
+ "description": "The menu rows.",
618
+ "type": "readonly KtSplitButtonItem[]"
619
+ },
620
+ {
621
+ "name": "variant",
622
+ "description": "Visual variant, forwarded to both segments.",
623
+ "type": "KtButtonVariant"
624
+ },
625
+ {
626
+ "name": "size",
627
+ "description": "Height, forwarded to both segments.",
628
+ "type": "KtButtonSize"
629
+ },
630
+ { "name": "disabled", "type": "boolean" },
631
+ {
632
+ "name": "icon",
633
+ "description": "Lucide icon name for the primary segment.",
634
+ "type": "string"
635
+ },
636
+ {
637
+ "name": "menuLabel",
638
+ "description": "Accessible name of the caret, which has no text of its own.",
639
+ "type": "string"
640
+ },
641
+ {
642
+ "name": "preferredPlacement",
643
+ "description": "Where to put the menu when there is room on both sides.",
644
+ "type": "KtDropdownPlacement"
645
+ },
646
+ { "name": "emptyText", "type": "string" },
647
+ {
648
+ "name": "isOpen",
649
+ "description": "Whether the menu is showing.",
650
+ "type": "boolean"
651
+ }
652
+ ],
653
+ "events": [
654
+ {
655
+ "name": "kt-select",
656
+ "description": "A menu row was chosen. `detail: { value, item }`."
657
+ },
658
+ { "name": "kt-open", "description": "The menu opened." },
659
+ { "name": "kt-close", "description": "The menu closed." }
660
+ ]
661
+ }
662
+ },
663
+ {
664
+ "name": "kt-chart",
665
+ "description": "A chart, drawn from the token layer.\n\nLine, area and bar — stacked, sideways or mixed — plus scatter, bubble,\npie, doughnut, polar area and radar, all in Kanto's voice: the eight\ncategorical hues in fixed order, one value axis, recessive grid, and the\ndata always available as a table.\n\n**Colour.** One series takes the brand hue: with nothing to tell apart there\nis no identity to encode, and the title names it. Two or more take the fixed\ncategorical order in `--chart-series-1…8`, assigned by position and never\ncycled, so a series keeps its colour when a filter removes its neighbours.\nSlices take the same order by slice.\n\n**The table is not optional.** Every chart also renders its data as a table,\nvisually hidden by default. It is what a screen reader reads, and it is the\nrelief that four of the light-theme series hues require, sitting as they do\nbelow 3:1 on a light surface.\n\n---\n\n\n### **Events:**\n - **kt-point-hover** - The active point changed. `detail: { index, series }`; `index` is -1 when nothing is active, `series` -1 when the index spans every series.\n- **kt-series-toggle** - A legend item was pressed. `detail: { series, hidden }`. Cancelable.\n\n### **CSS Parts:**\n - **svg** - The plot.\n- **legend** - The legend.\n- **table** - The data table.",
666
+ "doc-url": "",
667
+ "attributes": [
668
+ {
669
+ "name": "type",
670
+ "value": { "type": "KtChartType", "default": "'area'" }
671
+ },
672
+ {
673
+ "name": "height",
674
+ "value": { "type": "number", "default": "200" }
675
+ },
676
+ {
677
+ "name": "no-grid",
678
+ "description": "Grid lines.",
679
+ "value": { "type": "boolean", "default": "false" }
680
+ },
681
+ {
682
+ "name": "no-axis",
683
+ "description": "Hides the value axis labels, for a chart too small to carry them.",
684
+ "value": { "type": "boolean", "default": "false" }
685
+ },
686
+ {
687
+ "name": "show-table",
688
+ "description": "Puts the data table on screen instead of only in the accessibility tree.",
689
+ "value": { "type": "boolean", "default": "false" }
690
+ },
691
+ {
692
+ "name": "smooth",
693
+ "description": "Smooths lines and areas through a monotone spline.\n\nOff by default on purpose: a curve between two samples draws values that\nwere never measured. Turn it on when the underlying quantity really is\ncontinuous and the reader knows it.",
694
+ "value": { "type": "boolean", "default": "false" }
695
+ },
696
+ {
697
+ "name": "stacked",
698
+ "description": "Bars, and areas, on top of one another instead of side by side.",
699
+ "value": { "type": "boolean", "default": "false" }
700
+ },
701
+ {
702
+ "name": "horizontal",
703
+ "description": "Bars along the horizontal axis, with the categories down the left.",
704
+ "value": { "type": "boolean", "default": "false" }
705
+ },
706
+ {
707
+ "name": "min",
708
+ "description": "Pins the bottom of the value axis.",
709
+ "value": { "type": "number | null", "default": "null" }
710
+ },
711
+ {
712
+ "name": "max",
713
+ "description": "Pins the top of the value axis.",
714
+ "value": { "type": "number | null", "default": "null" }
715
+ },
716
+ {
717
+ "name": "center-label",
718
+ "description": "Names the total in the middle of a doughnut.",
719
+ "value": { "type": "string", "default": "'Total'" }
720
+ },
721
+ {
722
+ "name": "total-label",
723
+ "description": "Names the sum in a stacked chart's tooltip and table.",
724
+ "value": { "type": "string", "default": "'Total'" }
725
+ },
726
+ {
727
+ "name": "label",
728
+ "description": "Accessible name. Say what the chart shows.",
729
+ "value": { "type": "string", "default": "''" }
730
+ }
731
+ ],
732
+ "events": [
733
+ {
734
+ "name": "kt-point-hover",
735
+ "description": "The active point changed. `detail: { index, series }`; `index` is -1 when nothing is active, `series` -1 when the index spans every series."
736
+ },
737
+ {
738
+ "name": "kt-series-toggle",
739
+ "description": "A legend item was pressed. `detail: { series, hidden }`. Cancelable."
740
+ }
741
+ ],
742
+ "js": {
743
+ "properties": [
744
+ { "name": "type", "type": "KtChartType" },
745
+ { "name": "series", "type": "readonly KtSeries[]" },
746
+ {
747
+ "name": "labels",
748
+ "description": "One label per index along the category axis, or per slice or spoke.",
749
+ "type": "readonly string[]"
750
+ },
751
+ { "name": "height", "type": "number" },
752
+ {
753
+ "name": "format",
754
+ "description": "Formats a value for the value axis, the tooltip and the table.",
755
+ "type": "Format"
756
+ },
757
+ {
758
+ "name": "formatX",
759
+ "description": "Formats the x value of a scatter or bubble point.",
760
+ "type": "Format"
761
+ },
762
+ {
763
+ "name": "noGrid",
764
+ "description": "Grid lines.",
765
+ "type": "boolean"
766
+ },
767
+ {
768
+ "name": "noAxis",
769
+ "description": "Hides the value axis labels, for a chart too small to carry them.",
770
+ "type": "boolean"
771
+ },
772
+ {
773
+ "name": "showTable",
774
+ "description": "Puts the data table on screen instead of only in the accessibility tree.",
775
+ "type": "boolean"
776
+ },
777
+ {
778
+ "name": "smooth",
779
+ "description": "Smooths lines and areas through a monotone spline.\n\nOff by default on purpose: a curve between two samples draws values that\nwere never measured. Turn it on when the underlying quantity really is\ncontinuous and the reader knows it.",
780
+ "type": "boolean"
781
+ },
782
+ {
783
+ "name": "stacked",
784
+ "description": "Bars, and areas, on top of one another instead of side by side.",
785
+ "type": "boolean"
786
+ },
787
+ {
788
+ "name": "horizontal",
789
+ "description": "Bars along the horizontal axis, with the categories down the left.",
790
+ "type": "boolean"
791
+ },
792
+ {
793
+ "name": "min",
794
+ "description": "Pins the bottom of the value axis.",
795
+ "type": "number | null"
796
+ },
797
+ {
798
+ "name": "max",
799
+ "description": "Pins the top of the value axis.",
800
+ "type": "number | null"
801
+ },
802
+ {
803
+ "name": "centerLabel",
804
+ "description": "Names the total in the middle of a doughnut.",
805
+ "type": "string"
806
+ },
807
+ {
808
+ "name": "totalLabel",
809
+ "description": "Names the sum in a stacked chart's tooltip and table.",
810
+ "type": "string"
811
+ },
812
+ {
813
+ "name": "label",
814
+ "description": "Accessible name. Say what the chart shows.",
815
+ "type": "string"
816
+ }
817
+ ],
818
+ "events": [
819
+ {
820
+ "name": "kt-point-hover",
821
+ "description": "The active point changed. `detail: { index, series }`; `index` is -1 when nothing is active, `series` -1 when the index spans every series."
822
+ },
823
+ {
824
+ "name": "kt-series-toggle",
825
+ "description": "A legend item was pressed. `detail: { series, hidden }`. Cancelable."
826
+ }
827
+ ]
828
+ }
829
+ },
830
+ {
831
+ "name": "kt-meter",
832
+ "description": "How a fixed total is spent: storage by file type, a budget by category, seats\nby role.\n\nAgainst `<kt-progress-bar>`: a progress bar answers \"how far along\", so it\nfills toward completion and turns green when it gets there. A meter answers\n\"how is it divided\", so it is full from the start and reaching the end is\nbad news, not good. Different question, different component — and the bar\nthat shows one and means the other is a common way to mislead a reader.\n\n---\n\n\n### **CSS Parts:**\n - **base** - The container.\n- **track** - The bar.\n- **legend** - The legend list.",
833
+ "doc-url": "",
834
+ "attributes": [
835
+ { "name": "label", "value": { "type": "string", "default": "''" } },
836
+ {
837
+ "name": "used",
838
+ "description": "Free text on the left of the caption row — \"25.8 GB used\".",
839
+ "value": { "type": "string", "default": "''" }
840
+ },
841
+ {
842
+ "name": "total",
843
+ "description": "Free text on the right of the caption row — \"of 983 GB\".",
844
+ "value": { "type": "string", "default": "''" }
845
+ },
846
+ {
847
+ "name": "value",
848
+ "description": "A single filled proportion, as a percentage. Ignored when `segments` is set.",
849
+ "value": { "type": "number", "default": "0" }
850
+ },
851
+ {
852
+ "name": "max",
853
+ "description": "The total the segments are measured against. Defaults to their sum.",
854
+ "value": { "type": "number", "default": "0" }
855
+ },
856
+ {
857
+ "name": "show-legend",
858
+ "description": "Renders the segment list under the bar.",
859
+ "value": { "type": "boolean", "default": "false" }
860
+ }
861
+ ],
862
+ "events": [],
863
+ "js": {
864
+ "properties": [
865
+ { "name": "label", "type": "string" },
866
+ {
867
+ "name": "used",
868
+ "description": "Free text on the left of the caption row — \"25.8 GB used\".",
869
+ "type": "string"
870
+ },
871
+ {
872
+ "name": "total",
873
+ "description": "Free text on the right of the caption row — \"of 983 GB\".",
874
+ "type": "string"
875
+ },
876
+ {
877
+ "name": "value",
878
+ "description": "A single filled proportion, as a percentage. Ignored when `segments` is set.",
879
+ "type": "number"
880
+ },
881
+ {
882
+ "name": "segments",
883
+ "description": "The composition. Positions map to `--chart-series-N` unless given a colour.",
884
+ "type": "readonly KtMeterSegment[]"
885
+ },
886
+ {
887
+ "name": "max",
888
+ "description": "The total the segments are measured against. Defaults to their sum.",
889
+ "type": "number"
890
+ },
891
+ {
892
+ "name": "showLegend",
893
+ "description": "Renders the segment list under the bar.",
894
+ "type": "boolean"
895
+ },
896
+ {
897
+ "name": "format",
898
+ "description": "Formats a segment value in the legend.",
899
+ "type": "(value: number) => string"
900
+ }
901
+ ],
902
+ "events": []
903
+ }
904
+ },
905
+ {
906
+ "name": "kt-pagination",
907
+ "description": "Previous / next paging, with the position between them.\n\nExtracted from the table footer so a card list or a gallery can page the same\nway a table does.\n\nThe two controls are `<kt-button variant=\"dark\">`, not buttons of its own:\na paging control that invents its own colours, hover and disabled states is\nhow a design system ends up with two kinds of button on one screen.\n\n---\n\n\n### **Events:**\n - **kt-page-change** - A page was requested. `detail: { page }`.\n\n### **CSS Parts:**\n - **previous** - The previous button.\n- **next** - The next button.\n- **info** - The \"Page 2 / 7\" text.",
908
+ "doc-url": "",
909
+ "attributes": [
910
+ {
911
+ "name": "page",
912
+ "description": "The current page, 1-based.",
913
+ "value": { "type": "number", "default": "1" }
914
+ },
915
+ {
916
+ "name": "total-pages",
917
+ "value": { "type": "number", "default": "1" }
918
+ },
919
+ {
920
+ "name": "label",
921
+ "value": { "type": "string", "default": "'Pagination'" }
922
+ }
923
+ ],
924
+ "events": [
925
+ {
926
+ "name": "kt-page-change",
927
+ "description": "A page was requested. `detail: { page }`."
928
+ }
929
+ ],
930
+ "js": {
931
+ "properties": [
932
+ {
933
+ "name": "page",
934
+ "description": "The current page, 1-based.",
935
+ "type": "number"
936
+ },
937
+ { "name": "totalPages", "type": "number" },
938
+ { "name": "label", "type": "string" }
939
+ ],
940
+ "events": [
941
+ {
942
+ "name": "kt-page-change",
943
+ "description": "A page was requested. `detail: { page }`."
944
+ }
945
+ ]
946
+ }
947
+ },
948
+ {
949
+ "name": "kt-stat",
950
+ "description": "One headline figure: a label, a value, and how it moved.\n\nWorth its own element because every dashboard rebuilds this tile, and every\nrebuild makes the same two mistakes — the delta coloured by sign rather than\nby meaning, and the label competing with the number.\n\n**The colour comes from `trend`, not from the sign.** Falling costs are good\nnews; rising churn is not. Pass `trend` to say which, and `inverted` when\ndown is the direction you want.\n\n---\n\n\n### **Slots:**\n - _default_ - Extra content under the value — a sparkline, a caption.\n\n### **CSS Parts:**\n - **base** - The tile.\n- **value** - The figure.",
951
+ "doc-url": "",
952
+ "attributes": [
953
+ { "name": "label", "value": { "type": "string", "default": "''" } },
954
+ { "name": "value", "value": { "type": "string", "default": "''" } },
955
+ {
956
+ "name": "delta",
957
+ "description": "The movement, shown as a badge: `+12%`, `-3%`, `+2`.",
958
+ "value": { "type": "string", "default": "''" }
959
+ },
960
+ {
961
+ "name": "trend",
962
+ "description": "What the movement means. Drives the badge colour.\n`flat` — and the default — stay neutral.",
963
+ "value": { "type": "KtStatTrend", "default": "'flat'" }
964
+ },
965
+ {
966
+ "name": "inverted",
967
+ "description": "Down is the good direction here — churn, cost, latency.\nSwaps which trend reads as success.",
968
+ "value": { "type": "boolean", "default": "false" }
969
+ },
970
+ {
971
+ "name": "icon",
972
+ "description": "Lucide icon name, kebab-case.",
973
+ "value": { "type": "string", "default": "''" }
974
+ },
975
+ {
976
+ "name": "caption",
977
+ "description": "Small print under the figure — \"vs last month\".",
978
+ "value": { "type": "string", "default": "''" }
979
+ },
980
+ {
981
+ "name": "size",
982
+ "value": { "type": "'small' | 'medium'", "default": "'medium'" }
983
+ },
984
+ {
985
+ "name": "loading",
986
+ "value": { "type": "boolean", "default": "false" }
987
+ }
988
+ ],
989
+ "slots": [
990
+ {
991
+ "name": "",
992
+ "description": "Extra content under the value — a sparkline, a caption."
993
+ }
994
+ ],
995
+ "events": [],
996
+ "js": {
997
+ "properties": [
998
+ { "name": "label", "type": "string" },
999
+ { "name": "value", "type": "string" },
1000
+ {
1001
+ "name": "delta",
1002
+ "description": "The movement, shown as a badge: `+12%`, `-3%`, `+2`.",
1003
+ "type": "string"
1004
+ },
1005
+ {
1006
+ "name": "trend",
1007
+ "description": "What the movement means. Drives the badge colour.\n`flat` — and the default — stay neutral.",
1008
+ "type": "KtStatTrend"
1009
+ },
1010
+ {
1011
+ "name": "inverted",
1012
+ "description": "Down is the good direction here — churn, cost, latency.\nSwaps which trend reads as success.",
1013
+ "type": "boolean"
1014
+ },
1015
+ {
1016
+ "name": "icon",
1017
+ "description": "Lucide icon name, kebab-case.",
1018
+ "type": "string"
1019
+ },
1020
+ {
1021
+ "name": "caption",
1022
+ "description": "Small print under the figure — \"vs last month\".",
1023
+ "type": "string"
1024
+ },
1025
+ { "name": "size", "type": "'small' | 'medium'" },
1026
+ { "name": "loading", "type": "boolean" }
1027
+ ],
1028
+ "events": []
1029
+ }
1030
+ },
1031
+ {
1032
+ "name": "kt-table",
1033
+ "description": "A data table: tri-state sorting, single or multiple selection, paging.\n\n---\n\n\n### **Events:**\n - **kt-sort-change** - Sorting changed. `detail: { key, direction }`.\n- **kt-selection-change** - Selection changed. `detail: { selected, rows }`.\n- **kt-row-click** - A row was clicked. `detail: { row, index }`.\n- **kt-page-change** - The page changed. `detail: { page }`.\n\n### **CSS Parts:**\n - **table** - The `<table>`.\n- **header-cell** - A `<th>`.\n- **row** - A `<tr>`.\n- **cell** - A `<td>`.",
1034
+ "doc-url": "",
1035
+ "attributes": [
1036
+ {
1037
+ "name": "selectable",
1038
+ "value": { "type": "boolean", "default": "false" }
1039
+ },
1040
+ {
1041
+ "name": "selection-mode",
1042
+ "value": {
1043
+ "type": "'single' | 'multiple'",
1044
+ "default": "'multiple'"
1045
+ }
1046
+ },
1047
+ {
1048
+ "name": "page-size",
1049
+ "description": "Rows per page. Zero shows everything and hides the footer.",
1050
+ "value": { "type": "number", "default": "0" }
1051
+ },
1052
+ {
1053
+ "name": "loading",
1054
+ "value": { "type": "boolean", "default": "false" }
1055
+ },
1056
+ {
1057
+ "name": "compact",
1058
+ "value": { "type": "boolean", "default": "false" }
1059
+ },
1060
+ {
1061
+ "name": "sort-key",
1062
+ "value": { "type": "string | null", "default": "null" }
1063
+ },
1064
+ {
1065
+ "name": "sort-direction",
1066
+ "value": { "type": "KtSortDirection", "default": "null" }
1067
+ },
1068
+ {
1069
+ "name": "empty-text",
1070
+ "value": { "type": "string", "default": "'No data to display'" }
1071
+ },
1072
+ {
1073
+ "name": "loading-text",
1074
+ "value": { "type": "string", "default": "'Loading…'" }
1075
+ },
1076
+ {
1077
+ "name": "label",
1078
+ "description": "Accessible name for the table.",
1079
+ "value": { "type": "string", "default": "''" }
1080
+ }
1081
+ ],
1082
+ "events": [
1083
+ {
1084
+ "name": "kt-sort-change",
1085
+ "description": "Sorting changed. `detail: { key, direction }`."
1086
+ },
1087
+ {
1088
+ "name": "kt-selection-change",
1089
+ "description": "Selection changed. `detail: { selected, rows }`."
1090
+ },
1091
+ {
1092
+ "name": "kt-row-click",
1093
+ "description": "A row was clicked. `detail: { row, index }`."
1094
+ },
1095
+ {
1096
+ "name": "kt-page-change",
1097
+ "description": "The page changed. `detail: { page }`."
1098
+ }
1099
+ ],
1100
+ "js": {
1101
+ "properties": [
1102
+ { "name": "columns", "type": "readonly KtTableColumn[]" },
1103
+ { "name": "data", "type": "readonly KtTableRow[]" },
1104
+ { "name": "selectable", "type": "boolean" },
1105
+ { "name": "selectionMode", "type": "'single' | 'multiple'" },
1106
+ {
1107
+ "name": "selected",
1108
+ "description": "The identities of the selected rows.",
1109
+ "type": "readonly unknown[]"
1110
+ },
1111
+ {
1112
+ "name": "pageSize",
1113
+ "description": "Rows per page. Zero shows everything and hides the footer.",
1114
+ "type": "number"
1115
+ },
1116
+ { "name": "loading", "type": "boolean" },
1117
+ { "name": "compact", "type": "boolean" },
1118
+ { "name": "sortKey", "type": "string | null" },
1119
+ { "name": "sortDirection", "type": "KtSortDirection" },
1120
+ {
1121
+ "name": "renderCell",
1122
+ "description": "Renders a cell. Return `undefined` to fall back to the raw value.",
1123
+ "type": "KtCellRenderer | undefined"
1124
+ },
1125
+ { "name": "emptyText", "type": "string" },
1126
+ { "name": "loadingText", "type": "string" },
1127
+ {
1128
+ "name": "label",
1129
+ "description": "Accessible name for the table.",
1130
+ "type": "string"
1131
+ },
1132
+ {
1133
+ "name": "sortedRows",
1134
+ "description": "The rows after sorting, before paging.",
1135
+ "type": "readonly KtTableRow[]"
1136
+ },
1137
+ { "name": "totalPages", "type": "number" },
1138
+ {
1139
+ "name": "visibleRows",
1140
+ "description": "The rows actually on screen.",
1141
+ "type": "readonly KtTableRow[]"
1142
+ },
1143
+ {
1144
+ "name": "selectedRows",
1145
+ "description": "The selected rows themselves, not just their identities.",
1146
+ "type": "readonly KtTableRow[]"
1147
+ }
1148
+ ],
1149
+ "events": [
1150
+ {
1151
+ "name": "kt-sort-change",
1152
+ "description": "Sorting changed. `detail: { key, direction }`."
1153
+ },
1154
+ {
1155
+ "name": "kt-selection-change",
1156
+ "description": "Selection changed. `detail: { selected, rows }`."
1157
+ },
1158
+ {
1159
+ "name": "kt-row-click",
1160
+ "description": "A row was clicked. `detail: { row, index }`."
1161
+ },
1162
+ {
1163
+ "name": "kt-page-change",
1164
+ "description": "The page changed. `detail: { page }`."
1165
+ }
1166
+ ]
1167
+ }
1168
+ },
1169
+ {
1170
+ "name": "kt-timeline",
1171
+ "description": "An ordered run of events on a rail.\n\nThe same shape keeps reappearing — an activity feed, an audit log, a\nchangelog, the stages of a delivery, a résumé — and every time it gets\nrebuilt out of a list, a pseudo-element line and a hand-placed dot. The\nfiddly part is the rail: it must start at the first dot and stop at the\nlast, which a border on the list cannot do. Here each item draws its own\nsegment and the last one is told to stop.\n\n`<kt-timeline>` is the semantic list; `<kt-timeline-item>` is one event.\n\n---\n\n\n### **Slots:**\n - _default_ - The `<kt-timeline-item>` children.\n\n### **CSS Parts:**\n - **base** - The list.",
1172
+ "doc-url": "",
1173
+ "attributes": [
1174
+ {
1175
+ "name": "compact",
1176
+ "description": "Tighter rhythm, for a feed in a side panel.",
1177
+ "value": { "type": "boolean", "default": "false" }
1178
+ }
1179
+ ],
1180
+ "slots": [
1181
+ { "name": "", "description": "The `<kt-timeline-item>` children." }
1182
+ ],
1183
+ "events": [],
1184
+ "js": {
1185
+ "properties": [
1186
+ {
1187
+ "name": "compact",
1188
+ "description": "Tighter rhythm, for a feed in a side panel.",
1189
+ "type": "boolean"
1190
+ }
1191
+ ],
1192
+ "events": []
1193
+ }
1194
+ },
1195
+ {
1196
+ "name": "kt-timeline-item",
1197
+ "description": "One event on a `<kt-timeline>`.\n\n---\n\n\n### **Slots:**\n - _default_ - The body of the event.\n- **actions** - Trailing controls, aligned with the heading.\n\n### **CSS Parts:**\n - **base** - The row.\n- **marker** - The dot or icon.",
1198
+ "doc-url": "",
1199
+ "attributes": [
1200
+ {
1201
+ "name": "heading",
1202
+ "value": { "type": "string", "default": "''" }
1203
+ },
1204
+ {
1205
+ "name": "time",
1206
+ "description": "Shown right-aligned on the heading row. Any string — \"09:24\", \"2 days ago\".",
1207
+ "value": { "type": "string", "default": "''" }
1208
+ },
1209
+ {
1210
+ "name": "icon",
1211
+ "description": "Lucide icon name. Without one the marker is a plain dot.",
1212
+ "value": { "type": "string", "default": "''" }
1213
+ },
1214
+ {
1215
+ "name": "variant",
1216
+ "value": { "type": "KtTimelineVariant", "default": "'neutral'" }
1217
+ },
1218
+ {
1219
+ "name": "last",
1220
+ "description": "Set by the parent `<kt-timeline>`: drops the trailing rail segment.",
1221
+ "value": { "type": "boolean", "default": "false" }
1222
+ },
1223
+ {
1224
+ "name": "compact",
1225
+ "description": "Set by the parent `<kt-timeline>`.",
1226
+ "value": { "type": "boolean", "default": "false" }
1227
+ }
1228
+ ],
1229
+ "slots": [
1230
+ { "name": "", "description": "The body of the event." },
1231
+ {
1232
+ "name": "actions",
1233
+ "description": "Trailing controls, aligned with the heading."
1234
+ }
1235
+ ],
1236
+ "events": [],
1237
+ "js": {
1238
+ "properties": [
1239
+ { "name": "heading", "type": "string" },
1240
+ {
1241
+ "name": "time",
1242
+ "description": "Shown right-aligned on the heading row. Any string — \"09:24\", \"2 days ago\".",
1243
+ "type": "string"
1244
+ },
1245
+ {
1246
+ "name": "icon",
1247
+ "description": "Lucide icon name. Without one the marker is a plain dot.",
1248
+ "type": "string"
1249
+ },
1250
+ { "name": "variant", "type": "KtTimelineVariant" },
1251
+ {
1252
+ "name": "last",
1253
+ "description": "Set by the parent `<kt-timeline>`: drops the trailing rail segment.",
1254
+ "type": "boolean"
1255
+ },
1256
+ {
1257
+ "name": "compact",
1258
+ "description": "Set by the parent `<kt-timeline>`.",
1259
+ "type": "boolean"
1260
+ }
1261
+ ],
1262
+ "events": []
1263
+ }
1264
+ },
1265
+ {
1266
+ "name": "kt-alert",
1267
+ "description": "A message that stays on the page.\n\nAgainst a toast: a toast is transient and interrupts; an alert sits in the\nlayout and waits. Use an alert when the message belongs to the page — a form\nthat failed to save, a trial about to expire, a consent notice — and a toast\nwhen it belongs to the moment.\n\n---\n\n\n### **Events:**\n - **kt-close** - The dismiss button was pressed.\n\n### **Slots:**\n - _default_ - Body text, when `description` is not used.\n- **actions** - Buttons, at the end.\n\n### **CSS Parts:**\n - **base** - The alert.\n- **close** - The dismiss button.",
1268
+ "doc-url": "",
1269
+ "attributes": [
1270
+ {
1271
+ "name": "variant",
1272
+ "value": { "type": "KtAlertVariant", "default": "'info'" }
1273
+ },
1274
+ {
1275
+ "name": "heading",
1276
+ "value": { "type": "string", "default": "''" }
1277
+ },
1278
+ {
1279
+ "name": "description",
1280
+ "value": { "type": "string", "default": "''" }
1281
+ },
1282
+ {
1283
+ "name": "dismissible",
1284
+ "description": "Adds a dismiss button. Removing the alert is the caller's job.",
1285
+ "value": { "type": "boolean", "default": "false" }
1286
+ },
1287
+ {
1288
+ "name": "no-icon",
1289
+ "description": "Hides the leading icon.",
1290
+ "value": { "type": "boolean", "default": "false" }
1291
+ },
1292
+ {
1293
+ "name": "icon",
1294
+ "description": "Overrides the icon the variant would pick.",
1295
+ "value": { "type": "string", "default": "''" }
1296
+ }
1297
+ ],
1298
+ "slots": [
1299
+ {
1300
+ "name": "",
1301
+ "description": "Body text, when `description` is not used."
1302
+ },
1303
+ { "name": "actions", "description": "Buttons, at the end." }
1304
+ ],
1305
+ "events": [
1306
+ {
1307
+ "name": "kt-close",
1308
+ "description": "The dismiss button was pressed."
1309
+ }
1310
+ ],
1311
+ "js": {
1312
+ "properties": [
1313
+ { "name": "variant", "type": "KtAlertVariant" },
1314
+ { "name": "heading", "type": "string" },
1315
+ { "name": "description", "type": "string" },
1316
+ {
1317
+ "name": "dismissible",
1318
+ "description": "Adds a dismiss button. Removing the alert is the caller's job.",
1319
+ "type": "boolean"
1320
+ },
1321
+ {
1322
+ "name": "noIcon",
1323
+ "description": "Hides the leading icon.",
1324
+ "type": "boolean"
1325
+ },
1326
+ {
1327
+ "name": "icon",
1328
+ "description": "Overrides the icon the variant would pick.",
1329
+ "type": "string"
1330
+ }
1331
+ ],
1332
+ "events": [
1333
+ {
1334
+ "name": "kt-close",
1335
+ "description": "The dismiss button was pressed."
1336
+ }
1337
+ ]
1338
+ }
1339
+ },
1340
+ {
1341
+ "name": "kt-empty-state",
1342
+ "description": "What a screen shows when it has nothing to show.\n\nWorth a component because the empty case is where products are usually\nthinnest, and where they most need to say what to do next. An icon, a\nsentence and an action beat a blank panel every time.\n\n---\n\n\n### **Slots:**\n - _default_ - Extra content between the description and the actions.\n- **actions** - Buttons.\n\n### **CSS Parts:**\n - **base** - The container.",
1343
+ "doc-url": "",
1344
+ "attributes": [
1345
+ {
1346
+ "name": "icon",
1347
+ "description": "Lucide icon name, kebab-case.",
1348
+ "value": { "type": "string", "default": "'inbox'" }
1349
+ },
1350
+ {
1351
+ "name": "heading",
1352
+ "value": { "type": "string", "default": "''" }
1353
+ },
1354
+ {
1355
+ "name": "description",
1356
+ "value": { "type": "string", "default": "''" }
1357
+ },
1358
+ {
1359
+ "name": "compact",
1360
+ "description": "Tighter padding, for an empty state inside a card or a panel.",
1361
+ "value": { "type": "boolean", "default": "false" }
1362
+ }
1363
+ ],
1364
+ "slots": [
1365
+ {
1366
+ "name": "",
1367
+ "description": "Extra content between the description and the actions."
1368
+ },
1369
+ { "name": "actions", "description": "Buttons." }
1370
+ ],
1371
+ "events": [],
1372
+ "js": {
1373
+ "properties": [
1374
+ {
1375
+ "name": "icon",
1376
+ "description": "Lucide icon name, kebab-case.",
1377
+ "type": "string"
1378
+ },
1379
+ { "name": "heading", "type": "string" },
1380
+ { "name": "description", "type": "string" },
1381
+ {
1382
+ "name": "compact",
1383
+ "description": "Tighter padding, for an empty state inside a card or a panel.",
1384
+ "type": "boolean"
1385
+ }
1386
+ ],
1387
+ "events": []
1388
+ }
1389
+ },
1390
+ {
1391
+ "name": "kt-progress-bar",
1392
+ "description": "A determinate progress bar.\n\nReaching `max` switches the fill to the success colour, so \"done\" reads at a\nglance without the caller having to swap the variant.\n\n---\n\n\n### **CSS Parts:**\n - **track** - The groove.\n- **fill** - The filled portion.\n- **base** - The container.\n- **caption** - The row above the bar.\n- **value** - The percentage, when `show-value` is set.",
1393
+ "doc-url": "",
1394
+ "attributes": [
1395
+ { "name": "value", "value": { "type": "number", "default": "0" } },
1396
+ { "name": "max", "value": { "type": "number", "default": "100" } },
1397
+ {
1398
+ "name": "size",
1399
+ "value": { "type": "KtProgressSize", "default": "'medium'" }
1400
+ },
1401
+ {
1402
+ "name": "variant",
1403
+ "value": { "type": "KtProgressVariant", "default": "'primary'" }
1404
+ },
1405
+ {
1406
+ "name": "show-value",
1407
+ "description": "Draws the percentage in a caption above the bar.",
1408
+ "value": { "type": "boolean", "default": "false" }
1409
+ },
1410
+ {
1411
+ "name": "show-label",
1412
+ "description": "Shows `label` above the bar as visible text, beside the value.\n\n`label` alone is the accessible name and stays invisible, which is right\nwhen the surrounding copy already says what is progressing.",
1413
+ "value": { "type": "boolean", "default": "false" }
1414
+ },
1415
+ {
1416
+ "name": "striped",
1417
+ "value": { "type": "boolean", "default": "false" }
1418
+ },
1419
+ {
1420
+ "name": "animated",
1421
+ "description": "Animates the stripes. Requires `striped`.",
1422
+ "value": { "type": "boolean", "default": "false" }
1423
+ },
1424
+ {
1425
+ "name": "label",
1426
+ "description": "Accessible name — what is progressing.",
1427
+ "value": { "type": "string", "default": "''" }
1428
+ }
1429
+ ],
1430
+ "events": [],
1431
+ "js": {
1432
+ "properties": [
1433
+ { "name": "value", "type": "number" },
1434
+ { "name": "max", "type": "number" },
1435
+ { "name": "size", "type": "KtProgressSize" },
1436
+ { "name": "variant", "type": "KtProgressVariant" },
1437
+ {
1438
+ "name": "showValue",
1439
+ "description": "Draws the percentage in a caption above the bar.",
1440
+ "type": "boolean"
1441
+ },
1442
+ {
1443
+ "name": "showLabel",
1444
+ "description": "Shows `label` above the bar as visible text, beside the value.\n\n`label` alone is the accessible name and stays invisible, which is right\nwhen the surrounding copy already says what is progressing.",
1445
+ "type": "boolean"
1446
+ },
1447
+ { "name": "striped", "type": "boolean" },
1448
+ {
1449
+ "name": "animated",
1450
+ "description": "Animates the stripes. Requires `striped`.",
1451
+ "type": "boolean"
1452
+ },
1453
+ {
1454
+ "name": "label",
1455
+ "description": "Accessible name — what is progressing.",
1456
+ "type": "string"
1457
+ },
1458
+ {
1459
+ "name": "percent",
1460
+ "description": "The value as a whole percentage, clamped to 0–100.",
1461
+ "type": "number"
1462
+ }
1463
+ ],
1464
+ "events": []
1465
+ }
1466
+ },
1467
+ {
1468
+ "name": "kt-skeleton",
1469
+ "description": "A loading placeholder, pulsing between two steps of the surface ramp.\n\nWith `count` above one, the last line is drawn short — the shape a paragraph\nactually has, which is what makes a skeleton read as text rather than as\nstacked bars.\n\nThe whole thing is `aria-hidden`: it is a picture of content that is not\nthere yet. Announce loading state on the region that owns it, with\n`aria-busy`.\n\n---\n\n\n### **CSS Parts:**\n - **line** - One placeholder line.",
1470
+ "doc-url": "",
1471
+ "attributes": [
1472
+ {
1473
+ "name": "variant",
1474
+ "value": { "type": "KtSkeletonVariant", "default": "'text'" }
1475
+ },
1476
+ {
1477
+ "name": "width",
1478
+ "description": "Any CSS length. Defaults to the full width, or 40px for a circle.",
1479
+ "value": { "type": "string", "default": "''" }
1480
+ },
1481
+ {
1482
+ "name": "height",
1483
+ "description": "Any CSS length. Defaults to the variant's natural height.",
1484
+ "value": { "type": "string", "default": "''" }
1485
+ },
1486
+ {
1487
+ "name": "count",
1488
+ "description": "How many lines to draw. Above one, the last is shortened.",
1489
+ "value": { "type": "number", "default": "1" }
1490
+ },
1491
+ {
1492
+ "name": "animated",
1493
+ "value": { "type": "boolean", "default": "true" }
1494
+ }
1495
+ ],
1496
+ "events": [],
1497
+ "js": {
1498
+ "properties": [
1499
+ { "name": "variant", "type": "KtSkeletonVariant" },
1500
+ {
1501
+ "name": "width",
1502
+ "description": "Any CSS length. Defaults to the full width, or 40px for a circle.",
1503
+ "type": "string"
1504
+ },
1505
+ {
1506
+ "name": "height",
1507
+ "description": "Any CSS length. Defaults to the variant's natural height.",
1508
+ "type": "string"
1509
+ },
1510
+ {
1511
+ "name": "count",
1512
+ "description": "How many lines to draw. Above one, the last is shortened.",
1513
+ "type": "number"
1514
+ },
1515
+ { "name": "animated", "type": "boolean" }
1516
+ ],
1517
+ "events": []
1518
+ }
1519
+ },
1520
+ {
1521
+ "name": "kt-toast",
1522
+ "description": "A transient notification.\n\nThe only element in Kanto with a real shadow, and the only one that blurs\nwhat is behind it: a toast floats above the page, so it has to say so.\n\n---\n\n\n### **Events:**\n - **kt-toast-close** - The toast asked to be removed, by timeout or by the dismiss button. `<kt-toast-container>` listens for this.\n\n### **Methods:**\n - **pause(): _void_** - Pauses the countdown. The container calls this while the pointer is over the stack.\n- **resume(): _void_** - Resumes a paused countdown from where it stopped.\n- **close(): _void_** - Asks to be removed. The container is what actually removes it.\n\n### **CSS Parts:**\n - **base** - The toast surface.\n- **close** - The dismiss button.",
1523
+ "doc-url": "",
1524
+ "attributes": [
1525
+ {
1526
+ "name": "variant",
1527
+ "value": { "type": "KtToastVariant", "default": "'information'" }
1528
+ },
1529
+ {
1530
+ "name": "heading",
1531
+ "description": "The toast's title.\n\nNamed `heading` because every element already has a `title`, and shadowing\nit would turn the toast into its own tooltip.",
1532
+ "value": { "type": "string", "default": "''" }
1533
+ },
1534
+ {
1535
+ "name": "description",
1536
+ "value": { "type": "string", "default": "''" }
1537
+ },
1538
+ {
1539
+ "name": "dismissible",
1540
+ "value": { "type": "boolean", "default": "false" }
1541
+ },
1542
+ {
1543
+ "name": "duration",
1544
+ "description": "Auto-dismiss after this many milliseconds, with a countdown bar. Zero\nkeeps the toast until something removes it.",
1545
+ "value": { "type": "number", "default": "0" }
1546
+ }
1547
+ ],
1548
+ "events": [
1549
+ {
1550
+ "name": "kt-toast-close",
1551
+ "description": "The toast asked to be removed, by timeout or by the dismiss button. `<kt-toast-container>` listens for this."
1552
+ }
1553
+ ],
1554
+ "js": {
1555
+ "properties": [
1556
+ { "name": "variant", "type": "KtToastVariant" },
1557
+ {
1558
+ "name": "heading",
1559
+ "description": "The toast's title.\n\nNamed `heading` because every element already has a `title`, and shadowing\nit would turn the toast into its own tooltip.",
1560
+ "type": "string"
1561
+ },
1562
+ { "name": "description", "type": "string" },
1563
+ { "name": "dismissible", "type": "boolean" },
1564
+ {
1565
+ "name": "duration",
1566
+ "description": "Auto-dismiss after this many milliseconds, with a countdown bar. Zero\nkeeps the toast until something removes it.",
1567
+ "type": "number"
1568
+ }
1569
+ ],
1570
+ "events": [
1571
+ {
1572
+ "name": "kt-toast-close",
1573
+ "description": "The toast asked to be removed, by timeout or by the dismiss button. `<kt-toast-container>` listens for this."
1574
+ }
1575
+ ]
1576
+ }
1577
+ },
1578
+ {
1579
+ "name": "kt-toast-container",
1580
+ "description": "A fixed stack that owns the toasts on screen.\n\nToasts are appended and removed by the container, not by the code that\nraised them — a toast that removes itself from a list it does not own is how\nyou end up with two of them and neither disappearing.\n\n---\n\n\n### **Methods:**\n - **show(options: _KtToastOptions_): _KtToast_** - Raises a toast and returns it, so a caller can close it early.\n- **dismiss(toast: _KtToast_): _void_** - Removes one toast.\n- **clear(): _void_** - Removes every toast.\n\n### **Slots:**\n - _default_ - The toasts. Usually filled by `show()` rather than by hand.",
1581
+ "doc-url": "",
1582
+ "attributes": [
1583
+ {
1584
+ "name": "position",
1585
+ "value": {
1586
+ "type": "KtToastPosition",
1587
+ "default": "'bottom-right'"
1588
+ }
1589
+ },
1590
+ {
1591
+ "name": "limit",
1592
+ "description": "Oldest toasts are dropped once the stack reaches this many.",
1593
+ "value": { "type": "number", "default": "5" }
1594
+ }
1595
+ ],
1596
+ "slots": [
1597
+ {
1598
+ "name": "",
1599
+ "description": "The toasts. Usually filled by `show()` rather than by hand."
1600
+ }
1601
+ ],
1602
+ "events": [],
1603
+ "js": {
1604
+ "properties": [
1605
+ { "name": "position", "type": "KtToastPosition" },
1606
+ {
1607
+ "name": "limit",
1608
+ "description": "Oldest toasts are dropped once the stack reaches this many.",
1609
+ "type": "number"
1610
+ },
1611
+ {
1612
+ "name": "toasts",
1613
+ "description": "The toasts currently on screen, oldest first.",
1614
+ "type": "KtToast[]"
1615
+ }
1616
+ ],
1617
+ "events": []
1618
+ }
1619
+ },
1620
+ {
1621
+ "name": "kt-tooltip",
1622
+ "description": "A short label that appears on hover or focus.\n\nWrap the thing it describes:\n\n```html\n<kt-tooltip text=\"Refresh the data\">\n <kt-button icon=\"refresh-cw\" label=\"Refresh\"></kt-button>\n</kt-tooltip>\n```\n\nA tooltip is a *description*, never the only name of a control. If the\ntrigger has no visible text, give it its own `label` too — a tooltip that has\nto be hovered to be read leaves touch and screen-reader users with nothing.\n\n---\n\n\n### **Slots:**\n - _default_ - The trigger.\n\n### **CSS Parts:**\n - **bubble** - The tooltip bubble.",
1623
+ "doc-url": "",
1624
+ "attributes": [
1625
+ { "name": "text", "value": { "type": "string", "default": "''" } },
1626
+ {
1627
+ "name": "placement",
1628
+ "value": { "type": "KtTooltipPlacement", "default": "'top'" }
1629
+ },
1630
+ {
1631
+ "name": "disabled",
1632
+ "description": "Suppresses the tooltip without removing it from the markup.",
1633
+ "value": { "type": "boolean", "default": "false" }
1634
+ }
1635
+ ],
1636
+ "slots": [{ "name": "", "description": "The trigger." }],
1637
+ "events": [],
1638
+ "js": {
1639
+ "properties": [
1640
+ { "name": "text", "type": "string" },
1641
+ { "name": "placement", "type": "KtTooltipPlacement" },
1642
+ {
1643
+ "name": "disabled",
1644
+ "description": "Suppresses the tooltip without removing it from the markup.",
1645
+ "type": "boolean"
1646
+ }
1647
+ ],
1648
+ "events": []
1649
+ }
1650
+ },
1651
+ {
1652
+ "name": "kt-drag-drop",
1653
+ "description": "A file drop zone.\n\nAccepts a drop or a click, lists what was picked with sizes and types, and\nlets each entry be removed. It holds the files in memory and reports them —\nuploading is the application's business.\n\n---\n\n\n### **Events:**\n - **kt-files-change** - The selection changed. `detail: { files }`.\n- **kt-files-rejected** - Files were refused. `detail: { files, reason }`.\n\n### **Methods:**\n - **clear(): _void_** - Empties the selection without firing a rejection.\n\n### **CSS Parts:**\n - **base** - The dashed drop zone.\n- **list** - The list of chosen files.",
1654
+ "doc-url": "",
1655
+ "attributes": [
1656
+ {
1657
+ "name": "heading",
1658
+ "description": "The prompt above the browse link.\n\nNamed `heading`, not `title`: an element already has a `title`, and\nreusing it would put the prompt in a native tooltip on the whole zone.",
1659
+ "value": { "type": "string", "default": "'Drag and drop or'" }
1660
+ },
1661
+ {
1662
+ "name": "link-text",
1663
+ "description": "The clickable-looking part of the prompt.",
1664
+ "value": { "type": "string", "default": "'browse your files'" }
1665
+ },
1666
+ {
1667
+ "name": "recommended-size",
1668
+ "description": "Optional hint, e.g. `800×400px`.",
1669
+ "value": { "type": "string", "default": "''" }
1670
+ },
1671
+ {
1672
+ "name": "multiple",
1673
+ "value": { "type": "boolean", "default": "true" }
1674
+ },
1675
+ {
1676
+ "name": "accept",
1677
+ "description": "Same syntax as the native `accept`: `image/*`, `.pdf,.docx`.",
1678
+ "value": { "type": "string", "default": "''" }
1679
+ },
1680
+ {
1681
+ "name": "max-size",
1682
+ "description": "Largest accepted file, in bytes. Zero means no limit.",
1683
+ "value": { "type": "number", "default": "0" }
1684
+ },
1685
+ {
1686
+ "name": "disabled",
1687
+ "value": { "type": "boolean", "default": "false" }
1688
+ },
1689
+ {
1690
+ "name": "name",
1691
+ "description": "The files are submitted under this name, as by `<input type=\"file\">`.",
1692
+ "value": { "type": "string", "default": "''" }
1693
+ },
1694
+ {
1695
+ "name": "required",
1696
+ "value": { "type": "boolean", "default": "false" }
1697
+ }
1698
+ ],
1699
+ "events": [
1700
+ {
1701
+ "name": "kt-files-change",
1702
+ "description": "The selection changed. `detail: { files }`."
1703
+ },
1704
+ {
1705
+ "name": "kt-files-rejected",
1706
+ "description": "Files were refused. `detail: { files, reason }`."
1707
+ }
1708
+ ],
1709
+ "js": {
1710
+ "properties": [
1711
+ {
1712
+ "name": "heading",
1713
+ "description": "The prompt above the browse link.\n\nNamed `heading`, not `title`: an element already has a `title`, and\nreusing it would put the prompt in a native tooltip on the whole zone.",
1714
+ "type": "string"
1715
+ },
1716
+ {
1717
+ "name": "linkText",
1718
+ "description": "The clickable-looking part of the prompt.",
1719
+ "type": "string"
1720
+ },
1721
+ {
1722
+ "name": "recommendedSize",
1723
+ "description": "Optional hint, e.g. `800×400px`.",
1724
+ "type": "string"
1725
+ },
1726
+ { "name": "multiple", "type": "boolean" },
1727
+ {
1728
+ "name": "accept",
1729
+ "description": "Same syntax as the native `accept`: `image/*`, `.pdf,.docx`.",
1730
+ "type": "string"
1731
+ },
1732
+ {
1733
+ "name": "maxSize",
1734
+ "description": "Largest accepted file, in bytes. Zero means no limit.",
1735
+ "type": "number"
1736
+ },
1737
+ { "name": "disabled", "type": "boolean" },
1738
+ {
1739
+ "name": "name",
1740
+ "description": "The files are submitted under this name, as by `<input type=\"file\">`.",
1741
+ "type": "string"
1742
+ },
1743
+ { "name": "required", "type": "boolean" },
1744
+ {
1745
+ "name": "selectedFiles",
1746
+ "description": "The files currently held, newest last.",
1747
+ "type": "readonly File[]"
1748
+ }
1749
+ ],
1750
+ "events": [
1751
+ {
1752
+ "name": "kt-files-change",
1753
+ "description": "The selection changed. `detail: { files }`."
1754
+ },
1755
+ {
1756
+ "name": "kt-files-rejected",
1757
+ "description": "Files were refused. `detail: { files, reason }`."
1758
+ }
1759
+ ]
1760
+ }
1761
+ },
1762
+ {
1763
+ "name": "kt-form",
1764
+ "description": "A panel grouping related fields.\n\nIt sits one step above the page on `--surface-form`, so the fields inside —\nfilled at `--surface-field` — read as wells recessed into it rather than as\nboxes floating on it.\n\n**Put it inside your own `<form>`.** It renders a `<fieldset>`, not a form:\nKanto fields are form-associated custom elements, and a control finds its\nform by walking its *own* tree. A `<form>` inside this element's shadow root\nwould not own anything slotted into it, and `new FormData(form)` would come\nback empty. The `<form>` above stays in charge of submission, validation and\nreset; this owns the grouping and the look.\n\n---\n\n\n### **Slots:**\n - _default_ - The fields.\n- **heading** - Replaces the `heading` attribute, for markup.\n- **footer** - Actions, right-aligned. Hidden when empty.\n\n### **CSS Parts:**\n - **base** - The `<fieldset>`.\n- **header** - The heading and description.\n- **fields** - The field column.\n- **footer** - The action row.",
1765
+ "doc-url": "",
1766
+ "attributes": [
1767
+ {
1768
+ "name": "heading",
1769
+ "description": "Group heading. Also the fieldset's accessible name.",
1770
+ "value": { "type": "string", "default": "''" }
1771
+ },
1772
+ {
1773
+ "name": "description",
1774
+ "value": { "type": "string", "default": "''" }
1775
+ },
1776
+ {
1777
+ "name": "loading",
1778
+ "description": "Replaces the fields with placeholders.",
1779
+ "value": { "type": "boolean", "default": "false" }
1780
+ },
1781
+ {
1782
+ "name": "disabled",
1783
+ "description": "Switches off every field in the panel.",
1784
+ "value": { "type": "boolean", "default": "false" }
1785
+ },
1786
+ {
1787
+ "name": "loading-fields",
1788
+ "description": "How many placeholder fields `loading` draws.",
1789
+ "value": { "type": "number", "default": "3" }
1790
+ }
1791
+ ],
1792
+ "slots": [
1793
+ { "name": "", "description": "The fields." },
1794
+ {
1795
+ "name": "heading",
1796
+ "description": "Replaces the `heading` attribute, for markup."
1797
+ },
1798
+ {
1799
+ "name": "footer",
1800
+ "description": "Actions, right-aligned. Hidden when empty."
1801
+ }
1802
+ ],
1803
+ "events": [],
1804
+ "js": {
1805
+ "properties": [
1806
+ {
1807
+ "name": "heading",
1808
+ "description": "Group heading. Also the fieldset's accessible name.",
1809
+ "type": "string"
1810
+ },
1811
+ { "name": "description", "type": "string" },
1812
+ {
1813
+ "name": "loading",
1814
+ "description": "Replaces the fields with placeholders.",
1815
+ "type": "boolean"
1816
+ },
1817
+ {
1818
+ "name": "disabled",
1819
+ "description": "Switches off every field in the panel.",
1820
+ "type": "boolean"
1821
+ },
1822
+ {
1823
+ "name": "loadingFields",
1824
+ "description": "How many placeholder fields `loading` draws.",
1825
+ "type": "number"
1826
+ }
1827
+ ],
1828
+ "events": []
1829
+ }
1830
+ },
1831
+ {
1832
+ "name": "kt-input",
1833
+ "description": "A single-line text field.\n\nBorderless by design: the field is a fill on `--color-dark-12` that gains a\n2px *outline* — grey on hover, primary on focus, danger on error. An outline\nsits outside the box, so nothing reflows when the state changes.\n\nThe element is form-associated: it serialises into `FormData` under its\n`name`, resets with the form, and reports validity like a native input.\n\n---\n\n\n### **Events:**\n - **kt-input** - On every keystroke. `detail: { value }`.\n- **kt-change** - When the value is committed (blur or Enter). `detail: { value }`.\n- **kt-clear** - The clear button was pressed.\n\n### **Methods:**\n - **formResetCallback(): _void_** - Called by the platform when the enclosing form is reset.\n- **formStateRestoreCallback(state: _string_): _void_** - Called by the platform when the browser restores a session.\n- **select(): _void_** - Selects the field's contents, as `HTMLInputElement.select()` does.\n\n### **CSS Parts:**\n - **base** - The field container.\n- **control** - The native `<input>`.\n- **actions** - The trailing icon row.",
1834
+ "doc-url": "",
1835
+ "attributes": [
1836
+ {
1837
+ "name": "value",
1838
+ "description": "The field's value. The `value` attribute seeds it and acts as the reset value.",
1839
+ "value": { "type": "string", "default": "''" }
1840
+ },
1841
+ { "name": "name", "value": { "type": "string", "default": "''" } },
1842
+ {
1843
+ "name": "type",
1844
+ "description": "Any native input type. `password` adds the reveal toggle.",
1845
+ "value": { "type": "string", "default": "'text'" }
1846
+ },
1847
+ {
1848
+ "name": "placeholder",
1849
+ "value": { "type": "string", "default": "''" }
1850
+ },
1851
+ {
1852
+ "name": "size",
1853
+ "description": "Field height: 32 / 40 / 48px at the desktop scale.",
1854
+ "value": { "type": "KtInputSize", "default": "'medium'" }
1855
+ },
1856
+ {
1857
+ "name": "disabled",
1858
+ "value": { "type": "boolean", "default": "false" }
1859
+ },
1860
+ {
1861
+ "name": "readonly",
1862
+ "value": { "type": "boolean", "default": "false" }
1863
+ },
1864
+ {
1865
+ "name": "required",
1866
+ "value": { "type": "boolean", "default": "false" }
1867
+ },
1868
+ {
1869
+ "name": "icon",
1870
+ "description": "Trailing Lucide icon, kebab-case.",
1871
+ "value": { "type": "string", "default": "''" }
1872
+ },
1873
+ {
1874
+ "name": "error",
1875
+ "description": "Error message. A non-empty value puts the field in its error state.",
1876
+ "value": { "type": "string", "default": "''" }
1877
+ },
1878
+ {
1879
+ "name": "clearable",
1880
+ "description": "Shows the clear button once there is something to clear.",
1881
+ "value": { "type": "boolean", "default": "true" }
1882
+ },
1883
+ {
1884
+ "name": "label",
1885
+ "description": "Accessible name, when no `<kt-label-input>` wraps the field.",
1886
+ "value": { "type": "string", "default": "''" }
1887
+ },
1888
+ {
1889
+ "name": "autocomplete",
1890
+ "value": { "type": "string", "default": "''" }
1891
+ },
1892
+ { "name": "maxlength", "value": { "type": "number | undefined" } },
1893
+ {
1894
+ "name": "country",
1895
+ "description": "Selected country in phone mode, as an ISO 3166-1 alpha-2 code.",
1896
+ "value": { "type": "string", "default": "'us'" }
1897
+ }
1898
+ ],
1899
+ "events": [
1900
+ {
1901
+ "name": "kt-input",
1902
+ "description": "On every keystroke. `detail: { value }`."
1903
+ },
1904
+ {
1905
+ "name": "kt-change",
1906
+ "description": "When the value is committed (blur or Enter). `detail: { value }`."
1907
+ },
1908
+ {
1909
+ "name": "kt-clear",
1910
+ "description": "The clear button was pressed."
1911
+ }
1912
+ ],
1913
+ "js": {
1914
+ "properties": [
1915
+ {
1916
+ "name": "value",
1917
+ "description": "The field's value. The `value` attribute seeds it and acts as the reset value.",
1918
+ "type": "string"
1919
+ },
1920
+ { "name": "name", "type": "string" },
1921
+ {
1922
+ "name": "type",
1923
+ "description": "Any native input type. `password` adds the reveal toggle.",
1924
+ "type": "string"
1925
+ },
1926
+ { "name": "placeholder", "type": "string" },
1927
+ {
1928
+ "name": "size",
1929
+ "description": "Field height: 32 / 40 / 48px at the desktop scale.",
1930
+ "type": "KtInputSize"
1931
+ },
1932
+ { "name": "disabled", "type": "boolean" },
1933
+ { "name": "readonly", "type": "boolean" },
1934
+ { "name": "required", "type": "boolean" },
1935
+ {
1936
+ "name": "icon",
1937
+ "description": "Trailing Lucide icon, kebab-case.",
1938
+ "type": "string"
1939
+ },
1940
+ {
1941
+ "name": "error",
1942
+ "description": "Error message. A non-empty value puts the field in its error state.",
1943
+ "type": "string"
1944
+ },
1945
+ {
1946
+ "name": "clearable",
1947
+ "description": "Shows the clear button once there is something to clear.",
1948
+ "type": "boolean"
1949
+ },
1950
+ {
1951
+ "name": "label",
1952
+ "description": "Accessible name, when no `<kt-label-input>` wraps the field.",
1953
+ "type": "string"
1954
+ },
1955
+ { "name": "autocomplete", "type": "string" },
1956
+ { "name": "maxlength", "type": "number | undefined" },
1957
+ {
1958
+ "name": "countries",
1959
+ "description": "Countries offered in phone mode. Replace it to widen the list.",
1960
+ "type": "readonly KtCountry[]"
1961
+ },
1962
+ {
1963
+ "name": "country",
1964
+ "description": "Selected country in phone mode, as an ISO 3166-1 alpha-2 code.",
1965
+ "type": "string"
1966
+ }
1967
+ ],
1968
+ "events": [
1969
+ {
1970
+ "name": "kt-input",
1971
+ "description": "On every keystroke. `detail: { value }`."
1972
+ },
1973
+ {
1974
+ "name": "kt-change",
1975
+ "description": "When the value is committed (blur or Enter). `detail: { value }`."
1976
+ },
1977
+ {
1978
+ "name": "kt-clear",
1979
+ "description": "The clear button was pressed."
1980
+ }
1981
+ ]
1982
+ }
1983
+ },
1984
+ {
1985
+ "name": "kt-input-menu",
1986
+ "description": "A combobox: type to narrow the list, then pick.\n\nReach for it over `<kt-select>` once the list is long enough that scanning it\nis slower than typing three letters — somewhere around twenty options.\n\n---\n\n\n### **Events:**\n - **kt-change** - An option was chosen or cleared. `detail: { value, option }`.\n- **kt-filter** - The query changed. `detail: { query }`.\n\n### **CSS Parts:**\n - **control** - The field.\n- **input** - The native `<input>`.\n- **popup** - The option list.\n- **option** - An option row.",
1987
+ "doc-url": "",
1988
+ "attributes": [
1989
+ {
1990
+ "name": "value",
1991
+ "value": { "type": "string | number | null", "default": "null" }
1992
+ },
1993
+ {
1994
+ "name": "placeholder",
1995
+ "value": { "type": "string", "default": "''" }
1996
+ },
1997
+ { "name": "name", "value": { "type": "string", "default": "''" } },
1998
+ {
1999
+ "name": "disabled",
2000
+ "value": { "type": "boolean", "default": "false" }
2001
+ },
2002
+ {
2003
+ "name": "required",
2004
+ "value": { "type": "boolean", "default": "false" }
2005
+ },
2006
+ { "name": "error", "value": { "type": "string", "default": "''" } },
2007
+ { "name": "label", "value": { "type": "string", "default": "''" } },
2008
+ {
2009
+ "name": "empty-text",
2010
+ "value": { "type": "string", "default": "'No options available'" }
2011
+ }
2012
+ ],
2013
+ "events": [
2014
+ {
2015
+ "name": "kt-change",
2016
+ "description": "An option was chosen or cleared. `detail: { value, option }`."
2017
+ },
2018
+ {
2019
+ "name": "kt-filter",
2020
+ "description": "The query changed. `detail: { query }`."
2021
+ }
2022
+ ],
2023
+ "js": {
2024
+ "properties": [
2025
+ { "name": "options", "type": "readonly KtOption[]" },
2026
+ { "name": "value", "type": "string | number | null" },
2027
+ { "name": "placeholder", "type": "string" },
2028
+ { "name": "name", "type": "string" },
2029
+ { "name": "disabled", "type": "boolean" },
2030
+ { "name": "required", "type": "boolean" },
2031
+ { "name": "error", "type": "string" },
2032
+ { "name": "label", "type": "string" },
2033
+ { "name": "emptyText", "type": "string" },
2034
+ { "name": "selectedOption", "type": "KtOption | undefined" }
2035
+ ],
2036
+ "events": [
2037
+ {
2038
+ "name": "kt-change",
2039
+ "description": "An option was chosen or cleared. `detail: { value, option }`."
2040
+ },
2041
+ {
2042
+ "name": "kt-filter",
2043
+ "description": "The query changed. `detail: { query }`."
2044
+ }
2045
+ ]
2046
+ }
2047
+ },
2048
+ {
2049
+ "name": "kt-label-input",
2050
+ "description": "A label above a form control, with a red asterisk when it is required.\n\nNative label association does not cross a shadow boundary — `for` and\nimplicit wrapping both need the label and the control in the same tree — so\nthis element passes its text down to the slotted control's `label` property\ninstead, which becomes the control's `aria-label`. Clicking the label still\nfocuses the control, as it would natively.\n\n---\n\n\n### **Slots:**\n - _default_ - The form control to label.\n\n### **CSS Parts:**\n - **label** - The `<label>`.",
2051
+ "doc-url": "",
2052
+ "attributes": [
2053
+ {
2054
+ "name": "label",
2055
+ "description": "The label text.",
2056
+ "value": { "type": "string", "default": "''" }
2057
+ },
2058
+ {
2059
+ "name": "required",
2060
+ "description": "Appends a red asterisk and marks the control required for screen readers.",
2061
+ "value": { "type": "boolean", "default": "false" }
2062
+ }
2063
+ ],
2064
+ "slots": [
2065
+ { "name": "", "description": "The form control to label." }
2066
+ ],
2067
+ "events": [],
2068
+ "js": {
2069
+ "properties": [
2070
+ {
2071
+ "name": "label",
2072
+ "description": "The label text.",
2073
+ "type": "string"
2074
+ },
2075
+ {
2076
+ "name": "required",
2077
+ "description": "Appends a red asterisk and marks the control required for screen readers.",
2078
+ "type": "boolean"
2079
+ }
2080
+ ],
2081
+ "events": []
2082
+ }
2083
+ },
2084
+ {
2085
+ "name": "kt-select",
2086
+ "description": "A single-choice dropdown.\n\nUnlike the trigger-plus-div it replaces, this is a real listbox: arrow keys\nmove an active descendant, Home and End jump to the ends, Enter commits,\nEscape closes without changing anything, and disabled options are skipped\nrather than merely unclickable.\n\n---\n\n\n### **Events:**\n - **kt-change** - An option was chosen or cleared. `detail: { value, option }`.\n\n### **CSS Parts:**\n - **trigger** - The button that opens the list.\n- **popup** - The option list.\n- **option** - An option row.",
2087
+ "doc-url": "",
2088
+ "attributes": [
2089
+ {
2090
+ "name": "value",
2091
+ "description": "The selected option's id, or `null`.",
2092
+ "value": { "type": "string | number | null", "default": "null" }
2093
+ },
2094
+ {
2095
+ "name": "placeholder",
2096
+ "value": { "type": "string", "default": "'Select'" }
2097
+ },
2098
+ { "name": "name", "value": { "type": "string", "default": "''" } },
2099
+ {
2100
+ "name": "size",
2101
+ "value": { "type": "KtSelectSize", "default": "'medium'" }
2102
+ },
2103
+ {
2104
+ "name": "disabled",
2105
+ "value": { "type": "boolean", "default": "false" }
2106
+ },
2107
+ {
2108
+ "name": "required",
2109
+ "value": { "type": "boolean", "default": "false" }
2110
+ },
2111
+ {
2112
+ "name": "error",
2113
+ "description": "Error message. A non-empty value puts the control in its error state.",
2114
+ "value": { "type": "string", "default": "''" }
2115
+ },
2116
+ {
2117
+ "name": "clearable",
2118
+ "description": "Shows the clear button once something is selected.",
2119
+ "value": { "type": "boolean", "default": "true" }
2120
+ },
2121
+ {
2122
+ "name": "label",
2123
+ "description": "Accessible name, when no `<kt-label-input>` wraps the control.",
2124
+ "value": { "type": "string", "default": "''" }
2125
+ },
2126
+ {
2127
+ "name": "empty-text",
2128
+ "description": "Shown when `options` is empty.",
2129
+ "value": { "type": "string", "default": "'No options available'" }
2130
+ }
2131
+ ],
2132
+ "events": [
2133
+ {
2134
+ "name": "kt-change",
2135
+ "description": "An option was chosen or cleared. `detail: { value, option }`."
2136
+ }
2137
+ ],
2138
+ "js": {
2139
+ "properties": [
2140
+ {
2141
+ "name": "options",
2142
+ "description": "The options to choose from. A property: this is data, not an attribute.",
2143
+ "type": "readonly KtOption[]"
2144
+ },
2145
+ {
2146
+ "name": "value",
2147
+ "description": "The selected option's id, or `null`.",
2148
+ "type": "string | number | null"
2149
+ },
2150
+ { "name": "placeholder", "type": "string" },
2151
+ { "name": "name", "type": "string" },
2152
+ { "name": "size", "type": "KtSelectSize" },
2153
+ { "name": "disabled", "type": "boolean" },
2154
+ { "name": "required", "type": "boolean" },
2155
+ {
2156
+ "name": "error",
2157
+ "description": "Error message. A non-empty value puts the control in its error state.",
2158
+ "type": "string"
2159
+ },
2160
+ {
2161
+ "name": "clearable",
2162
+ "description": "Shows the clear button once something is selected.",
2163
+ "type": "boolean"
2164
+ },
2165
+ {
2166
+ "name": "label",
2167
+ "description": "Accessible name, when no `<kt-label-input>` wraps the control.",
2168
+ "type": "string"
2169
+ },
2170
+ {
2171
+ "name": "emptyText",
2172
+ "description": "Shown when `options` is empty.",
2173
+ "type": "string"
2174
+ },
2175
+ {
2176
+ "name": "selectedOption",
2177
+ "description": "The currently selected option, if the id still matches one.",
2178
+ "type": "KtOption | undefined"
2179
+ }
2180
+ ],
2181
+ "events": [
2182
+ {
2183
+ "name": "kt-change",
2184
+ "description": "An option was chosen or cleared. `detail: { value, option }`."
2185
+ }
2186
+ ]
2187
+ }
2188
+ },
2189
+ {
2190
+ "name": "kt-textarea",
2191
+ "description": "A multi-line text field, with the same borderless fill and outline states as\n`<kt-input>`.\n\nA character counter appears whenever `maxlength` is set — the field tells\nthe user where the limit is before the browser silently stops accepting\nkeystrokes.\n\n---\n\n\n### **Events:**\n - **kt-input** - On every keystroke. `detail: { value }`.\n- **kt-change** - When the value is committed. `detail: { value }`.\n\n### **CSS Parts:**\n - **base** - The field container.\n- **control** - The native `<textarea>`.\n- **counter** - The character counter.",
2192
+ "doc-url": "",
2193
+ "attributes": [
2194
+ { "name": "value", "value": { "type": "string", "default": "''" } },
2195
+ { "name": "name", "value": { "type": "string", "default": "''" } },
2196
+ {
2197
+ "name": "placeholder",
2198
+ "value": { "type": "string", "default": "''" }
2199
+ },
2200
+ { "name": "rows", "value": { "type": "number", "default": "3" } },
2201
+ { "name": "maxlength", "value": { "type": "number | undefined" } },
2202
+ {
2203
+ "name": "disabled",
2204
+ "value": { "type": "boolean", "default": "false" }
2205
+ },
2206
+ {
2207
+ "name": "readonly",
2208
+ "value": { "type": "boolean", "default": "false" }
2209
+ },
2210
+ {
2211
+ "name": "required",
2212
+ "value": { "type": "boolean", "default": "false" }
2213
+ },
2214
+ {
2215
+ "name": "error",
2216
+ "description": "Error message. A non-empty value puts the field in its error state.",
2217
+ "value": { "type": "string", "default": "''" }
2218
+ },
2219
+ {
2220
+ "name": "label",
2221
+ "description": "Accessible name, when no `<kt-label-input>` wraps the field.",
2222
+ "value": { "type": "string", "default": "''" }
2223
+ },
2224
+ {
2225
+ "name": "resize",
2226
+ "description": "Whether the reader may drag the field taller.\n\nOff by default, as in the rest of Kanto: the grip is drawn by the operating\nsystem, lands on the field's rounded corner and belongs to no design\nsystem — and a field the layout sized is not usually the reader's to\nresize. Turn it on where the content genuinely varies.",
2227
+ "value": { "type": "'vertical' | 'none'", "default": "'none'" }
2228
+ }
2229
+ ],
2230
+ "events": [
2231
+ {
2232
+ "name": "kt-input",
2233
+ "description": "On every keystroke. `detail: { value }`."
2234
+ },
2235
+ {
2236
+ "name": "kt-change",
2237
+ "description": "When the value is committed. `detail: { value }`."
2238
+ }
2239
+ ],
2240
+ "js": {
2241
+ "properties": [
2242
+ { "name": "value", "type": "string" },
2243
+ { "name": "name", "type": "string" },
2244
+ { "name": "placeholder", "type": "string" },
2245
+ { "name": "rows", "type": "number" },
2246
+ { "name": "maxlength", "type": "number | undefined" },
2247
+ { "name": "disabled", "type": "boolean" },
2248
+ { "name": "readonly", "type": "boolean" },
2249
+ { "name": "required", "type": "boolean" },
2250
+ {
2251
+ "name": "error",
2252
+ "description": "Error message. A non-empty value puts the field in its error state.",
2253
+ "type": "string"
2254
+ },
2255
+ {
2256
+ "name": "label",
2257
+ "description": "Accessible name, when no `<kt-label-input>` wraps the field.",
2258
+ "type": "string"
2259
+ },
2260
+ {
2261
+ "name": "resize",
2262
+ "description": "Whether the reader may drag the field taller.\n\nOff by default, as in the rest of Kanto: the grip is drawn by the operating\nsystem, lands on the field's rounded corner and belongs to no design\nsystem — and a field the layout sized is not usually the reader's to\nresize. Turn it on where the content genuinely varies.",
2263
+ "type": "'vertical' | 'none'"
2264
+ }
2265
+ ],
2266
+ "events": [
2267
+ {
2268
+ "name": "kt-input",
2269
+ "description": "On every keystroke. `detail: { value }`."
2270
+ },
2271
+ {
2272
+ "name": "kt-change",
2273
+ "description": "When the value is committed. `detail: { value }`."
2274
+ }
2275
+ ]
2276
+ }
2277
+ },
2278
+ {
2279
+ "name": "kt-toggle",
2280
+ "description": "An on/off switch.\n\nSized off the button heights so a toggle lines up with the controls beside\nit: the track is 1.8× the field height, the thumb is inset by 12% of it.\nChange `--button-height` and the switch follows.\n\n---\n\n\n### **Events:**\n - **kt-change** - The state changed. `detail: { checked }`.\n\n### **Slots:**\n - _default_ - Optional label, rendered beside the switch and clickable.\n\n### **CSS Parts:**\n - **base** - The button carrying `role=\"switch\"`.\n- **track** - The track.\n- **thumb** - The sliding thumb.",
2281
+ "doc-url": "",
2282
+ "attributes": [
2283
+ {
2284
+ "name": "checked",
2285
+ "value": { "type": "boolean", "default": "false" }
2286
+ },
2287
+ {
2288
+ "name": "disabled",
2289
+ "value": { "type": "boolean", "default": "false" }
2290
+ },
2291
+ {
2292
+ "name": "size",
2293
+ "value": { "type": "KtToggleSize", "default": "'medium'" }
2294
+ },
2295
+ { "name": "name", "value": { "type": "string", "default": "''" } },
2296
+ {
2297
+ "name": "value",
2298
+ "description": "Submitted when checked, as for a native checkbox.",
2299
+ "value": { "type": "string", "default": "'on'" }
2300
+ },
2301
+ {
2302
+ "name": "label",
2303
+ "description": "Accessible name, when nothing is slotted.",
2304
+ "value": { "type": "string", "default": "''" }
2305
+ }
2306
+ ],
2307
+ "slots": [
2308
+ {
2309
+ "name": "",
2310
+ "description": "Optional label, rendered beside the switch and clickable."
2311
+ }
2312
+ ],
2313
+ "events": [
2314
+ {
2315
+ "name": "kt-change",
2316
+ "description": "The state changed. `detail: { checked }`."
2317
+ }
2318
+ ],
2319
+ "js": {
2320
+ "properties": [
2321
+ { "name": "checked", "type": "boolean" },
2322
+ { "name": "disabled", "type": "boolean" },
2323
+ { "name": "size", "type": "KtToggleSize" },
2324
+ { "name": "name", "type": "string" },
2325
+ {
2326
+ "name": "value",
2327
+ "description": "Submitted when checked, as for a native checkbox.",
2328
+ "type": "string"
2329
+ },
2330
+ {
2331
+ "name": "label",
2332
+ "description": "Accessible name, when nothing is slotted.",
2333
+ "type": "string"
2334
+ }
2335
+ ],
2336
+ "events": [
2337
+ {
2338
+ "name": "kt-change",
2339
+ "description": "The state changed. `detail: { checked }`."
2340
+ }
2341
+ ]
2342
+ }
2343
+ },
2344
+ {
2345
+ "name": "kt-breadcrumb",
2346
+ "description": "A trail showing where the current page sits.\n\nThe 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\nare already on is a dead control.\n\n---\n\n\n### **Events:**\n - **kt-navigate** - An entry was activated. `detail: { item, index }`. Cancel it to keep the browser from following the href.\n\n### **CSS Parts:**\n - **nav** - The `<nav>`.\n- **item** - A trail entry.",
2347
+ "doc-url": "",
2348
+ "attributes": [
2349
+ {
2350
+ "name": "label",
2351
+ "description": "Accessible name for the navigation landmark.",
2352
+ "value": { "type": "string", "default": "'Breadcrumb'" }
2353
+ }
2354
+ ],
2355
+ "events": [
2356
+ {
2357
+ "name": "kt-navigate",
2358
+ "description": "An entry was activated. `detail: { item, index }`. Cancel it to keep the browser from following the href."
2359
+ }
2360
+ ],
2361
+ "js": {
2362
+ "properties": [
2363
+ {
2364
+ "name": "items",
2365
+ "description": "The trail, root first. The last entry is the current page.",
2366
+ "type": "readonly KtBreadcrumbItem[]"
2367
+ },
2368
+ {
2369
+ "name": "label",
2370
+ "description": "Accessible name for the navigation landmark.",
2371
+ "type": "string"
2372
+ }
2373
+ ],
2374
+ "events": [
2375
+ {
2376
+ "name": "kt-navigate",
2377
+ "description": "An entry was activated. `detail: { item, index }`. Cancel it to keep the browser from following the href."
2378
+ }
2379
+ ]
2380
+ }
2381
+ },
2382
+ {
2383
+ "name": "kt-header",
2384
+ "description": "The application header: a banner landmark holding the brand, the primary\nnavigation and a row of actions.\n\nBelow `--kt-header-breakpoint` (900px by default) the navigation collapses\nbehind a menu button and reappears as a panel under the bar. That threshold\nis a token rather than a hard-coded media query, because how much navigation\nfits depends on how much navigation you put in.\n\n---\n\n\n### **Events:**\n - **kt-menu-toggle** - The mobile menu opened or closed. `detail: { open }`.\n\n### **Methods:**\n - **closeMenu(): _void_** - Closes the collapsed navigation — call it after routing.\n\n### **Slots:**\n - **brand** - Logo or wordmark, at the start.\n- _default_ - Primary navigation, in the middle.\n- **actions** - Buttons and links, at the end. Stays visible on mobile.\n- **menu** - What the menu button reveals below the breakpoint. Separate from the default slot because a node can only be assigned to one slot; put a compact copy of the navigation here.\n- **bottom** - A second row under the bar — sub-navigation, a breadcrumb.\n\n### **CSS Properties:**\n - **--kt-header-breakpoint** - Where the navigation collapses. 900px. _(default: undefined)_\n- **--kt-header-height** - Height of the main row. 64px. _(default: undefined)_\n\n### **CSS Parts:**\n - **base** - The `<header>`.\n- **bar** - The main row.\n- **bottom** - The second row. The bar is a three-column grid whose outer columns are equal, so the navigation is centred in the bar rather than in whatever the brand and the actions left over. Set `nav-align=\"start\"` to butt it against the brand instead.",
2385
+ "doc-url": "",
2386
+ "attributes": [
2387
+ {
2388
+ "name": "sticky",
2389
+ "description": "Pins the header to the top of the viewport.",
2390
+ "value": { "type": "boolean", "default": "false" }
2391
+ },
2392
+ {
2393
+ "name": "nav-align",
2394
+ "description": "Where the navigation sits: centred in the bar, or against the brand.",
2395
+ "value": { "type": "'center' | 'start'", "default": "'center'" }
2396
+ },
2397
+ {
2398
+ "name": "bordered",
2399
+ "value": { "type": "boolean", "default": "true" }
2400
+ },
2401
+ {
2402
+ "name": "label",
2403
+ "description": "Accessible name for the banner, when a page has more than one.",
2404
+ "value": { "type": "string", "default": "''" }
2405
+ }
2406
+ ],
2407
+ "slots": [
2408
+ {
2409
+ "name": "brand",
2410
+ "description": "Logo or wordmark, at the start."
2411
+ },
2412
+ { "name": "", "description": "Primary navigation, in the middle." },
2413
+ {
2414
+ "name": "actions",
2415
+ "description": "Buttons and links, at the end. Stays visible on mobile."
2416
+ },
2417
+ {
2418
+ "name": "menu",
2419
+ "description": "What the menu button reveals below the breakpoint. Separate from the default slot because a node can only be assigned to one slot; put a compact copy of the navigation here."
2420
+ },
2421
+ {
2422
+ "name": "bottom",
2423
+ "description": "A second row under the bar — sub-navigation, a breadcrumb."
2424
+ }
2425
+ ],
2426
+ "events": [
2427
+ {
2428
+ "name": "kt-menu-toggle",
2429
+ "description": "The mobile menu opened or closed. `detail: { open }`."
2430
+ }
2431
+ ],
2432
+ "js": {
2433
+ "properties": [
2434
+ {
2435
+ "name": "sticky",
2436
+ "description": "Pins the header to the top of the viewport.",
2437
+ "type": "boolean"
2438
+ },
2439
+ {
2440
+ "name": "navAlign",
2441
+ "description": "Where the navigation sits: centred in the bar, or against the brand.",
2442
+ "type": "'center' | 'start'"
2443
+ },
2444
+ { "name": "bordered", "type": "boolean" },
2445
+ {
2446
+ "name": "label",
2447
+ "description": "Accessible name for the banner, when a page has more than one.",
2448
+ "type": "string"
2449
+ },
2450
+ {
2451
+ "name": "isMenuOpen",
2452
+ "description": "Whether the collapsed navigation panel is showing.",
2453
+ "type": "boolean"
2454
+ }
2455
+ ],
2456
+ "events": [
2457
+ {
2458
+ "name": "kt-menu-toggle",
2459
+ "description": "The mobile menu opened or closed. `detail: { open }`."
2460
+ }
2461
+ ]
2462
+ }
2463
+ },
2464
+ {
2465
+ "name": "kt-page-header",
2466
+ "description": "The block every screen opens with: an overline, a title, a sentence, and the\nactions that belong to the page rather than to anything on it.\n\nIt exists because it was being rebuilt on every screen, and the copies drifted\n— different heading levels, different gaps, actions sometimes above and\nsometimes beside. Those are not decisions worth making twice.\n\nAt `level=\"section\"` the same block introduces a region inside a page: a\nsmaller heading, and the action is usually a link onward rather than a button.\n\n---\n\n\n### **Slots:**\n - _default_ - Extra content under the description.\n- **actions** - Buttons or a link, trailing on wide screens.\n\n### **CSS Parts:**\n - **base** - The container.\n- **heading** - The heading element.",
2467
+ "doc-url": "",
2468
+ "attributes": [
2469
+ {
2470
+ "name": "eyebrow",
2471
+ "description": "Small uppercase label above the heading — \"Dashboard\", \"Settings\".",
2472
+ "value": { "type": "string", "default": "''" }
2473
+ },
2474
+ {
2475
+ "name": "heading",
2476
+ "value": { "type": "string", "default": "''" }
2477
+ },
2478
+ {
2479
+ "name": "description",
2480
+ "value": { "type": "string", "default": "''" }
2481
+ },
2482
+ {
2483
+ "name": "level",
2484
+ "description": "`page` renders an `<h1>`; `section` an `<h2>` at body scale.",
2485
+ "value": { "type": "'page' | 'section'", "default": "'page'" }
2486
+ }
2487
+ ],
2488
+ "slots": [
2489
+ {
2490
+ "name": "",
2491
+ "description": "Extra content under the description."
2492
+ },
2493
+ {
2494
+ "name": "actions",
2495
+ "description": "Buttons or a link, trailing on wide screens."
2496
+ }
2497
+ ],
2498
+ "events": [],
2499
+ "js": {
2500
+ "properties": [
2501
+ {
2502
+ "name": "eyebrow",
2503
+ "description": "Small uppercase label above the heading — \"Dashboard\", \"Settings\".",
2504
+ "type": "string"
2505
+ },
2506
+ { "name": "heading", "type": "string" },
2507
+ { "name": "description", "type": "string" },
2508
+ {
2509
+ "name": "level",
2510
+ "description": "`page` renders an `<h1>`; `section` an `<h2>` at body scale.",
2511
+ "type": "'page' | 'section'"
2512
+ }
2513
+ ],
2514
+ "events": []
2515
+ }
2516
+ },
2517
+ {
2518
+ "name": "kt-segmented-control",
2519
+ "description": "A small set of mutually exclusive choices, shown as one inset track with the\nselected segment raised out of it.\n\nUse it for two to five options that all fit on screen — a view switch, a date\nrange. Past that, `<kt-select>`.\n\nImplemented as a radio group: one tab stop for the whole control, arrows to\nmove between segments. That is what a keyboard user expects here, and it\nkeeps a five-option control from adding five tab stops to the page.\n\n---\n\n\n### **Events:**\n - **kt-change** - A segment was chosen. `detail: { value, option }`.\n\n### **CSS Parts:**\n - **base** - The track.\n- **option** - A segment.",
2520
+ "doc-url": "",
2521
+ "attributes": [
2522
+ {
2523
+ "name": "value",
2524
+ "value": { "type": "string | number | null", "default": "null" }
2525
+ },
2526
+ {
2527
+ "name": "size",
2528
+ "value": { "type": "KtSegmentedSize", "default": "'medium'" }
2529
+ },
2530
+ {
2531
+ "name": "orientation",
2532
+ "value": {
2533
+ "type": "'horizontal' | 'vertical'",
2534
+ "default": "'horizontal'"
2535
+ }
2536
+ },
2537
+ {
2538
+ "name": "disabled",
2539
+ "value": { "type": "boolean", "default": "false" }
2540
+ },
2541
+ {
2542
+ "name": "label",
2543
+ "description": "Accessible name for the group.",
2544
+ "value": { "type": "string", "default": "''" }
2545
+ },
2546
+ { "name": "name", "value": { "type": "string", "default": "''" } },
2547
+ {
2548
+ "name": "required",
2549
+ "value": { "type": "boolean", "default": "false" }
2550
+ }
2551
+ ],
2552
+ "events": [
2553
+ {
2554
+ "name": "kt-change",
2555
+ "description": "A segment was chosen. `detail: { value, option }`."
2556
+ }
2557
+ ],
2558
+ "js": {
2559
+ "properties": [
2560
+ { "name": "options", "type": "readonly KtSegmentedOption[]" },
2561
+ { "name": "value", "type": "string | number | null" },
2562
+ { "name": "size", "type": "KtSegmentedSize" },
2563
+ { "name": "orientation", "type": "'horizontal' | 'vertical'" },
2564
+ { "name": "disabled", "type": "boolean" },
2565
+ {
2566
+ "name": "label",
2567
+ "description": "Accessible name for the group.",
2568
+ "type": "string"
2569
+ },
2570
+ { "name": "name", "type": "string" },
2571
+ { "name": "required", "type": "boolean" }
2572
+ ],
2573
+ "events": [
2574
+ {
2575
+ "name": "kt-change",
2576
+ "description": "A segment was chosen. `detail: { value, option }`."
2577
+ }
2578
+ ]
2579
+ }
2580
+ },
2581
+ {
2582
+ "name": "kt-sub-menu-navigation",
2583
+ "description": "The sidebar navigation: uppercase overline section titles over lists of\nlinks, to any depth.\n\nThe recursion is the point. Every product grows a third level eventually —\nSettings holds Members holds Roles — and the usual answer is to hand-roll\nthat one branch beside the component, which is how two navigation styles end\nup on one screen. Here a branch renders exactly like the level above it,\nindented by depth, and a branch containing the current page opens itself.\n\n---\n\n\n### **Events:**\n - **kt-navigate** - A link was activated. `detail: { item }`. Cancel it to keep the browser from following the href, for client-side routing.\n- **kt-toggle** - A branch opened or closed. `detail: { item, open }`.\n\n### **CSS Parts:**\n - **nav** - The `<nav>`.\n- **section** - A section.\n- **title** - A section title.\n- **item** - A navigation link or branch button, at any depth.",
2584
+ "doc-url": "",
2585
+ "attributes": [
2586
+ {
2587
+ "name": "active-href",
2588
+ "description": "The href of the current page. Marks the matching link active.",
2589
+ "value": { "type": "string", "default": "''" }
2590
+ },
2591
+ {
2592
+ "name": "label",
2593
+ "value": { "type": "string", "default": "'Secondary navigation'" }
2594
+ },
2595
+ {
2596
+ "name": "flush",
2597
+ "description": "Drops the card background, for a sidebar that owns its own surface.",
2598
+ "value": { "type": "boolean", "default": "false" }
2599
+ },
2600
+ {
2601
+ "name": "collapsed",
2602
+ "description": "Icons only. Labels, badges and branches are hidden rather than clipped.",
2603
+ "value": { "type": "boolean", "default": "false" }
2604
+ }
2605
+ ],
2606
+ "events": [
2607
+ {
2608
+ "name": "kt-navigate",
2609
+ "description": "A link was activated. `detail: { item }`. Cancel it to keep the browser from following the href, for client-side routing."
2610
+ },
2611
+ {
2612
+ "name": "kt-toggle",
2613
+ "description": "A branch opened or closed. `detail: { item, open }`."
2614
+ }
2615
+ ],
2616
+ "js": {
2617
+ "properties": [
2618
+ { "name": "sections", "type": "readonly KtNavSection[]" },
2619
+ {
2620
+ "name": "activeHref",
2621
+ "description": "The href of the current page. Marks the matching link active.",
2622
+ "type": "string"
2623
+ },
2624
+ { "name": "label", "type": "string" },
2625
+ {
2626
+ "name": "flush",
2627
+ "description": "Drops the card background, for a sidebar that owns its own surface.",
2628
+ "type": "boolean"
2629
+ },
2630
+ {
2631
+ "name": "collapsed",
2632
+ "description": "Icons only. Labels, badges and branches are hidden rather than clipped.",
2633
+ "type": "boolean"
2634
+ }
2635
+ ],
2636
+ "events": [
2637
+ {
2638
+ "name": "kt-navigate",
2639
+ "description": "A link was activated. `detail: { item }`. Cancel it to keep the browser from following the href, for client-side routing."
2640
+ },
2641
+ {
2642
+ "name": "kt-toggle",
2643
+ "description": "A branch opened or closed. `detail: { item, open }`."
2644
+ }
2645
+ ]
2646
+ }
2647
+ },
2648
+ {
2649
+ "name": "kt-tabs",
2650
+ "description": "An underlined tab bar.\n\nAgainst `<kt-segmented-control>`: a segmented control picks a *value* — a\ndate range, a unit — and sits inside a form or a toolbar. Tabs switch which\n*region of the page* you are looking at, and read as part of the page\nstructure rather than as a control on it. The shapes say so: an inset track\nwith a raised pill, versus a rule with one segment underlined.\n\nLike the segmented control, this only manages selection. Swapping the panel\nis the consumer's business.\n\n---\n\n\n### **Events:**\n - **kt-change** - A tab was selected. `detail: { value, tab }`.\n\n### **CSS Parts:**\n - **base** - The tablist.\n- **tab** - One tab.",
2651
+ "doc-url": "",
2652
+ "attributes": [
2653
+ {
2654
+ "name": "value",
2655
+ "description": "The selected tab's value.",
2656
+ "value": { "type": "string | number | null", "default": "null" }
2657
+ },
2658
+ {
2659
+ "name": "disabled",
2660
+ "value": { "type": "boolean", "default": "false" }
2661
+ },
2662
+ {
2663
+ "name": "loading",
2664
+ "description": "Renders placeholder tabs instead of the real ones.",
2665
+ "value": { "type": "boolean", "default": "false" }
2666
+ },
2667
+ {
2668
+ "name": "label",
2669
+ "description": "Accessible name for the tablist.",
2670
+ "value": { "type": "string", "default": "''" }
2671
+ }
2672
+ ],
2673
+ "events": [
2674
+ {
2675
+ "name": "kt-change",
2676
+ "description": "A tab was selected. `detail: { value, tab }`."
2677
+ }
2678
+ ],
2679
+ "js": {
2680
+ "properties": [
2681
+ {
2682
+ "name": "tabs",
2683
+ "description": "The tabs to show. A property: this is data.",
2684
+ "type": "readonly KtTab[]"
2685
+ },
2686
+ {
2687
+ "name": "value",
2688
+ "description": "The selected tab's value.",
2689
+ "type": "string | number | null"
2690
+ },
2691
+ { "name": "disabled", "type": "boolean" },
2692
+ {
2693
+ "name": "loading",
2694
+ "description": "Renders placeholder tabs instead of the real ones.",
2695
+ "type": "boolean"
2696
+ },
2697
+ {
2698
+ "name": "label",
2699
+ "description": "Accessible name for the tablist.",
2700
+ "type": "string"
2701
+ }
2702
+ ],
2703
+ "events": [
2704
+ {
2705
+ "name": "kt-change",
2706
+ "description": "A tab was selected. `detail: { value, tab }`."
2707
+ }
2708
+ ]
2709
+ }
2710
+ },
2711
+ {
2712
+ "name": "kt-toggle-button",
2713
+ "description": "A button that stays pressed.\n\n`aria-pressed` rather than `aria-checked`: this is a control that holds a\nstate, not one option among several. Put several in a\n`<kt-toggle-button-group>` when they are.\n\n---\n\n\n### **Events:**\n - **kt-change** - The state changed. `detail: { selected, value }`.\n\n### **Slots:**\n - _default_ - The button label.\n\n### **CSS Parts:**\n - **button** - The native `<button>`.",
2714
+ "doc-url": "",
2715
+ "attributes": [
2716
+ {
2717
+ "name": "selected",
2718
+ "value": { "type": "boolean", "default": "false" }
2719
+ },
2720
+ {
2721
+ "name": "disabled",
2722
+ "value": { "type": "boolean", "default": "false" }
2723
+ },
2724
+ {
2725
+ "name": "variant",
2726
+ "value": {
2727
+ "type": "KtToggleButtonVariant",
2728
+ "default": "'primary'"
2729
+ }
2730
+ },
2731
+ {
2732
+ "name": "size",
2733
+ "value": { "type": "KtToggleButtonSize", "default": "'medium'" }
2734
+ },
2735
+ {
2736
+ "name": "value",
2737
+ "description": "Identifies this button inside a `<kt-toggle-button-group>`.",
2738
+ "value": { "type": "string", "default": "''" }
2739
+ },
2740
+ { "name": "icon", "value": { "type": "string", "default": "''" } },
2741
+ {
2742
+ "name": "icon-position",
2743
+ "value": { "type": "'left' | 'right'", "default": "'left'" }
2744
+ },
2745
+ {
2746
+ "name": "label",
2747
+ "description": "Accessible name. Required when the button is icon-only.",
2748
+ "value": { "type": "string", "default": "''" }
2749
+ }
2750
+ ],
2751
+ "slots": [{ "name": "", "description": "The button label." }],
2752
+ "events": [
2753
+ {
2754
+ "name": "kt-change",
2755
+ "description": "The state changed. `detail: { selected, value }`."
2756
+ }
2757
+ ],
2758
+ "js": {
2759
+ "properties": [
2760
+ { "name": "selected", "type": "boolean" },
2761
+ { "name": "disabled", "type": "boolean" },
2762
+ { "name": "variant", "type": "KtToggleButtonVariant" },
2763
+ { "name": "size", "type": "KtToggleButtonSize" },
2764
+ {
2765
+ "name": "value",
2766
+ "description": "Identifies this button inside a `<kt-toggle-button-group>`.",
2767
+ "type": "string"
2768
+ },
2769
+ { "name": "icon", "type": "string" },
2770
+ { "name": "iconPosition", "type": "'left' | 'right'" },
2771
+ {
2772
+ "name": "label",
2773
+ "description": "Accessible name. Required when the button is icon-only.",
2774
+ "type": "string"
2775
+ },
2776
+ {
2777
+ "name": "managed",
2778
+ "description": "Set by `<kt-toggle-button-group>` on the buttons it owns.\n\nA managed button is a display, not a control: it neither flips itself nor\nemits. The group reads the click, decides what the selection now is, and\nwrites `selected` back. Without this the two both react to the same click\nand consumers hear two different kt-change events for one press.",
2779
+ "type": "boolean"
2780
+ }
2781
+ ],
2782
+ "events": [
2783
+ {
2784
+ "name": "kt-change",
2785
+ "description": "The state changed. `detail: { selected, value }`."
2786
+ }
2787
+ ]
2788
+ }
2789
+ },
2790
+ {
2791
+ "name": "kt-toggle-button-group",
2792
+ "description": "Joins `<kt-toggle-button>`s into one segmented bar and coordinates their\nselection.\n\nSingle mode behaves like a radio group with a deselect: clicking the active\nbutton clears it. Multiple mode is a set of independent checkboxes that\nhappen to be drawn together.\n\nThe buttons are slotted rather than described by an options array, so a\nbutton can hold whatever its label needs — an icon, a count, a badge.\n\n---\n\n\n### **Events:**\n - **kt-change** - The selection changed. `detail: { value }` — a single value or `null`, or an array in multiple mode.\n\n### **Slots:**\n - _default_ - The `<kt-toggle-button>` children.\n\n### **CSS Parts:**\n - **base** - The group container.",
2793
+ "doc-url": "",
2794
+ "attributes": [
2795
+ {
2796
+ "name": "multiple",
2797
+ "description": "`false`: one selection at a time. `true`: any number.",
2798
+ "value": { "type": "boolean", "default": "false" }
2799
+ },
2800
+ {
2801
+ "name": "orientation",
2802
+ "value": {
2803
+ "type": "'horizontal' | 'vertical'",
2804
+ "default": "'horizontal'"
2805
+ }
2806
+ },
2807
+ {
2808
+ "name": "label",
2809
+ "description": "Accessible name for the group.",
2810
+ "value": { "type": "string", "default": "''" }
2811
+ }
2812
+ ],
2813
+ "slots": [
2814
+ { "name": "", "description": "The `<kt-toggle-button>` children." }
2815
+ ],
2816
+ "events": [
2817
+ {
2818
+ "name": "kt-change",
2819
+ "description": "The selection changed. `detail: { value }` — a single value or `null`, or an array in multiple mode."
2820
+ }
2821
+ ],
2822
+ "js": {
2823
+ "properties": [
2824
+ {
2825
+ "name": "multiple",
2826
+ "description": "`false`: one selection at a time. `true`: any number.",
2827
+ "type": "boolean"
2828
+ },
2829
+ { "name": "orientation", "type": "'horizontal' | 'vertical'" },
2830
+ {
2831
+ "name": "label",
2832
+ "description": "Accessible name for the group.",
2833
+ "type": "string"
2834
+ },
2835
+ {
2836
+ "name": "value",
2837
+ "description": "The selected value, or values in multiple mode.",
2838
+ "type": "string | string[] | null"
2839
+ }
2840
+ ],
2841
+ "events": [
2842
+ {
2843
+ "name": "kt-change",
2844
+ "description": "The selection changed. `detail: { value }` — a single value or `null`, or an array in multiple mode."
2845
+ }
2846
+ ]
2847
+ }
2848
+ },
2849
+ {
2850
+ "name": "kt-collapsible",
2851
+ "description": "A section that folds away.\n\nBuilt on `<details>`, which means it works before the JavaScript loads,\nsurvives find-in-page — the browser opens a closed section to reveal a match —\nand needs no ARIA of its own.\n\n---\n\n\n### **Events:**\n - **kt-toggle** - Opened or closed. `detail: { open }`.\n\n### **Slots:**\n - _default_ - The contents.\n- **summary** - Replaces the `heading` attribute.\n\n### **CSS Parts:**\n - **base** - The `<details>`.\n- **summary** - The clickable row.\n- **content** - The revealed panel.",
2852
+ "doc-url": "",
2853
+ "attributes": [
2854
+ {
2855
+ "name": "open",
2856
+ "value": { "type": "boolean", "default": "false" }
2857
+ },
2858
+ {
2859
+ "name": "heading",
2860
+ "value": { "type": "string", "default": "''" }
2861
+ },
2862
+ {
2863
+ "name": "plain",
2864
+ "description": "Drops the bottom rule, for a collapsible that is not part of a list.",
2865
+ "value": { "type": "boolean", "default": "false" }
2866
+ }
2867
+ ],
2868
+ "slots": [
2869
+ { "name": "", "description": "The contents." },
2870
+ {
2871
+ "name": "summary",
2872
+ "description": "Replaces the `heading` attribute."
2873
+ }
2874
+ ],
2875
+ "events": [
2876
+ {
2877
+ "name": "kt-toggle",
2878
+ "description": "Opened or closed. `detail: { open }`."
2879
+ }
2880
+ ],
2881
+ "js": {
2882
+ "properties": [
2883
+ { "name": "open", "type": "boolean" },
2884
+ { "name": "heading", "type": "string" },
2885
+ {
2886
+ "name": "plain",
2887
+ "description": "Drops the bottom rule, for a collapsible that is not part of a list.",
2888
+ "type": "boolean"
2889
+ }
2890
+ ],
2891
+ "events": [
2892
+ {
2893
+ "name": "kt-toggle",
2894
+ "description": "Opened or closed. `detail: { open }`."
2895
+ }
2896
+ ]
2897
+ }
2898
+ },
2899
+ {
2900
+ "name": "kt-confirm-dialog",
2901
+ "description": "A centred yes/no overlay, for an action worth stopping to think about.\n\nConfirmations are for destructive or irreversible work. Editing belongs in a\n`<kt-side-panel>`, which does not block the page behind it.\n\n`role=\"alertdialog\"` and the cancel button takes focus on open, so a stray\nEnter dismisses rather than confirms.\n\n---\n\n\n### **Events:**\n - **kt-confirm** - The confirm button was pressed.\n- **kt-cancel** - Dismissed, by button, Escape or backdrop.\n\n### **Slots:**\n - _default_ - Extra content between the message and the buttons.\n\n### **CSS Parts:**\n - **dialog** - The `<dialog>`.\n- **actions** - The button row.",
2902
+ "doc-url": "",
2903
+ "attributes": [
2904
+ {
2905
+ "name": "open",
2906
+ "value": { "type": "boolean", "default": "false" }
2907
+ },
2908
+ {
2909
+ "name": "heading",
2910
+ "value": { "type": "string", "default": "'Are you sure?'" }
2911
+ },
2912
+ {
2913
+ "name": "message",
2914
+ "value": { "type": "string", "default": "''" }
2915
+ },
2916
+ {
2917
+ "name": "confirm-label",
2918
+ "value": { "type": "string", "default": "'Confirm'" }
2919
+ },
2920
+ {
2921
+ "name": "cancel-label",
2922
+ "value": { "type": "string", "default": "'Cancel'" }
2923
+ },
2924
+ {
2925
+ "name": "variant",
2926
+ "description": "`danger` gives the confirm button the solid red treatment.",
2927
+ "value": { "type": "KtConfirmVariant", "default": "'danger'" }
2928
+ }
2929
+ ],
2930
+ "slots": [
2931
+ {
2932
+ "name": "",
2933
+ "description": "Extra content between the message and the buttons."
2934
+ }
2935
+ ],
2936
+ "events": [
2937
+ {
2938
+ "name": "kt-confirm",
2939
+ "description": "The confirm button was pressed."
2940
+ },
2941
+ {
2942
+ "name": "kt-cancel",
2943
+ "description": "Dismissed, by button, Escape or backdrop."
2944
+ }
2945
+ ],
2946
+ "js": {
2947
+ "properties": [
2948
+ { "name": "open", "type": "boolean" },
2949
+ { "name": "heading", "type": "string" },
2950
+ { "name": "message", "type": "string" },
2951
+ { "name": "confirmLabel", "type": "string" },
2952
+ { "name": "cancelLabel", "type": "string" },
2953
+ {
2954
+ "name": "variant",
2955
+ "description": "`danger` gives the confirm button the solid red treatment.",
2956
+ "type": "KtConfirmVariant"
2957
+ }
2958
+ ],
2959
+ "events": [
2960
+ {
2961
+ "name": "kt-confirm",
2962
+ "description": "The confirm button was pressed."
2963
+ },
2964
+ {
2965
+ "name": "kt-cancel",
2966
+ "description": "Dismissed, by button, Escape or backdrop."
2967
+ }
2968
+ ]
2969
+ }
2970
+ },
2971
+ {
2972
+ "name": "kt-dropdown",
2973
+ "description": "A panel anchored to a trigger.\n\nThe generic overlay: pass `options` for a menu, or slot anything into\n`panel` for arbitrary content. For choosing a value in a form, reach for\n`<kt-select>` or `<kt-input-menu>` instead — they carry the listbox\nsemantics this one deliberately does not assume.\n\n---\n\n\n### **Events:**\n - **kt-select** - A menu row was chosen. `detail: { value, option }`.\n- **kt-open** - The panel opened.\n- **kt-close** - The panel closed.\n\n### **Methods:**\n - **show(): _void_** - Opens the panel.\n- **hide(): _void_** - Closes the panel.\n- **toggle(): _void_** - Opens or closes it.\n\n### **Slots:**\n - **trigger** - What opens the panel.\n- **panel** - Panel contents, when `options` is not used.\n\n### **CSS Parts:**\n - **trigger** - The trigger wrapper.\n- **panel** - The floating panel.\n- **option** - A menu row.",
2974
+ "doc-url": "",
2975
+ "attributes": [
2976
+ {
2977
+ "name": "value",
2978
+ "description": "Marks one row as current.",
2979
+ "value": { "type": "string | number | null", "default": "null" }
2980
+ },
2981
+ {
2982
+ "name": "preferred-placement",
2983
+ "description": "Where to put the panel when there is room on both sides.",
2984
+ "value": { "type": "KtDropdownPlacement", "default": "'bottom'" }
2985
+ },
2986
+ {
2987
+ "name": "align",
2988
+ "description": "Which edge of the trigger the panel lines up with.",
2989
+ "value": { "type": "KtDropdownAlign", "default": "'start'" }
2990
+ },
2991
+ {
2992
+ "name": "disabled",
2993
+ "value": { "type": "boolean", "default": "false" }
2994
+ },
2995
+ {
2996
+ "name": "empty-text",
2997
+ "value": { "type": "string", "default": "'No results'" }
2998
+ }
2999
+ ],
3000
+ "slots": [
3001
+ { "name": "trigger", "description": "What opens the panel." },
3002
+ {
3003
+ "name": "panel",
3004
+ "description": "Panel contents, when `options` is not used."
3005
+ }
3006
+ ],
3007
+ "events": [
3008
+ {
3009
+ "name": "kt-select",
3010
+ "description": "A menu row was chosen. `detail: { value, option }`."
3011
+ },
3012
+ { "name": "kt-open", "description": "The panel opened." },
3013
+ { "name": "kt-close", "description": "The panel closed." }
3014
+ ],
3015
+ "js": {
3016
+ "properties": [
3017
+ {
3018
+ "name": "options",
3019
+ "description": "Menu rows. Leave empty and slot into `panel` for custom content.",
3020
+ "type": "readonly KtOption[]"
3021
+ },
3022
+ {
3023
+ "name": "value",
3024
+ "description": "Marks one row as current.",
3025
+ "type": "string | number | null"
3026
+ },
3027
+ {
3028
+ "name": "preferredPlacement",
3029
+ "description": "Where to put the panel when there is room on both sides.",
3030
+ "type": "KtDropdownPlacement"
3031
+ },
3032
+ {
3033
+ "name": "align",
3034
+ "description": "Which edge of the trigger the panel lines up with.",
3035
+ "type": "KtDropdownAlign"
3036
+ },
3037
+ { "name": "disabled", "type": "boolean" },
3038
+ { "name": "emptyText", "type": "string" },
3039
+ {
3040
+ "name": "isOpen",
3041
+ "description": "Whether the panel is showing.",
3042
+ "type": "boolean"
3043
+ }
3044
+ ],
3045
+ "events": [
3046
+ {
3047
+ "name": "kt-select",
3048
+ "description": "A menu row was chosen. `detail: { value, option }`."
3049
+ },
3050
+ { "name": "kt-open", "description": "The panel opened." },
3051
+ { "name": "kt-close", "description": "The panel closed." }
3052
+ ]
3053
+ }
3054
+ },
3055
+ {
3056
+ "name": "kt-modal",
3057
+ "description": "A centred dialog for anything that is not a yes/no question.\n\n`<kt-confirm-dialog>` asks one thing and offers two answers. This one holds\ncontent — a compose window, a command palette, a picker — and lets you put\nwhatever you like in the footer.\n\nBuilt on the native `<dialog>`, so the top layer, focus containment, page\ninertness and Escape all come from the platform rather than from a focus trap\nthat leaks.\n\n---\n\n\n### **Events:**\n - **kt-close** - Dismissal requested. Cancelable, for an unsaved-changes guard.\n\n### **Methods:**\n - **requestClose(): _void_** - Asks to close. A cancelled `kt-close` keeps the modal open.\n\n### **Slots:**\n - _default_ - The body.\n- **header** - Replaces the `heading` attribute.\n- **footer** - Actions. Hidden when empty.\n\n### **CSS Parts:**\n - **dialog** - The `<dialog>`.\n- **header** - The header row.\n- **body** - The scrolling body.\n- **footer** - The action row.",
3058
+ "doc-url": "",
3059
+ "attributes": [
3060
+ {
3061
+ "name": "open",
3062
+ "value": { "type": "boolean", "default": "false" }
3063
+ },
3064
+ {
3065
+ "name": "heading",
3066
+ "value": { "type": "string", "default": "''" }
3067
+ },
3068
+ {
3069
+ "name": "description",
3070
+ "value": { "type": "string", "default": "''" }
3071
+ },
3072
+ {
3073
+ "name": "size",
3074
+ "value": { "type": "KtModalSize", "default": "'medium'" }
3075
+ },
3076
+ {
3077
+ "name": "no-close-button",
3078
+ "description": "Hides the close button. Escape still works — a modal you cannot leave is a trap.",
3079
+ "value": { "type": "boolean", "default": "false" }
3080
+ },
3081
+ {
3082
+ "name": "no-backdrop-close",
3083
+ "description": "Stops a backdrop click from dismissing.",
3084
+ "value": { "type": "boolean", "default": "false" }
3085
+ }
3086
+ ],
3087
+ "slots": [
3088
+ { "name": "", "description": "The body." },
3089
+ {
3090
+ "name": "header",
3091
+ "description": "Replaces the `heading` attribute."
3092
+ },
3093
+ { "name": "footer", "description": "Actions. Hidden when empty." }
3094
+ ],
3095
+ "events": [
3096
+ {
3097
+ "name": "kt-close",
3098
+ "description": "Dismissal requested. Cancelable, for an unsaved-changes guard."
3099
+ }
3100
+ ],
3101
+ "js": {
3102
+ "properties": [
3103
+ { "name": "open", "type": "boolean" },
3104
+ { "name": "heading", "type": "string" },
3105
+ { "name": "description", "type": "string" },
3106
+ { "name": "size", "type": "KtModalSize" },
3107
+ {
3108
+ "name": "noCloseButton",
3109
+ "description": "Hides the close button. Escape still works — a modal you cannot leave is a trap.",
3110
+ "type": "boolean"
3111
+ },
3112
+ {
3113
+ "name": "noBackdropClose",
3114
+ "description": "Stops a backdrop click from dismissing.",
3115
+ "type": "boolean"
3116
+ }
3117
+ ],
3118
+ "events": [
3119
+ {
3120
+ "name": "kt-close",
3121
+ "description": "Dismissal requested. Cancelable, for an unsaved-changes guard."
3122
+ }
3123
+ ]
3124
+ }
3125
+ },
3126
+ {
3127
+ "name": "kt-side-panel",
3128
+ "description": "A drawer that slides in from the right, for viewing or editing one record\nwithout leaving the list behind it.\n\nBuilt on the native `<dialog>`: the panel lands in the top layer, focus is\ntrapped inside it, the page behind goes inert, and Escape closes it — none of\nwhich the fixed-position div this replaces did.\n\n---\n\n\n### **Events:**\n - **kt-close** - The panel was dismissed. Cancelable: cancel it to keep the panel open, for an unsaved-changes prompt.\n\n### **Methods:**\n - **requestClose(): _void_** - Asks to close. A cancelled `kt-close` keeps the panel open.\n\n### **Slots:**\n - _default_ - The panel body.\n- **footer** - Pinned below the body.\n\n### **CSS Parts:**\n - **dialog** - The `<dialog>`.\n- **header** - The header row.\n- **body** - The scrolling body.",
3129
+ "doc-url": "",
3130
+ "attributes": [
3131
+ {
3132
+ "name": "open",
3133
+ "value": { "type": "boolean", "default": "false" }
3134
+ },
3135
+ {
3136
+ "name": "eyebrow",
3137
+ "description": "Small uppercase label above the heading — \"Details\", \"Editing\".",
3138
+ "value": { "type": "string", "default": "'Details'" }
3139
+ },
3140
+ {
3141
+ "name": "heading",
3142
+ "value": { "type": "string", "default": "''" }
3143
+ },
3144
+ {
3145
+ "name": "no-backdrop-close",
3146
+ "description": "Suppresses dismissal by backdrop click. Escape still works, by design.",
3147
+ "value": { "type": "boolean", "default": "false" }
3148
+ }
3149
+ ],
3150
+ "slots": [
3151
+ { "name": "", "description": "The panel body." },
3152
+ { "name": "footer", "description": "Pinned below the body." }
3153
+ ],
3154
+ "events": [
3155
+ {
3156
+ "name": "kt-close",
3157
+ "description": "The panel was dismissed. Cancelable: cancel it to keep the panel open, for an unsaved-changes prompt."
3158
+ }
3159
+ ],
3160
+ "js": {
3161
+ "properties": [
3162
+ { "name": "open", "type": "boolean" },
3163
+ {
3164
+ "name": "eyebrow",
3165
+ "description": "Small uppercase label above the heading — \"Details\", \"Editing\".",
3166
+ "type": "string"
3167
+ },
3168
+ { "name": "heading", "type": "string" },
3169
+ {
3170
+ "name": "noBackdropClose",
3171
+ "description": "Suppresses dismissal by backdrop click. Escape still works, by design.",
3172
+ "type": "boolean"
3173
+ }
3174
+ ],
3175
+ "events": [
3176
+ {
3177
+ "name": "kt-close",
3178
+ "description": "The panel was dismissed. Cancelable: cancel it to keep the panel open, for an unsaved-changes prompt."
3179
+ }
3180
+ ]
3181
+ }
3182
+ }
3183
+ ]
3184
+ }
3185
+ }
3186
+ }