kanto-ds 1.2.0 → 1.4.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 (116) hide show
  1. package/README.md +24 -6
  2. package/dist/chunks/{defaults-DKzFsNbv.js → defaults-BwgjMcww.js} +27 -26
  3. package/dist/chunks/{defaults-DKzFsNbv.js.map → defaults-BwgjMcww.js.map} +1 -1
  4. package/dist/chunks/index-DSSLJirw.js +79 -0
  5. package/dist/chunks/index-DSSLJirw.js.map +1 -0
  6. package/dist/chunks/kt-element-E-tfJpGQ.js +52 -0
  7. package/dist/chunks/kt-element-E-tfJpGQ.js.map +1 -0
  8. package/dist/components/core/kt-avatar/kt-avatar.js +8 -7
  9. package/dist/components/core/kt-avatar/kt-avatar.js.map +1 -1
  10. package/dist/components/core/kt-badge/kt-badge.js +7 -6
  11. package/dist/components/core/kt-badge/kt-badge.js.map +1 -1
  12. package/dist/components/core/kt-button/kt-button.js +1 -1
  13. package/dist/components/core/kt-card/kt-card.js +1 -1
  14. package/dist/components/core/kt-code/kt-code.js +31 -30
  15. package/dist/components/core/kt-code/kt-code.js.map +1 -1
  16. package/dist/components/core/kt-icon/kt-icon.js +2 -2
  17. package/dist/components/core/kt-kbd/kt-kbd.js +1 -1
  18. package/dist/components/core/kt-split-button/kt-split-button.d.ts +2 -2
  19. package/dist/components/core/kt-split-button/kt-split-button.js +27 -26
  20. package/dist/components/core/kt-split-button/kt-split-button.js.map +1 -1
  21. package/dist/components/data/kt-chart/kt-chart.d.ts +2 -2
  22. package/dist/components/data/kt-chart/kt-chart.js +222 -221
  23. package/dist/components/data/kt-chart/kt-chart.js.map +1 -1
  24. package/dist/components/data/kt-meter/kt-meter.js +1 -1
  25. package/dist/components/data/kt-pagination/kt-pagination.d.ts +1 -1
  26. package/dist/components/data/kt-pagination/kt-pagination.js +29 -28
  27. package/dist/components/data/kt-pagination/kt-pagination.js.map +1 -1
  28. package/dist/components/data/kt-stat/kt-stat.js +1 -1
  29. package/dist/components/data/kt-table/kt-table.d.ts +2 -2
  30. package/dist/components/data/kt-table/kt-table.js +30 -29
  31. package/dist/components/data/kt-table/kt-table.js.map +1 -1
  32. package/dist/components/data/kt-timeline/kt-timeline.js +1 -1
  33. package/dist/components/feedback/kt-alert/kt-alert.js +17 -16
  34. package/dist/components/feedback/kt-alert/kt-alert.js.map +1 -1
  35. package/dist/components/feedback/kt-empty-state/kt-empty-state.js +1 -1
  36. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +1 -1
  37. package/dist/components/feedback/kt-skeleton/kt-skeleton.js +1 -1
  38. package/dist/components/feedback/kt-toast/kt-toast.js +25 -19
  39. package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -1
  40. package/dist/components/feedback/kt-toast-container/kt-toast-container.js +1 -1
  41. package/dist/components/feedback/kt-tooltip/kt-tooltip.js +1 -1
  42. package/dist/components/forms/kt-checkbox/kt-checkbox.d.ts +66 -0
  43. package/dist/components/forms/kt-checkbox/kt-checkbox.js +198 -0
  44. package/dist/components/forms/kt-checkbox/kt-checkbox.js.map +1 -0
  45. package/dist/components/forms/kt-drag-drop/kt-drag-drop.d.ts +2 -2
  46. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +60 -57
  47. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -1
  48. package/dist/components/forms/kt-form/kt-form.js +11 -10
  49. package/dist/components/forms/kt-form/kt-form.js.map +1 -1
  50. package/dist/components/forms/kt-input/kt-input.js +56 -55
  51. package/dist/components/forms/kt-input/kt-input.js.map +1 -1
  52. package/dist/components/forms/kt-input-menu/kt-input-menu.d.ts +1 -1
  53. package/dist/components/forms/kt-input-menu/kt-input-menu.js +57 -56
  54. package/dist/components/forms/kt-input-menu/kt-input-menu.js.map +1 -1
  55. package/dist/components/forms/kt-label-input/kt-label-input.js +1 -1
  56. package/dist/components/forms/kt-radio-group/kt-radio-group.d.ts +103 -0
  57. package/dist/components/forms/kt-radio-group/kt-radio-group.js +265 -0
  58. package/dist/components/forms/kt-radio-group/kt-radio-group.js.map +1 -0
  59. package/dist/components/forms/kt-select/kt-select.d.ts +2 -2
  60. package/dist/components/forms/kt-select/kt-select.js +62 -61
  61. package/dist/components/forms/kt-select/kt-select.js.map +1 -1
  62. package/dist/components/forms/kt-textarea/kt-textarea.js +9 -8
  63. package/dist/components/forms/kt-textarea/kt-textarea.js.map +1 -1
  64. package/dist/components/forms/kt-toggle/kt-toggle.js +1 -1
  65. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.d.ts +1 -1
  66. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +6 -5
  67. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js.map +1 -1
  68. package/dist/components/navigation/kt-header/kt-header.js +11 -10
  69. package/dist/components/navigation/kt-header/kt-header.js.map +1 -1
  70. package/dist/components/navigation/kt-page-header/kt-page-header.js +1 -1
  71. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +44 -43
  72. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js.map +1 -1
  73. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.d.ts +1 -1
  74. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +6 -5
  75. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js.map +1 -1
  76. package/dist/components/navigation/kt-tabs/kt-tabs.js +1 -1
  77. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +1 -1
  78. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +12 -6
  79. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js.map +1 -1
  80. package/dist/components/overlays/kt-collapsible/kt-collapsible.js +1 -1
  81. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.d.ts +3 -3
  82. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +30 -27
  83. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js.map +1 -1
  84. package/dist/components/overlays/kt-dropdown/kt-dropdown.d.ts +1 -1
  85. package/dist/components/overlays/kt-dropdown/kt-dropdown.js +8 -7
  86. package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -1
  87. package/dist/components/overlays/kt-modal/kt-modal.js +5 -4
  88. package/dist/components/overlays/kt-modal/kt-modal.js.map +1 -1
  89. package/dist/components/overlays/kt-side-panel/kt-side-panel.d.ts +1 -1
  90. package/dist/components/overlays/kt-side-panel/kt-side-panel.js +24 -23
  91. package/dist/components/overlays/kt-side-panel/kt-side-panel.js.map +1 -1
  92. package/dist/custom-elements.json +1870 -1071
  93. package/dist/icons/defaults.d.ts +1 -0
  94. package/dist/icons/index.js +1 -1
  95. package/dist/index.d.ts +5 -0
  96. package/dist/index.js +93 -83
  97. package/dist/index.js.map +1 -1
  98. package/dist/internal/kt-element.d.ts +6 -1
  99. package/dist/internal/strings.d.ts +103 -0
  100. package/dist/react/index.d.ts +13 -0
  101. package/dist/react/index.js +176 -157
  102. package/dist/react/index.js.map +1 -1
  103. package/dist/react/jsx.d.ts +12 -1
  104. package/dist/strings/index.d.ts +11 -0
  105. package/dist/strings/index.js +8 -0
  106. package/dist/strings/index.js.map +1 -0
  107. package/dist/tokens/base.css +56 -0
  108. package/dist/vscode.css-custom-data.json +12 -0
  109. package/dist/vscode.html-custom-data.json +85 -0
  110. package/dist/vue/index.d.ts +6 -0
  111. package/dist/vue/index.js +9 -7
  112. package/dist/vue/index.js.map +1 -1
  113. package/dist/web-types.json +263 -39
  114. package/package.json +19 -3
  115. package/dist/chunks/kt-element-B_jjQDhg.js +0 -38
  116. package/dist/chunks/kt-element-B_jjQDhg.js.map +0 -1
package/README.md CHANGED
@@ -38,7 +38,7 @@ One implementation, every framework. The alternative — a React port, a Vue
38
38
  port, an Angular library — is three codebases drifting apart.
39
39
 
40
40
  The trade is real and worth naming: custom elements need JavaScript to upgrade,
41
- so they render unstyled-but-present during SSR until the bundle lands. In
41
+ so during SSR they hold their place, hidden, until the bundle lands. In
42
42
  return, a component is written once and a fix reaches every consumer at the same
43
43
  time.
44
44
 
@@ -75,19 +75,37 @@ how an operation says it is still working when the number is not moving.
75
75
  section titles. No emoji in product UI — the one exception is the flag in the
76
76
  phone-input country picker, which is functional.
77
77
 
78
- Every default string is a property, so a screen can override any of them, and
79
- an application that needs another language sets them at the call site.
78
+ Every string an element writes itself — empty states, button labels,
79
+ validation messages, and the accessible names only a screen reader hears — comes
80
+ from one registry. An application in another language replaces them once:
81
+
82
+ ```js
83
+ import { setStrings } from 'kanto-ds/strings';
84
+
85
+ setStrings({
86
+ clear: 'Effacer',
87
+ noData: 'Aucune donnée',
88
+ pageOf: (page, total) => `Page ${page} sur ${total}`,
89
+ });
90
+ ```
91
+
92
+ Anything left out stays in English, and switching at runtime re-renders every
93
+ element. Strings that carry a value are functions, so a translation owns the
94
+ word order. Where an element also takes a string as a property (`emptyText`,
95
+ `placeholder`, `confirmLabel`…), setting it still wins for that one element.
96
+ The full list is `KtStrings` in
97
+ [src/internal/strings.ts](src/internal/strings.ts).
80
98
 
81
99
  Full details in **[src/tokens/README.md](src/tokens/README.md)**.
82
100
 
83
101
  ## Components
84
102
 
85
- Forty-two elements. Each has a page beside its source.
103
+ Forty-four elements. Each has a page beside its source.
86
104
 
87
105
  | Group | Elements |
88
106
  | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
89
107
  | **Core** | [button](src/components/core/kt-button/kt-button.md) · [split-button](src/components/core/kt-split-button/kt-split-button.md) · [card](src/components/core/kt-card/kt-card.md) · [code](src/components/core/kt-code/kt-code.md) · [icon](src/components/core/kt-icon/kt-icon.md) · [avatar](src/components/core/kt-avatar/kt-avatar.md) · [badge](src/components/core/kt-badge/kt-badge.md) · [kbd](src/components/core/kt-kbd/kt-kbd.md) |
90
- | **Forms** | [input](src/components/forms/kt-input/kt-input.md) · [textarea](src/components/forms/kt-textarea/kt-textarea.md) · [label-input](src/components/forms/kt-label-input/kt-label-input.md) · [form](src/components/forms/kt-form/kt-form.md) · [select](src/components/forms/kt-select/kt-select.md) · [input-menu](src/components/forms/kt-input-menu/kt-input-menu.md) · [toggle](src/components/forms/kt-toggle/kt-toggle.md) · [drag-drop](src/components/forms/kt-drag-drop/kt-drag-drop.md) |
108
+ | **Forms** | [input](src/components/forms/kt-input/kt-input.md) · [textarea](src/components/forms/kt-textarea/kt-textarea.md) · [label-input](src/components/forms/kt-label-input/kt-label-input.md) · [form](src/components/forms/kt-form/kt-form.md) · [select](src/components/forms/kt-select/kt-select.md) · [checkbox](src/components/forms/kt-checkbox/kt-checkbox.md) · [radio-group](src/components/forms/kt-radio-group/kt-radio-group.md) · [input-menu](src/components/forms/kt-input-menu/kt-input-menu.md) · [toggle](src/components/forms/kt-toggle/kt-toggle.md) · [drag-drop](src/components/forms/kt-drag-drop/kt-drag-drop.md) |
91
109
  | **Navigation** | [header](src/components/navigation/kt-header/kt-header.md) · [breadcrumb](src/components/navigation/kt-breadcrumb/kt-breadcrumb.md) · [sub-menu-navigation](src/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.md) · [page-header](src/components/navigation/kt-page-header/kt-page-header.md) · [tabs](src/components/navigation/kt-tabs/kt-tabs.md) · [segmented-control](src/components/navigation/kt-segmented-control/kt-segmented-control.md) · [toggle-button](src/components/navigation/kt-toggle-button/kt-toggle-button.md) · [toggle-button-group](src/components/navigation/kt-toggle-button-group/kt-toggle-button-group.md) |
92
110
  | **Feedback** | [progress-bar](src/components/feedback/kt-progress-bar/kt-progress-bar.md) · [skeleton](src/components/feedback/kt-skeleton/kt-skeleton.md) · [tooltip](src/components/feedback/kt-tooltip/kt-tooltip.md) · [toast](src/components/feedback/kt-toast/kt-toast.md) · [toast-container + toaster](src/components/feedback/kt-toast-container/kt-toast-container.md) · [alert](src/components/feedback/kt-alert/kt-alert.md) · [empty-state](src/components/feedback/kt-empty-state/kt-empty-state.md) |
93
111
  | **Overlays** | [dropdown](src/components/overlays/kt-dropdown/kt-dropdown.md) · [side-panel](src/components/overlays/kt-side-panel/kt-side-panel.md) · [confirm-dialog](src/components/overlays/kt-confirm-dialog/kt-confirm-dialog.md) · [modal](src/components/overlays/kt-modal/kt-modal.md) · [collapsible](src/components/overlays/kt-collapsible/kt-collapsible.md) |
@@ -103,7 +121,7 @@ import 'kanto-ds/components/core/kt-button'; // just this one
103
121
  ## Icons
104
122
 
105
123
  `<kt-icon>` resolves [Lucide](https://lucide.dev) icons by name at render time,
106
- which means the set cannot be tree-shaken. So Kanto ships only the 22 its own
124
+ which means the set cannot be tree-shaken. So Kanto ships only the 23 its own
107
125
  elements draw. Register what your application uses:
108
126
 
109
127
  ```js
@@ -1,14 +1,14 @@
1
- import { X as s, User as a, TriangleAlert as c, Trash2 as i, Search as f, Menu as g, LoaderCircle as p, Info as u, FileUp as y, File as A, EyeOff as C, Eye as l, Copy as I, CircleCheck as h, CircleAlert as w, ChevronUp as $, ChevronRight as b, ChevronLeft as d, ChevronDown as v, Check as U, ArrowUp as Z, ArrowDown as k } from "lucide";
1
+ import { X as s, User as a, TriangleAlert as c, Trash2 as i, Search as f, Minus as g, Menu as p, LoaderCircle as u, Info as y, FileUp as A, File as C, EyeOff as l, Eye as I, Copy as h, CircleCheck as w, CircleAlert as $, ChevronUp as b, ChevronRight as d, ChevronLeft as v, ChevronDown as U, Check as Z, ArrowUp as k, ArrowDown as m } from "lucide";
2
2
  const n = /* @__PURE__ */ new Map();
3
3
  function t(e) {
4
4
  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();
5
5
  }
6
- function m(e, r) {
6
+ function z(e, r) {
7
7
  n.set(t(e), r);
8
8
  }
9
- function z(e) {
9
+ function L(e) {
10
10
  for (const [r, o] of Object.entries(e))
11
- L(o) && m(r, o);
11
+ M(o) && z(r, o);
12
12
  }
13
13
  function E(e) {
14
14
  return n.get(t(e));
@@ -16,42 +16,43 @@ function E(e) {
16
16
  function F() {
17
17
  return [...n.keys()].sort();
18
18
  }
19
- function L(e) {
19
+ function M(e) {
20
20
  return Array.isArray(e) && e.every(
21
21
  (r) => Array.isArray(r) && typeof r[0] == "string" && typeof r[1] == "object" && r[1] !== null
22
22
  );
23
23
  }
24
24
  const j = {
25
- ArrowDown: k,
26
- ArrowUp: Z,
27
- Check: U,
28
- ChevronDown: v,
29
- ChevronLeft: d,
30
- ChevronRight: b,
31
- ChevronUp: $,
32
- CircleAlert: w,
33
- CircleCheck: h,
34
- Copy: I,
35
- Eye: l,
36
- EyeOff: C,
37
- File: A,
38
- FileUp: y,
39
- Info: u,
40
- LoaderCircle: p,
41
- Menu: g,
25
+ ArrowDown: m,
26
+ ArrowUp: k,
27
+ Check: Z,
28
+ ChevronDown: U,
29
+ ChevronLeft: v,
30
+ ChevronRight: d,
31
+ ChevronUp: b,
32
+ CircleAlert: $,
33
+ CircleCheck: w,
34
+ Copy: h,
35
+ Eye: I,
36
+ EyeOff: l,
37
+ File: C,
38
+ FileUp: A,
39
+ Info: y,
40
+ LoaderCircle: u,
41
+ Menu: p,
42
+ Minus: g,
42
43
  Search: f,
43
44
  Trash2: i,
44
45
  TriangleAlert: c,
45
46
  User: a,
46
47
  X: s
47
48
  };
48
- z(j);
49
+ L(j);
49
50
  export {
50
- z as a,
51
+ L as a,
51
52
  F as b,
52
53
  j as d,
53
54
  E as g,
54
- m as r,
55
+ z as r,
55
56
  t
56
57
  };
57
- //# sourceMappingURL=defaults-DKzFsNbv.js.map
58
+ //# sourceMappingURL=defaults-BwgjMcww.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults-DKzFsNbv.js","sources":["../../src/icons/registry.ts","../../src/icons/defaults.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","/**\n * The icons the design system uses in its own elements.\n *\n * Importing any Kanto element pulls this set in — roughly 2 kB of path data,\n * the price of `<kt-select>` being able to draw its own chevron. Application\n * icons are registered separately through `registerIcons`.\n */\nimport {\n ArrowDown,\n ArrowUp,\n Check,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n CircleAlert,\n CircleCheck,\n Copy,\n Eye,\n EyeOff,\n File,\n FileUp,\n Info,\n LoaderCircle,\n Menu,\n Search,\n Trash2,\n TriangleAlert,\n User,\n X,\n} from 'lucide';\n// The sibling registry, not the `kanto-ds` barrel: the barrel pulls in every\n// element, and one of them pulls in this file — a cycle that leaves\n// `registerIcons` undefined by the time the call below runs.\nimport { registerIcons } from './registry.js';\n\n/** Icons referenced by Kanto elements, keyed by their Lucide name. */\nexport const defaultIcons = {\n ArrowDown,\n ArrowUp,\n Check,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n CircleAlert,\n CircleCheck,\n Copy,\n Eye,\n EyeOff,\n File,\n FileUp,\n Info,\n LoaderCircle,\n Menu,\n Search,\n Trash2,\n TriangleAlert,\n User,\n X,\n};\n\nregisterIcons(defaultIcons);\n"],"names":["registry","toKebabCase","name","registerIcon","node","registerIcons","icons","isIconNode","getIcon","registeredIcons","value","child","defaultIcons","ArrowDown","ArrowUp","Check","ChevronDown","ChevronLeft","ChevronRight","ChevronUp","CircleAlert","CircleCheck","Copy","Eye","EyeOff","File","FileUp","Info","LoaderCircle","Menu","Search","Trash2","TriangleAlert","User","X"],"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;ACtCO,MAAMC,IAAe;AAAA,EAC1B,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,cAAAC;AAAA,EACA,WAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,MAAAC;AAAA,EACA,KAAAC;AAAA,EACA,QAAAC;AAAA,EACA,MAAAC;AAAA,EACA,QAAAC;AAAA,EACA,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,MAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,eAAAC;AAAA,EACA,MAAAC;AAAA,EACA,GAAAC;AACF;AAEA7B,EAAcO,CAAY;"}
1
+ {"version":3,"file":"defaults-BwgjMcww.js","sources":["../../src/icons/registry.ts","../../src/icons/defaults.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","/**\n * The icons the design system uses in its own elements.\n *\n * Importing any Kanto element pulls this set in — roughly 2 kB of path data,\n * the price of `<kt-select>` being able to draw its own chevron. Application\n * icons are registered separately through `registerIcons`.\n */\nimport {\n ArrowDown,\n ArrowUp,\n Check,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n CircleAlert,\n CircleCheck,\n Copy,\n Eye,\n EyeOff,\n File,\n FileUp,\n Info,\n LoaderCircle,\n Menu,\n Minus,\n Search,\n Trash2,\n TriangleAlert,\n User,\n X,\n} from 'lucide';\n// The sibling registry, not the `kanto-ds` barrel: the barrel pulls in every\n// element, and one of them pulls in this file — a cycle that leaves\n// `registerIcons` undefined by the time the call below runs.\nimport { registerIcons } from './registry.js';\n\n/** Icons referenced by Kanto elements, keyed by their Lucide name. */\nexport const defaultIcons = {\n ArrowDown,\n ArrowUp,\n Check,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n CircleAlert,\n CircleCheck,\n Copy,\n Eye,\n EyeOff,\n File,\n FileUp,\n Info,\n LoaderCircle,\n Menu,\n Minus,\n Search,\n Trash2,\n TriangleAlert,\n User,\n X,\n};\n\nregisterIcons(defaultIcons);\n"],"names":["registry","toKebabCase","name","registerIcon","node","registerIcons","icons","isIconNode","getIcon","registeredIcons","value","child","defaultIcons","ArrowDown","ArrowUp","Check","ChevronDown","ChevronLeft","ChevronRight","ChevronUp","CircleAlert","CircleCheck","Copy","Eye","EyeOff","File","FileUp","Info","LoaderCircle","Menu","Minus","Search","Trash2","TriangleAlert","User","X"],"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;ACrCO,MAAMC,IAAe;AAAA,EAC1B,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,cAAAC;AAAA,EACA,WAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,MAAAC;AAAA,EACA,KAAAC;AAAA,EACA,QAAAC;AAAA,EACA,MAAAC;AAAA,EACA,QAAAC;AAAA,EACA,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,eAAAC;AAAA,EACA,MAAAC;AAAA,EACA,GAAAC;AACF;AAEA9B,EAAcO,CAAY;"}
@@ -0,0 +1,79 @@
1
+ const i = Object.freeze({
2
+ clear: "Clear",
3
+ close: "Close",
4
+ dismiss: "Dismiss",
5
+ copy: "Copy",
6
+ copied: "Copied",
7
+ copyCode: "Copy code",
8
+ timeRemaining: "Time remaining",
9
+ remove: (e) => e ? `Remove ${e}` : "Remove",
10
+ noOptions: "No options available",
11
+ noResults: "No results",
12
+ noActions: "No actions",
13
+ noData: "No data to display",
14
+ loading: "Loading…",
15
+ select: "Select",
16
+ openList: "Open list",
17
+ closeList: "Close list",
18
+ showPassword: "Show password",
19
+ hidePassword: "Hide password",
20
+ searchCountry: "Search country or dial code",
21
+ noCountry: "No country found",
22
+ countryCode: (e) => `Country code: ${e ?? "none"}`,
23
+ dragAndDrop: "Drag and drop or",
24
+ browseFiles: "browse your files",
25
+ recommendedSize: (e) => `Recommended image size: ${e}`,
26
+ selectedFiles: "Selected files",
27
+ required: "This field is required.",
28
+ selectOption: "Select an option.",
29
+ selectFile: "Select a file.",
30
+ checkRequired: "Check this box to continue.",
31
+ openMenu: "Open menu",
32
+ closeMenu: "Close menu",
33
+ breadcrumb: "Breadcrumb",
34
+ secondaryNavigation: "Secondary navigation",
35
+ pagination: "Pagination",
36
+ previous: "Previous",
37
+ next: "Next",
38
+ pageOf: (e, o) => `Page ${e} / ${o}`,
39
+ moreActions: "More actions",
40
+ options: "Options",
41
+ formSection: "Form section",
42
+ selectRow: "Select row",
43
+ selectAll: "Select all",
44
+ total: "Total",
45
+ chartSeries: "Series",
46
+ chartPoint: "Point",
47
+ chartSlice: "Slice",
48
+ chartShare: "Share",
49
+ chartData: "Chart data",
50
+ chartValue: "Value",
51
+ confirmHeading: "Are you sure?",
52
+ confirm: "Confirm",
53
+ cancel: "Cancel",
54
+ details: "Details",
55
+ avatar: "Avatar"
56
+ });
57
+ let t = { ...i };
58
+ const n = /* @__PURE__ */ new Set();
59
+ function r() {
60
+ return t;
61
+ }
62
+ function s(e) {
63
+ t = { ...t, ...e };
64
+ for (const o of n) o();
65
+ }
66
+ function a() {
67
+ s(i);
68
+ }
69
+ function c(e) {
70
+ return n.add(e), () => n.delete(e);
71
+ }
72
+ export {
73
+ s as a,
74
+ i as d,
75
+ c as o,
76
+ a as r,
77
+ r as s
78
+ };
79
+ //# sourceMappingURL=index-DSSLJirw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DSSLJirw.js","sources":["../../src/internal/strings.ts"],"sourcesContent":["/**\n * Every piece of copy the elements write themselves — empty states, button\n * labels, validation messages, and the accessible names a screen reader\n * announces but nobody sees.\n *\n * English by default. An application in another language replaces them once,\n * at start-up, and every element follows:\n *\n * import { setStrings } from 'kanto-ds/strings';\n *\n * setStrings({\n * clear: 'Effacer',\n * pageOf: (page, total) => `Page ${page} sur ${total}`,\n * });\n *\n * Anything left out keeps its English default. A string an element also takes\n * as a property — `emptyText`, `placeholder`, `confirmLabel` — still wins when\n * it is set, so one screen can say something different from the rest.\n *\n * Copy that carries a value is a function, not a template with placeholders:\n * the translation owns the word order, and \"Remove {name}\" does not survive\n * languages that put the object first.\n */\n\nexport interface KtStrings {\n // --- Shared actions ---\n /** Clear button in fields. */\n clear: string;\n /** Close button on toasts, alerts' dismiss button. */\n close: string;\n dismiss: string;\n /** Copy button on `kt-code`, and its state once copied. */\n copy: string;\n copied: string;\n copyCode: string;\n /** The countdown bar on a toast that closes itself. */\n timeRemaining: string;\n /** Remove button on a badge or a dropped file. */\n remove: (name: string) => string;\n\n // --- Empty and loading states ---\n noOptions: string;\n noResults: string;\n noActions: string;\n noData: string;\n loading: string;\n\n // --- Fields ---\n /** `kt-select` with nothing chosen. */\n select: string;\n openList: string;\n closeList: string;\n showPassword: string;\n hidePassword: string;\n searchCountry: string;\n noCountry: string;\n countryCode: (country: string | undefined) => string;\n dragAndDrop: string;\n browseFiles: string;\n recommendedSize: (size: string) => string;\n selectedFiles: string;\n\n // --- Validation messages, shown by the browser on submit ---\n required: string;\n selectOption: string;\n selectFile: string;\n /** A required checkbox left unchecked. */\n checkRequired: string;\n\n // --- Navigation ---\n openMenu: string;\n closeMenu: string;\n breadcrumb: string;\n secondaryNavigation: string;\n pagination: string;\n previous: string;\n next: string;\n pageOf: (page: number, total: number) => string;\n moreActions: string;\n\n // --- Groups and sections ---\n /** A button or choice group with no label of its own. */\n options: string;\n /** A `kt-form` section with no heading. */\n formSection: string;\n\n // --- Data ---\n selectRow: string;\n selectAll: string;\n total: string;\n /** Column headers of the data table every chart renders for assistive tech. */\n chartSeries: string;\n chartPoint: string;\n chartSlice: string;\n chartShare: string;\n /** Caption of a chart's data table when the chart has no label. */\n chartData: string;\n /** Value column of a single-series chart's data table when the series has no name. */\n chartValue: string;\n\n // --- Overlays ---\n confirmHeading: string;\n confirm: string;\n cancel: string;\n details: string;\n\n // --- Identity ---\n avatar: string;\n}\n\nexport const defaultStrings: Readonly<KtStrings> = Object.freeze({\n clear: 'Clear',\n close: 'Close',\n dismiss: 'Dismiss',\n copy: 'Copy',\n copied: 'Copied',\n copyCode: 'Copy code',\n timeRemaining: 'Time remaining',\n remove: (name: string) => (name ? `Remove ${name}` : 'Remove'),\n\n noOptions: 'No options available',\n noResults: 'No results',\n noActions: 'No actions',\n noData: 'No data to display',\n loading: 'Loading…',\n\n select: 'Select',\n openList: 'Open list',\n closeList: 'Close list',\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n searchCountry: 'Search country or dial code',\n noCountry: 'No country found',\n countryCode: (country: string | undefined) => `Country code: ${country ?? 'none'}`,\n dragAndDrop: 'Drag and drop or',\n browseFiles: 'browse your files',\n recommendedSize: (size: string) => `Recommended image size: ${size}`,\n selectedFiles: 'Selected files',\n\n required: 'This field is required.',\n selectOption: 'Select an option.',\n selectFile: 'Select a file.',\n checkRequired: 'Check this box to continue.',\n\n openMenu: 'Open menu',\n closeMenu: 'Close menu',\n breadcrumb: 'Breadcrumb',\n secondaryNavigation: 'Secondary navigation',\n pagination: 'Pagination',\n previous: 'Previous',\n next: 'Next',\n pageOf: (page: number, total: number) => `Page ${page} / ${total}`,\n moreActions: 'More actions',\n\n options: 'Options',\n formSection: 'Form section',\n\n selectRow: 'Select row',\n selectAll: 'Select all',\n total: 'Total',\n chartSeries: 'Series',\n chartPoint: 'Point',\n chartSlice: 'Slice',\n chartShare: 'Share',\n chartData: 'Chart data',\n chartValue: 'Value',\n\n confirmHeading: 'Are you sure?',\n confirm: 'Confirm',\n cancel: 'Cancel',\n details: 'Details',\n\n avatar: 'Avatar',\n});\n\nlet current: KtStrings = { ...defaultStrings };\nconst listeners = new Set<() => void>();\n\n/** The strings in effect. Elements read them at render time. */\nexport function strings(): Readonly<KtStrings> {\n return current;\n}\n\n/**\n * Replaces some or all of the strings, and re-renders every connected element\n * so the change shows at once — switching language at runtime works.\n */\nexport function setStrings(overrides: Partial<KtStrings>): void {\n current = { ...current, ...overrides };\n for (const listener of listeners) listener();\n}\n\n/** Back to the English defaults. */\nexport function resetStrings(): void {\n setStrings(defaultStrings);\n}\n\n/** Calls `listener` after every `setStrings`. Returns the unsubscribe function. */\nexport function onStringsChange(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n"],"names":["defaultStrings","name","country","size","page","total","current","listeners","strings","setStrings","overrides","listener","resetStrings","onStringsChange"],"mappings":"AA8GO,MAAMA,IAAsC,OAAO,OAAO;AAAA,EAC/D,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,eAAe;AAAA,EACf,QAAQ,CAACC,MAAkBA,IAAO,UAAUA,CAAI,KAAK;AAAA,EAErD,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,SAAS;AAAA,EAET,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA,EACf,WAAW;AAAA,EACX,aAAa,CAACC,MAAgC,iBAAiBA,KAAW,MAAM;AAAA,EAChF,aAAa;AAAA,EACb,aAAa;AAAA,EACb,iBAAiB,CAACC,MAAiB,2BAA2BA,CAAI;AAAA,EAClE,eAAe;AAAA,EAEf,UAAU;AAAA,EACV,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,eAAe;AAAA,EAEf,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,qBAAqB;AAAA,EACrB,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ,CAACC,GAAcC,MAAkB,QAAQD,CAAI,MAAMC,CAAK;AAAA,EAChE,aAAa;AAAA,EAEb,SAAS;AAAA,EACT,aAAa;AAAA,EAEb,WAAW;AAAA,EACX,WAAW;AAAA,EACX,OAAO;AAAA,EACP,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY;AAAA,EAEZ,gBAAgB;AAAA,EAChB,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EAET,QAAQ;AACV,CAAC;AAED,IAAIC,IAAqB,EAAE,GAAGN,EAAA;AAC9B,MAAMO,wBAAgB,IAAA;AAGf,SAASC,IAA+B;AAC7C,SAAOF;AACT;AAMO,SAASG,EAAWC,GAAqC;AAC9D,EAAAJ,IAAU,EAAE,GAAGA,GAAS,GAAGI,EAAA;AAC3B,aAAWC,KAAYJ,EAAW,CAAAI,EAAA;AACpC;AAGO,SAASC,IAAqB;AACnC,EAAAH,EAAWT,CAAc;AAC3B;AAGO,SAASa,EAAgBF,GAAkC;AAChE,SAAAJ,EAAU,IAAII,CAAQ,GACf,MAAMJ,EAAU,OAAOI,CAAQ;AACxC;"}
@@ -0,0 +1,52 @@
1
+ import { LitElement as n, css as i } from "lit";
2
+ import { o } from "./index-DSSLJirw.js";
3
+ const t = "kt-strings";
4
+ class c extends n {
5
+ static {
6
+ this.styles = i`
7
+ :host {
8
+ box-sizing: border-box;
9
+ }
10
+
11
+ :host([hidden]) {
12
+ display: none !important;
13
+ }
14
+
15
+ *,
16
+ *::before,
17
+ *::after {
18
+ box-sizing: inherit;
19
+ }
20
+
21
+ /* Read by assistive technology, never drawn. */
22
+ .visually-hidden {
23
+ position: absolute;
24
+ width: 1px;
25
+ height: 1px;
26
+ overflow: hidden;
27
+ clip-path: inset(50%);
28
+ white-space: nowrap;
29
+ }
30
+ `;
31
+ }
32
+ connectedCallback() {
33
+ super.connectedCallback(), this.unsubscribeStrings = o(
34
+ () => this.requestUpdate(t, /* @__PURE__ */ Symbol("previous strings"))
35
+ );
36
+ }
37
+ disconnectedCallback() {
38
+ super.disconnectedCallback(), this.unsubscribeStrings?.(), this.unsubscribeStrings = void 0;
39
+ }
40
+ /** True when this update was triggered by `setStrings`. */
41
+ stringsChanged(s) {
42
+ return s.has(t);
43
+ }
44
+ }
45
+ function d(e, s) {
46
+ customElements.get(e) || customElements.define(e, s);
47
+ }
48
+ export {
49
+ c as K,
50
+ d
51
+ };
52
+ //# sourceMappingURL=kt-element-E-tfJpGQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kt-element-E-tfJpGQ.js","sources":["../../src/internal/kt-element.ts"],"sourcesContent":["import { LitElement, css, type CSSResultGroup, type PropertyValues } from 'lit';\nimport { onStringsChange } from './strings.js';\n\n/**\n * The key a `setStrings` call marks in `changedProperties`, so an element can\n * recompute copy it caches outside `render()` — a validation message.\n */\nconst STRINGS_CHANGED = 'kt-strings';\n\n/**\n * Base class for every Kanto element.\n *\n * It exists for two reasons. First, `box-sizing: border-box` does not cross a\n * shadow boundary, so each root has to re-establish it. Second, `[hidden]`\n * loses to a `:host { display: flex }` rule inside the shadow root, and every\n * element in this system sets its own display — without the override here,\n * hiding a Kanto element from the outside silently does nothing.\n */\nexport class KtElement extends LitElement {\n static override styles: CSSResultGroup = css`\n :host {\n box-sizing: border-box;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n *,\n *::before,\n *::after {\n box-sizing: inherit;\n }\n\n /* Read by assistive technology, never drawn. */\n .visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n `;\n\n private unsubscribeStrings: (() => void) | undefined;\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Copy comes from the strings registry at render time; follow it when an\n // application switches language.\n // A fresh old value, because Lit skips a named update whose value did not\n // change — and 'kt-strings' is not a property, so it is always undefined.\n this.unsubscribeStrings = onStringsChange(() =>\n this.requestUpdate(STRINGS_CHANGED, Symbol('previous strings')),\n );\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.unsubscribeStrings?.();\n this.unsubscribeStrings = undefined;\n }\n\n /** True when this update was triggered by `setStrings`. */\n protected stringsChanged(changed: PropertyValues): boolean {\n return changed.has(STRINGS_CHANGED);\n }\n}\n\n/**\n * Registers a custom element, tolerating a repeat call.\n *\n * A design system gets loaded twice more often than you would like — two\n * versions in one dependency tree, a dev-server hot reload, a micro-frontend\n * mounting a second copy. `customElements.define` throws on a duplicate tag\n * and would take the whole page down with it.\n */\nexport function defineElement(tag: string, ctor: CustomElementConstructor): void {\n if (customElements.get(tag)) return;\n customElements.define(tag, ctor);\n}\n"],"names":["STRINGS_CHANGED","KtElement","LitElement","css","onStringsChange","changed","defineElement","tag","ctor"],"mappings":";;AAOA,MAAMA,IAAkB;AAWjB,MAAMC,UAAkBC,EAAW;AAAA,EACxC,OAAA;AAAA,SAAgB,SAAyBC;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,EAAA;AAAA,EA4BhC,oBAA0B;AACjC,UAAM,kBAAA,GAKN,KAAK,qBAAqBC;AAAA,MAAgB,MACxC,KAAK,cAAcJ,GAAiB,uBAAO,kBAAkB,CAAC;AAAA,IAAA;AAAA,EAElE;AAAA,EAES,uBAA6B;AACpC,UAAM,qBAAA,GACN,KAAK,qBAAA,GACL,KAAK,qBAAqB;AAAA,EAC5B;AAAA;AAAA,EAGU,eAAeK,GAAkC;AACzD,WAAOA,EAAQ,IAAIL,CAAe;AAAA,EACpC;AACF;AAUO,SAASM,EAAcC,GAAaC,GAAsC;AAC/E,EAAI,eAAe,IAAID,CAAG,KAC1B,eAAe,OAAOA,GAAKC,CAAI;AACjC;"}
@@ -1,15 +1,16 @@
1
1
  import { css as p, nothing as f, html as n } from "lit";
2
2
  import { state as v, property as o } from "lit/decorators.js";
3
3
  import { classMap as c } from "lit/directives/class-map.js";
4
- import { K as d, d as g } from "../../../chunks/kt-element-B_jjQDhg.js";
4
+ import { K as d, d as g } from "../../../chunks/kt-element-E-tfJpGQ.js";
5
+ import { s as m } from "../../../chunks/index-DSSLJirw.js";
5
6
  import "../kt-icon/kt-icon.js";
6
- var m = Object.defineProperty, s = (a, e, t, b) => {
7
+ var y = Object.defineProperty, s = (a, e, t, k) => {
7
8
  for (var i = void 0, l = a.length - 1, h; l >= 0; l--)
8
9
  (h = a[l]) && (i = h(e, t, i) || i);
9
- return i && m(e, t, i), i;
10
+ return i && y(e, t, i), i;
10
11
  };
11
12
  const u = Array.from({ length: 8 }, (a, e) => `var(--chart-series-${e + 1})`);
12
- function y(a) {
13
+ function b(a) {
13
14
  const t = (a.includes("@") ? a.split("@")[0] ?? "" : a).split(/[\s._-]+/).filter(Boolean);
14
15
  return t.length === 0 ? "" : t.length === 1 ? (t[0] ?? "").slice(0, 2).toUpperCase() : `${t[0][0]}${t[t.length - 1][0]}`.toUpperCase();
15
16
  }
@@ -110,13 +111,13 @@ class r extends d {
110
111
  return u[e % u.length];
111
112
  }
112
113
  render() {
113
- const e = y(this.name), t = !!this.src && !this.failed;
114
+ const e = b(this.name), t = !!this.src && !this.failed;
114
115
  return n`<span
115
116
  part="base"
116
117
  class=${c({ avatar: !0, "has-image": t, anonymous: !this.name })}
117
118
  style=${t ? "" : `--kt-avatar-hue:${this.hue}`}
118
119
  role="img"
119
- aria-label=${this.name || "Avatar"}
120
+ aria-label=${this.name || m().avatar}
120
121
  >
121
122
  ${t ? n`<img
122
123
  part="image"
@@ -154,6 +155,6 @@ s([
154
155
  g("kt-avatar", r);
155
156
  export {
156
157
  r as KtAvatar,
157
- y as initialsOf
158
+ b as initialsOf
158
159
  };
159
160
  //# sourceMappingURL=kt-avatar.js.map
@@ -1 +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 /* The hue alone is too faint on its own 12% tint. Pulled towards the\n body text — lighter in dark, darker in light — it keeps its identity\n and clears 4.5:1 for all eight hues in both themes. */\n color: color-mix(in srgb, var(--kt-avatar-hue, var(--text-muted)) 45%, var(--text-body));\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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"}
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 { strings } from '#internal/strings';\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 /* The hue alone is too faint on its own 12% tint. Pulled towards the\n body text — lighter in dark, darker in light — it keeps its identity\n and clears 4.5:1 for all eight hues in both themes. */\n color: color-mix(in srgb, var(--kt-avatar-hue, var(--text-muted)) 45%, var(--text-body));\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 || strings().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","strings","nothing","__decorateClass","state","property","defineElement"],"mappings":"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"}
@@ -2,13 +2,14 @@ import { css as h, nothing as n, html as l } from "lit";
2
2
  import { property as e } from "lit/decorators.js";
3
3
  import { classMap as b } from "lit/directives/class-map.js";
4
4
  import { styleMap as m } from "lit/directives/style-map.js";
5
- import { K as p, d as v } from "../../../chunks/kt-element-B_jjQDhg.js";
5
+ import { K as p, d as v } from "../../../chunks/kt-element-E-tfJpGQ.js";
6
6
  import { e as u } from "../../../chunks/events-Bjl5Zmmq.js";
7
+ import { s as g } from "../../../chunks/index-DSSLJirw.js";
7
8
  import "../kt-icon/kt-icon.js";
8
- var g = Object.defineProperty, t = (c, r, i, f) => {
9
- for (var a = void 0, s = c.length - 1, d; s >= 0; s--)
10
- (d = c[s]) && (a = d(r, i, a) || a);
11
- return a && g(r, i, a), a;
9
+ var f = Object.defineProperty, t = (s, r, i, y) => {
10
+ for (var a = void 0, c = s.length - 1, d; c >= 0; c--)
11
+ (d = s[c]) && (a = d(r, i, a) || a);
12
+ return a && f(r, i, a), a;
12
13
  };
13
14
  class o extends p {
14
15
  constructor() {
@@ -209,7 +210,7 @@ class o extends p {
209
210
  part="remove"
210
211
  type="button"
211
212
  class="remove"
212
- aria-label=${`Remove ${this.display || "this"}`}
213
+ aria-label=${g().remove(this.display || this.textContent?.trim() || "")}
213
214
  @click=${this.onRemove}
214
215
  >
215
216
  <kt-icon name="x" size="12"></kt-icon>
@@ -1 +1 @@
1
- {"version":3,"file":"kt-badge.js","sources":["../../../../src/components/core/kt-badge/kt-badge.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport '../kt-icon/kt-icon.js';\n\nexport type KtBadgeVariant = 'tag' | 'code' | 'category' | 'count';\nexport type KtBadgeTone = 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info';\nexport type KtBadgeSize = 'small' | 'medium';\n\n/**\n * A compact label: a pill `tag`, a monospaced `code` token, a `category`\n * tinted with a colour of your choosing, or a `count`.\n *\n * Two independent axes, because they answer different questions. `variant` is\n * the **shape** — what kind of thing this is. `tone` is the **colour** — what\n * it means. A tag can be neutral or dangerous; so can a count. Folding them\n * into one list would give you nine variants and no way to say \"a tag, but\n * this one is a warning\".\n *\n * `count` is the exception that carries no border, because a number pinned to\n * a nav item is not a label with an outline — it is a mark on the thing it\n * counts.\n *\n * @element kt-badge\n *\n * @slot - The text. Falls back to the `label` attribute.\n *\n * @csspart base - The container.\n * @csspart remove - The remove button, when `removable`.\n *\n * @cssproperty --kt-badge-color - Category hue. The fill is this colour at 20%.\n *\n * @fires kt-badge-click - A `clickable` badge was activated. Cancelable.\n * @fires kt-remove - The remove button was pressed. Cancelable: cancel it and\n * remove the badge yourself once the server agrees.\n *\n * @example\n * ```html\n * <kt-badge>Design systems</kt-badge>\n * <kt-badge tone=\"success\">Active</kt-badge>\n * <kt-badge variant=\"code\">--surface-card</kt-badge>\n * <kt-badge variant=\"category\" color=\"#3987e5\">Infrastructure</kt-badge>\n * <kt-badge variant=\"count\" tone=\"danger\" max=\"99\">128</kt-badge>\n * <kt-badge icon=\"user\" removable>Assigned to me</kt-badge>\n * ```\n */\nexport class KtBadge extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n --kt-badge-color: var(--color-primary-text);\n }\n\n .badge {\n display: inline-flex;\n align-items: center;\n gap: var(--gap-element);\n width: fit-content;\n margin: 0;\n padding: var(--padding-chip);\n color: var(--text-body);\n font: var(--font-normal-regular);\n background-color: var(--color-dark-20);\n border: var(--border-width) solid var(--color-text-600);\n border-radius: var(--radius-input);\n white-space: normal;\n }\n\n .small {\n padding: 2px 8px;\n font: var(--font-normal-small);\n }\n\n /* === TAG === */\n .tag {\n border-radius: var(--radius-pill);\n }\n\n /* === CODE ===\n Uses the semantic code surface rather than a ramp step: --color-dark-8\n is the darkest surface in the dark theme and pure white in the light\n one, which made this badge white-on-white. */\n .code {\n color: var(--text-code);\n font: var(--font-code-regular);\n background-color: var(--surface-code);\n border-color: var(--border-code);\n }\n\n /* === CATEGORY ===\n color-mix keeps the 20% fill honest for any colour notation the host\n hands us; concatenating a \"33\" onto a hex string produces garbage\n for rgb() and named colours. */\n .category {\n color: var(--kt-badge-color);\n background-color: color-mix(in srgb, var(--kt-badge-color) 20%, transparent);\n border-color: var(--kt-badge-color);\n }\n\n /* === COUNT ===\n No border: a number pinned to a nav item is a mark on the thing it\n counts, not a label with an outline of its own. */\n .count {\n min-width: 20px;\n padding: 2px 6px;\n justify-content: center;\n color: var(--text-muted);\n font: var(--font-normal-small);\n font-variant-numeric: tabular-nums;\n line-height: 1.4;\n white-space: nowrap;\n background: var(--surface-raised);\n border: none;\n border-radius: var(--radius-pill);\n }\n\n /* === TONES ===\n The system's tinted pair everywhere: the colour at 12% behind, the\n colour itself as the ink. The border follows on the bordered shapes\n and is simply absent on the count shape. */\n .primary {\n color: var(--color-primary-text);\n background-color: var(--color-primary-soft);\n border-color: var(--color-primary-base);\n }\n .success {\n color: var(--color-success-text);\n background-color: var(--color-success-soft);\n border-color: var(--color-success-base);\n }\n .warning {\n color: var(--color-warning-text);\n background-color: var(--color-warning-soft);\n border-color: var(--color-warning-base);\n }\n .danger {\n color: var(--color-danger-text);\n background-color: var(--color-danger-soft);\n border-color: var(--color-danger-base);\n }\n .info {\n color: var(--color-info-text);\n background-color: var(--color-info-soft);\n border-color: var(--color-info-base);\n }\n\n .count.primary,\n .count.success,\n .count.warning,\n .count.danger,\n .count.info {\n border: none;\n }\n\n /* === CLICKABLE === */\n .clickable {\n cursor: pointer;\n }\n .clickable:hover {\n outline: var(--outline-width) solid var(--text-muted);\n }\n .clickable:active {\n color: var(--color-white);\n background-color: var(--color-primary-base);\n border-color: transparent;\n }\n .clickable:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 2px;\n }\n\n .remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-right: -4px;\n padding: 0;\n color: inherit;\n background: none;\n border: none;\n border-radius: var(--radius-pill);\n cursor: pointer;\n opacity: 0.65;\n }\n\n .remove:hover {\n opacity: 1;\n }\n\n .remove:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n kt-icon {\n flex: none;\n }\n `,\n ];\n\n /** The shape: what kind of thing this is. */\n @property({ type: String, reflect: true })\n variant: KtBadgeVariant = 'tag';\n\n /** The colour: what it means. Independent of `variant`. */\n @property({ type: String, reflect: true })\n tone: KtBadgeTone = 'neutral';\n\n @property({ type: String, reflect: true })\n size: KtBadgeSize = 'medium';\n\n /** Badge text. The default slot wins when both are present. */\n @property({ type: String })\n label = '';\n\n /** Category hue: any CSS colour. The fill is this colour at 20%. */\n @property({ type: String })\n color = '';\n\n /** Lucide icon name, before the text. */\n @property({ type: String })\n icon = '';\n\n @property({ type: Boolean, reflect: true })\n clickable = false;\n\n /** Adds a remove button. Fires a cancelable `kt-remove`. */\n @property({ type: Boolean, reflect: true })\n removable = false;\n\n /**\n * Caps a numeric label: `max=\"99\"` shows `99+`.\n * Ignored when the content is not a number.\n */\n @property({ type: Number })\n max?: number;\n\n /** Shorthand for `tone=\"danger\"`, kept from the field components. */\n @property({ type: Boolean, reflect: true })\n error = false;\n\n private get display(): string {\n const raw = this.label || (this.textContent ?? '').trim();\n if (this.max === undefined) return raw;\n\n const n = Number(raw);\n return Number.isFinite(n) && n > this.max ? `${this.max}+` : raw;\n }\n\n private activate(): void {\n if (this.clickable) emit(this, 'kt-badge-click');\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n if (!this.clickable) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n this.activate();\n }\n\n private onRemove(event: Event): void {\n // Otherwise a removable clickable badge reports both at once.\n event.stopPropagation();\n emit(this, 'kt-remove');\n }\n\n override render(): TemplateResult {\n const tone = this.error ? 'danger' : this.tone;\n\n return html`<span\n part=\"base\"\n class=${classMap({\n badge: true,\n [this.variant]: true,\n [tone]: tone !== 'neutral',\n small: this.size === 'small',\n clickable: this.clickable,\n })}\n style=${styleMap(this.color ? { '--kt-badge-color': this.color } : {})}\n role=${this.clickable ? 'button' : nothing}\n tabindex=${this.clickable ? 0 : nothing}\n @click=${this.activate}\n @keydown=${this.onKeyDown}\n >\n ${this.icon ? html`<kt-icon name=${this.icon} size=\"14\"></kt-icon>` : nothing}\n ${this.max === undefined ? html`<slot>${this.label}</slot>` : this.display}\n ${\n this.removable\n ? html`<button\n part=\"remove\"\n type=\"button\"\n class=\"remove\"\n aria-label=${`Remove ${this.display || 'this'}`}\n @click=${this.onRemove}\n >\n <kt-icon name=\"x\" size=\"12\"></kt-icon>\n </button>`\n : nothing\n }\n </span>`;\n }\n}\n\ndefineElement('kt-badge', KtBadge);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-badge': KtBadge;\n }\n}\n"],"names":["KtBadge","KtElement","css","raw","n","emit","event","tone","html","classMap","styleMap","nothing","__decorateClass","property","defineElement"],"mappings":"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"}
1
+ {"version":3,"file":"kt-badge.js","sources":["../../../../src/components/core/kt-badge/kt-badge.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport { strings } from '#internal/strings';\nimport '../kt-icon/kt-icon.js';\n\nexport type KtBadgeVariant = 'tag' | 'code' | 'category' | 'count';\nexport type KtBadgeTone = 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info';\nexport type KtBadgeSize = 'small' | 'medium';\n\n/**\n * A compact label: a pill `tag`, a monospaced `code` token, a `category`\n * tinted with a colour of your choosing, or a `count`.\n *\n * Two independent axes, because they answer different questions. `variant` is\n * the **shape** — what kind of thing this is. `tone` is the **colour** — what\n * it means. A tag can be neutral or dangerous; so can a count. Folding them\n * into one list would give you nine variants and no way to say \"a tag, but\n * this one is a warning\".\n *\n * `count` is the exception that carries no border, because a number pinned to\n * a nav item is not a label with an outline — it is a mark on the thing it\n * counts.\n *\n * @element kt-badge\n *\n * @slot - The text. Falls back to the `label` attribute.\n *\n * @csspart base - The container.\n * @csspart remove - The remove button, when `removable`.\n *\n * @cssproperty --kt-badge-color - Category hue. The fill is this colour at 20%.\n *\n * @fires kt-badge-click - A `clickable` badge was activated. Cancelable.\n * @fires kt-remove - The remove button was pressed. Cancelable: cancel it and\n * remove the badge yourself once the server agrees.\n *\n * @example\n * ```html\n * <kt-badge>Design systems</kt-badge>\n * <kt-badge tone=\"success\">Active</kt-badge>\n * <kt-badge variant=\"code\">--surface-card</kt-badge>\n * <kt-badge variant=\"category\" color=\"#3987e5\">Infrastructure</kt-badge>\n * <kt-badge variant=\"count\" tone=\"danger\" max=\"99\">128</kt-badge>\n * <kt-badge icon=\"user\" removable>Assigned to me</kt-badge>\n * ```\n */\nexport class KtBadge extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n --kt-badge-color: var(--color-primary-text);\n }\n\n .badge {\n display: inline-flex;\n align-items: center;\n gap: var(--gap-element);\n width: fit-content;\n margin: 0;\n padding: var(--padding-chip);\n color: var(--text-body);\n font: var(--font-normal-regular);\n background-color: var(--color-dark-20);\n border: var(--border-width) solid var(--color-text-600);\n border-radius: var(--radius-input);\n white-space: normal;\n }\n\n .small {\n padding: 2px 8px;\n font: var(--font-normal-small);\n }\n\n /* === TAG === */\n .tag {\n border-radius: var(--radius-pill);\n }\n\n /* === CODE ===\n Uses the semantic code surface rather than a ramp step: --color-dark-8\n is the darkest surface in the dark theme and pure white in the light\n one, which made this badge white-on-white. */\n .code {\n color: var(--text-code);\n font: var(--font-code-regular);\n background-color: var(--surface-code);\n border-color: var(--border-code);\n }\n\n /* === CATEGORY ===\n color-mix keeps the 20% fill honest for any colour notation the host\n hands us; concatenating a \"33\" onto a hex string produces garbage\n for rgb() and named colours. */\n .category {\n color: var(--kt-badge-color);\n background-color: color-mix(in srgb, var(--kt-badge-color) 20%, transparent);\n border-color: var(--kt-badge-color);\n }\n\n /* === COUNT ===\n No border: a number pinned to a nav item is a mark on the thing it\n counts, not a label with an outline of its own. */\n .count {\n min-width: 20px;\n padding: 2px 6px;\n justify-content: center;\n color: var(--text-muted);\n font: var(--font-normal-small);\n font-variant-numeric: tabular-nums;\n line-height: 1.4;\n white-space: nowrap;\n background: var(--surface-raised);\n border: none;\n border-radius: var(--radius-pill);\n }\n\n /* === TONES ===\n The system's tinted pair everywhere: the colour at 12% behind, the\n colour itself as the ink. The border follows on the bordered shapes\n and is simply absent on the count shape. */\n .primary {\n color: var(--color-primary-text);\n background-color: var(--color-primary-soft);\n border-color: var(--color-primary-base);\n }\n .success {\n color: var(--color-success-text);\n background-color: var(--color-success-soft);\n border-color: var(--color-success-base);\n }\n .warning {\n color: var(--color-warning-text);\n background-color: var(--color-warning-soft);\n border-color: var(--color-warning-base);\n }\n .danger {\n color: var(--color-danger-text);\n background-color: var(--color-danger-soft);\n border-color: var(--color-danger-base);\n }\n .info {\n color: var(--color-info-text);\n background-color: var(--color-info-soft);\n border-color: var(--color-info-base);\n }\n\n .count.primary,\n .count.success,\n .count.warning,\n .count.danger,\n .count.info {\n border: none;\n }\n\n /* === CLICKABLE === */\n .clickable {\n cursor: pointer;\n }\n .clickable:hover {\n outline: var(--outline-width) solid var(--text-muted);\n }\n .clickable:active {\n color: var(--color-white);\n background-color: var(--color-primary-base);\n border-color: transparent;\n }\n .clickable:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 2px;\n }\n\n .remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-right: -4px;\n padding: 0;\n color: inherit;\n background: none;\n border: none;\n border-radius: var(--radius-pill);\n cursor: pointer;\n opacity: 0.65;\n }\n\n .remove:hover {\n opacity: 1;\n }\n\n .remove:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n kt-icon {\n flex: none;\n }\n `,\n ];\n\n /** The shape: what kind of thing this is. */\n @property({ type: String, reflect: true })\n variant: KtBadgeVariant = 'tag';\n\n /** The colour: what it means. Independent of `variant`. */\n @property({ type: String, reflect: true })\n tone: KtBadgeTone = 'neutral';\n\n @property({ type: String, reflect: true })\n size: KtBadgeSize = 'medium';\n\n /** Badge text. The default slot wins when both are present. */\n @property({ type: String })\n label = '';\n\n /** Category hue: any CSS colour. The fill is this colour at 20%. */\n @property({ type: String })\n color = '';\n\n /** Lucide icon name, before the text. */\n @property({ type: String })\n icon = '';\n\n @property({ type: Boolean, reflect: true })\n clickable = false;\n\n /** Adds a remove button. Fires a cancelable `kt-remove`. */\n @property({ type: Boolean, reflect: true })\n removable = false;\n\n /**\n * Caps a numeric label: `max=\"99\"` shows `99+`.\n * Ignored when the content is not a number.\n */\n @property({ type: Number })\n max?: number;\n\n /** Shorthand for `tone=\"danger\"`, kept from the field components. */\n @property({ type: Boolean, reflect: true })\n error = false;\n\n private get display(): string {\n const raw = this.label || (this.textContent ?? '').trim();\n if (this.max === undefined) return raw;\n\n const n = Number(raw);\n return Number.isFinite(n) && n > this.max ? `${this.max}+` : raw;\n }\n\n private activate(): void {\n if (this.clickable) emit(this, 'kt-badge-click');\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n if (!this.clickable) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n this.activate();\n }\n\n private onRemove(event: Event): void {\n // Otherwise a removable clickable badge reports both at once.\n event.stopPropagation();\n emit(this, 'kt-remove');\n }\n\n override render(): TemplateResult {\n const tone = this.error ? 'danger' : this.tone;\n\n return html`<span\n part=\"base\"\n class=${classMap({\n badge: true,\n [this.variant]: true,\n [tone]: tone !== 'neutral',\n small: this.size === 'small',\n clickable: this.clickable,\n })}\n style=${styleMap(this.color ? { '--kt-badge-color': this.color } : {})}\n role=${this.clickable ? 'button' : nothing}\n tabindex=${this.clickable ? 0 : nothing}\n @click=${this.activate}\n @keydown=${this.onKeyDown}\n >\n ${this.icon ? html`<kt-icon name=${this.icon} size=\"14\"></kt-icon>` : nothing}\n ${this.max === undefined ? html`<slot>${this.label}</slot>` : this.display}\n ${\n this.removable\n ? html`<button\n part=\"remove\"\n type=\"button\"\n class=\"remove\"\n aria-label=${strings().remove(this.display || this.textContent?.trim() || '')}\n @click=${this.onRemove}\n >\n <kt-icon name=\"x\" size=\"12\"></kt-icon>\n </button>`\n : nothing\n }\n </span>`;\n }\n}\n\ndefineElement('kt-badge', KtBadge);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-badge': KtBadge;\n }\n}\n"],"names":["KtBadge","KtElement","css","raw","n","emit","event","tone","html","classMap","styleMap","nothing","strings","__decorateClass","property","defineElement"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { css as h, html as d, nothing as i } from "lit";
2
2
  import { property as e } from "lit/decorators.js";
3
3
  import { classMap as p } from "lit/directives/class-map.js";
4
- import { K as u, d as v } from "../../../chunks/kt-element-B_jjQDhg.js";
4
+ import { K as u, d as v } from "../../../chunks/kt-element-E-tfJpGQ.js";
5
5
  import "../kt-icon/kt-icon.js";
6
6
  var g = Object.defineProperty, a = (l, t, o, y) => {
7
7
  for (var n = void 0, c = l.length - 1, s; c >= 0; c--)
@@ -2,7 +2,7 @@ import { css as f, nothing as r, html as d } from "lit";
2
2
  import { state as g, property as a } from "lit/decorators.js";
3
3
  import { classMap as n } from "lit/directives/class-map.js";
4
4
  import { styleMap as u } from "lit/directives/style-map.js";
5
- import { K as m, d as v } from "../../../chunks/kt-element-B_jjQDhg.js";
5
+ import { K as m, d as v } from "../../../chunks/kt-element-E-tfJpGQ.js";
6
6
  import { e as b } from "../../../chunks/events-Bjl5Zmmq.js";
7
7
  import { h as p } from "../../../chunks/slots-BPbIdxAJ.js";
8
8
  var y = Object.defineProperty, i = (s, e, c, k) => {