premium-ds 0.1.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 (257) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +113 -0
  3. package/dist/alert.d.ts +31 -0
  4. package/dist/alert.js +6 -0
  5. package/dist/alert.js.map +1 -0
  6. package/dist/avatar-group.d.ts +13 -0
  7. package/dist/avatar-group.js +3 -0
  8. package/dist/avatar-group.js.map +1 -0
  9. package/dist/avatar.d.ts +25 -0
  10. package/dist/avatar.js +3 -0
  11. package/dist/avatar.js.map +1 -0
  12. package/dist/badge.d.ts +23 -0
  13. package/dist/badge.js +3 -0
  14. package/dist/badge.js.map +1 -0
  15. package/dist/button.d.ts +20 -0
  16. package/dist/button.js +3 -0
  17. package/dist/button.js.map +1 -0
  18. package/dist/checkbox.d.ts +25 -0
  19. package/dist/checkbox.js +3 -0
  20. package/dist/checkbox.js.map +1 -0
  21. package/dist/chunk-2OWHZ4JT.js +36 -0
  22. package/dist/chunk-2OWHZ4JT.js.map +1 -0
  23. package/dist/chunk-34SIXSYL.js +64 -0
  24. package/dist/chunk-34SIXSYL.js.map +1 -0
  25. package/dist/chunk-37O2ZXD6.js +55 -0
  26. package/dist/chunk-37O2ZXD6.js.map +1 -0
  27. package/dist/chunk-4AZL76UJ.js +89 -0
  28. package/dist/chunk-4AZL76UJ.js.map +1 -0
  29. package/dist/chunk-4HSCN5TZ.js +86 -0
  30. package/dist/chunk-4HSCN5TZ.js.map +1 -0
  31. package/dist/chunk-5DDOOT33.js +258 -0
  32. package/dist/chunk-5DDOOT33.js.map +1 -0
  33. package/dist/chunk-5FVHWIMY.js +117 -0
  34. package/dist/chunk-5FVHWIMY.js.map +1 -0
  35. package/dist/chunk-5K6KRJGX.js +147 -0
  36. package/dist/chunk-5K6KRJGX.js.map +1 -0
  37. package/dist/chunk-5PQMQBQC.js +74 -0
  38. package/dist/chunk-5PQMQBQC.js.map +1 -0
  39. package/dist/chunk-7OCTVQ7C.js +95 -0
  40. package/dist/chunk-7OCTVQ7C.js.map +1 -0
  41. package/dist/chunk-7OPMOET7.js +39 -0
  42. package/dist/chunk-7OPMOET7.js.map +1 -0
  43. package/dist/chunk-BXXS7YRC.js +270 -0
  44. package/dist/chunk-BXXS7YRC.js.map +1 -0
  45. package/dist/chunk-CV2Q4YXX.js +272 -0
  46. package/dist/chunk-CV2Q4YXX.js.map +1 -0
  47. package/dist/chunk-EIMMDWIW.js +282 -0
  48. package/dist/chunk-EIMMDWIW.js.map +1 -0
  49. package/dist/chunk-EZ2CWTBE.js +230 -0
  50. package/dist/chunk-EZ2CWTBE.js.map +1 -0
  51. package/dist/chunk-FGHDG3Y4.js +89 -0
  52. package/dist/chunk-FGHDG3Y4.js.map +1 -0
  53. package/dist/chunk-FPP2XLKX.js +127 -0
  54. package/dist/chunk-FPP2XLKX.js.map +1 -0
  55. package/dist/chunk-G6OY35DI.js +295 -0
  56. package/dist/chunk-G6OY35DI.js.map +1 -0
  57. package/dist/chunk-H6KWJNOE.js +65 -0
  58. package/dist/chunk-H6KWJNOE.js.map +1 -0
  59. package/dist/chunk-HGILYGY3.js +45 -0
  60. package/dist/chunk-HGILYGY3.js.map +1 -0
  61. package/dist/chunk-I3BCB4Z5.js +88 -0
  62. package/dist/chunk-I3BCB4Z5.js.map +1 -0
  63. package/dist/chunk-KBWNUUWM.js +582 -0
  64. package/dist/chunk-KBWNUUWM.js.map +1 -0
  65. package/dist/chunk-KN7JFAZ6.js +113 -0
  66. package/dist/chunk-KN7JFAZ6.js.map +1 -0
  67. package/dist/chunk-MEF7PI6U.js +16 -0
  68. package/dist/chunk-MEF7PI6U.js.map +1 -0
  69. package/dist/chunk-NKGMQL6I.js +310 -0
  70. package/dist/chunk-NKGMQL6I.js.map +1 -0
  71. package/dist/chunk-NMFQRGLL.js +127 -0
  72. package/dist/chunk-NMFQRGLL.js.map +1 -0
  73. package/dist/chunk-OUBWD6CX.js +433 -0
  74. package/dist/chunk-OUBWD6CX.js.map +1 -0
  75. package/dist/chunk-PFNXVBLU.js +96 -0
  76. package/dist/chunk-PFNXVBLU.js.map +1 -0
  77. package/dist/chunk-PUPZ4HME.js +165 -0
  78. package/dist/chunk-PUPZ4HME.js.map +1 -0
  79. package/dist/chunk-QFS52OK5.js +690 -0
  80. package/dist/chunk-QFS52OK5.js.map +1 -0
  81. package/dist/chunk-QNC6O3PG.js +45 -0
  82. package/dist/chunk-QNC6O3PG.js.map +1 -0
  83. package/dist/chunk-QUHOXWBK.js +82 -0
  84. package/dist/chunk-QUHOXWBK.js.map +1 -0
  85. package/dist/chunk-UIQGSTBJ.js +106 -0
  86. package/dist/chunk-UIQGSTBJ.js.map +1 -0
  87. package/dist/chunk-UJQKVP6V.js +193 -0
  88. package/dist/chunk-UJQKVP6V.js.map +1 -0
  89. package/dist/chunk-VVPGEAC6.js +11 -0
  90. package/dist/chunk-VVPGEAC6.js.map +1 -0
  91. package/dist/chunk-XA3T5KWA.js +58 -0
  92. package/dist/chunk-XA3T5KWA.js.map +1 -0
  93. package/dist/chunk-YSHJHSJM.js +19 -0
  94. package/dist/chunk-YSHJHSJM.js.map +1 -0
  95. package/dist/chunk-YVHOAVSM.js +182 -0
  96. package/dist/chunk-YVHOAVSM.js.map +1 -0
  97. package/dist/collapse.d.ts +16 -0
  98. package/dist/collapse.js +3 -0
  99. package/dist/collapse.js.map +1 -0
  100. package/dist/count-badge.d.ts +11 -0
  101. package/dist/count-badge.js +4 -0
  102. package/dist/count-badge.js.map +1 -0
  103. package/dist/date-field.d.ts +39 -0
  104. package/dist/date-field.js +8 -0
  105. package/dist/date-field.js.map +1 -0
  106. package/dist/date-range-field.d.ts +30 -0
  107. package/dist/date-range-field.js +8 -0
  108. package/dist/date-range-field.js.map +1 -0
  109. package/dist/datetime-field.d.ts +28 -0
  110. package/dist/datetime-field.js +10 -0
  111. package/dist/datetime-field.js.map +1 -0
  112. package/dist/dialog.d.ts +26 -0
  113. package/dist/dialog.js +7 -0
  114. package/dist/dialog.js.map +1 -0
  115. package/dist/index.d.ts +35 -0
  116. package/dist/index.js +40 -0
  117. package/dist/index.js.map +1 -0
  118. package/dist/motion-tokens.d.ts +29 -0
  119. package/dist/motion-tokens.js +3 -0
  120. package/dist/motion-tokens.js.map +1 -0
  121. package/dist/multi-select.d.ts +25 -0
  122. package/dist/multi-select.js +7 -0
  123. package/dist/multi-select.js.map +1 -0
  124. package/dist/number-field.d.ts +24 -0
  125. package/dist/number-field.js +4 -0
  126. package/dist/number-field.js.map +1 -0
  127. package/dist/otp-field.d.ts +20 -0
  128. package/dist/otp-field.js +3 -0
  129. package/dist/otp-field.js.map +1 -0
  130. package/dist/overlay.d.ts +31 -0
  131. package/dist/overlay.js +4 -0
  132. package/dist/overlay.js.map +1 -0
  133. package/dist/pagination.d.ts +24 -0
  134. package/dist/pagination.js +5 -0
  135. package/dist/pagination.js.map +1 -0
  136. package/dist/radio-group.d.ts +46 -0
  137. package/dist/radio-group.js +6 -0
  138. package/dist/radio-group.js.map +1 -0
  139. package/dist/select-core-SAyS-8w0.d.ts +16 -0
  140. package/dist/select.d.ts +27 -0
  141. package/dist/select.js +7 -0
  142. package/dist/select.js.map +1 -0
  143. package/dist/status-badge.d.ts +17 -0
  144. package/dist/status-badge.js +5 -0
  145. package/dist/status-badge.js.map +1 -0
  146. package/dist/table.d.ts +65 -0
  147. package/dist/table.js +5 -0
  148. package/dist/table.js.map +1 -0
  149. package/dist/tabs.d.ts +44 -0
  150. package/dist/tabs.js +5 -0
  151. package/dist/tabs.js.map +1 -0
  152. package/dist/tag.d.ts +28 -0
  153. package/dist/tag.js +5 -0
  154. package/dist/tag.js.map +1 -0
  155. package/dist/text-field.d.ts +30 -0
  156. package/dist/text-field.js +6 -0
  157. package/dist/text-field.js.map +1 -0
  158. package/dist/textarea.d.ts +33 -0
  159. package/dist/textarea.js +5 -0
  160. package/dist/textarea.js.map +1 -0
  161. package/dist/time-field.d.ts +27 -0
  162. package/dist/time-field.js +6 -0
  163. package/dist/time-field.js.map +1 -0
  164. package/dist/toast-store.d.ts +75 -0
  165. package/dist/toast-store.js +3 -0
  166. package/dist/toast-store.js.map +1 -0
  167. package/dist/toast.d.ts +3 -0
  168. package/dist/toast.js +6 -0
  169. package/dist/toast.js.map +1 -0
  170. package/dist/toggle-tag.d.ts +24 -0
  171. package/dist/toggle-tag.js +4 -0
  172. package/dist/toggle-tag.js.map +1 -0
  173. package/dist/toggle.d.ts +21 -0
  174. package/dist/toggle.js +3 -0
  175. package/dist/toggle.js.map +1 -0
  176. package/dist/tooltip.d.ts +27 -0
  177. package/dist/tooltip.js +4 -0
  178. package/dist/tooltip.js.map +1 -0
  179. package/llms.txt +165 -0
  180. package/package.json +205 -0
  181. package/src/components/alert/Alert.tsx +118 -0
  182. package/src/components/alert/alert.css +136 -0
  183. package/src/components/avatar/Avatar.tsx +128 -0
  184. package/src/components/avatar/AvatarGroup.tsx +50 -0
  185. package/src/components/avatar/avatar.css +200 -0
  186. package/src/components/badge/Badge.tsx +66 -0
  187. package/src/components/badge/CountBadge.tsx +46 -0
  188. package/src/components/badge/StatusBadge.tsx +132 -0
  189. package/src/components/badge/badge.css +243 -0
  190. package/src/components/button/Button.tsx +68 -0
  191. package/src/components/button/button.css +222 -0
  192. package/src/components/checkbox/Checkbox.tsx +90 -0
  193. package/src/components/checkbox/checkbox.css +179 -0
  194. package/src/components/date-picker/DateField.tsx +362 -0
  195. package/src/components/date-picker/DateRangeField.tsx +533 -0
  196. package/src/components/date-picker/DateTimeField.tsx +177 -0
  197. package/src/components/date-picker/TimeField.tsx +100 -0
  198. package/src/components/date-picker/date-picker.css +591 -0
  199. package/src/components/date-picker/date-utils.ts +55 -0
  200. package/src/components/date-picker/field-shell.tsx +78 -0
  201. package/src/components/date-picker/glide-pill.tsx +81 -0
  202. package/src/components/date-picker/time-core.tsx +305 -0
  203. package/src/components/dialog/Dialog.tsx +181 -0
  204. package/src/components/dialog/dialog.css +170 -0
  205. package/src/components/glass/glass.css +100 -0
  206. package/src/components/icon/Icon.tsx +76 -0
  207. package/src/components/icon/IconSlot.tsx +11 -0
  208. package/src/components/icon/icon.css +33 -0
  209. package/src/components/input/NumberField.tsx +117 -0
  210. package/src/components/input/OtpField.tsx +118 -0
  211. package/src/components/input/TextField.tsx +123 -0
  212. package/src/components/input/input.css +335 -0
  213. package/src/components/motion/Collapse.tsx +33 -0
  214. package/src/components/motion/collapse.css +41 -0
  215. package/src/components/overlay/Overlay.tsx +239 -0
  216. package/src/components/overlay/overlay-core.tsx +565 -0
  217. package/src/components/overlay/overlay.css +119 -0
  218. package/src/components/overlay/sheet-drag.tsx +146 -0
  219. package/src/components/pagination/Pagination.tsx +140 -0
  220. package/src/components/pagination/pagination.css +48 -0
  221. package/src/components/radio-group/RadioGroup.tsx +182 -0
  222. package/src/components/radio-group/radio-group.css +277 -0
  223. package/src/components/select/MultiSelect.tsx +251 -0
  224. package/src/components/select/Select.tsx +235 -0
  225. package/src/components/select/select-core.tsx +417 -0
  226. package/src/components/select/select.css +386 -0
  227. package/src/components/table/Table.tsx +433 -0
  228. package/src/components/table/table.css +348 -0
  229. package/src/components/tabs/Tabs.tsx +371 -0
  230. package/src/components/tabs/tabs.css +228 -0
  231. package/src/components/tag/Tag.tsx +145 -0
  232. package/src/components/tag/ToggleTag.tsx +125 -0
  233. package/src/components/tag/tag.css +248 -0
  234. package/src/components/textarea/Textarea.tsx +197 -0
  235. package/src/components/textarea/textarea.css +219 -0
  236. package/src/components/toast/Toast.tsx +349 -0
  237. package/src/components/toast/toast-store.ts +266 -0
  238. package/src/components/toast/toast.css +233 -0
  239. package/src/components/toggle/Toggle.tsx +94 -0
  240. package/src/components/toggle/toggle.css +152 -0
  241. package/src/components/tooltip/Tooltip.tsx +365 -0
  242. package/src/components/tooltip/tooltip.css +86 -0
  243. package/src/index.ts +42 -0
  244. package/src/styles.css +39 -0
  245. package/src/tokens/avatar.css +20 -0
  246. package/src/tokens/color.css +56 -0
  247. package/src/tokens/elevation.css +20 -0
  248. package/src/tokens/fonts.css +3 -0
  249. package/src/tokens/glass.css +21 -0
  250. package/src/tokens/icons.css +7 -0
  251. package/src/tokens/layers.css +6 -0
  252. package/src/tokens/motion-tokens.ts +72 -0
  253. package/src/tokens/motion.css +49 -0
  254. package/src/tokens/radius.css +11 -0
  255. package/src/tokens/semantic.css +75 -0
  256. package/src/tokens/spacing.css +26 -0
  257. package/src/tokens/typography.css +54 -0
@@ -0,0 +1,282 @@
1
+ 'use client';import { Icon } from './chunk-KBWNUUWM.js';
2
+ import { UIMotion } from './chunk-37O2ZXD6.js';
3
+ import * as React from 'react';
4
+ import { motion } from 'motion/react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var { useState, useRef, useEffect, useMemo } = React;
8
+ function tblCompare(a, b) {
9
+ if (a == null && b == null) return 0;
10
+ if (a == null) return 1;
11
+ if (b == null) return -1;
12
+ if (typeof a === "number" && typeof b === "number") return a - b;
13
+ return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
14
+ }
15
+ function TblCheckbox({ checked, indeterminate, ariaLabel, onChange, onClick }) {
16
+ const ref = useRef(null);
17
+ useEffect(() => {
18
+ if (ref.current) ref.current.indeterminate = !!indeterminate;
19
+ }, [indeterminate, checked]);
20
+ return /* @__PURE__ */ jsxs("label", { className: "cbx tbl__cbx", children: [
21
+ /* @__PURE__ */ jsx(
22
+ "input",
23
+ {
24
+ ref,
25
+ type: "checkbox",
26
+ className: "cbx__input",
27
+ checked,
28
+ "aria-label": ariaLabel,
29
+ onChange,
30
+ onClick
31
+ }
32
+ ),
33
+ /* @__PURE__ */ jsxs("span", { className: "cbx__box", "aria-hidden": "true", children: [
34
+ /* @__PURE__ */ jsx("svg", { className: "cbx__mark", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { className: "cbx__tick", d: "M3.5 8.5 L6.75 11.5 L12.5 4.75" }) }),
35
+ /* @__PURE__ */ jsx("span", { className: "cbx__dash" })
36
+ ] })
37
+ ] });
38
+ }
39
+ var TBL_DIGITS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
40
+ function TblOdo({ value }) {
41
+ const str = String(value);
42
+ return /* @__PURE__ */ jsx("span", { className: "odo", role: "text", "aria-label": str, children: str.split("").map(
43
+ (ch, i) => /\d/.test(ch) ? /* @__PURE__ */ jsx("span", { className: "odo__col", "aria-hidden": "true", children: /* @__PURE__ */ jsx("span", { className: "odo__strip odo__strip--" + ch, children: TBL_DIGITS.map((d) => /* @__PURE__ */ jsx("span", { children: d }, d)) }) }, i) : /* @__PURE__ */ jsx("span", { className: "odo__fixed", "aria-hidden": "true", children: ch }, i)
44
+ ) });
45
+ }
46
+ function Table({
47
+ columns = [],
48
+ rows = [],
49
+ rowKey = "id",
50
+ label,
51
+ selectable = false,
52
+ onSelectionChange,
53
+ bulkActions,
54
+ selectionLabel,
55
+ defaultSort = null,
56
+ onSortChange,
57
+ density = "cozy",
58
+ pinFirst = true,
59
+ loading = false,
60
+ empty,
61
+ footer,
62
+ onRowClick,
63
+ className = ""
64
+ }) {
65
+ const [sort, setSort] = useState(defaultSort);
66
+ const [selected, setSelected] = useState(() => /* @__PURE__ */ new Set());
67
+ const wrapRef = useRef(null);
68
+ const scrollRef = useRef(null);
69
+ const lastIdxRef = useRef(-1);
70
+ const shiftRef = useRef(false);
71
+ const lastCountRef = useRef(0);
72
+ const keyOf = (row) => row[rowKey];
73
+ const sortedRows = useMemo(() => {
74
+ if (!sort) return rows;
75
+ const col = columns.find((c) => c.key === sort.key);
76
+ if (!col) return rows;
77
+ const get = typeof col.sortBy === "function" ? col.sortBy : col.sortBy ? (r) => r[col.sortBy] : (r) => r[col.key];
78
+ const dir = sort.dir === "desc" ? -1 : 1;
79
+ return rows.slice().sort((a, b) => dir * tblCompare(get(a), get(b)));
80
+ }, [rows, columns, sort]);
81
+ function cycleSort(col) {
82
+ const next = sort && sort.key === col.key ? { key: col.key, dir: sort.dir === "asc" ? "desc" : "asc" } : { key: col.key, dir: "asc" };
83
+ setSort(next);
84
+ if (onSortChange) onSortChange(next);
85
+ }
86
+ const allSelected = sortedRows.length > 0 && sortedRows.every((r) => selected.has(keyOf(r)));
87
+ const someSelected = selected.size > 0 && !allSelected;
88
+ function commitSelection(next) {
89
+ setSelected(next);
90
+ if (onSelectionChange) onSelectionChange(Array.from(next));
91
+ }
92
+ function clearSelection() {
93
+ lastIdxRef.current = -1;
94
+ commitSelection(/* @__PURE__ */ new Set());
95
+ }
96
+ function toggleAll() {
97
+ const next = /* @__PURE__ */ new Set();
98
+ if (!allSelected) sortedRows.forEach((r) => next.add(keyOf(r)));
99
+ commitSelection(next);
100
+ }
101
+ function toggleRow(idx) {
102
+ const next = new Set(selected);
103
+ const on = !next.has(keyOf(sortedRows[idx]));
104
+ if (shiftRef.current && lastIdxRef.current >= 0 && lastIdxRef.current !== idx) {
105
+ const lo = Math.min(lastIdxRef.current, idx);
106
+ const hi = Math.max(lastIdxRef.current, idx);
107
+ for (let i = lo; i <= hi; i++) {
108
+ const k = keyOf(sortedRows[i]);
109
+ if (on) next.add(k);
110
+ else next.delete(k);
111
+ }
112
+ } else if (on) {
113
+ next.add(keyOf(sortedRows[idx]));
114
+ } else {
115
+ next.delete(keyOf(sortedRows[idx]));
116
+ }
117
+ lastIdxRef.current = idx;
118
+ shiftRef.current = false;
119
+ commitSelection(next);
120
+ }
121
+ useEffect(() => {
122
+ const el = scrollRef.current;
123
+ const w = wrapRef.current;
124
+ if (!el || !w) return;
125
+ const set = (attr, on) => {
126
+ if (on) w.setAttribute(attr, "");
127
+ else w.removeAttribute(attr);
128
+ };
129
+ const sync = () => {
130
+ set("data-scrolled", el.scrollTop > 0);
131
+ set("data-x-back", el.scrollLeft > 1);
132
+ set("data-x-more", el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
133
+ };
134
+ sync();
135
+ el.addEventListener("scroll", sync, { passive: true });
136
+ const ro = new ResizeObserver(sync);
137
+ ro.observe(el);
138
+ if (el.firstElementChild) ro.observe(el.firstElementChild);
139
+ return () => {
140
+ el.removeEventListener("scroll", sync);
141
+ ro.disconnect();
142
+ };
143
+ }, []);
144
+ function cellMods(col, i) {
145
+ const a = [];
146
+ if (col.align === "end") a.push("tbl__cell--end");
147
+ if (col.align === "center") a.push("tbl__cell--center");
148
+ if (col.grow) a.push("tbl__cell--grow");
149
+ if (col.hideBelow) a.push("tbl__cell--hide-" + col.hideBelow);
150
+ if (pinFirst && i === 0) {
151
+ a.push("tbl__cell--pin", "tbl__cell--pinEdge");
152
+ if (selectable) a.push("tbl__cell--pinOff");
153
+ }
154
+ return a;
155
+ }
156
+ const t = UIMotion.t;
157
+ const colCount = columns.length + (selectable ? 1 : 0);
158
+ const showEmpty = !loading && sortedRows.length === 0;
159
+ const checkCellCls = "tbl__cell--check" + (pinFirst ? " tbl__cell--pin" : "");
160
+ const bulkOpen = selectable && selected.size > 0;
161
+ if (selected.size > 0) lastCountRef.current = selected.size;
162
+ const rootCls = [
163
+ "tbl",
164
+ density === "compact" ? "tbl--compact" : "",
165
+ pinFirst ? "tbl--pin" : "",
166
+ loading ? "tbl--loading" : "",
167
+ onRowClick ? "tbl--clickable" : "",
168
+ className
169
+ ].filter(Boolean).join(" ");
170
+ return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: rootCls, children: [
171
+ selectable ? /* @__PURE__ */ jsxs(
172
+ "div",
173
+ {
174
+ className: "tbl__bulk",
175
+ "data-open": bulkOpen ? "" : void 0,
176
+ "aria-hidden": bulkOpen ? void 0 : true,
177
+ role: "toolbar",
178
+ "aria-label": "Selection actions",
179
+ children: [
180
+ /* @__PURE__ */ jsx(
181
+ TblCheckbox,
182
+ {
183
+ checked: allSelected,
184
+ indeterminate: someSelected,
185
+ ariaLabel: "Select all rows",
186
+ onChange: toggleAll
187
+ }
188
+ ),
189
+ /* @__PURE__ */ jsxs("span", { className: "tbl__bulkCount", "aria-live": "polite", "aria-atomic": "true", children: [
190
+ /* @__PURE__ */ jsx(TblOdo, { value: bulkOpen ? selected.size : lastCountRef.current }),
191
+ /* @__PURE__ */ jsx("span", { children: " selected" })
192
+ ] }),
193
+ /* @__PURE__ */ jsx("span", { className: "tbl__bulkSpacer" }),
194
+ bulkActions ? bulkActions(Array.from(selected), clearSelection) : null,
195
+ /* @__PURE__ */ jsx("button", { type: "button", className: "btn btn--ghost btn--sm", onClick: clearSelection, children: "Clear" })
196
+ ]
197
+ }
198
+ ) : null,
199
+ /* @__PURE__ */ jsxs("div", { className: "tbl__viewport", children: [
200
+ /* @__PURE__ */ jsx("div", { className: "tbl__scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs("table", { className: "tbl__table", "aria-label": label, "aria-busy": loading || void 0, children: [
201
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
202
+ selectable ? /* @__PURE__ */ jsx("th", { scope: "col", className: checkCellCls, children: /* @__PURE__ */ jsx(
203
+ TblCheckbox,
204
+ {
205
+ checked: allSelected,
206
+ indeterminate: someSelected,
207
+ ariaLabel: "Select all rows",
208
+ onChange: toggleAll
209
+ }
210
+ ) }) : null,
211
+ columns.map((c, i) => {
212
+ const active = sort && sort.key === c.key;
213
+ const cls = (c.sortable ? ["tbl__cell--sortable"] : []).concat(cellMods(c, i));
214
+ return /* @__PURE__ */ jsx(
215
+ "th",
216
+ {
217
+ scope: "col",
218
+ className: cls.join(" "),
219
+ "aria-sort": active ? sort.dir === "asc" ? "ascending" : "descending" : void 0,
220
+ children: c.sortable ? /* @__PURE__ */ jsxs("button", { type: "button", className: "tbl__sort", onClick: () => cycleSort(c), children: [
221
+ /* @__PURE__ */ jsx("span", { className: "tbl__sortLbl", children: c.label }),
222
+ /* @__PURE__ */ jsx(
223
+ "span",
224
+ {
225
+ className: "tbl__sortIcon" + (active ? " is-on" : "") + (active && sort.dir === "desc" ? " is-desc" : ""),
226
+ "aria-hidden": "true",
227
+ children: /* @__PURE__ */ jsx(Icon, { name: "arrow-up", size: "sm" })
228
+ }
229
+ )
230
+ ] }) : c.label != null ? /* @__PURE__ */ jsx("span", { className: "tbl__hLbl", children: c.label }) : null
231
+ },
232
+ c.key
233
+ );
234
+ })
235
+ ] }) }),
236
+ /* @__PURE__ */ jsx("tbody", { children: showEmpty ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: colCount, className: "tbl__emptyCell", children: empty != null ? empty : "Nothing to show" }) }) : sortedRows.map((row, idx) => {
237
+ const k = keyOf(row);
238
+ const isSel = selected.has(k);
239
+ return /* @__PURE__ */ jsxs(
240
+ motion.tr,
241
+ {
242
+ layout: "position",
243
+ transition: t.layout,
244
+ className: "tbl__row",
245
+ "data-selected": isSel ? "" : void 0,
246
+ onClick: onRowClick ? () => onRowClick(row) : void 0,
247
+ children: [
248
+ selectable ? /* @__PURE__ */ jsx("td", { className: checkCellCls, onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
249
+ TblCheckbox,
250
+ {
251
+ checked: isSel,
252
+ ariaLabel: selectionLabel ? selectionLabel(row) : "Select row",
253
+ onClick: (e) => {
254
+ shiftRef.current = e.shiftKey;
255
+ },
256
+ onChange: () => toggleRow(idx)
257
+ }
258
+ ) }) : null,
259
+ columns.map((c, i) => /* @__PURE__ */ jsx(
260
+ "td",
261
+ {
262
+ className: cellMods(c, i).concat(c.mono ? ["tbl__cell--mono"] : []).concat(c.strong ? ["tbl__cell--strong"] : []).join(" "),
263
+ children: c.render ? c.render(row) : row[c.key]
264
+ },
265
+ c.key
266
+ ))
267
+ ]
268
+ },
269
+ k
270
+ );
271
+ }) })
272
+ ] }) }),
273
+ /* @__PURE__ */ jsx("div", { className: "tbl__edge tbl__edge--l", "aria-hidden": "true" }),
274
+ /* @__PURE__ */ jsx("div", { className: "tbl__edge tbl__edge--r", "aria-hidden": "true" })
275
+ ] }),
276
+ footer ? /* @__PURE__ */ jsx("div", { className: "tbl__foot", children: footer }) : null
277
+ ] });
278
+ }
279
+
280
+ export { Table };
281
+ //# sourceMappingURL=chunk-EIMMDWIW.js.map
282
+ //# sourceMappingURL=chunk-EIMMDWIW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/table/Table.tsx"],"names":[],"mappings":"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","file":"chunk-EIMMDWIW.js","sourcesContent":["'use client';\n\n/* Table - opinionated data table: columns + rows in; owns sort, selection, sticky header, pinned column, motion. */\n\nimport * as React from 'react';\nimport { motion } from 'motion/react';\nimport { UIMotion } from '../../tokens/motion-tokens';\nimport { Icon } from '../icon/Icon';\n\nconst { useState, useRef, useEffect, useMemo } = React;\n\nexport type TableAlign = 'start' | 'end' | 'center';\nexport type TableHideBelow = 'sm' | 'md';\n\nexport interface TableColumn<Row = any> {\n /** Unique column id; also the default data accessor (row[key]). */\n key: string;\n label?: React.ReactNode;\n /** Cell + header alignment. Default 'start'. */\n align?: TableAlign;\n /** Mono + tabular numerals (timestamps, counts, IDs - section E). */\n mono?: boolean;\n /** Identity emphasis: strong text, medium weight. */\n strong?: boolean;\n /** The one greedy column - absorbs slack width. Others size to content. */\n grow?: boolean;\n /** Header becomes a sort control. Sort is local; asc - desc, no third state. */\n sortable?: boolean;\n /** Sort accessor: a row property name, or a function. Defaults to row[key]. */\n sortBy?: string | ((row: Row) => unknown);\n /** Collapse this column below a container breakpoint (30rem / 42rem). */\n hideBelow?: TableHideBelow;\n /** Custom cell renderer. Defaults to row[key]. */\n render?: (row: Row) => React.ReactNode;\n}\n\nexport interface TableSort {\n key: string;\n dir: 'asc' | 'desc';\n}\n\nexport interface TableProps<Row = any> {\n columns: TableColumn<Row>[];\n rows: Row[];\n /** Row identity property. Default 'id'. Must be unique and stable. */\n rowKey?: string;\n /** aria-label for the <table>. */\n label?: string;\n\n /** Checkbox column + bulk bar. Selection is a Set of row keys, owned here. */\n selectable?: boolean;\n onSelectionChange?: (keys: Array<string | number>) => void;\n /** Rendered in the bulk bar between the count and the built-in Clear. */\n bulkActions?: (keys: Array<string | number>, clear: () => void) => React.ReactNode;\n /** Per-row checkbox aria-label. Default 'Select row'. */\n selectionLabel?: (row: Row) => string;\n\n /** Initial sort; sorting stays local and uncontrolled after that. */\n defaultSort?: TableSort | null;\n /** Notification only - fires after the local sort updates. */\n onSortChange?: (sort: TableSort) => void;\n\n /** Row rhythm. Default 'cozy' (46px rows); 'compact' is 38px. */\n density?: 'cozy' | 'compact';\n /** Pin checkbox + first column under horizontal overflow. Default true. */\n pinFirst?: boolean;\n\n /** Rows recede and go inert (list-fetch convention). */\n loading?: boolean;\n /** Shown when rows is empty and not loading. Default 'Nothing to show'. */\n empty?: React.ReactNode;\n /** Footer strip - pagination, summaries. */\n footer?: React.ReactNode;\n\n /** Makes rows clickable (checkbox cell excluded). */\n onRowClick?: (row: Row) => void;\n /** Size the table here - the internal scroller absorbs the constraint. */\n className?: string;\n}\n\n/* numbers compare numerically, else natural-order text; null/undefined sink to the end */\nfunction tblCompare(a: unknown, b: unknown) {\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n if (typeof a === 'number' && typeof b === 'number') return a - b;\n return String(a).localeCompare(String(b), undefined, { numeric: true, sensitivity: 'base' });\n}\n\ninterface TblCheckboxProps {\n checked?: boolean;\n indeterminate?: boolean;\n ariaLabel?: string;\n onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onClick?: (e: React.MouseEvent<HTMLInputElement>) => void;\n}\n\n/* the Checkbox primitive's exact DOM minus label - its CSS state machine paints it */\nfunction TblCheckbox({ checked, indeterminate, ariaLabel, onChange, onClick }: TblCheckboxProps) {\n const ref = useRef<HTMLInputElement>(null);\n useEffect(() => {\n if (ref.current) ref.current.indeterminate = !!indeterminate;\n }, [indeterminate, checked]);\n return (\n <label className=\"cbx tbl__cbx\">\n <input\n ref={ref}\n type=\"checkbox\"\n className=\"cbx__input\"\n checked={checked}\n aria-label={ariaLabel}\n onChange={onChange}\n onClick={onClick}\n />\n <span className=\"cbx__box\" aria-hidden=\"true\">\n <svg className=\"cbx__mark\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path className=\"cbx__tick\" d=\"M3.5 8.5 L6.75 11.5 L12.5 4.75\"></path>\n </svg>\n <span className=\"cbx__dash\"></span>\n </span>\n </label>\n );\n}\n\n/* count odometer - reuses badge.css's .odo vocabulary: each digit clips a 0-9 strip */\nconst TBL_DIGITS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\nfunction TblOdo({ value }: { value: number }) {\n const str = String(value);\n return (\n <span className=\"odo\" role=\"text\" aria-label={str}>\n {str.split('').map((ch, i) =>\n /\\d/.test(ch) ? (\n <span key={i} className=\"odo__col\" aria-hidden=\"true\">\n <span className={'odo__strip odo__strip--' + ch}>\n {TBL_DIGITS.map((d) => (\n <span key={d}>{d}</span>\n ))}\n </span>\n </span>\n ) : (\n <span key={i} className=\"odo__fixed\" aria-hidden=\"true\">\n {ch}\n </span>\n ),\n )}\n </span>\n );\n}\n\nexport function Table<Row = any>({\n columns = [],\n rows = [],\n rowKey = 'id',\n label,\n selectable = false,\n onSelectionChange,\n bulkActions,\n selectionLabel,\n defaultSort = null,\n onSortChange,\n density = 'cozy',\n pinFirst = true,\n loading = false,\n empty,\n footer,\n onRowClick,\n className = '',\n}: TableProps<Row>) {\n const [sort, setSort] = useState<TableSort | null>(defaultSort);\n const [selected, setSelected] = useState<Set<string | number>>(() => new Set());\n const wrapRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const lastIdxRef = useRef(-1); // anchor for shift-click ranges\n const shiftRef = useRef(false); // shift held on the click that fired change\n const lastCountRef = useRef(0); // freezes the bulk count during its exit fade\n\n const keyOf = (row: Row): string | number => (row as Record<string, string | number>)[rowKey];\n\n const sortedRows = useMemo(() => {\n if (!sort) return rows;\n const col = columns.find((c) => c.key === sort.key);\n if (!col) return rows;\n const get =\n typeof col.sortBy === 'function'\n ? col.sortBy\n : col.sortBy\n ? (r: Row) => (r as Record<string, unknown>)[col.sortBy as string]\n : (r: Row) => (r as Record<string, unknown>)[col.key];\n const dir = sort.dir === 'desc' ? -1 : 1;\n return rows.slice().sort((a, b) => dir * tblCompare(get(a), get(b)));\n }, [rows, columns, sort]);\n\n function cycleSort(col: TableColumn<Row>) {\n const next: TableSort =\n sort && sort.key === col.key\n ? { key: col.key, dir: sort.dir === 'asc' ? 'desc' : 'asc' }\n : { key: col.key, dir: 'asc' };\n setSort(next);\n if (onSortChange) onSortChange(next);\n }\n\n const allSelected = sortedRows.length > 0 && sortedRows.every((r) => selected.has(keyOf(r)));\n const someSelected = selected.size > 0 && !allSelected;\n\n function commitSelection(next: Set<string | number>) {\n setSelected(next);\n if (onSelectionChange) onSelectionChange(Array.from(next));\n }\n function clearSelection() {\n lastIdxRef.current = -1;\n commitSelection(new Set());\n }\n function toggleAll() {\n const next = new Set<string | number>();\n if (!allSelected) sortedRows.forEach((r) => next.add(keyOf(r)));\n commitSelection(next);\n }\n function toggleRow(idx: number) {\n const next = new Set(selected);\n const on = !next.has(keyOf(sortedRows[idx]));\n if (shiftRef.current && lastIdxRef.current >= 0 && lastIdxRef.current !== idx) {\n const lo = Math.min(lastIdxRef.current, idx);\n const hi = Math.max(lastIdxRef.current, idx);\n for (let i = lo; i <= hi; i++) {\n const k = keyOf(sortedRows[i]);\n if (on) next.add(k);\n else next.delete(k);\n }\n } else if (on) {\n next.add(keyOf(sortedRows[idx]));\n } else {\n next.delete(keyOf(sortedRows[idx]));\n }\n lastIdxRef.current = idx;\n shiftRef.current = false;\n commitSelection(next);\n }\n\n /* live scroll - data attrs that CSS reads for header elevation, pin cast, edge fades */\n useEffect(() => {\n const el = scrollRef.current;\n const w = wrapRef.current;\n if (!el || !w) return;\n const set = (attr: string, on: boolean) => {\n if (on) w.setAttribute(attr, '');\n else w.removeAttribute(attr);\n };\n const sync = () => {\n set('data-scrolled', el.scrollTop > 0);\n set('data-x-back', el.scrollLeft > 1);\n set('data-x-more', el.scrollLeft + el.clientWidth < el.scrollWidth - 1);\n };\n sync();\n el.addEventListener('scroll', sync, { passive: true });\n const ro = new ResizeObserver(sync);\n ro.observe(el);\n if (el.firstElementChild) ro.observe(el.firstElementChild);\n return () => {\n el.removeEventListener('scroll', sync);\n ro.disconnect();\n };\n }, []);\n\n function cellMods(col: TableColumn<Row>, i: number) {\n const a: string[] = [];\n if (col.align === 'end') a.push('tbl__cell--end');\n if (col.align === 'center') a.push('tbl__cell--center');\n if (col.grow) a.push('tbl__cell--grow');\n if (col.hideBelow) a.push('tbl__cell--hide-' + col.hideBelow);\n if (pinFirst && i === 0) {\n a.push('tbl__cell--pin', 'tbl__cell--pinEdge');\n if (selectable) a.push('tbl__cell--pinOff');\n }\n return a;\n }\n\n const t = UIMotion.t;\n const colCount = columns.length + (selectable ? 1 : 0);\n const showEmpty = !loading && sortedRows.length === 0;\n const checkCellCls = 'tbl__cell--check' + (pinFirst ? ' tbl__cell--pin' : '');\n\n /* one persistent node, CSS open/close - AnimatePresence ghosted here; count frozen so exit doesn't roll to 0 */\n const bulkOpen = selectable && selected.size > 0;\n if (selected.size > 0) lastCountRef.current = selected.size;\n\n const rootCls = [\n 'tbl',\n density === 'compact' ? 'tbl--compact' : '',\n pinFirst ? 'tbl--pin' : '',\n loading ? 'tbl--loading' : '',\n onRowClick ? 'tbl--clickable' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div ref={wrapRef} className={rootCls}>\n {selectable ? (\n <div\n className=\"tbl__bulk\"\n data-open={bulkOpen ? '' : undefined}\n aria-hidden={bulkOpen ? undefined : true}\n role=\"toolbar\"\n aria-label=\"Selection actions\"\n >\n <TblCheckbox\n checked={allSelected}\n indeterminate={someSelected}\n ariaLabel=\"Select all rows\"\n onChange={toggleAll}\n />\n <span className=\"tbl__bulkCount\" aria-live=\"polite\" aria-atomic=\"true\">\n <TblOdo value={bulkOpen ? selected.size : lastCountRef.current} />\n <span> selected</span>\n </span>\n <span className=\"tbl__bulkSpacer\"></span>\n {bulkActions ? bulkActions(Array.from(selected), clearSelection) : null}\n <button type=\"button\" className=\"btn btn--ghost btn--sm\" onClick={clearSelection}>\n Clear\n </button>\n </div>\n ) : null}\n\n <div className=\"tbl__viewport\">\n <div className=\"tbl__scroll\" ref={scrollRef}>\n <table className=\"tbl__table\" aria-label={label} aria-busy={loading || undefined}>\n <thead>\n <tr>\n {selectable ? (\n <th scope=\"col\" className={checkCellCls}>\n <TblCheckbox\n checked={allSelected}\n indeterminate={someSelected}\n ariaLabel=\"Select all rows\"\n onChange={toggleAll}\n />\n </th>\n ) : null}\n {columns.map((c, i) => {\n const active = sort && sort.key === c.key;\n const cls = (c.sortable ? ['tbl__cell--sortable'] : []).concat(cellMods(c, i));\n return (\n <th\n key={c.key}\n scope=\"col\"\n className={cls.join(' ')}\n aria-sort={\n active ? (sort.dir === 'asc' ? 'ascending' : 'descending') : undefined\n }\n >\n {c.sortable ? (\n <button type=\"button\" className=\"tbl__sort\" onClick={() => cycleSort(c)}>\n <span className=\"tbl__sortLbl\">{c.label}</span>\n <span\n className={\n 'tbl__sortIcon' +\n (active ? ' is-on' : '') +\n (active && sort.dir === 'desc' ? ' is-desc' : '')\n }\n aria-hidden=\"true\"\n >\n <Icon name=\"arrow-up\" size=\"sm\" />\n </span>\n </button>\n ) : c.label != null ? (\n <span className=\"tbl__hLbl\">{c.label}</span>\n ) : null}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {showEmpty ? (\n <tr>\n <td colSpan={colCount} className=\"tbl__emptyCell\">\n {empty != null ? empty : 'Nothing to show'}\n </td>\n </tr>\n ) : (\n sortedRows.map((row, idx) => {\n const k = keyOf(row);\n const isSel = selected.has(k);\n return (\n <motion.tr\n key={k}\n layout=\"position\"\n transition={t.layout}\n className=\"tbl__row\"\n data-selected={isSel ? '' : undefined}\n onClick={onRowClick ? () => onRowClick(row) : undefined}\n >\n {selectable ? (\n <td className={checkCellCls} onClick={(e) => e.stopPropagation()}>\n <TblCheckbox\n checked={isSel}\n ariaLabel={selectionLabel ? selectionLabel(row) : 'Select row'}\n onClick={(e) => {\n shiftRef.current = e.shiftKey;\n }}\n onChange={() => toggleRow(idx)}\n />\n </td>\n ) : null}\n {columns.map((c, i) => (\n <td\n key={c.key}\n className={cellMods(c, i)\n .concat(c.mono ? ['tbl__cell--mono'] : [])\n .concat(c.strong ? ['tbl__cell--strong'] : [])\n .join(' ')}\n >\n {c.render\n ? c.render(row)\n : (row as Record<string, React.ReactNode>)[c.key]}\n </td>\n ))}\n </motion.tr>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n <div className=\"tbl__edge tbl__edge--l\" aria-hidden=\"true\"></div>\n <div className=\"tbl__edge tbl__edge--r\" aria-hidden=\"true\"></div>\n </div>\n\n {footer ? <div className=\"tbl__foot\">{footer}</div> : null}\n </div>\n );\n}\n"]}
@@ -0,0 +1,230 @@
1
+ 'use client';import { IconSlot } from './chunk-VVPGEAC6.js';
2
+ import { UIMotion } from './chunk-37O2ZXD6.js';
3
+ import * as React from 'react';
4
+ import { motion, animate } from 'motion/react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ var TabsSM = UIMotion;
8
+ var TABS_EDGE_PAD = 24;
9
+ var TABS_ENTER_X = 10;
10
+ function Tabs({
11
+ items = [],
12
+ value,
13
+ onChange,
14
+ name,
15
+ label,
16
+ className = "",
17
+ ...rest
18
+ }) {
19
+ const autoId = React.useId();
20
+ const base = name || autoId;
21
+ const listRef = React.useRef(null);
22
+ const inkRef = React.useRef(null);
23
+ const tabRefs = React.useRef({});
24
+ const animRef = React.useRef(null);
25
+ const placedRef = React.useRef(false);
26
+ const valueRef = React.useRef(value);
27
+ valueRef.current = value;
28
+ const [hovered, setHovered] = React.useState(null);
29
+ const [inList, setInList] = React.useState(false);
30
+ const wasInRef = React.useRef(false);
31
+ React.useEffect(() => {
32
+ wasInRef.current = inList;
33
+ });
34
+ const place = (animated) => {
35
+ const list = listRef.current, ink = inkRef.current;
36
+ const el = valueRef.current != null ? tabRefs.current[valueRef.current] : null;
37
+ if (!list || !ink) return;
38
+ if (animRef.current) animRef.current.stop();
39
+ if (!el) {
40
+ ink.style.opacity = "0";
41
+ placedRef.current = false;
42
+ return;
43
+ }
44
+ const next = { x: el.offsetLeft, w: el.offsetWidth };
45
+ ink.style.opacity = "1";
46
+ if (!animated || !placedRef.current || TabsSM.reduced) {
47
+ ink.style.transform = "translateX(" + next.x + "px)";
48
+ ink.style.width = next.w + "px";
49
+ } else {
50
+ const lr = list.getBoundingClientRect();
51
+ const ir = ink.getBoundingClientRect();
52
+ const cur = { x: ir.left - lr.left + list.scrollLeft, w: ir.width };
53
+ if (Math.abs(cur.x - next.x) > 0.5 || Math.abs(cur.w - next.w) > 0.5) {
54
+ const dir = next.x + next.w / 2 >= cur.x + cur.w / 2 ? 1 : -1;
55
+ const span = dir === 1 ? next.x + next.w - cur.x : cur.x + cur.w - next.x;
56
+ const kf = dir === 1 ? {
57
+ x: [cur.x, cur.x, next.x],
58
+ width: [cur.w, span, next.w]
59
+ } : {
60
+ x: [cur.x, next.x, next.x],
61
+ width: [cur.w, span, next.w]
62
+ };
63
+ animRef.current = animate(ink, kf, {
64
+ duration: TabsSM.dur.slow,
65
+ times: [0, 0.55, 1],
66
+ ease: [TabsSM.ease.standard, TabsSM.ease.entrance]
67
+ });
68
+ }
69
+ }
70
+ placedRef.current = true;
71
+ };
72
+ const updateEdges = () => {
73
+ const l = listRef.current;
74
+ if (!l) return;
75
+ const max = l.scrollWidth - l.clientWidth;
76
+ l.dataset.fade = ((l.scrollLeft > 1 ? "start " : "") + (l.scrollLeft < max - 1 ? "end" : "")).trim();
77
+ };
78
+ React.useLayoutEffect(() => {
79
+ place(true);
80
+ const l = listRef.current, el = value != null ? tabRefs.current[value] : null;
81
+ if (l && el && l.scrollWidth > l.clientWidth) {
82
+ const behavior = TabsSM.reduced ? "auto" : "smooth";
83
+ if (el.offsetLeft < l.scrollLeft + TABS_EDGE_PAD) {
84
+ l.scrollTo({ left: el.offsetLeft - TABS_EDGE_PAD, behavior });
85
+ } else if (el.offsetLeft + el.offsetWidth > l.scrollLeft + l.clientWidth - TABS_EDGE_PAD) {
86
+ l.scrollTo({
87
+ left: el.offsetLeft + el.offsetWidth - l.clientWidth + TABS_EDGE_PAD,
88
+ behavior
89
+ });
90
+ }
91
+ }
92
+ }, [value]);
93
+ React.useLayoutEffect(() => {
94
+ const ro = new ResizeObserver(() => {
95
+ place(false);
96
+ updateEdges();
97
+ });
98
+ if (listRef.current) ro.observe(listRef.current);
99
+ Object.values(tabRefs.current).forEach((el) => el && ro.observe(el));
100
+ updateEdges();
101
+ return () => ro.disconnect();
102
+ }, [items.length]);
103
+ const select = (v) => {
104
+ if (v === value || !onChange) return;
105
+ const idx = (x) => items.findIndex((i) => i.value === x);
106
+ onChange(v, idx(v) >= idx(value) ? 1 : -1);
107
+ };
108
+ const onKeyDown = (e) => {
109
+ const enabled = items.filter((i) => !i.disabled);
110
+ if (!enabled.length) return;
111
+ let next = null;
112
+ if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
113
+ const step = e.key === "ArrowRight" ? 1 : -1;
114
+ const i = enabled.findIndex((it) => it.value === value);
115
+ next = enabled[(i + step + enabled.length) % enabled.length];
116
+ } else if (e.key === "Home") {
117
+ next = enabled[0];
118
+ } else if (e.key === "End") {
119
+ next = enabled[enabled.length - 1];
120
+ }
121
+ if (!next) return;
122
+ e.preventDefault();
123
+ select(next.value);
124
+ const el = tabRefs.current[next.value];
125
+ if (el) el.focus();
126
+ };
127
+ const focusValue = items.some((i) => i.value === value && !i.disabled) ? value : (items.find((i) => !i.disabled) || {}).value;
128
+ return /* @__PURE__ */ jsx("div", { className: ("tabs " + className).trim(), ...rest, children: /* @__PURE__ */ jsxs(
129
+ motion.div,
130
+ {
131
+ className: "tabs__list",
132
+ role: "tablist",
133
+ "aria-label": label,
134
+ ref: listRef,
135
+ layoutScroll: true,
136
+ onScroll: updateEdges,
137
+ onKeyDown,
138
+ onPointerLeave: () => setInList(false),
139
+ children: [
140
+ items.map((it) => {
141
+ const selected = it.value === value;
142
+ return /* @__PURE__ */ jsx(
143
+ "button",
144
+ {
145
+ type: "button",
146
+ role: "tab",
147
+ id: base + "-tab-" + it.value,
148
+ "aria-selected": selected,
149
+ "aria-controls": name ? name + "-panel-" + it.value : void 0,
150
+ tabIndex: it.value === focusValue ? 0 : -1,
151
+ disabled: it.disabled,
152
+ className: "tab" + (selected ? " is-selected" : ""),
153
+ ref: (el) => {
154
+ tabRefs.current[it.value] = el;
155
+ },
156
+ onClick: () => select(it.value),
157
+ onPointerEnter: it.disabled ? void 0 : () => {
158
+ setHovered(it.value);
159
+ setInList(true);
160
+ },
161
+ children: /* @__PURE__ */ jsxs("span", { className: "tab__pad", children: [
162
+ hovered === it.value && /* @__PURE__ */ jsx(
163
+ motion.span,
164
+ {
165
+ className: "tab__hover",
166
+ layoutId: base + "-hover",
167
+ "aria-hidden": "true",
168
+ initial: wasInRef.current ? false : { opacity: 0 },
169
+ animate: { opacity: inList ? 1 : 0 },
170
+ transition: {
171
+ /* glide: slow travel, soft-start (ease.standard) - for
172
+ continuous hover sweeps the early gentle pickup reads
173
+ better than the fuller in-out (--ease-glide). Fresh
174
+ entry snaps in place instead of gliding from a stale
175
+ position. */
176
+ layout: wasInRef.current ? { duration: TabsSM.dur.slow, ease: TabsSM.ease.standard } : { duration: 0 },
177
+ opacity: inList ? { duration: TabsSM.dur.fast, ease: TabsSM.ease.standard } : { duration: TabsSM.dur.fast, ease: TabsSM.ease.exit }
178
+ },
179
+ onAnimationComplete: () => {
180
+ if (!inList) setHovered(null);
181
+ }
182
+ },
183
+ "pill"
184
+ ),
185
+ it.icon && /* @__PURE__ */ jsx(IconSlot, { size: "sm", children: it.icon }),
186
+ /* @__PURE__ */ jsx("span", { className: "tab__label", children: it.label }),
187
+ it.count != null && /* @__PURE__ */ jsx("span", { className: "tab__count", children: it.count })
188
+ ] })
189
+ },
190
+ it.value
191
+ );
192
+ }),
193
+ /* @__PURE__ */ jsx("span", { className: "tabs__ink", ref: inkRef, "aria-hidden": "true" }, "ink")
194
+ ]
195
+ }
196
+ ) });
197
+ }
198
+ function TabPanel({ tab, name, dir = 0, className = "", children, ...rest }) {
199
+ const innerRef = React.useRef(null);
200
+ const firstRef = React.useRef(true);
201
+ React.useLayoutEffect(() => {
202
+ if (firstRef.current) {
203
+ firstRef.current = false;
204
+ return;
205
+ }
206
+ if (TabsSM.reduced) return;
207
+ const anim = animate(
208
+ innerRef.current,
209
+ { opacity: [0, 1], x: [dir * TABS_ENTER_X, 0] },
210
+ TabsSM.t.enter
211
+ );
212
+ return () => anim.stop();
213
+ }, [tab]);
214
+ return /* @__PURE__ */ jsx(
215
+ "div",
216
+ {
217
+ role: "tabpanel",
218
+ tabIndex: 0,
219
+ id: name ? name + "-panel-" + tab : void 0,
220
+ "aria-labelledby": name ? name + "-tab-" + tab : void 0,
221
+ className: ("tab-panel " + className).trim(),
222
+ ...rest,
223
+ children: /* @__PURE__ */ jsx("div", { className: "tab-panel__inner", ref: innerRef, children })
224
+ }
225
+ );
226
+ }
227
+
228
+ export { TabPanel, Tabs };
229
+ //# sourceMappingURL=chunk-EZ2CWTBE.js.map
230
+ //# sourceMappingURL=chunk-EZ2CWTBE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/tabs/Tabs.tsx"],"names":["tabsAnimate","tabsMotion"],"mappings":"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","file":"chunk-EZ2CWTBE.js","sourcesContent":["'use client';\n\n// Tabs.tsx - Tabs: line tabs for view switching.\n// Sits on a hairline baseline; a single accent ink marks the active view.\n// `TabPanel` is the matching content wrapper (aria wiring + directional\n// entrance). All styling lives in tabs.css; this file composes class names\n// and drives the ink.\n//\n// TWO MOTIONS, BOTH IMPLICIT - consumers configure neither.\n//\n// 1 - \"the ink reaches, then releases\" (selection).\n// One persistent ink node. On selection, the edge facing the destination\n// travels FIRST (the ink stretches across the gap, ease-standard), then the\n// trailing edge releases and settles (ease-entrance). Implemented as Motion\n// keyframes on x (transform) + width (measured px - measured px - the\n// surfaced section C morph exception, Tooltip precedent: the destination width is\n// unknowable to transforms, and scaleX would distort the radius). Interrupts\n// are honest: a new travel starts from the ink's LIVE rect, not the last\n// target. Reduced motion: tokens collapse durations, and placement falls\n// back to an instant set.\n//\n// 2 - the gliding hover. ONE shared pill instead of per-tab hover\n// backgrounds: it fades in under the first tab the pointer touches, GLIDES -\n// morphing position and width - as the pointer moves along the row, and\n// fades out when it leaves. Declarative: a `layoutId` node conditionally\n// rendered inside the hovered tab - Motion's FLIP owns the travel. Tab-to-tab\n// is an ATOMIC remount: old pill out + new pill in within one commit, so\n// exactly one node carries the layoutId per frame. (AnimatePresence is\n// deliberately NOT used here: it holds the exiting pill for a tick, two\n// same-layoutId nodes overlap, and the handoff can hide both for a frame -\n// an intermittent white flicker.) True leave keeps the pill MOUNTED in the\n// last tab and fades it via `animate`; the engine's completion callback\n// unmounts it - no hand-rolled exit timer. Hover state is per-tab\n// pointerenter (disabled buttons don't fire it, so the pill holds - same for\n// the gaps); only pointerleave of the LIST starts the fade-out.\n//\n// Keyboard (WAI-ARIA tabs, automatic activation): roving tabindex; left/right arrows cycle\n// (wrapping, skipping disabled), Home/End jump; selection follows focus.\n// Overflow is honest: the row scrolls, clipped edges fade (data-fade set from\n// scroll geometry), and the selected tab is kept in view.\n\nimport * as React from 'react';\nimport { motion as tabsMotion, animate as tabsAnimate } from 'motion/react';\nimport { UIMotion } from '../../tokens/motion-tokens';\nimport { IconSlot } from '../icon/IconSlot';\n\nconst TabsSM = UIMotion;\n\n/** One tab in the row. */\nexport interface TabItem {\n /** Stable identity - also used in the tab/panel id pair. */\n value: string;\n label: React.ReactNode;\n /** Leading icon - your own node. */\n icon?: React.ReactNode;\n /** Rendered mono + tabular. Pass a number or a preformatted string. */\n count?: number | string;\n disabled?: boolean;\n}\n\nexport interface TabsProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n items: TabItem[];\n /** Controlled - the value of the active tab (null/undefined hides the ink). */\n value: string | null | undefined;\n /**\n * Fires on click and on arrow-key travel (automatic activation).\n * `dir` is the direction of travel (+1 right / -1 left) - hand it to\n * TabPanel so content enters from the side the user moved toward.\n */\n onChange?: (value: string, dir: 1 | -1) => void;\n /**\n * Shared id prefix wiring tab and panel aria. Give Tabs and its TabPanel the\n * same `name`; omit it when the tabs have no managed panel.\n */\n name?: string;\n /** aria-label for the tablist (e.g. \"Section views\"). */\n label?: string;\n}\n\n/* Scroll-geometry constants (px) - measurement math, not styling.\n EDGE_PAD ~ --space-6: breathing room kept between the selected tab and a\n faded edge. ENTER_X: TabPanel's entrance travel (bespoke motion geometry,\n like Tooltip's offsets - there is no spatial motion token). */\nconst TABS_EDGE_PAD = 24;\nconst TABS_ENTER_X = 10;\n\nexport function Tabs({\n items = [],\n value,\n onChange,\n name,\n label,\n className = '',\n ...rest\n}: TabsProps) {\n const autoId = React.useId();\n const base = name || autoId;\n\n const listRef = React.useRef<HTMLDivElement>(null);\n const inkRef = React.useRef<HTMLSpanElement>(null);\n const tabRefs = React.useRef<Record<string, HTMLButtonElement | null>>({});\n const animRef = React.useRef<ReturnType<typeof tabsAnimate> | null>(null);\n const placedRef = React.useRef(false);\n const valueRef = React.useRef(value);\n valueRef.current = value;\n\n /* The gliding hover - the only state here. `hovered` is STICKY (the last\n tab the pointer touched; it outlives the pointer so the leave-fade plays\n in place), `inList` is whether the pointer is currently in the row.\n wasInRef (one render behind) picks the entrance: fresh entry = fade in\n where it lands (layout snap, no glide from a stale spot); tab-to-tab =\n opaque glide. */\n const [hovered, setHovered] = React.useState<string | null>(null);\n const [inList, setInList] = React.useState(false);\n const wasInRef = React.useRef(false);\n React.useEffect(() => {\n wasInRef.current = inList;\n });\n\n /* Place the ink under the active tab - instantly (mount, resize, reduced\n motion) or as the reach-then-release travel. Coordinates are offsetLeft\n space (layout, scroll-independent) since the ink lives in the scroller. */\n const place = (animated: boolean) => {\n const list = listRef.current,\n ink = inkRef.current;\n const el = valueRef.current != null ? tabRefs.current[valueRef.current] : null;\n if (!list || !ink) return;\n if (animRef.current) animRef.current.stop();\n if (!el) {\n ink.style.opacity = '0';\n placedRef.current = false;\n return;\n }\n const next = { x: el.offsetLeft, w: el.offsetWidth };\n ink.style.opacity = '1';\n\n if (!animated || !placedRef.current || TabsSM.reduced) {\n ink.style.transform = 'translateX(' + next.x + 'px)';\n ink.style.width = next.w + 'px';\n } else {\n /* start from the LIVE rect so an interrupted travel never jumps back */\n const lr = list.getBoundingClientRect();\n const ir = ink.getBoundingClientRect();\n const cur = { x: ir.left - lr.left + list.scrollLeft, w: ir.width };\n if (Math.abs(cur.x - next.x) > 0.5 || Math.abs(cur.w - next.w) > 0.5) {\n const dir = next.x + next.w / 2 >= cur.x + cur.w / 2 ? 1 : -1;\n const span = dir === 1 ? next.x + next.w - cur.x : cur.x + cur.w - next.x;\n const kf =\n dir === 1\n ? {\n x: [cur.x, cur.x, next.x],\n width: [cur.w, span, next.w],\n } /* right edge reaches, left releases */\n : {\n x: [cur.x, next.x, next.x],\n width: [cur.w, span, next.w],\n }; /* left edge reaches, right releases */\n animRef.current = tabsAnimate(ink, kf, {\n duration: TabsSM.dur.slow,\n times: [0, 0.55, 1],\n ease: [TabsSM.ease.standard, TabsSM.ease.entrance],\n });\n }\n }\n placedRef.current = true;\n };\n\n /* Edge fades: pure scroll geometry - data-fade=\"start end\" on the list. */\n const updateEdges = () => {\n const l = listRef.current;\n if (!l) return;\n const max = l.scrollWidth - l.clientWidth;\n l.dataset.fade = (\n (l.scrollLeft > 1 ? 'start ' : '') + (l.scrollLeft < max - 1 ? 'end' : '')\n ).trim();\n };\n\n /* Selection drives the travel + keeps the active tab clear of a faded edge. */\n React.useLayoutEffect(() => {\n place(true);\n const l = listRef.current,\n el = value != null ? tabRefs.current[value] : null;\n if (l && el && l.scrollWidth > l.clientWidth) {\n const behavior: ScrollBehavior = TabsSM.reduced ? 'auto' : 'smooth';\n if (el.offsetLeft < l.scrollLeft + TABS_EDGE_PAD) {\n l.scrollTo({ left: el.offsetLeft - TABS_EDGE_PAD, behavior });\n } else if (el.offsetLeft + el.offsetWidth > l.scrollLeft + l.clientWidth - TABS_EDGE_PAD) {\n l.scrollTo({\n left: el.offsetLeft + el.offsetWidth - l.clientWidth + TABS_EDGE_PAD,\n behavior,\n });\n }\n }\n }, [value]);\n\n /* Any size change (fonts arriving, container resize, label edits) re-seats\n the ink instantly and re-derives the edge fades. */\n React.useLayoutEffect(() => {\n const ro = new ResizeObserver(() => {\n place(false);\n updateEdges();\n });\n if (listRef.current) ro.observe(listRef.current);\n Object.values(tabRefs.current).forEach((el) => el && ro.observe(el));\n updateEdges();\n return () => ro.disconnect();\n }, [items.length]);\n\n const select = (v: string) => {\n if (v === value || !onChange) return;\n const idx = (x: string | null | undefined) => items.findIndex((i) => i.value === x);\n onChange(v, idx(v) >= idx(value) ? 1 : -1);\n };\n\n const onKeyDown = (e: React.KeyboardEvent) => {\n const enabled = items.filter((i) => !i.disabled);\n if (!enabled.length) return;\n let next: TabItem | null = null;\n if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {\n const step = e.key === 'ArrowRight' ? 1 : -1;\n const i = enabled.findIndex((it) => it.value === value);\n next = enabled[(i + step + enabled.length) % enabled.length];\n } else if (e.key === 'Home') {\n next = enabled[0];\n } else if (e.key === 'End') {\n next = enabled[enabled.length - 1];\n }\n if (!next) return;\n e.preventDefault();\n select(next.value);\n const el = tabRefs.current[next.value];\n if (el) el.focus();\n };\n\n /* Roving tabindex - the selected tab is the stop; if nothing is selected\n yet, the first enabled tab takes it so the list stays reachable. */\n const focusValue = items.some((i) => i.value === value && !i.disabled)\n ? value\n : (items.find((i) => !i.disabled) || ({} as Partial<TabItem>)).value;\n\n return (\n <div className={('tabs ' + className).trim()} {...rest}>\n {/* layoutScroll: the pill FLIPs correctly even while this row is being\n scrolled. NOTE: framer-motion@12.40.0's UMD dev build prints a\n spurious React key warning when any motion component mounts -\n pre-existing and system-wide (stable Toggle prints the same one at\n load), harmless, dev-only. Not caused by, or fixable in, this code. */}\n <tabsMotion.div\n className=\"tabs__list\"\n role=\"tablist\"\n aria-label={label}\n ref={listRef}\n layoutScroll\n onScroll={updateEdges}\n onKeyDown={onKeyDown}\n onPointerLeave={() => setInList(false)}\n >\n {items.map((it) => {\n const selected = it.value === value;\n return (\n <button\n key={it.value}\n type=\"button\"\n role=\"tab\"\n id={base + '-tab-' + it.value}\n aria-selected={selected}\n aria-controls={name ? name + '-panel-' + it.value : undefined}\n tabIndex={it.value === focusValue ? 0 : -1}\n disabled={it.disabled}\n className={'tab' + (selected ? ' is-selected' : '')}\n ref={(el) => {\n tabRefs.current[it.value] = el;\n }}\n onClick={() => select(it.value)}\n onPointerEnter={\n it.disabled\n ? undefined\n : () => {\n setHovered(it.value);\n setInList(true);\n }\n }\n >\n <span className=\"tab__pad\">\n {hovered === it.value && (\n <tabsMotion.span\n key=\"pill\"\n className=\"tab__hover\"\n layoutId={base + '-hover'}\n aria-hidden=\"true\"\n initial={wasInRef.current ? false : { opacity: 0 }}\n animate={{ opacity: inList ? 1 : 0 }}\n transition={{\n /* glide: slow travel, soft-start (ease.standard) - for\n continuous hover sweeps the early gentle pickup reads\n better than the fuller in-out (--ease-glide). Fresh\n entry snaps in place instead of gliding from a stale\n position. */\n layout: wasInRef.current\n ? { duration: TabsSM.dur.slow, ease: TabsSM.ease.standard }\n : { duration: 0 },\n opacity: inList\n ? { duration: TabsSM.dur.fast, ease: TabsSM.ease.standard }\n : { duration: TabsSM.dur.fast, ease: TabsSM.ease.exit },\n }}\n onAnimationComplete={() => {\n if (!inList) setHovered(null);\n }}\n ></tabsMotion.span>\n )}\n {it.icon && <IconSlot size=\"sm\">{it.icon}</IconSlot>}\n <span className=\"tab__label\">{it.label}</span>\n {it.count != null && <span className=\"tab__count\">{it.count}</span>}\n </span>\n </button>\n );\n })}\n <span className=\"tabs__ink\" key=\"ink\" ref={inkRef} aria-hidden=\"true\"></span>\n </tabsMotion.div>\n </div>\n );\n}\n\nexport interface TabPanelProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'dir'> {\n /** The active tab's value - changing it cuts to the new content. */\n tab: string;\n /** Same `name` as the paired Tabs - wires role/id/aria-labelledby. */\n name?: string;\n /** Direction of travel from Tabs' onChange; 0 = plain fade. */\n dir?: -1 | 0 | 1;\n children?: React.ReactNode;\n}\n\n// TabPanel - the content side of a Tabs pair. The ROOT is static chrome:\n// whatever border/padding/background the consumer styles it with never\n// moves. Switching `tab` cuts to the new content, then ONLY the inner\n// content node enters from the direction of travel (pass Tabs' onChange dir\n// through) via an imperative Motion tween on one persistent node - same\n// resolved pattern as Tooltip's content: cut + entrance, no exit\n// choreography, and no remount, so first paint is naturally static.\nexport function TabPanel({ tab, name, dir = 0, className = '', children, ...rest }: TabPanelProps) {\n const innerRef = React.useRef<HTMLDivElement>(null);\n const firstRef = React.useRef(true);\n React.useLayoutEffect(() => {\n if (firstRef.current) {\n firstRef.current = false;\n return;\n }\n if (TabsSM.reduced) return;\n const anim = tabsAnimate(\n innerRef.current,\n { opacity: [0, 1], x: [dir * TABS_ENTER_X, 0] },\n TabsSM.t.enter,\n );\n return () => anim.stop();\n }, [tab]);\n return (\n <div\n role=\"tabpanel\"\n tabIndex={0}\n id={name ? name + '-panel-' + tab : undefined}\n aria-labelledby={name ? name + '-tab-' + tab : undefined}\n className={('tab-panel ' + className).trim()}\n {...rest}\n >\n <div className=\"tab-panel__inner\" ref={innerRef}>\n {children}\n </div>\n </div>\n );\n}\n"]}