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,64 @@
1
+ import { type TemplateResult } from 'lit';
2
+ import { KtElement } from '#internal/kt-element';
3
+ import '../../core/kt-icon/kt-icon.js';
4
+ import '../../feedback/kt-skeleton/kt-skeleton.js';
5
+ export interface KtTab {
6
+ readonly value: string | number;
7
+ readonly label?: string;
8
+ /** Lucide icon name, kebab-case. */
9
+ readonly icon?: string;
10
+ readonly disabled?: boolean;
11
+ /** id of the element this tab controls, for `aria-controls`. */
12
+ readonly panel?: string;
13
+ }
14
+ /**
15
+ * An underlined tab bar.
16
+ *
17
+ * Against `<kt-segmented-control>`: a segmented control picks a *value* — a
18
+ * date range, a unit — and sits inside a form or a toolbar. Tabs switch which
19
+ * *region of the page* you are looking at, and read as part of the page
20
+ * structure rather than as a control on it. The shapes say so: an inset track
21
+ * with a raised pill, versus a rule with one segment underlined.
22
+ *
23
+ * Like the segmented control, this only manages selection. Swapping the panel
24
+ * is the consumer's business.
25
+ *
26
+ * @element kt-tabs
27
+ *
28
+ * @csspart base - The tablist.
29
+ * @csspart tab - One tab.
30
+ *
31
+ * @fires kt-change - A tab was selected. `detail: { value, tab }`.
32
+ *
33
+ * @example
34
+ * ```js
35
+ * tabs.tabs = [
36
+ * { value: 'usage', label: 'Usage' },
37
+ * { value: 'api', label: 'API', icon: 'code' },
38
+ * ];
39
+ * ```
40
+ */
41
+ export declare class KtTabs extends KtElement {
42
+ static styles: import("lit").CSSResultGroup[];
43
+ private tabElements;
44
+ /** The tabs to show. A property: this is data. */
45
+ tabs: readonly KtTab[];
46
+ /** The selected tab's value. */
47
+ value: string | number | null;
48
+ disabled: boolean;
49
+ /** Renders placeholder tabs instead of the real ones. */
50
+ loading: boolean;
51
+ /** Accessible name for the tablist. */
52
+ label: string;
53
+ private get selectedIndex();
54
+ private select;
55
+ /** Moves to the next selectable tab in `direction`, wrapping at both ends. */
56
+ private step;
57
+ private onKeyDown;
58
+ render(): TemplateResult;
59
+ }
60
+ declare global {
61
+ interface HTMLElementTagNameMap {
62
+ 'kt-tabs': KtTabs;
63
+ }
64
+ }
@@ -0,0 +1,175 @@
1
+ import { css as u, html as l, nothing as p } from "lit";
2
+ import { queryAll as h, property as n } from "lit/decorators.js";
3
+ import { classMap as f } from "lit/directives/class-map.js";
4
+ import { K as c, d as v } from "../../../chunks/kt-element-CcMLO5e8.js";
5
+ import { e as m } from "../../../chunks/events-Bjl5Zmmq.js";
6
+ import "../../core/kt-icon/kt-icon.js";
7
+ import "../../feedback/kt-skeleton/kt-skeleton.js";
8
+ var x = Object.defineProperty, i = (d, e, t, r) => {
9
+ for (var s = void 0, a = d.length - 1, b; a >= 0; a--)
10
+ (b = d[a]) && (s = b(e, t, s) || s);
11
+ return s && x(e, t, s), s;
12
+ };
13
+ class o extends c {
14
+ constructor() {
15
+ super(...arguments), this.tabs = [], this.value = null, this.disabled = !1, this.loading = !1, this.label = "";
16
+ }
17
+ static {
18
+ this.styles = [
19
+ c.styles,
20
+ u`
21
+ :host {
22
+ display: block;
23
+ }
24
+
25
+ .tablist {
26
+ display: flex;
27
+ gap: var(--gap-drag-drop);
28
+ border-bottom: var(--border-width) solid var(--border-subtle);
29
+ overflow-x: auto;
30
+ scrollbar-width: none;
31
+ }
32
+
33
+ .tablist::-webkit-scrollbar {
34
+ display: none;
35
+ }
36
+
37
+ :host([disabled]) .tablist {
38
+ opacity: 0.5;
39
+ pointer-events: none;
40
+ }
41
+
42
+ .tab {
43
+ display: inline-flex;
44
+ align-items: center;
45
+ gap: 6px;
46
+ /* The -1px pulls the active underline over the container's rule so the
47
+ two read as one line rather than two stacked ones. */
48
+ margin-bottom: calc(var(--border-width) * -1);
49
+ padding: 10px 2px;
50
+ color: var(--text-muted);
51
+ font: var(--font-normal-medium);
52
+ white-space: nowrap;
53
+ background: transparent;
54
+ border: none;
55
+ border-bottom: 2px solid transparent;
56
+ cursor: pointer;
57
+ transition:
58
+ color var(--duration-instant),
59
+ border-color var(--duration-instant);
60
+ }
61
+
62
+ .tab:hover:not(:disabled) {
63
+ color: var(--text-body);
64
+ }
65
+
66
+ .tab.selected {
67
+ color: var(--text-body);
68
+ border-bottom-color: var(--color-primary-base);
69
+ }
70
+
71
+ .tab:disabled {
72
+ color: var(--text-disabled);
73
+ cursor: not-allowed;
74
+ }
75
+
76
+ .tab:focus-visible {
77
+ outline: var(--outline-width) solid var(--color-primary-base);
78
+ outline-offset: 2px;
79
+ border-radius: 4px;
80
+ }
81
+
82
+ .loading {
83
+ display: flex;
84
+ gap: var(--gap-drag-drop);
85
+ padding: 10px 0;
86
+ }
87
+ `
88
+ ];
89
+ }
90
+ get selectedIndex() {
91
+ return this.tabs.findIndex((e) => e.value === this.value);
92
+ }
93
+ select(e) {
94
+ e.disabled || this.value === e.value || (this.value = e.value, m(this, "kt-change", { value: e.value, tab: e }));
95
+ }
96
+ /** Moves to the next selectable tab in `direction`, wrapping at both ends. */
97
+ step(e) {
98
+ const t = this.tabs.length;
99
+ if (t === 0) return;
100
+ const r = this.selectedIndex < 0 ? e === 1 ? -1 : 0 : this.selectedIndex;
101
+ for (let s = 1; s <= t; s += 1) {
102
+ const a = ((r + e * s) % t + t) % t;
103
+ if (!this.tabs[a]?.disabled) return a;
104
+ }
105
+ }
106
+ onKeyDown(e) {
107
+ let t;
108
+ if (e.key === "ArrowRight") t = this.step(1);
109
+ else if (e.key === "ArrowLeft") t = this.step(-1);
110
+ else if (e.key === "Home") t = this.tabs.findIndex((a) => !a.disabled);
111
+ else if (e.key === "End")
112
+ t = this.tabs.length - 1 - [...this.tabs].reverse().findIndex((a) => !a.disabled);
113
+ else return;
114
+ if (e.preventDefault(), t === void 0 || t < 0) return;
115
+ const r = this.tabs[t];
116
+ if (!r) return;
117
+ const s = t;
118
+ this.select(r), this.updateComplete.then(() => this.tabElements[s]?.focus());
119
+ }
120
+ render() {
121
+ if (this.loading)
122
+ return l`<div class="loading" aria-hidden="true">
123
+ ${[0, 1, 2].map(() => l`<kt-skeleton variant="rect" width="64px" height="22px"></kt-skeleton>`)}
124
+ </div>`;
125
+ const e = this.selectedIndex, t = e >= 0 ? e : this.tabs.findIndex((r) => !r.disabled);
126
+ return l`<div
127
+ part="base"
128
+ class="tablist"
129
+ role="tablist"
130
+ aria-label=${this.label || p}
131
+ @keydown=${this.onKeyDown}
132
+ >
133
+ ${this.tabs.map((r, s) => {
134
+ const a = r.value === this.value;
135
+ return l`<button
136
+ part="tab"
137
+ type="button"
138
+ role="tab"
139
+ class=${f({ tab: !0, selected: a })}
140
+ aria-selected=${a ? "true" : "false"}
141
+ aria-controls=${r.panel ?? p}
142
+ tabindex=${s === t ? 0 : -1}
143
+ ?disabled=${this.disabled || r.disabled}
144
+ @click=${() => this.select(r)}
145
+ >
146
+ ${r.icon ? l`<kt-icon name=${r.icon} size="16"></kt-icon>` : p}
147
+ ${r.label ?? String(r.value)}
148
+ </button>`;
149
+ })}
150
+ </div>`;
151
+ }
152
+ }
153
+ i([
154
+ h(".tab")
155
+ ], o.prototype, "tabElements");
156
+ i([
157
+ n({ attribute: !1 })
158
+ ], o.prototype, "tabs");
159
+ i([
160
+ n({ type: String })
161
+ ], o.prototype, "value");
162
+ i([
163
+ n({ type: Boolean, reflect: !0 })
164
+ ], o.prototype, "disabled");
165
+ i([
166
+ n({ type: Boolean, reflect: !0 })
167
+ ], o.prototype, "loading");
168
+ i([
169
+ n({ type: String })
170
+ ], o.prototype, "label");
171
+ v("kt-tabs", o);
172
+ export {
173
+ o as KtTabs
174
+ };
175
+ //# sourceMappingURL=kt-tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kt-tabs.js","sources":["../../../../src/components/navigation/kt-tabs/kt-tabs.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, queryAll } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport '../../core/kt-icon/kt-icon.js';\nimport '../../feedback/kt-skeleton/kt-skeleton.js';\n\nexport interface KtTab {\n readonly value: string | number;\n readonly label?: string;\n /** Lucide icon name, kebab-case. */\n readonly icon?: string;\n readonly disabled?: boolean;\n /** id of the element this tab controls, for `aria-controls`. */\n readonly panel?: string;\n}\n\n/**\n * An underlined tab bar.\n *\n * Against `<kt-segmented-control>`: a segmented control picks a *value* — a\n * date range, a unit — and sits inside a form or a toolbar. Tabs switch which\n * *region of the page* you are looking at, and read as part of the page\n * structure rather than as a control on it. The shapes say so: an inset track\n * with a raised pill, versus a rule with one segment underlined.\n *\n * Like the segmented control, this only manages selection. Swapping the panel\n * is the consumer's business.\n *\n * @element kt-tabs\n *\n * @csspart base - The tablist.\n * @csspart tab - One tab.\n *\n * @fires kt-change - A tab was selected. `detail: { value, tab }`.\n *\n * @example\n * ```js\n * tabs.tabs = [\n * { value: 'usage', label: 'Usage' },\n * { value: 'api', label: 'API', icon: 'code' },\n * ];\n * ```\n */\nexport class KtTabs extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n .tablist {\n display: flex;\n gap: var(--gap-drag-drop);\n border-bottom: var(--border-width) solid var(--border-subtle);\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .tablist::-webkit-scrollbar {\n display: none;\n }\n\n :host([disabled]) .tablist {\n opacity: 0.5;\n pointer-events: none;\n }\n\n .tab {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n /* The -1px pulls the active underline over the container's rule so the\n two read as one line rather than two stacked ones. */\n margin-bottom: calc(var(--border-width) * -1);\n padding: 10px 2px;\n color: var(--text-muted);\n font: var(--font-normal-medium);\n white-space: nowrap;\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n transition:\n color var(--duration-instant),\n border-color var(--duration-instant);\n }\n\n .tab:hover:not(:disabled) {\n color: var(--text-body);\n }\n\n .tab.selected {\n color: var(--text-body);\n border-bottom-color: var(--color-primary-base);\n }\n\n .tab:disabled {\n color: var(--text-disabled);\n cursor: not-allowed;\n }\n\n .tab:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 2px;\n border-radius: 4px;\n }\n\n .loading {\n display: flex;\n gap: var(--gap-drag-drop);\n padding: 10px 0;\n }\n `,\n ];\n\n @queryAll('.tab')\n private tabElements!: NodeListOf<HTMLButtonElement>;\n\n /** The tabs to show. A property: this is data. */\n @property({ attribute: false })\n tabs: readonly KtTab[] = [];\n\n /** The selected tab's value. */\n @property({ type: String })\n value: string | number | null = null;\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /** Renders placeholder tabs instead of the real ones. */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n /** Accessible name for the tablist. */\n @property({ type: String })\n label = '';\n\n private get selectedIndex(): number {\n return this.tabs.findIndex((tab) => tab.value === this.value);\n }\n\n private select(tab: KtTab): void {\n if (tab.disabled || this.value === tab.value) return;\n this.value = tab.value;\n emit(this, 'kt-change', { value: tab.value, tab });\n }\n\n /** Moves to the next selectable tab in `direction`, wrapping at both ends. */\n private step(direction: 1 | -1): number | undefined {\n const count = this.tabs.length;\n if (count === 0) return undefined;\n\n const from = this.selectedIndex < 0 ? (direction === 1 ? -1 : 0) : this.selectedIndex;\n for (let offset = 1; offset <= count; offset += 1) {\n const index = (((from + direction * offset) % count) + count) % count;\n if (!this.tabs[index]?.disabled) return index;\n }\n return undefined;\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n let target: number | undefined;\n\n if (event.key === 'ArrowRight') target = this.step(1);\n else if (event.key === 'ArrowLeft') target = this.step(-1);\n else if (event.key === 'Home') target = this.tabs.findIndex((tab) => !tab.disabled);\n else if (event.key === 'End')\n target = this.tabs.length - 1 - [...this.tabs].reverse().findIndex((tab) => !tab.disabled);\n else return;\n\n event.preventDefault();\n if (target === undefined || target < 0) return;\n\n const tab = this.tabs[target];\n if (!tab) return;\n\n const index = target;\n this.select(tab);\n void this.updateComplete.then(() => this.tabElements[index]?.focus());\n }\n\n override render(): TemplateResult {\n if (this.loading) {\n return html`<div class=\"loading\" aria-hidden=\"true\">\n ${[0, 1, 2].map(() => html`<kt-skeleton variant=\"rect\" width=\"64px\" height=\"22px\"></kt-skeleton>`)}\n </div>`;\n }\n\n const selectedIndex = this.selectedIndex;\n // One tab stop for the whole bar, as a tablist should have.\n const tabStop = selectedIndex >= 0 ? selectedIndex : this.tabs.findIndex((t) => !t.disabled);\n\n return html`<div\n part=\"base\"\n class=\"tablist\"\n role=\"tablist\"\n aria-label=${this.label || nothing}\n @keydown=${this.onKeyDown}\n >\n ${this.tabs.map((tab, index) => {\n const selected = tab.value === this.value;\n\n return html`<button\n part=\"tab\"\n type=\"button\"\n role=\"tab\"\n class=${classMap({ tab: true, selected })}\n aria-selected=${selected ? 'true' : 'false'}\n aria-controls=${tab.panel ?? nothing}\n tabindex=${index === tabStop ? 0 : -1}\n ?disabled=${this.disabled || tab.disabled}\n @click=${() => this.select(tab)}\n >\n ${tab.icon ? html`<kt-icon name=${tab.icon} size=\"16\"></kt-icon>` : nothing}\n ${tab.label ?? String(tab.value)}\n </button>`;\n })}\n </div>`;\n }\n}\n\ndefineElement('kt-tabs', KtTabs);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-tabs': KtTabs;\n }\n}\n"],"names":["KtTabs","KtElement","css","tab","emit","direction","count","from","offset","index","event","target","html","selectedIndex","tabStop","t","nothing","selected","classMap","__decorateClass","queryAll","property","defineElement"],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { type TemplateResult } from 'lit';
2
+ import { KtElement } from '#internal/kt-element';
3
+ import '../../core/kt-icon/kt-icon.js';
4
+ export type KtToggleButtonVariant = 'primary' | 'secondary' | 'outline';
5
+ export type KtToggleButtonSize = 'small' | 'medium' | 'large';
6
+ /**
7
+ * A button that stays pressed.
8
+ *
9
+ * `aria-pressed` rather than `aria-checked`: this is a control that holds a
10
+ * state, not one option among several. Put several in a
11
+ * `<kt-toggle-button-group>` when they are.
12
+ *
13
+ * @element kt-toggle-button
14
+ *
15
+ * @slot - The button label.
16
+ *
17
+ * @csspart button - The native `<button>`.
18
+ *
19
+ * @fires kt-change - The state changed. `detail: { selected, value }`.
20
+ */
21
+ export declare class KtToggleButton extends KtElement {
22
+ static styles: import("lit").CSSResultGroup[];
23
+ selected: boolean;
24
+ disabled: boolean;
25
+ variant: KtToggleButtonVariant;
26
+ size: KtToggleButtonSize;
27
+ /** Identifies this button inside a `<kt-toggle-button-group>`. */
28
+ value: string;
29
+ icon: string;
30
+ iconPosition: 'left' | 'right';
31
+ /** Accessible name. Required when the button is icon-only. */
32
+ label: string;
33
+ /**
34
+ * Set by `<kt-toggle-button-group>` on the buttons it owns.
35
+ *
36
+ * A managed button is a display, not a control: it neither flips itself nor
37
+ * emits. The group reads the click, decides what the selection now is, and
38
+ * writes `selected` back. Without this the two both react to the same click
39
+ * and consumers hear two different kt-change events for one press.
40
+ */
41
+ managed: boolean;
42
+ focus(options?: FocusOptions): void;
43
+ private toggle;
44
+ render(): TemplateResult;
45
+ }
46
+ declare global {
47
+ interface HTMLElementTagNameMap {
48
+ 'kt-toggle-button': KtToggleButton;
49
+ }
50
+ }
@@ -0,0 +1,191 @@
1
+ import { css as p, html as c, nothing as n } from "lit";
2
+ import { property as o } from "lit/decorators.js";
3
+ import { classMap as b } from "lit/directives/class-map.js";
4
+ import { K as u, d as g } from "../../../chunks/kt-element-CcMLO5e8.js";
5
+ import { e as v } from "../../../chunks/events-Bjl5Zmmq.js";
6
+ import "../../core/kt-icon/kt-icon.js";
7
+ var m = Object.defineProperty, r = (l, e, i, s) => {
8
+ for (var a = void 0, d = l.length - 1, h; d >= 0; d--)
9
+ (h = l[d]) && (a = h(e, i, a) || a);
10
+ return a && m(e, i, a), a;
11
+ };
12
+ const y = { small: 16, medium: 20, large: 24 };
13
+ class t extends u {
14
+ constructor() {
15
+ super(...arguments), this.selected = !1, this.disabled = !1, this.variant = "primary", this.size = "medium", this.value = "", this.icon = "", this.iconPosition = "left", this.label = "", this.managed = !1;
16
+ }
17
+ static {
18
+ this.styles = [
19
+ u.styles,
20
+ p`
21
+ :host {
22
+ display: inline-flex;
23
+ }
24
+
25
+ button {
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ box-sizing: border-box;
30
+ width: 100%;
31
+ height: var(--button-height);
32
+ padding: 0 var(--button-padding-x);
33
+ gap: var(--gap-button);
34
+ font: var(--font-normal-regular);
35
+ border: var(--border-width) solid transparent;
36
+ /* Overridden by kt-toggle-button-group, which is the only thing that
37
+ knows whether this button is first, last or in the middle. */
38
+ border-radius: var(--kt-toggle-button-radius, var(--border-radius));
39
+ cursor: pointer;
40
+ transition:
41
+ background-color var(--duration-normal) var(--easing-standard),
42
+ border-color var(--duration-normal) var(--easing-standard),
43
+ color var(--duration-normal) var(--easing-standard);
44
+ }
45
+
46
+ button:disabled {
47
+ color: var(--text-disabled);
48
+ background-color: var(--color-dark-14);
49
+ border-color: transparent;
50
+ pointer-events: none;
51
+ }
52
+
53
+ button:focus-visible {
54
+ outline: var(--outline-width) solid var(--color-primary-base);
55
+ outline-offset: 2px;
56
+ }
57
+
58
+ .small {
59
+ height: var(--button-height-small);
60
+ padding: 0 8px;
61
+ font: var(--font-normal-small);
62
+ }
63
+ .large {
64
+ height: var(--button-height-large);
65
+ padding: 0 calc(var(--button-padding-x) + 8px);
66
+ font: var(--font-normal-medium);
67
+ }
68
+
69
+ /* === PRIMARY === */
70
+ .primary {
71
+ color: var(--text-muted);
72
+ background-color: var(--surface-raised);
73
+ }
74
+ .primary:hover:not(:disabled) {
75
+ background-color: var(--surface-hover);
76
+ }
77
+ .primary.selected {
78
+ color: var(--color-white);
79
+ background-color: var(--color-primary-base);
80
+ border-color: var(--color-primary-base);
81
+ }
82
+ .primary.selected:hover:not(:disabled) {
83
+ background-color: var(--color-primary-hover);
84
+ }
85
+
86
+ /* === SECONDARY === */
87
+ .secondary {
88
+ color: var(--text-muted);
89
+ background-color: var(--color-dark-14);
90
+ }
91
+ .secondary:hover:not(:disabled) {
92
+ background-color: var(--color-secondary-hover);
93
+ }
94
+ .secondary.selected {
95
+ color: var(--color-primary-base);
96
+ background-color: var(--color-primary-soft);
97
+ }
98
+
99
+ /* === OUTLINE === */
100
+ .outline {
101
+ color: var(--text-muted);
102
+ background-color: transparent;
103
+ border-color: var(--color-text-600);
104
+ }
105
+ .outline:hover:not(:disabled) {
106
+ background-color: var(--color-dark-14);
107
+ border-color: var(--text-muted);
108
+ }
109
+ .outline.selected {
110
+ color: var(--color-primary-base);
111
+ background-color: var(--color-primary-soft);
112
+ border-color: var(--color-primary-base);
113
+ }
114
+
115
+ .icon-only {
116
+ width: var(--button-height);
117
+ padding: 0;
118
+ }
119
+ .icon-only.small {
120
+ width: var(--button-height-small);
121
+ }
122
+ .icon-only.large {
123
+ width: var(--button-height-large);
124
+ }
125
+
126
+ .text {
127
+ white-space: nowrap;
128
+ }
129
+ `
130
+ ];
131
+ }
132
+ focus(e) {
133
+ this.shadowRoot?.querySelector("button")?.focus(e);
134
+ }
135
+ toggle() {
136
+ this.disabled || this.managed || (this.selected = !this.selected, v(this, "kt-change", { selected: this.selected, value: this.value }));
137
+ }
138
+ render() {
139
+ const e = this.textContent !== null && this.textContent.trim().length > 0, i = !!this.icon && !e, s = this.icon ? c`<kt-icon name=${this.icon} size=${y[this.size]}></kt-icon>` : n;
140
+ return c`<button
141
+ part="button"
142
+ type="button"
143
+ class=${b({
144
+ [this.variant]: !0,
145
+ [this.size]: !0,
146
+ selected: this.selected,
147
+ "icon-only": i
148
+ })}
149
+ aria-pressed=${this.selected ? "true" : "false"}
150
+ aria-label=${this.label || n}
151
+ ?disabled=${this.disabled}
152
+ @click=${this.toggle}
153
+ >
154
+ ${this.iconPosition === "left" ? s : n}
155
+ ${i ? n : c`<span class="text"><slot></slot></span>`}
156
+ ${this.iconPosition === "right" ? s : n}
157
+ </button>`;
158
+ }
159
+ }
160
+ r([
161
+ o({ type: Boolean, reflect: !0 })
162
+ ], t.prototype, "selected");
163
+ r([
164
+ o({ type: Boolean, reflect: !0 })
165
+ ], t.prototype, "disabled");
166
+ r([
167
+ o({ type: String, reflect: !0 })
168
+ ], t.prototype, "variant");
169
+ r([
170
+ o({ type: String, reflect: !0 })
171
+ ], t.prototype, "size");
172
+ r([
173
+ o({ type: String })
174
+ ], t.prototype, "value");
175
+ r([
176
+ o({ type: String })
177
+ ], t.prototype, "icon");
178
+ r([
179
+ o({ type: String, attribute: "icon-position" })
180
+ ], t.prototype, "iconPosition");
181
+ r([
182
+ o({ type: String })
183
+ ], t.prototype, "label");
184
+ r([
185
+ o({ attribute: !1 })
186
+ ], t.prototype, "managed");
187
+ g("kt-toggle-button", t);
188
+ export {
189
+ t as KtToggleButton
190
+ };
191
+ //# sourceMappingURL=kt-toggle-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kt-toggle-button.js","sources":["../../../../src/components/navigation/kt-toggle-button/kt-toggle-button.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 { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport type KtToggleButtonVariant = 'primary' | 'secondary' | 'outline';\nexport type KtToggleButtonSize = 'small' | 'medium' | 'large';\n\nconst ICON_SIZE: Record<KtToggleButtonSize, number> = { small: 16, medium: 20, large: 24 };\n\n/**\n * A button that stays pressed.\n *\n * `aria-pressed` rather than `aria-checked`: this is a control that holds a\n * state, not one option among several. Put several in a\n * `<kt-toggle-button-group>` when they are.\n *\n * @element kt-toggle-button\n *\n * @slot - The button label.\n *\n * @csspart button - The native `<button>`.\n *\n * @fires kt-change - The state changed. `detail: { selected, value }`.\n */\nexport class KtToggleButton extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: inline-flex;\n }\n\n button {\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n width: 100%;\n height: var(--button-height);\n padding: 0 var(--button-padding-x);\n gap: var(--gap-button);\n font: var(--font-normal-regular);\n border: var(--border-width) solid transparent;\n /* Overridden by kt-toggle-button-group, which is the only thing that\n knows whether this button is first, last or in the middle. */\n border-radius: var(--kt-toggle-button-radius, var(--border-radius));\n cursor: pointer;\n transition:\n background-color var(--duration-normal) var(--easing-standard),\n border-color var(--duration-normal) var(--easing-standard),\n color var(--duration-normal) var(--easing-standard);\n }\n\n button:disabled {\n color: var(--text-disabled);\n background-color: var(--color-dark-14);\n border-color: transparent;\n pointer-events: none;\n }\n\n button:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 2px;\n }\n\n .small {\n height: var(--button-height-small);\n padding: 0 8px;\n font: var(--font-normal-small);\n }\n .large {\n height: var(--button-height-large);\n padding: 0 calc(var(--button-padding-x) + 8px);\n font: var(--font-normal-medium);\n }\n\n /* === PRIMARY === */\n .primary {\n color: var(--text-muted);\n background-color: var(--surface-raised);\n }\n .primary:hover:not(:disabled) {\n background-color: var(--surface-hover);\n }\n .primary.selected {\n color: var(--color-white);\n background-color: var(--color-primary-base);\n border-color: var(--color-primary-base);\n }\n .primary.selected:hover:not(:disabled) {\n background-color: var(--color-primary-hover);\n }\n\n /* === SECONDARY === */\n .secondary {\n color: var(--text-muted);\n background-color: var(--color-dark-14);\n }\n .secondary:hover:not(:disabled) {\n background-color: var(--color-secondary-hover);\n }\n .secondary.selected {\n color: var(--color-primary-base);\n background-color: var(--color-primary-soft);\n }\n\n /* === OUTLINE === */\n .outline {\n color: var(--text-muted);\n background-color: transparent;\n border-color: var(--color-text-600);\n }\n .outline:hover:not(:disabled) {\n background-color: var(--color-dark-14);\n border-color: var(--text-muted);\n }\n .outline.selected {\n color: var(--color-primary-base);\n background-color: var(--color-primary-soft);\n border-color: var(--color-primary-base);\n }\n\n .icon-only {\n width: var(--button-height);\n padding: 0;\n }\n .icon-only.small {\n width: var(--button-height-small);\n }\n .icon-only.large {\n width: var(--button-height-large);\n }\n\n .text {\n white-space: nowrap;\n }\n `,\n ];\n\n @property({ type: Boolean, reflect: true })\n selected = false;\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: String, reflect: true })\n variant: KtToggleButtonVariant = 'primary';\n\n @property({ type: String, reflect: true })\n size: KtToggleButtonSize = 'medium';\n\n /** Identifies this button inside a `<kt-toggle-button-group>`. */\n @property({ type: String })\n value = '';\n\n @property({ type: String })\n icon = '';\n\n @property({ type: String, attribute: 'icon-position' })\n iconPosition: 'left' | 'right' = 'left';\n\n /** Accessible name. Required when the button is icon-only. */\n @property({ type: String })\n label = '';\n\n /**\n * Set by `<kt-toggle-button-group>` on the buttons it owns.\n *\n * A managed button is a display, not a control: it neither flips itself nor\n * emits. The group reads the click, decides what the selection now is, and\n * writes `selected` back. Without this the two both react to the same click\n * and consumers hear two different kt-change events for one press.\n */\n @property({ attribute: false })\n managed = false;\n\n override focus(options?: FocusOptions): void {\n this.shadowRoot?.querySelector('button')?.focus(options);\n }\n\n private toggle(): void {\n if (this.disabled || this.managed) return;\n this.selected = !this.selected;\n emit(this, 'kt-change', { selected: this.selected, value: this.value });\n }\n\n override render(): TemplateResult {\n const hasText = this.textContent !== null && this.textContent.trim().length > 0;\n const iconOnly = Boolean(this.icon) && !hasText;\n const icon = this.icon\n ? html`<kt-icon name=${this.icon} size=${ICON_SIZE[this.size]}></kt-icon>`\n : nothing;\n\n return html`<button\n part=\"button\"\n type=\"button\"\n class=${classMap({\n [this.variant]: true,\n [this.size]: true,\n selected: this.selected,\n 'icon-only': iconOnly,\n })}\n aria-pressed=${this.selected ? 'true' : 'false'}\n aria-label=${this.label || nothing}\n ?disabled=${this.disabled}\n @click=${this.toggle}\n >\n ${this.iconPosition === 'left' ? icon : nothing}\n ${iconOnly ? nothing : html`<span class=\"text\"><slot></slot></span>`}\n ${this.iconPosition === 'right' ? icon : nothing}\n </button>`;\n }\n}\n\ndefineElement('kt-toggle-button', KtToggleButton);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-toggle-button': KtToggleButton;\n }\n}\n"],"names":["ICON_SIZE","KtToggleButton","KtElement","css","options","emit","hasText","iconOnly","icon","html","nothing","classMap","__decorateClass","property","defineElement"],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { type PropertyValues, type TemplateResult } from 'lit';
2
+ import { KtElement } from '#internal/kt-element';
3
+ /**
4
+ * Joins `<kt-toggle-button>`s into one segmented bar and coordinates their
5
+ * selection.
6
+ *
7
+ * Single mode behaves like a radio group with a deselect: clicking the active
8
+ * button clears it. Multiple mode is a set of independent checkboxes that
9
+ * happen to be drawn together.
10
+ *
11
+ * The buttons are slotted rather than described by an options array, so a
12
+ * button can hold whatever its label needs — an icon, a count, a badge.
13
+ *
14
+ * @element kt-toggle-button-group
15
+ *
16
+ * @slot - The `<kt-toggle-button>` children.
17
+ *
18
+ * @csspart base - The group container.
19
+ *
20
+ * @fires kt-change - The selection changed.
21
+ * `detail: { value }` — a single value or `null`, or an array in multiple mode.
22
+ *
23
+ * @example
24
+ * ```html
25
+ * <kt-toggle-button-group>
26
+ * <kt-toggle-button value="list" icon="list" label="List"></kt-toggle-button>
27
+ * <kt-toggle-button value="grid" icon="grid" label="Grid"></kt-toggle-button>
28
+ * </kt-toggle-button-group>
29
+ * ```
30
+ */
31
+ export declare class KtToggleButtonGroup extends KtElement {
32
+ static styles: import("lit").CSSResultGroup[];
33
+ private buttons;
34
+ /** `false`: one selection at a time. `true`: any number. */
35
+ multiple: boolean;
36
+ orientation: 'horizontal' | 'vertical';
37
+ /** Accessible name for the group. */
38
+ label: string;
39
+ /** The selected value, or values in multiple mode. */
40
+ value: string | string[] | null;
41
+ connectedCallback(): void;
42
+ disconnectedCallback(): void;
43
+ firstUpdated(): void;
44
+ updated(changed: PropertyValues<this>): void;
45
+ private isSelected;
46
+ /** Pushes the group's state down; the buttons are the display, not the truth. */
47
+ private syncButtons;
48
+ private onButtonClick;
49
+ render(): TemplateResult;
50
+ }
51
+ declare global {
52
+ interface HTMLElementTagNameMap {
53
+ 'kt-toggle-button-group': KtToggleButtonGroup;
54
+ }
55
+ }