kanto-ds 1.0.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 (192) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +155 -0
  3. package/dist/assets/fonts/README.md +19 -0
  4. package/dist/assets/fonts/manrope/OFL.txt +93 -0
  5. package/dist/assets/fonts/manrope/manrope-cyrillic-ext-wght-normal.woff2 +0 -0
  6. package/dist/assets/fonts/manrope/manrope-cyrillic-wght-normal.woff2 +0 -0
  7. package/dist/assets/fonts/manrope/manrope-latin-ext-wght-normal.woff2 +0 -0
  8. package/dist/assets/fonts/manrope/manrope-latin-wght-normal.woff2 +0 -0
  9. package/dist/assets/fonts/mulish/OFL.txt +93 -0
  10. package/dist/assets/fonts/mulish/mulish-cyrillic-ext-wght-italic.woff2 +0 -0
  11. package/dist/assets/fonts/mulish/mulish-cyrillic-ext-wght-normal.woff2 +0 -0
  12. package/dist/assets/fonts/mulish/mulish-cyrillic-wght-italic.woff2 +0 -0
  13. package/dist/assets/fonts/mulish/mulish-cyrillic-wght-normal.woff2 +0 -0
  14. package/dist/assets/fonts/mulish/mulish-latin-ext-wght-italic.woff2 +0 -0
  15. package/dist/assets/fonts/mulish/mulish-latin-ext-wght-normal.woff2 +0 -0
  16. package/dist/assets/fonts/mulish/mulish-latin-wght-italic.woff2 +0 -0
  17. package/dist/assets/fonts/mulish/mulish-latin-wght-normal.woff2 +0 -0
  18. package/dist/assets/fonts/source_code_pro/OFL.txt +93 -0
  19. package/dist/assets/fonts/source_code_pro/SourceCodePro-Regular.woff2 +0 -0
  20. package/dist/chunks/dialog-CPIfFIlF.js +29 -0
  21. package/dist/chunks/dialog-CPIfFIlF.js.map +1 -0
  22. package/dist/chunks/events-Bjl5Zmmq.js +18 -0
  23. package/dist/chunks/events-Bjl5Zmmq.js.map +1 -0
  24. package/dist/chunks/form-control-CxjBTt1c.js +17 -0
  25. package/dist/chunks/form-control-CxjBTt1c.js.map +1 -0
  26. package/dist/chunks/kt-element-CcMLO5e8.js +28 -0
  27. package/dist/chunks/kt-element-CcMLO5e8.js.map +1 -0
  28. package/dist/chunks/listbox-CUXYn_3S.js +101 -0
  29. package/dist/chunks/listbox-CUXYn_3S.js.map +1 -0
  30. package/dist/chunks/registry-X4LS9J5K.js +30 -0
  31. package/dist/chunks/registry-X4LS9J5K.js.map +1 -0
  32. package/dist/chunks/slots-BPbIdxAJ.js +7 -0
  33. package/dist/chunks/slots-BPbIdxAJ.js.map +1 -0
  34. package/dist/chunks/toaster-PmdKSV5x.js +40 -0
  35. package/dist/chunks/toaster-PmdKSV5x.js.map +1 -0
  36. package/dist/components/core/kt-avatar/kt-avatar.d.ts +49 -0
  37. package/dist/components/core/kt-avatar/kt-avatar.js +156 -0
  38. package/dist/components/core/kt-avatar/kt-avatar.js.map +1 -0
  39. package/dist/components/core/kt-badge/kt-badge.d.ts +77 -0
  40. package/dist/components/core/kt-badge/kt-badge.js +254 -0
  41. package/dist/components/core/kt-badge/kt-badge.js.map +1 -0
  42. package/dist/components/core/kt-button/kt-button.d.ts +71 -0
  43. package/dist/components/core/kt-button/kt-button.js +271 -0
  44. package/dist/components/core/kt-button/kt-button.js.map +1 -0
  45. package/dist/components/core/kt-card/kt-card.d.ts +62 -0
  46. package/dist/components/core/kt-card/kt-card.js +230 -0
  47. package/dist/components/core/kt-card/kt-card.js.map +1 -0
  48. package/dist/components/core/kt-code/kt-code.d.ts +55 -0
  49. package/dist/components/core/kt-code/kt-code.js +155 -0
  50. package/dist/components/core/kt-code/kt-code.js.map +1 -0
  51. package/dist/components/core/kt-icon/kt-icon.d.ts +44 -0
  52. package/dist/components/core/kt-icon/kt-icon.js +85 -0
  53. package/dist/components/core/kt-icon/kt-icon.js.map +1 -0
  54. package/dist/components/core/kt-kbd/kt-kbd.d.ts +38 -0
  55. package/dist/components/core/kt-kbd/kt-kbd.js +89 -0
  56. package/dist/components/core/kt-kbd/kt-kbd.js.map +1 -0
  57. package/dist/components/data/kt-chart/kt-chart.d.ts +99 -0
  58. package/dist/components/data/kt-chart/kt-chart.js +406 -0
  59. package/dist/components/data/kt-chart/kt-chart.js.map +1 -0
  60. package/dist/components/data/kt-meter/kt-meter.d.ts +63 -0
  61. package/dist/components/data/kt-meter/kt-meter.js +177 -0
  62. package/dist/components/data/kt-meter/kt-meter.js.map +1 -0
  63. package/dist/components/data/kt-pagination/kt-pagination.d.ts +35 -0
  64. package/dist/components/data/kt-pagination/kt-pagination.js +88 -0
  65. package/dist/components/data/kt-pagination/kt-pagination.js.map +1 -0
  66. package/dist/components/data/kt-stat/kt-stat.d.ts +60 -0
  67. package/dist/components/data/kt-stat/kt-stat.js +137 -0
  68. package/dist/components/data/kt-stat/kt-stat.js.map +1 -0
  69. package/dist/components/data/kt-table/kt-table.d.ts +99 -0
  70. package/dist/components/data/kt-table/kt-table.js +340 -0
  71. package/dist/components/data/kt-table/kt-table.js.map +1 -0
  72. package/dist/components/data/kt-timeline/kt-timeline.d.ts +78 -0
  73. package/dist/components/data/kt-timeline/kt-timeline.js +252 -0
  74. package/dist/components/data/kt-timeline/kt-timeline.js.map +1 -0
  75. package/dist/components/feedback/kt-alert/kt-alert.d.ts +46 -0
  76. package/dist/components/feedback/kt-alert/kt-alert.js +180 -0
  77. package/dist/components/feedback/kt-alert/kt-alert.js.map +1 -0
  78. package/dist/components/feedback/kt-empty-state/kt-empty-state.d.ts +40 -0
  79. package/dist/components/feedback/kt-empty-state/kt-empty-state.js +100 -0
  80. package/dist/components/feedback/kt-empty-state/kt-empty-state.js.map +1 -0
  81. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.d.ts +53 -0
  82. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +212 -0
  83. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js.map +1 -0
  84. package/dist/components/feedback/kt-skeleton/kt-skeleton.d.ts +43 -0
  85. package/dist/components/feedback/kt-skeleton/kt-skeleton.js +117 -0
  86. package/dist/components/feedback/kt-skeleton/kt-skeleton.js.map +1 -0
  87. package/dist/components/feedback/kt-toast/kt-toast.d.ts +57 -0
  88. package/dist/components/feedback/kt-toast/kt-toast.js +231 -0
  89. package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -0
  90. package/dist/components/feedback/kt-toast-container/kt-toast-container.d.ts +60 -0
  91. package/dist/components/feedback/kt-toast-container/kt-toast-container.js +100 -0
  92. package/dist/components/feedback/kt-toast-container/kt-toast-container.js.map +1 -0
  93. package/dist/components/feedback/kt-toast-container/toaster.d.ts +37 -0
  94. package/dist/components/feedback/kt-tooltip/kt-tooltip.d.ts +57 -0
  95. package/dist/components/feedback/kt-tooltip/kt-tooltip.js +138 -0
  96. package/dist/components/feedback/kt-tooltip/kt-tooltip.js.map +1 -0
  97. package/dist/components/forms/kt-drag-drop/kt-drag-drop.d.ts +68 -0
  98. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +287 -0
  99. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -0
  100. package/dist/components/forms/kt-form/kt-form.d.ts +75 -0
  101. package/dist/components/forms/kt-form/kt-form.js +187 -0
  102. package/dist/components/forms/kt-form/kt-form.js.map +1 -0
  103. package/dist/components/forms/kt-input/kt-input.d.ts +112 -0
  104. package/dist/components/forms/kt-input/kt-input.js +556 -0
  105. package/dist/components/forms/kt-input/kt-input.js.map +1 -0
  106. package/dist/components/forms/kt-input-menu/kt-input-menu.d.ts +60 -0
  107. package/dist/components/forms/kt-input-menu/kt-input-menu.js +313 -0
  108. package/dist/components/forms/kt-input-menu/kt-input-menu.js.map +1 -0
  109. package/dist/components/forms/kt-label-input/kt-label-input.d.ts +42 -0
  110. package/dist/components/forms/kt-label-input/kt-label-input.js +69 -0
  111. package/dist/components/forms/kt-label-input/kt-label-input.js.map +1 -0
  112. package/dist/components/forms/kt-select/kt-select.d.ts +80 -0
  113. package/dist/components/forms/kt-select/kt-select.js +334 -0
  114. package/dist/components/forms/kt-select/kt-select.js.map +1 -0
  115. package/dist/components/forms/kt-textarea/kt-textarea.d.ts +62 -0
  116. package/dist/components/forms/kt-textarea/kt-textarea.js +239 -0
  117. package/dist/components/forms/kt-textarea/kt-textarea.js.map +1 -0
  118. package/dist/components/forms/kt-toggle/kt-toggle.d.ts +53 -0
  119. package/dist/components/forms/kt-toggle/kt-toggle.js +170 -0
  120. package/dist/components/forms/kt-toggle/kt-toggle.js.map +1 -0
  121. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.d.ts +45 -0
  122. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +93 -0
  123. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js.map +1 -0
  124. package/dist/components/navigation/kt-header/kt-header.d.ts +67 -0
  125. package/dist/components/navigation/kt-header/kt-header.js +195 -0
  126. package/dist/components/navigation/kt-header/kt-header.js.map +1 -0
  127. package/dist/components/navigation/kt-page-header/kt-page-header.d.ts +48 -0
  128. package/dist/components/navigation/kt-page-header/kt-page-header.js +111 -0
  129. package/dist/components/navigation/kt-page-header/kt-page-header.js.map +1 -0
  130. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.d.ts +63 -0
  131. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +228 -0
  132. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js.map +1 -0
  133. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.d.ts +94 -0
  134. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +265 -0
  135. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js.map +1 -0
  136. package/dist/components/navigation/kt-tabs/kt-tabs.d.ts +64 -0
  137. package/dist/components/navigation/kt-tabs/kt-tabs.js +175 -0
  138. package/dist/components/navigation/kt-tabs/kt-tabs.js.map +1 -0
  139. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.d.ts +50 -0
  140. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +191 -0
  141. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js.map +1 -0
  142. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.d.ts +55 -0
  143. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +128 -0
  144. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js.map +1 -0
  145. package/dist/components/overlays/kt-collapsible/kt-collapsible.d.ts +42 -0
  146. package/dist/components/overlays/kt-collapsible/kt-collapsible.js +107 -0
  147. package/dist/components/overlays/kt-collapsible/kt-collapsible.js.map +1 -0
  148. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.d.ts +56 -0
  149. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +155 -0
  150. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js.map +1 -0
  151. package/dist/components/overlays/kt-dropdown/kt-dropdown.d.ts +64 -0
  152. package/dist/components/overlays/kt-dropdown/kt-dropdown.js +212 -0
  153. package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -0
  154. package/dist/components/overlays/kt-modal/kt-modal.d.ts +61 -0
  155. package/dist/components/overlays/kt-modal/kt-modal.js +207 -0
  156. package/dist/components/overlays/kt-modal/kt-modal.js.map +1 -0
  157. package/dist/components/overlays/kt-side-panel/kt-side-panel.d.ts +52 -0
  158. package/dist/components/overlays/kt-side-panel/kt-side-panel.js +178 -0
  159. package/dist/components/overlays/kt-side-panel/kt-side-panel.js.map +1 -0
  160. package/dist/icons/defaults.d.ts +25 -0
  161. package/dist/icons/index.d.ts +3 -0
  162. package/dist/icons/index.js +37 -0
  163. package/dist/icons/index.js.map +1 -0
  164. package/dist/icons/registry.d.ts +38 -0
  165. package/dist/index.d.ts +81 -0
  166. package/dist/index.js +96 -0
  167. package/dist/index.js.map +1 -0
  168. package/dist/internal/countries.d.ts +37 -0
  169. package/dist/internal/dialog.d.ts +22 -0
  170. package/dist/internal/events.d.ts +14 -0
  171. package/dist/internal/form-control.d.ts +27 -0
  172. package/dist/internal/format.d.ts +8 -0
  173. package/dist/internal/kt-element.d.ts +22 -0
  174. package/dist/internal/listbox.d.ts +36 -0
  175. package/dist/internal/slots.d.ts +10 -0
  176. package/dist/react/index.d.ts +208 -0
  177. package/dist/react/index.js +314 -0
  178. package/dist/react/index.js.map +1 -0
  179. package/dist/styles.css +13 -0
  180. package/dist/tokens/README.md +63 -0
  181. package/dist/tokens/base.css +79 -0
  182. package/dist/tokens/colors.css +125 -0
  183. package/dist/tokens/fonts.css +136 -0
  184. package/dist/tokens/index.css +12 -0
  185. package/dist/tokens/responsive.css +108 -0
  186. package/dist/tokens/spacing.css +66 -0
  187. package/dist/tokens/theme-light.css +144 -0
  188. package/dist/tokens/typography.css +41 -0
  189. package/dist/vue/index.d.ts +143 -0
  190. package/dist/vue/index.js +56 -0
  191. package/dist/vue/index.js.map +1 -0
  192. package/package.json +296 -0
@@ -0,0 +1,101 @@
1
+ import { css as i } from "lit";
2
+ function o(t) {
3
+ return t.label ?? String(t.id);
4
+ }
5
+ function l(t, e) {
6
+ const r = e.trim().toLowerCase();
7
+ return r ? t.filter((n) => o(n).toLowerCase().includes(r)) : t;
8
+ }
9
+ function s(t, e, r) {
10
+ if (t.length === 0) return -1;
11
+ for (let n = 1; n <= t.length; n += 1) {
12
+ const a = (e + r * n + t.length * n) % t.length;
13
+ if (!t[a]?.disabled) return a;
14
+ }
15
+ return -1;
16
+ }
17
+ function p(t) {
18
+ return t.findIndex((e) => !e.disabled);
19
+ }
20
+ function u(t) {
21
+ for (let e = t.length - 1; e >= 0; e -= 1)
22
+ if (!t[e]?.disabled) return e;
23
+ return -1;
24
+ }
25
+ const f = i`
26
+ .popup {
27
+ position: absolute;
28
+ top: calc(var(--field-height, var(--button-height)) + 6px);
29
+ left: 0;
30
+ z-index: var(--z-dropdown);
31
+ display: flex;
32
+ flex-direction: column;
33
+ gap: var(--gap-element);
34
+ box-sizing: border-box;
35
+ width: 100%;
36
+ max-height: 300px;
37
+ margin: 0;
38
+ padding: var(--padding-expand);
39
+ overflow: auto;
40
+ list-style: none;
41
+ background: var(--color-dark-20);
42
+ border-radius: var(--radius-input);
43
+ scrollbar-width: thin;
44
+
45
+ visibility: hidden;
46
+ opacity: 0;
47
+ transform: translateY(-6px) scaleY(0.98);
48
+ transform-origin: top left;
49
+ pointer-events: none;
50
+ transition:
51
+ opacity var(--duration-fast) var(--easing-standard),
52
+ transform var(--duration-fast) var(--easing-standard);
53
+ }
54
+
55
+ .popup.open {
56
+ visibility: visible;
57
+ opacity: 1;
58
+ transform: translateY(0) scaleY(1);
59
+ pointer-events: auto;
60
+ }
61
+
62
+ .option {
63
+ padding: var(--padding-expand-item);
64
+ color: var(--text-muted);
65
+ font: var(--font-input);
66
+ border-radius: var(--radius-input);
67
+ cursor: pointer;
68
+ }
69
+
70
+ .option:hover,
71
+ .option.active {
72
+ background: var(--color-dark-22);
73
+ }
74
+
75
+ .option.selected {
76
+ color: var(--text-body);
77
+ font-weight: 600;
78
+ background: var(--color-dark-23);
79
+ }
80
+
81
+ .option.disabled {
82
+ opacity: 0.5;
83
+ pointer-events: none;
84
+ }
85
+
86
+ .empty {
87
+ padding: var(--padding-expand-item);
88
+ color: var(--text-muted);
89
+ font: var(--font-normal-small);
90
+ pointer-events: none;
91
+ }
92
+ `;
93
+ export {
94
+ p as a,
95
+ u as b,
96
+ l as f,
97
+ f as l,
98
+ s as n,
99
+ o
100
+ };
101
+ //# sourceMappingURL=listbox-CUXYn_3S.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listbox-CUXYn_3S.js","sources":["../../src/internal/listbox.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * Shared pieces of the two option-list controls, `<kt-select>` and\n * `<kt-input-menu>`.\n *\n * They differ in how an option is chosen — pick from a list, or filter by\n * typing — but the popup, the option rows and the keyboard model are the same,\n * and having them drift apart is how a design system stops looking like one.\n */\n\nexport interface KtOption {\n readonly id: string | number;\n readonly label?: string;\n readonly disabled?: boolean;\n}\n\n/** The text to display for an option: its label, or its id as a fallback. */\nexport function optionLabel(option: KtOption): string {\n return option.label ?? String(option.id);\n}\n\n/** Case-insensitive substring match on the visible label. */\nexport function filterOptions(options: readonly KtOption[], query: string): readonly KtOption[] {\n const needle = query.trim().toLowerCase();\n if (!needle) return options;\n return options.filter((option) => optionLabel(option).toLowerCase().includes(needle));\n}\n\n/**\n * The next selectable index in `direction`, skipping disabled options and\n * wrapping at both ends. Returns -1 when every option is disabled, so a caller\n * never lands the active descendant on something that cannot be chosen.\n */\nexport function nextEnabledIndex(\n options: readonly KtOption[],\n from: number,\n direction: 1 | -1,\n): number {\n if (options.length === 0) return -1;\n\n for (let step = 1; step <= options.length; step += 1) {\n const index = (from + direction * step + options.length * step) % options.length;\n if (!options[index]?.disabled) return index;\n }\n return -1;\n}\n\n/** The first selectable index, for opening a list with nothing selected. */\nexport function firstEnabledIndex(options: readonly KtOption[]): number {\n return options.findIndex((option) => !option.disabled);\n}\n\n/** The last selectable index, for End. */\nexport function lastEnabledIndex(options: readonly KtOption[]): number {\n for (let index = options.length - 1; index >= 0; index -= 1) {\n if (!options[index]?.disabled) return index;\n }\n return -1;\n}\n\n/**\n * The popup and option-row styles.\n *\n * The panel animates through opacity and transform while staying in the layout\n * as `visibility: hidden`, rather than being added and removed: a popup that\n * unmounts cannot animate out, and one that only sets `display: none` cannot\n * animate at all.\n */\nexport const listboxStyles = css`\n .popup {\n position: absolute;\n top: calc(var(--field-height, var(--button-height)) + 6px);\n left: 0;\n z-index: var(--z-dropdown);\n display: flex;\n flex-direction: column;\n gap: var(--gap-element);\n box-sizing: border-box;\n width: 100%;\n max-height: 300px;\n margin: 0;\n padding: var(--padding-expand);\n overflow: auto;\n list-style: none;\n background: var(--color-dark-20);\n border-radius: var(--radius-input);\n scrollbar-width: thin;\n\n visibility: hidden;\n opacity: 0;\n transform: translateY(-6px) scaleY(0.98);\n transform-origin: top left;\n pointer-events: none;\n transition:\n opacity var(--duration-fast) var(--easing-standard),\n transform var(--duration-fast) var(--easing-standard);\n }\n\n .popup.open {\n visibility: visible;\n opacity: 1;\n transform: translateY(0) scaleY(1);\n pointer-events: auto;\n }\n\n .option {\n padding: var(--padding-expand-item);\n color: var(--text-muted);\n font: var(--font-input);\n border-radius: var(--radius-input);\n cursor: pointer;\n }\n\n .option:hover,\n .option.active {\n background: var(--color-dark-22);\n }\n\n .option.selected {\n color: var(--text-body);\n font-weight: 600;\n background: var(--color-dark-23);\n }\n\n .option.disabled {\n opacity: 0.5;\n pointer-events: none;\n }\n\n .empty {\n padding: var(--padding-expand-item);\n color: var(--text-muted);\n font: var(--font-normal-small);\n pointer-events: none;\n }\n`;\n"],"names":["optionLabel","option","filterOptions","options","query","needle","nextEnabledIndex","from","direction","step","index","firstEnabledIndex","lastEnabledIndex","listboxStyles","css"],"mappings":";AAkBO,SAASA,EAAYC,GAA0B;AACpD,SAAOA,EAAO,SAAS,OAAOA,EAAO,EAAE;AACzC;AAGO,SAASC,EAAcC,GAA8BC,GAAoC;AAC9F,QAAMC,IAASD,EAAM,KAAA,EAAO,YAAA;AAC5B,SAAKC,IACEF,EAAQ,OAAO,CAACF,MAAWD,EAAYC,CAAM,EAAE,YAAA,EAAc,SAASI,CAAM,CAAC,IADhEF;AAEtB;AAOO,SAASG,EACdH,GACAI,GACAC,GACQ;AACR,MAAIL,EAAQ,WAAW,EAAG,QAAO;AAEjC,WAASM,IAAO,GAAGA,KAAQN,EAAQ,QAAQM,KAAQ,GAAG;AACpD,UAAMC,KAASH,IAAOC,IAAYC,IAAON,EAAQ,SAASM,KAAQN,EAAQ;AAC1E,QAAI,CAACA,EAAQO,CAAK,GAAG,SAAU,QAAOA;AAAA,EACxC;AACA,SAAO;AACT;AAGO,SAASC,EAAkBR,GAAsC;AACtE,SAAOA,EAAQ,UAAU,CAACF,MAAW,CAACA,EAAO,QAAQ;AACvD;AAGO,SAASW,EAAiBT,GAAsC;AACrE,WAASO,IAAQP,EAAQ,SAAS,GAAGO,KAAS,GAAGA,KAAS;AACxD,QAAI,CAACP,EAAQO,CAAK,GAAG,SAAU,QAAOA;AAExC,SAAO;AACT;AAUO,MAAMG,IAAgBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
@@ -0,0 +1,30 @@
1
+ const t = /* @__PURE__ */ new Map();
2
+ function o(e) {
3
+ return e.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-zA-Z])(\d)/g, "$1-$2").replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
4
+ }
5
+ function s(e, r) {
6
+ t.set(o(e), r);
7
+ }
8
+ function c(e) {
9
+ for (const [r, n] of Object.entries(e))
10
+ a(n) && s(r, n);
11
+ }
12
+ function i(e) {
13
+ return t.get(o(e));
14
+ }
15
+ function g() {
16
+ return [...t.keys()].sort();
17
+ }
18
+ function a(e) {
19
+ return Array.isArray(e) && e.every(
20
+ (r) => Array.isArray(r) && typeof r[0] == "string" && typeof r[1] == "object" && r[1] !== null
21
+ );
22
+ }
23
+ export {
24
+ c as a,
25
+ g as b,
26
+ i as g,
27
+ s as r,
28
+ o as t
29
+ };
30
+ //# sourceMappingURL=registry-X4LS9J5K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-X4LS9J5K.js","sources":["../../src/icons/registry.ts"],"sourcesContent":["/**\n * The icon registry.\n *\n * `<kt-icon>` looks icons up by name at render time, which means the set of\n * icons cannot be statically analysed and a bundler cannot tree-shake it. So\n * Kanto does not bundle all two thousand Lucide icons: the elements register\n * the handful they need themselves, and an application registers whatever else\n * it uses.\n *\n * import { Rocket, Wallet } from 'lucide';\n * import { registerIcons } from 'kanto-ds/icons';\n *\n * registerIcons({ Rocket, Wallet });\n *\n * Names are normalised to kebab-case, so `Rocket`, `rocket` and\n * `ChevronDown` / `chevron-down` all resolve.\n */\n\n/** A Lucide icon: a flat list of SVG children, each `[tag, attributes]`. */\nexport type IconNode = [tag: string, attrs: Record<string, string | number | undefined>][];\n\nconst registry = new Map<string, IconNode>();\n\n/**\n * `ChevronDown` → `chevron-down`, `Trash2` → `trash-2`, `AArrowDown` →\n * `a-arrow-down`.\n *\n * The digit boundary matters: Lucide names that icon `trash-2`, so a rule that\n * only splits on case produces `trash2` and the lookup quietly misses.\n */\nexport function toKebabCase(name: string): string {\n return name\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2') // acronym run before a word\n .replace(/([a-zA-Z])(\\d)/g, '$1-$2') // letter before a digit\n .replace(/([a-z])([A-Z])/g, '$1-$2') // ordinary camel boundary\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\n/** Registers a single icon under `name`. */\nexport function registerIcon(name: string, node: IconNode): void {\n registry.set(toKebabCase(name), node);\n}\n\n/**\n * Registers a map of icons. Accepts a Lucide namespace import directly:\n * every non-icon export (`createElement`, `createIcons`, …) is skipped.\n */\nexport function registerIcons(icons: Record<string, unknown>): void {\n for (const [name, node] of Object.entries(icons)) {\n if (isIconNode(node)) registerIcon(name, node);\n }\n}\n\n/** Returns the icon registered under `name`, or `undefined`. */\nexport function getIcon(name: string): IconNode | undefined {\n return registry.get(toKebabCase(name));\n}\n\n/** Every registered name, kebab-cased and sorted. Useful for docs and tests. */\nexport function registeredIcons(): string[] {\n return [...registry.keys()].sort();\n}\n\nfunction isIconNode(value: unknown): value is IconNode {\n return (\n Array.isArray(value) &&\n value.every(\n (child) =>\n Array.isArray(child) &&\n typeof child[0] === 'string' &&\n typeof child[1] === 'object' &&\n child[1] !== null,\n )\n );\n}\n"],"names":["registry","toKebabCase","name","registerIcon","node","registerIcons","icons","isIconNode","getIcon","registeredIcons","value","child"],"mappings":"AAqBA,MAAMA,wBAAe,IAAA;AASd,SAASC,EAAYC,GAAsB;AAChD,SAAOA,EACJ,QAAQ,yBAAyB,OAAO,EACxC,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,WAAW,GAAG,EACtB,YAAA;AACL;AAGO,SAASC,EAAaD,GAAcE,GAAsB;AAC/D,EAAAJ,EAAS,IAAIC,EAAYC,CAAI,GAAGE,CAAI;AACtC;AAMO,SAASC,EAAcC,GAAsC;AAClE,aAAW,CAACJ,GAAME,CAAI,KAAK,OAAO,QAAQE,CAAK;AAC7C,IAAIC,EAAWH,CAAI,KAAGD,EAAaD,GAAME,CAAI;AAEjD;AAGO,SAASI,EAAQN,GAAoC;AAC1D,SAAOF,EAAS,IAAIC,EAAYC,CAAI,CAAC;AACvC;AAGO,SAASO,IAA4B;AAC1C,SAAO,CAAC,GAAGT,EAAS,KAAA,CAAM,EAAE,KAAA;AAC9B;AAEA,SAASO,EAAWG,GAAmC;AACrD,SACE,MAAM,QAAQA,CAAK,KACnBA,EAAM;AAAA,IACJ,CAACC,MACC,MAAM,QAAQA,CAAK,KACnB,OAAOA,EAAM,CAAC,KAAM,YACpB,OAAOA,EAAM,CAAC,KAAM,YACpBA,EAAM,CAAC,MAAM;AAAA,EAAA;AAGrB;"}
@@ -0,0 +1,7 @@
1
+ function n(e) {
2
+ return e ? e.assignedElements({ flatten: !0 }).length > 0 ? !0 : e.assignedNodes({ flatten: !0 }).some((t) => t.nodeType === Node.TEXT_NODE && (t.textContent ?? "").trim() !== "") : !1;
3
+ }
4
+ export {
5
+ n as h
6
+ };
7
+ //# sourceMappingURL=slots-BPbIdxAJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slots-BPbIdxAJ.js","sources":["../../src/internal/slots.ts"],"sourcesContent":["/**\n * Knowing whether a slot actually received anything.\n *\n * CSS cannot answer this. A wrapper around `<slot>` always has one element\n * child — the slot itself — so `:has(*)` matches whether or not anything was\n * assigned, and `:empty` looks at the slot's *fallback* children rather than\n * its assigned nodes. Both read as working and neither does.\n */\n\n/** True when the slot has assigned elements, or non-whitespace assigned text. */\nexport function hasAssignedContent(slot: HTMLSlotElement | null | undefined): boolean {\n if (!slot) return false;\n if (slot.assignedElements({ flatten: true }).length > 0) return true;\n\n return slot\n .assignedNodes({ flatten: true })\n .some((node) => node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim() !== '');\n}\n"],"names":["hasAssignedContent","slot","node"],"mappings":"AAUO,SAASA,EAAmBC,GAAmD;AACpF,SAAKA,IACDA,EAAK,iBAAiB,EAAE,SAAS,IAAM,EAAE,SAAS,IAAU,KAEzDA,EACJ,cAAc,EAAE,SAAS,GAAA,CAAM,EAC/B,KAAK,CAACC,MAASA,EAAK,aAAa,KAAK,cAAcA,EAAK,eAAe,IAAI,KAAA,MAAW,EAAE,IAL1E;AAMpB;"}
@@ -0,0 +1,40 @@
1
+ import { KtToastContainer as r } from "../components/feedback/kt-toast-container/kt-toast-container.js";
2
+ class o {
3
+ constructor() {
4
+ this.position = "bottom-right";
5
+ }
6
+ /** The container in use, created on first call. */
7
+ getContainer() {
8
+ if (this.container?.isConnected) return this.container;
9
+ const t = document.querySelector("kt-toast-container");
10
+ if (t)
11
+ return this.container = t, t;
12
+ const n = new r();
13
+ return n.position = this.position, document.body.append(n), this.container = n, n;
14
+ }
15
+ show(t) {
16
+ return this.getContainer().show(t);
17
+ }
18
+ success(t, n = {}) {
19
+ return this.show({ duration: 4e3, ...n, variant: "success", heading: t });
20
+ }
21
+ info(t, n = {}) {
22
+ return this.show({ duration: 4e3, ...n, variant: "information", heading: t });
23
+ }
24
+ warning(t, n = {}) {
25
+ return this.show({ duration: 6e3, ...n, variant: "warning", heading: t });
26
+ }
27
+ /** Errors do not dismiss themselves: the user has to see this one. */
28
+ error(t, n = {}) {
29
+ return this.show({ duration: 0, ...n, variant: "error", heading: t });
30
+ }
31
+ /** Clears the stack. */
32
+ clear() {
33
+ this.container?.clear();
34
+ }
35
+ }
36
+ const s = new o();
37
+ export {
38
+ s as t
39
+ };
40
+ //# sourceMappingURL=toaster-PmdKSV5x.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toaster-PmdKSV5x.js","sources":["../../src/components/feedback/kt-toast-container/toaster.ts"],"sourcesContent":["import {\n KtToastContainer,\n type KtToastOptions,\n type KtToastPosition,\n} from '../kt-toast-container/kt-toast-container.js';\nimport type { KtToast } from '../kt-toast/kt-toast.js';\nimport '../kt-toast-container/kt-toast-container.js';\n\n/**\n * The imperative way to raise a toast, for the many places where reaching a\n * container element is inconvenient — an interceptor, a store, a catch block.\n *\n * It lazily creates one `<kt-toast-container>` on `<body>` and reuses it.\n *\n * ```js\n * import { toaster } from 'kanto-ds';\n *\n * toaster.success('Entity created');\n * toaster.error('Could not save', { description: 'Try again in a moment.' });\n * ```\n *\n * Prefer placing a `<kt-toast-container>` in your own markup when you care\n * where in the DOM it lives — inside a dialog, or scoped to one region.\n */\nclass Toaster {\n private container: KtToastContainer | undefined;\n\n /** Where the auto-created container sits. Changing it moves the stack. */\n position: KtToastPosition = 'bottom-right';\n\n /** The container in use, created on first call. */\n getContainer(): KtToastContainer {\n if (this.container?.isConnected) return this.container;\n\n const existing = document.querySelector('kt-toast-container');\n if (existing) {\n this.container = existing;\n return existing;\n }\n\n const created = new KtToastContainer();\n created.position = this.position;\n document.body.append(created);\n this.container = created;\n return created;\n }\n\n show(options: KtToastOptions): KtToast {\n return this.getContainer().show(options);\n }\n\n success(heading: string, options: Omit<KtToastOptions, 'variant' | 'heading'> = {}): KtToast {\n return this.show({ duration: 4000, ...options, variant: 'success', heading });\n }\n\n info(heading: string, options: Omit<KtToastOptions, 'variant' | 'heading'> = {}): KtToast {\n return this.show({ duration: 4000, ...options, variant: 'information', heading });\n }\n\n warning(heading: string, options: Omit<KtToastOptions, 'variant' | 'heading'> = {}): KtToast {\n return this.show({ duration: 6000, ...options, variant: 'warning', heading });\n }\n\n /** Errors do not dismiss themselves: the user has to see this one. */\n error(heading: string, options: Omit<KtToastOptions, 'variant' | 'heading'> = {}): KtToast {\n return this.show({ duration: 0, ...options, variant: 'error', heading });\n }\n\n /** Clears the stack. */\n clear(): void {\n this.container?.clear();\n }\n}\n\n/** The shared toaster. */\nexport const toaster = new Toaster();\n"],"names":["Toaster","existing","created","KtToastContainer","options","heading","toaster"],"mappings":";AAwBA,MAAMA,EAAQ;AAAA,EAAd,cAAA;AAIE,SAAA,WAA4B;AAAA,EAAA;AAAA;AAAA,EAG5B,eAAiC;AAC/B,QAAI,KAAK,WAAW,YAAa,QAAO,KAAK;AAE7C,UAAMC,IAAW,SAAS,cAAc,oBAAoB;AAC5D,QAAIA;AACF,kBAAK,YAAYA,GACVA;AAGT,UAAMC,IAAU,IAAIC,EAAA;AACpB,WAAAD,EAAQ,WAAW,KAAK,UACxB,SAAS,KAAK,OAAOA,CAAO,GAC5B,KAAK,YAAYA,GACVA;AAAA,EACT;AAAA,EAEA,KAAKE,GAAkC;AACrC,WAAO,KAAK,eAAe,KAAKA,CAAO;AAAA,EACzC;AAAA,EAEA,QAAQC,GAAiBD,IAAuD,IAAa;AAC3F,WAAO,KAAK,KAAK,EAAE,UAAU,KAAM,GAAGA,GAAS,SAAS,WAAW,SAAAC,GAAS;AAAA,EAC9E;AAAA,EAEA,KAAKA,GAAiBD,IAAuD,IAAa;AACxF,WAAO,KAAK,KAAK,EAAE,UAAU,KAAM,GAAGA,GAAS,SAAS,eAAe,SAAAC,GAAS;AAAA,EAClF;AAAA,EAEA,QAAQA,GAAiBD,IAAuD,IAAa;AAC3F,WAAO,KAAK,KAAK,EAAE,UAAU,KAAM,GAAGA,GAAS,SAAS,WAAW,SAAAC,GAAS;AAAA,EAC9E;AAAA;AAAA,EAGA,MAAMA,GAAiBD,IAAuD,IAAa;AACzF,WAAO,KAAK,KAAK,EAAE,UAAU,GAAG,GAAGA,GAAS,SAAS,SAAS,SAAAC,GAAS;AAAA,EACzE;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,WAAW,MAAA;AAAA,EAClB;AACF;AAGO,MAAMC,IAAU,IAAIN,EAAA;"}
@@ -0,0 +1,49 @@
1
+ import { type TemplateResult } from 'lit';
2
+ import { KtElement } from '#internal/kt-element';
3
+ import '../kt-icon/kt-icon.js';
4
+ export type KtAvatarSize = 'small' | 'medium' | 'large';
5
+ export type KtAvatarStatus = 'online' | 'away' | 'busy' | 'offline';
6
+ /** "Benjamin Canac" → "BC", "emma.davis@example.com" → "ED". */
7
+ export declare function initialsOf(name: string): string;
8
+ /**
9
+ * A person or an organisation, as a picture or as their initials.
10
+ *
11
+ * The fallback is not decoration: most rows in most products have no photo, so
12
+ * the initials path is the one that renders. It picks a colour from the name,
13
+ * which means the same person is the same colour on every screen and the eye
14
+ * can use it.
15
+ *
16
+ * @element kt-avatar
17
+ *
18
+ * @csspart base - The avatar circle.
19
+ * @csspart image - The `<img>`, when `src` is set and loads.
20
+ *
21
+ * @example
22
+ * ```html
23
+ * <kt-avatar name="Benjamin Canac"></kt-avatar>
24
+ * <kt-avatar name="Emma Davis" src="/emma.jpg" status="online"></kt-avatar>
25
+ * ```
26
+ */
27
+ export declare class KtAvatar extends KtElement {
28
+ static styles: import("lit").CSSResultGroup[];
29
+ private failed;
30
+ /** The person's name. Drives the initials, the colour and the label. */
31
+ name: string;
32
+ /** Photo. Falls back to initials if it is missing or fails to load. */
33
+ src: string;
34
+ size: KtAvatarSize;
35
+ /** Rounds to the card radius instead of a circle — for organisations. */
36
+ square: boolean;
37
+ /** Presence dot. Omit for none. */
38
+ status?: KtAvatarStatus;
39
+ /** Overrides the colour picked from the name. */
40
+ color: string;
41
+ willUpdate(changed: Map<string, unknown>): void;
42
+ private get hue();
43
+ render(): TemplateResult;
44
+ }
45
+ declare global {
46
+ interface HTMLElementTagNameMap {
47
+ 'kt-avatar': KtAvatar;
48
+ }
49
+ }
@@ -0,0 +1,156 @@
1
+ import { css as p, nothing as f, html as n } from "lit";
2
+ import { state as v, property as o } from "lit/decorators.js";
3
+ import { classMap as c } from "lit/directives/class-map.js";
4
+ import { K as u, d as g } from "../../../chunks/kt-element-CcMLO5e8.js";
5
+ import "../kt-icon/kt-icon.js";
6
+ var m = Object.defineProperty, s = (a, e, t, b) => {
7
+ for (var i = void 0, l = a.length - 1, h; l >= 0; l--)
8
+ (h = a[l]) && (i = h(e, t, i) || i);
9
+ return i && m(e, t, i), i;
10
+ };
11
+ const d = Array.from({ length: 8 }, (a, e) => `var(--chart-series-${e + 1})`);
12
+ function y(a) {
13
+ const t = (a.includes("@") ? a.split("@")[0] ?? "" : a).split(/[\s._-]+/).filter(Boolean);
14
+ return t.length === 0 ? "" : t.length === 1 ? (t[0] ?? "").slice(0, 2).toUpperCase() : `${t[0][0]}${t[t.length - 1][0]}`.toUpperCase();
15
+ }
16
+ class r extends u {
17
+ constructor() {
18
+ super(...arguments), this.failed = !1, this.name = "", this.src = "", this.size = "medium", this.square = !1, this.color = "";
19
+ }
20
+ static {
21
+ this.styles = [
22
+ u.styles,
23
+ p`
24
+ :host {
25
+ display: inline-flex;
26
+ --kt-avatar-size: 32px;
27
+ }
28
+
29
+ :host([size='small']) {
30
+ --kt-avatar-size: 24px;
31
+ }
32
+ :host([size='large']) {
33
+ --kt-avatar-size: 48px;
34
+ }
35
+
36
+ /* The identity hue is worn exactly the way every other tinted thing in
37
+ Kanto wears one: the colour at 12% behind, the colour itself as the
38
+ ink, and no border — the same pair as a secondary button, a danger
39
+ button or a badge tone. A saturated fill with white initials is a
40
+ different system's idea, and beside those it looks like one. */
41
+ .avatar {
42
+ position: relative;
43
+ display: inline-flex;
44
+ flex: none;
45
+ align-items: center;
46
+ justify-content: center;
47
+ box-sizing: border-box;
48
+ width: var(--kt-avatar-size);
49
+ height: var(--kt-avatar-size);
50
+ overflow: hidden;
51
+ color: var(--kt-avatar-hue, var(--text-muted));
52
+ font: 600 calc(var(--kt-avatar-size) * 0.36) / 1 var(--font-family-body);
53
+ background: color-mix(in srgb, var(--kt-avatar-hue, transparent) 12%, transparent);
54
+ border-radius: var(--radius-full);
55
+ user-select: none;
56
+ }
57
+
58
+ /* No hue to tint with, and a photograph that fills the circle anyway. */
59
+ .avatar.has-image,
60
+ .avatar.anonymous {
61
+ background: var(--surface-raised);
62
+ }
63
+
64
+ :host([square]) .avatar {
65
+ border-radius: var(--border-radius);
66
+ }
67
+
68
+ img {
69
+ width: 100%;
70
+ height: 100%;
71
+ object-fit: cover;
72
+ }
73
+
74
+ /* The dot sits outside the clipped circle, so it needs its own box. */
75
+ .status {
76
+ position: absolute;
77
+ right: 0;
78
+ bottom: 0;
79
+ width: calc(var(--kt-avatar-size) * 0.28);
80
+ height: calc(var(--kt-avatar-size) * 0.28);
81
+ border: 2px solid var(--surface-page);
82
+ border-radius: var(--radius-full);
83
+ }
84
+
85
+ .online {
86
+ background: var(--color-success-base);
87
+ }
88
+ .away {
89
+ background: var(--color-warning-base);
90
+ }
91
+ .busy {
92
+ background: var(--color-danger-base);
93
+ }
94
+ .offline {
95
+ background: var(--color-text-500);
96
+ }
97
+ `
98
+ ];
99
+ }
100
+ willUpdate(e) {
101
+ e.has("src") && (this.failed = !1);
102
+ }
103
+ get hue() {
104
+ if (this.color) return this.color;
105
+ let e = 0;
106
+ for (const t of this.name) e += t.charCodeAt(0);
107
+ return d[e % d.length];
108
+ }
109
+ render() {
110
+ const e = y(this.name), t = !!this.src && !this.failed;
111
+ return n`<span
112
+ part="base"
113
+ class=${c({ avatar: !0, "has-image": t, anonymous: !this.name })}
114
+ style=${t ? "" : `--kt-avatar-hue:${this.hue}`}
115
+ role="img"
116
+ aria-label=${this.name || "Avatar"}
117
+ >
118
+ ${t ? n`<img
119
+ part="image"
120
+ src=${this.src}
121
+ alt=""
122
+ @error=${() => {
123
+ this.failed = !0;
124
+ }}
125
+ />` : e || n`<kt-icon name="user" size="16"></kt-icon>`}
126
+ ${this.status ? n`<span class=${c({ status: !0, [this.status]: !0 })}></span>` : f}
127
+ </span>`;
128
+ }
129
+ }
130
+ s([
131
+ v()
132
+ ], r.prototype, "failed");
133
+ s([
134
+ o({ type: String })
135
+ ], r.prototype, "name");
136
+ s([
137
+ o({ type: String })
138
+ ], r.prototype, "src");
139
+ s([
140
+ o({ type: String, reflect: !0 })
141
+ ], r.prototype, "size");
142
+ s([
143
+ o({ type: Boolean, reflect: !0 })
144
+ ], r.prototype, "square");
145
+ s([
146
+ o({ type: String, reflect: !0 })
147
+ ], r.prototype, "status");
148
+ s([
149
+ o({ type: String })
150
+ ], r.prototype, "color");
151
+ g("kt-avatar", r);
152
+ export {
153
+ r as KtAvatar,
154
+ y as initialsOf
155
+ };
156
+ //# sourceMappingURL=kt-avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kt-avatar.js","sources":["../../../../src/components/core/kt-avatar/kt-avatar.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport '../kt-icon/kt-icon.js';\n\nexport type KtAvatarSize = 'small' | 'medium' | 'large';\nexport type KtAvatarStatus = 'online' | 'away' | 'busy' | 'offline';\n\n/**\n * Deterministic hue per name, so a person keeps their colour everywhere.\n *\n * From the chart palette, not the semantic one: status colours are reserved,\n * and a person filled with `--color-danger-base` reads as an error rather than\n * as a person. These eight are the same slots a chart uses, in the same fixed\n * order, so an avatar never impersonates a state.\n */\nconst HUES = Array.from({ length: 8 }, (_, i) => `var(--chart-series-${i + 1})`);\n\n/** \"Benjamin Canac\" → \"BC\", \"emma.davis@example.com\" → \"ED\". */\nexport function initialsOf(name: string): string {\n const cleaned = name.includes('@') ? (name.split('@')[0] ?? '') : name;\n const parts = cleaned.split(/[\\s._-]+/).filter(Boolean);\n\n if (parts.length === 0) return '';\n if (parts.length === 1) return (parts[0] ?? '').slice(0, 2).toUpperCase();\n return `${parts[0]![0]}${parts[parts.length - 1]![0]}`.toUpperCase();\n}\n\n/**\n * A person or an organisation, as a picture or as their initials.\n *\n * The fallback is not decoration: most rows in most products have no photo, so\n * the initials path is the one that renders. It picks a colour from the name,\n * which means the same person is the same colour on every screen and the eye\n * can use it.\n *\n * @element kt-avatar\n *\n * @csspart base - The avatar circle.\n * @csspart image - The `<img>`, when `src` is set and loads.\n *\n * @example\n * ```html\n * <kt-avatar name=\"Benjamin Canac\"></kt-avatar>\n * <kt-avatar name=\"Emma Davis\" src=\"/emma.jpg\" status=\"online\"></kt-avatar>\n * ```\n */\nexport class KtAvatar extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: inline-flex;\n --kt-avatar-size: 32px;\n }\n\n :host([size='small']) {\n --kt-avatar-size: 24px;\n }\n :host([size='large']) {\n --kt-avatar-size: 48px;\n }\n\n /* The identity hue is worn exactly the way every other tinted thing in\n Kanto wears one: the colour at 12% behind, the colour itself as the\n ink, and no border — the same pair as a secondary button, a danger\n button or a badge tone. A saturated fill with white initials is a\n different system's idea, and beside those it looks like one. */\n .avatar {\n position: relative;\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n width: var(--kt-avatar-size);\n height: var(--kt-avatar-size);\n overflow: hidden;\n color: var(--kt-avatar-hue, var(--text-muted));\n font: 600 calc(var(--kt-avatar-size) * 0.36) / 1 var(--font-family-body);\n background: color-mix(in srgb, var(--kt-avatar-hue, transparent) 12%, transparent);\n border-radius: var(--radius-full);\n user-select: none;\n }\n\n /* No hue to tint with, and a photograph that fills the circle anyway. */\n .avatar.has-image,\n .avatar.anonymous {\n background: var(--surface-raised);\n }\n\n :host([square]) .avatar {\n border-radius: var(--border-radius);\n }\n\n img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n /* The dot sits outside the clipped circle, so it needs its own box. */\n .status {\n position: absolute;\n right: 0;\n bottom: 0;\n width: calc(var(--kt-avatar-size) * 0.28);\n height: calc(var(--kt-avatar-size) * 0.28);\n border: 2px solid var(--surface-page);\n border-radius: var(--radius-full);\n }\n\n .online {\n background: var(--color-success-base);\n }\n .away {\n background: var(--color-warning-base);\n }\n .busy {\n background: var(--color-danger-base);\n }\n .offline {\n background: var(--color-text-500);\n }\n `,\n ];\n\n @state()\n private failed = false;\n\n /** The person's name. Drives the initials, the colour and the label. */\n @property({ type: String })\n name = '';\n\n /** Photo. Falls back to initials if it is missing or fails to load. */\n @property({ type: String })\n src = '';\n\n @property({ type: String, reflect: true })\n size: KtAvatarSize = 'medium';\n\n /** Rounds to the card radius instead of a circle — for organisations. */\n @property({ type: Boolean, reflect: true })\n square = false;\n\n /** Presence dot. Omit for none. */\n @property({ type: String, reflect: true })\n status?: KtAvatarStatus;\n\n /** Overrides the colour picked from the name. */\n @property({ type: String })\n color = '';\n\n override willUpdate(changed: Map<string, unknown>): void {\n // A new source deserves a fresh attempt; without this a single failure\n // would stick for the element's lifetime.\n if (changed.has('src')) this.failed = false;\n }\n\n private get hue(): string {\n if (this.color) return this.color;\n\n let sum = 0;\n for (const char of this.name) sum += char.charCodeAt(0);\n return HUES[sum % HUES.length]!;\n }\n\n override render(): TemplateResult {\n const initials = initialsOf(this.name);\n const showImage = Boolean(this.src) && !this.failed;\n\n return html`<span\n part=\"base\"\n class=${classMap({ avatar: true, 'has-image': showImage, anonymous: !this.name })}\n style=${showImage ? '' : `--kt-avatar-hue:${this.hue}`}\n role=\"img\"\n aria-label=${this.name || 'Avatar'}\n >\n ${\n showImage\n ? html`<img\n part=\"image\"\n src=${this.src}\n alt=\"\"\n @error=${() => {\n this.failed = true;\n }}\n />`\n : initials || html`<kt-icon name=\"user\" size=\"16\"></kt-icon>`\n }\n ${\n this.status\n ? html`<span class=${classMap({ status: true, [this.status]: true })}></span>`\n : nothing\n }\n </span>`;\n }\n}\n\ndefineElement('kt-avatar', KtAvatar);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-avatar': KtAvatar;\n }\n}\n"],"names":["HUES","_","i","initialsOf","name","parts","KtAvatar","KtElement","css","changed","sum","char","initials","showImage","html","classMap","nothing","__decorateClass","state","property","defineElement"],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import { type TemplateResult } from 'lit';
2
+ import { KtElement } from '#internal/kt-element';
3
+ import '../kt-icon/kt-icon.js';
4
+ export type KtBadgeVariant = 'tag' | 'code' | 'category' | 'count';
5
+ export type KtBadgeTone = 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
6
+ export type KtBadgeSize = 'small' | 'medium';
7
+ /**
8
+ * A compact label: a pill `tag`, a monospaced `code` token, a `category`
9
+ * tinted with a colour of your choosing, or a `count`.
10
+ *
11
+ * Two independent axes, because they answer different questions. `variant` is
12
+ * the **shape** — what kind of thing this is. `tone` is the **colour** — what
13
+ * it means. A tag can be neutral or dangerous; so can a count. Folding them
14
+ * into one list would give you nine variants and no way to say "a tag, but
15
+ * this one is a warning".
16
+ *
17
+ * `count` is the exception that carries no border, because a number pinned to
18
+ * a nav item is not a label with an outline — it is a mark on the thing it
19
+ * counts.
20
+ *
21
+ * @element kt-badge
22
+ *
23
+ * @slot - The text. Falls back to the `label` attribute.
24
+ *
25
+ * @csspart base - The container.
26
+ * @csspart remove - The remove button, when `removable`.
27
+ *
28
+ * @cssproperty --kt-badge-color - Category hue. The fill is this colour at 20%.
29
+ *
30
+ * @fires kt-badge-click - A `clickable` badge was activated. Cancelable.
31
+ * @fires kt-remove - The remove button was pressed. Cancelable: cancel it and
32
+ * remove the badge yourself once the server agrees.
33
+ *
34
+ * @example
35
+ * ```html
36
+ * <kt-badge>Design systems</kt-badge>
37
+ * <kt-badge tone="success">Active</kt-badge>
38
+ * <kt-badge variant="code">--surface-card</kt-badge>
39
+ * <kt-badge variant="category" color="#3987e5">Infrastructure</kt-badge>
40
+ * <kt-badge variant="count" tone="danger" max="99">128</kt-badge>
41
+ * <kt-badge icon="user" removable>Assigned to me</kt-badge>
42
+ * ```
43
+ */
44
+ export declare class KtBadge extends KtElement {
45
+ static styles: import("lit").CSSResultGroup[];
46
+ /** The shape: what kind of thing this is. */
47
+ variant: KtBadgeVariant;
48
+ /** The colour: what it means. Independent of `variant`. */
49
+ tone: KtBadgeTone;
50
+ size: KtBadgeSize;
51
+ /** Badge text. The default slot wins when both are present. */
52
+ label: string;
53
+ /** Category hue: any CSS colour. The fill is this colour at 20%. */
54
+ color: string;
55
+ /** Lucide icon name, before the text. */
56
+ icon: string;
57
+ clickable: boolean;
58
+ /** Adds a remove button. Fires a cancelable `kt-remove`. */
59
+ removable: boolean;
60
+ /**
61
+ * Caps a numeric label: `max="99"` shows `99+`.
62
+ * Ignored when the content is not a number.
63
+ */
64
+ max?: number;
65
+ /** Shorthand for `tone="danger"`, kept from the field components. */
66
+ error: boolean;
67
+ private get display();
68
+ private activate;
69
+ private onKeyDown;
70
+ private onRemove;
71
+ render(): TemplateResult;
72
+ }
73
+ declare global {
74
+ interface HTMLElementTagNameMap {
75
+ 'kt-badge': KtBadge;
76
+ }
77
+ }