@ansh-ui/react 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-5CFQFMP5.js +178 -0
  3. package/dist/chunk-5CFQFMP5.js.map +1 -0
  4. package/dist/chunk-6VRF7X5C.cjs +164 -0
  5. package/dist/chunk-6VRF7X5C.cjs.map +1 -0
  6. package/dist/chunk-AVPEA5PB.cjs +718 -0
  7. package/dist/chunk-AVPEA5PB.cjs.map +1 -0
  8. package/dist/chunk-C32LKF23.cjs +198 -0
  9. package/dist/chunk-C32LKF23.cjs.map +1 -0
  10. package/dist/chunk-C5JG6TMM.cjs +1200 -0
  11. package/dist/chunk-C5JG6TMM.cjs.map +1 -0
  12. package/dist/chunk-DATBU46V.cjs +614 -0
  13. package/dist/chunk-DATBU46V.cjs.map +1 -0
  14. package/dist/chunk-EGG4CP7C.js +320 -0
  15. package/dist/chunk-EGG4CP7C.js.map +1 -0
  16. package/dist/chunk-H34OXXJU.js +55 -0
  17. package/dist/chunk-H34OXXJU.js.map +1 -0
  18. package/dist/chunk-HO2YSF5O.js +187 -0
  19. package/dist/chunk-HO2YSF5O.js.map +1 -0
  20. package/dist/chunk-HPGCILO4.js +760 -0
  21. package/dist/chunk-HPGCILO4.js.map +1 -0
  22. package/dist/chunk-IBXLC5IE.js +154 -0
  23. package/dist/chunk-IBXLC5IE.js.map +1 -0
  24. package/dist/chunk-LDCZQP3R.js +1185 -0
  25. package/dist/chunk-LDCZQP3R.js.map +1 -0
  26. package/dist/chunk-LXCIXR5T.js +27 -0
  27. package/dist/chunk-LXCIXR5T.js.map +1 -0
  28. package/dist/chunk-O2PX54KX.js +94 -0
  29. package/dist/chunk-O2PX54KX.js.map +1 -0
  30. package/dist/chunk-OHBWBXLO.cjs +101 -0
  31. package/dist/chunk-OHBWBXLO.cjs.map +1 -0
  32. package/dist/chunk-OJN5JBNP.cjs +776 -0
  33. package/dist/chunk-OJN5JBNP.cjs.map +1 -0
  34. package/dist/chunk-OLTS6G5M.js +606 -0
  35. package/dist/chunk-OLTS6G5M.js.map +1 -0
  36. package/dist/chunk-PO5DU3FU.cjs +29 -0
  37. package/dist/chunk-PO5DU3FU.cjs.map +1 -0
  38. package/dist/chunk-QO3E7TJS.js +2940 -0
  39. package/dist/chunk-QO3E7TJS.js.map +1 -0
  40. package/dist/chunk-RHTLNSVW.cjs +2976 -0
  41. package/dist/chunk-RHTLNSVW.cjs.map +1 -0
  42. package/dist/chunk-SFU5EPSN.cjs +61 -0
  43. package/dist/chunk-SFU5EPSN.cjs.map +1 -0
  44. package/dist/chunk-T4AK2KLM.js +699 -0
  45. package/dist/chunk-T4AK2KLM.js.map +1 -0
  46. package/dist/chunk-WGYNCSTP.cjs +333 -0
  47. package/dist/chunk-WGYNCSTP.cjs.map +1 -0
  48. package/dist/chunk-XEP6P7E6.js +279 -0
  49. package/dist/chunk-XEP6P7E6.js.map +1 -0
  50. package/dist/chunk-XMXECSQO.cjs +286 -0
  51. package/dist/chunk-XMXECSQO.cjs.map +1 -0
  52. package/dist/chunk-ZWAFLHC2.cjs +181 -0
  53. package/dist/chunk-ZWAFLHC2.cjs.map +1 -0
  54. package/dist/data.cjs +71 -0
  55. package/dist/data.cjs.map +1 -0
  56. package/dist/data.d.cts +316 -0
  57. package/dist/data.d.ts +316 -0
  58. package/dist/data.js +6 -0
  59. package/dist/data.js.map +1 -0
  60. package/dist/form.cjs +153 -0
  61. package/dist/form.cjs.map +1 -0
  62. package/dist/form.d.cts +660 -0
  63. package/dist/form.d.ts +660 -0
  64. package/dist/form.js +8 -0
  65. package/dist/form.js.map +1 -0
  66. package/dist/index.cjs +1641 -0
  67. package/dist/index.cjs.map +1 -0
  68. package/dist/index.d.cts +552 -0
  69. package/dist/index.d.ts +552 -0
  70. package/dist/index.js +956 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/layout.cjs +68 -0
  73. package/dist/layout.cjs.map +1 -0
  74. package/dist/layout.d.cts +169 -0
  75. package/dist/layout.d.ts +169 -0
  76. package/dist/layout.js +7 -0
  77. package/dist/layout.js.map +1 -0
  78. package/dist/motion-CQmCq6_k.d.ts +395 -0
  79. package/dist/motion-CSX4g2N8.d.cts +395 -0
  80. package/dist/motion.cjs +79 -0
  81. package/dist/motion.cjs.map +1 -0
  82. package/dist/motion.d.cts +4 -0
  83. package/dist/motion.d.ts +4 -0
  84. package/dist/motion.js +6 -0
  85. package/dist/motion.js.map +1 -0
  86. package/dist/navigation.cjs +48 -0
  87. package/dist/navigation.cjs.map +1 -0
  88. package/dist/navigation.d.cts +210 -0
  89. package/dist/navigation.d.ts +210 -0
  90. package/dist/navigation.js +7 -0
  91. package/dist/navigation.js.map +1 -0
  92. package/dist/overlay.cjs +69 -0
  93. package/dist/overlay.cjs.map +1 -0
  94. package/dist/overlay.d.cts +330 -0
  95. package/dist/overlay.d.ts +330 -0
  96. package/dist/overlay.js +8 -0
  97. package/dist/overlay.js.map +1 -0
  98. package/dist/position-DVScKcaa.d.cts +66 -0
  99. package/dist/position-DVScKcaa.d.ts +66 -0
  100. package/dist/primitives.cjs +162 -0
  101. package/dist/primitives.cjs.map +1 -0
  102. package/dist/primitives.d.cts +294 -0
  103. package/dist/primitives.d.ts +294 -0
  104. package/dist/primitives.js +9 -0
  105. package/dist/primitives.js.map +1 -0
  106. package/dist/sidebar-D-PafAXw.d.cts +71 -0
  107. package/dist/sidebar-D-PafAXw.d.ts +71 -0
  108. package/dist/styles.css +5575 -0
  109. package/dist/use-observers-B9qtimrk.d.cts +99 -0
  110. package/dist/use-observers-B9qtimrk.d.ts +99 -0
  111. package/package.json +92 -0
@@ -0,0 +1,776 @@
1
+ 'use strict';
2
+
3
+ var chunkPO5DU3FU_cjs = require('./chunk-PO5DU3FU.cjs');
4
+ var chunkSFU5EPSN_cjs = require('./chunk-SFU5EPSN.cjs');
5
+ var react = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var core = require('@ansh-ui/core');
8
+
9
+ function compare(a, b) {
10
+ if (a == null && b == null) return 0;
11
+ if (a == null) return 1;
12
+ if (b == null) return -1;
13
+ if (typeof a === "number" && typeof b === "number") return a - b;
14
+ if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
15
+ return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
16
+ }
17
+ function DataTable({
18
+ data,
19
+ columns,
20
+ getRowId,
21
+ caption,
22
+ selectable = false,
23
+ selected,
24
+ onSelectedChange,
25
+ sort,
26
+ defaultSort = null,
27
+ onSortChange,
28
+ pageSize,
29
+ page,
30
+ onPageChange,
31
+ loading = false,
32
+ emptyState,
33
+ onRowClick,
34
+ stickyHeader = false,
35
+ density = "comfortable",
36
+ striped = false,
37
+ className,
38
+ rowClassName
39
+ }) {
40
+ const [sortState, setSortState] = chunkPO5DU3FU_cjs.useControllableState({
41
+ value: sort,
42
+ defaultValue: defaultSort,
43
+ onChange: onSortChange
44
+ });
45
+ const [selection, setSelection] = chunkPO5DU3FU_cjs.useControllableState({
46
+ value: selected,
47
+ defaultValue: [],
48
+ onChange: onSelectedChange
49
+ });
50
+ const [currentPage, setCurrentPage] = chunkPO5DU3FU_cjs.useControllableState({
51
+ value: page,
52
+ defaultValue: 0,
53
+ onChange: onPageChange
54
+ });
55
+ const sorted = react.useMemo(() => {
56
+ if (!sortState) return data;
57
+ const column = columns.find((c) => c.id === sortState.columnId);
58
+ if (!column?.sortValue) return data;
59
+ const rows = [...data];
60
+ rows.sort((a, b) => {
61
+ const result = compare(column.sortValue(a), column.sortValue(b));
62
+ return sortState.direction === "asc" ? result : -result;
63
+ });
64
+ return rows;
65
+ }, [data, columns, sortState]);
66
+ const pageCount = pageSize ? Math.max(1, Math.ceil(sorted.length / pageSize)) : 1;
67
+ const safePage = Math.min(currentPage, pageCount - 1);
68
+ const visible = pageSize ? sorted.slice(safePage * pageSize, safePage * pageSize + pageSize) : sorted;
69
+ const visibleIds = react.useMemo(() => visible.map(getRowId), [visible, getRowId]);
70
+ const selectedSet = react.useMemo(() => new Set(selection), [selection]);
71
+ const allVisibleSelected = visibleIds.length > 0 && visibleIds.every((rowId) => selectedSet.has(rowId));
72
+ const someVisibleSelected = visibleIds.some((rowId) => selectedSet.has(rowId));
73
+ const toggleAll = react.useCallback(() => {
74
+ if (allVisibleSelected) {
75
+ setSelection(selection.filter((rowId) => !visibleIds.includes(rowId)));
76
+ } else {
77
+ setSelection([.../* @__PURE__ */ new Set([...selection, ...visibleIds])]);
78
+ }
79
+ }, [allVisibleSelected, selection, visibleIds, setSelection]);
80
+ const toggleRow = react.useCallback(
81
+ (rowId) => {
82
+ setSelection(
83
+ selectedSet.has(rowId) ? selection.filter((v) => v !== rowId) : [...selection, rowId]
84
+ );
85
+ },
86
+ [selection, selectedSet, setSelection]
87
+ );
88
+ const onSort = (column) => {
89
+ if (!column.sortable) return;
90
+ if (sortState?.columnId !== column.id) {
91
+ setSortState({ columnId: column.id, direction: "asc" });
92
+ } else if (sortState.direction === "asc") {
93
+ setSortState({ columnId: column.id, direction: "desc" });
94
+ } else {
95
+ setSortState(null);
96
+ }
97
+ };
98
+ const columnCount = columns.length + (selectable ? 1 : 0);
99
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkSFU5EPSN_cjs.cx("ansh-table-wrap", stickyHeader && "ansh-table-wrap--sticky", className), children: [
100
+ /* @__PURE__ */ jsxRuntime.jsxs(
101
+ "table",
102
+ {
103
+ className: chunkSFU5EPSN_cjs.cx("ansh-table", `ansh-table--${density}`, striped && "ansh-table--striped"),
104
+ children: [
105
+ /* @__PURE__ */ jsxRuntime.jsxs("caption", { className: "ansh-visually-hidden", children: [
106
+ caption,
107
+ sortState ? `, sorted by ${columns.find((c) => c.id === sortState.columnId)?.id} ${sortState.direction === "asc" ? "ascending" : "descending"}` : ""
108
+ ] }),
109
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "ansh-table__head", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
110
+ selectable ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "ansh-table__cell ansh-table__cell--check", children: /* @__PURE__ */ jsxRuntime.jsx(
111
+ "input",
112
+ {
113
+ type: "checkbox",
114
+ className: "ansh-table__checkbox",
115
+ checked: allVisibleSelected,
116
+ ref: (node) => {
117
+ if (node) node.indeterminate = !allVisibleSelected && someVisibleSelected;
118
+ },
119
+ "aria-label": allVisibleSelected ? "Deselect all rows" : "Select all rows",
120
+ onChange: toggleAll
121
+ }
122
+ ) }) : null,
123
+ columns.map((column) => {
124
+ const isSorted = sortState?.columnId === column.id;
125
+ return /* @__PURE__ */ jsxRuntime.jsx(
126
+ "th",
127
+ {
128
+ scope: "col",
129
+ className: chunkSFU5EPSN_cjs.cx(
130
+ "ansh-table__cell",
131
+ "ansh-table__cell--head",
132
+ column.align && `ansh-table__cell--${column.align}`,
133
+ column.hideBelow && `ansh-hide-below-${column.hideBelow}`
134
+ ),
135
+ style: column.width ? { width: column.width } : void 0,
136
+ "aria-sort": isSorted ? sortState.direction === "asc" ? "ascending" : "descending" : void 0,
137
+ children: column.sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
138
+ "button",
139
+ {
140
+ type: "button",
141
+ className: "ansh-table__sort ansh-focusable",
142
+ onClick: () => onSort(column),
143
+ "aria-label": column.ariaLabel ? `Sort by ${column.ariaLabel}` : typeof column.header === "string" ? `Sort by ${column.header}` : "Sort column",
144
+ children: [
145
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: column.header }),
146
+ /* @__PURE__ */ jsxRuntime.jsx(
147
+ "span",
148
+ {
149
+ className: chunkSFU5EPSN_cjs.cx("ansh-table__arrow", isSorted && "ansh-table__arrow--on"),
150
+ "aria-hidden": "true",
151
+ "data-direction": isSorted ? sortState.direction : "none",
152
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 10 12", width: "10", height: "12", children: /* @__PURE__ */ jsxRuntime.jsx(
153
+ "path",
154
+ {
155
+ d: "M5 1v10M2 4l3-3 3 3M2 8l3 3 3-3",
156
+ stroke: "currentColor",
157
+ strokeWidth: "1.4",
158
+ fill: "none",
159
+ strokeLinecap: "round",
160
+ strokeLinejoin: "round"
161
+ }
162
+ ) })
163
+ }
164
+ )
165
+ ]
166
+ }
167
+ ) : column.header
168
+ },
169
+ column.id
170
+ );
171
+ })
172
+ ] }) }),
173
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? Array.from({ length: pageSize ?? 5 }, (_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "ansh-table__row", children: Array.from({ length: columnCount }, (_2, cellIndex) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "ansh-table__cell", children: /* @__PURE__ */ jsxRuntime.jsx(
174
+ "span",
175
+ {
176
+ className: "ansh-skeleton",
177
+ style: { width: `${50 + cellIndex * 37 % 40}%`, height: "1em" }
178
+ }
179
+ ) }, cellIndex)) }, `skeleton-${rowIndex}`)) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: columnCount, className: "ansh-table__empty", children: emptyState ?? "No results" }) }) : visible.map((row, index) => {
180
+ const rowId = getRowId(row);
181
+ const isSelected = selectedSet.has(rowId);
182
+ return /* @__PURE__ */ jsxRuntime.jsxs(
183
+ "tr",
184
+ {
185
+ className: chunkSFU5EPSN_cjs.cx(
186
+ "ansh-table__row",
187
+ isSelected && "ansh-table__row--selected",
188
+ onRowClick && "ansh-table__row--clickable",
189
+ rowClassName?.(row)
190
+ ),
191
+ "aria-selected": selectable ? isSelected : void 0,
192
+ ...onRowClick ? {
193
+ onClick: (event) => {
194
+ const target = event.target;
195
+ if (target.closest("button, a, input, select, textarea")) return;
196
+ onRowClick(row);
197
+ }
198
+ } : null,
199
+ children: [
200
+ selectable ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "ansh-table__cell ansh-table__cell--check", children: /* @__PURE__ */ jsxRuntime.jsx(
201
+ "input",
202
+ {
203
+ type: "checkbox",
204
+ className: "ansh-table__checkbox",
205
+ checked: isSelected,
206
+ "aria-label": `Select row ${index + 1}`,
207
+ onChange: () => toggleRow(rowId)
208
+ }
209
+ ) }) : null,
210
+ columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
211
+ "td",
212
+ {
213
+ className: chunkSFU5EPSN_cjs.cx(
214
+ "ansh-table__cell",
215
+ column.align && `ansh-table__cell--${column.align}`,
216
+ column.hideBelow && `ansh-hide-below-${column.hideBelow}`
217
+ ),
218
+ children: column.cell(row, index)
219
+ },
220
+ column.id
221
+ ))
222
+ ]
223
+ },
224
+ rowId
225
+ );
226
+ }) })
227
+ ]
228
+ }
229
+ ),
230
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-visually-hidden", role: "status", "aria-live": "polite", children: selectable && selection.length > 0 ? `${selection.length} selected` : "" }),
231
+ pageSize && pageCount > 1 ? /* @__PURE__ */ jsxRuntime.jsx(
232
+ Pagination,
233
+ {
234
+ page: safePage,
235
+ pageCount,
236
+ onPageChange: setCurrentPage,
237
+ total: sorted.length,
238
+ pageSize
239
+ }
240
+ ) : null
241
+ ] });
242
+ }
243
+ function Pagination({
244
+ page,
245
+ pageCount,
246
+ onPageChange,
247
+ total,
248
+ pageSize,
249
+ siblings = 1,
250
+ className
251
+ }) {
252
+ const pages = react.useMemo(() => {
253
+ const result = [];
254
+ const first = 0;
255
+ const last = pageCount - 1;
256
+ for (let index = first; index <= last; index++) {
257
+ const nearCurrent = Math.abs(index - page) <= siblings;
258
+ const isEdge = index === first || index === last;
259
+ if (nearCurrent || isEdge) {
260
+ result.push(index);
261
+ } else if (result[result.length - 1] !== "gap") {
262
+ result.push("gap");
263
+ }
264
+ }
265
+ return result;
266
+ }, [page, pageCount, siblings]);
267
+ const from = pageSize ? page * pageSize + 1 : null;
268
+ const to = pageSize && total ? Math.min((page + 1) * pageSize, total) : null;
269
+ return /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: chunkSFU5EPSN_cjs.cx("ansh-pagination", className), "aria-label": "Pagination", children: [
270
+ from !== null && to !== null ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "ansh-pagination__summary", children: [
271
+ from,
272
+ "\u2013",
273
+ to,
274
+ " of ",
275
+ total
276
+ ] }) : null,
277
+ /* @__PURE__ */ jsxRuntime.jsxs("ol", { className: "ansh-pagination__list", children: [
278
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
279
+ "button",
280
+ {
281
+ type: "button",
282
+ className: "ansh-pagination__button ansh-focusable",
283
+ disabled: page === 0,
284
+ "aria-label": "Previous page",
285
+ onClick: () => onPageChange(page - 1),
286
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
287
+ "path",
288
+ {
289
+ d: "M7.5 2.5L4 6l3.5 3.5",
290
+ stroke: "currentColor",
291
+ strokeWidth: "1.5",
292
+ fill: "none",
293
+ strokeLinecap: "round",
294
+ strokeLinejoin: "round"
295
+ }
296
+ ) })
297
+ }
298
+ ) }),
299
+ pages.map(
300
+ (entry, index) => entry === "gap" ? /* @__PURE__ */ jsxRuntime.jsx("li", { "aria-hidden": "true", className: "ansh-pagination__gap", children: "\u2026" }, `gap-${index}`) : /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
301
+ "button",
302
+ {
303
+ type: "button",
304
+ className: chunkSFU5EPSN_cjs.cx(
305
+ "ansh-pagination__button",
306
+ entry === page && "ansh-pagination__button--current",
307
+ "ansh-focusable"
308
+ ),
309
+ "aria-current": entry === page ? "page" : void 0,
310
+ "aria-label": `Page ${entry + 1}`,
311
+ onClick: () => onPageChange(entry),
312
+ children: entry + 1
313
+ }
314
+ ) }, entry)
315
+ ),
316
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
317
+ "button",
318
+ {
319
+ type: "button",
320
+ className: "ansh-pagination__button ansh-focusable",
321
+ disabled: page >= pageCount - 1,
322
+ "aria-label": "Next page",
323
+ onClick: () => onPageChange(page + 1),
324
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
325
+ "path",
326
+ {
327
+ d: "M4.5 2.5L8 6l-3.5 3.5",
328
+ stroke: "currentColor",
329
+ strokeWidth: "1.5",
330
+ fill: "none",
331
+ strokeLinecap: "round",
332
+ strokeLinejoin: "round"
333
+ }
334
+ ) })
335
+ }
336
+ ) })
337
+ ] })
338
+ ] });
339
+ }
340
+ function Table({
341
+ caption,
342
+ density = "comfortable",
343
+ striped = false,
344
+ className,
345
+ children
346
+ }) {
347
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkSFU5EPSN_cjs.cx("ansh-table-wrap", className), children: /* @__PURE__ */ jsxRuntime.jsxs(
348
+ "table",
349
+ {
350
+ className: chunkSFU5EPSN_cjs.cx("ansh-table", `ansh-table--${density}`, striped && "ansh-table--striped"),
351
+ children: [
352
+ caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "ansh-visually-hidden", children: caption }) : null,
353
+ children
354
+ ]
355
+ }
356
+ ) });
357
+ }
358
+ function Badge({
359
+ tone = "neutral",
360
+ variant = "soft",
361
+ size = "md",
362
+ dot = false,
363
+ icon,
364
+ className,
365
+ children,
366
+ ...rest
367
+ }) {
368
+ return /* @__PURE__ */ jsxRuntime.jsxs(
369
+ "span",
370
+ {
371
+ className: chunkSFU5EPSN_cjs.cx(
372
+ "ansh-badge",
373
+ `ansh-badge--${tone}`,
374
+ `ansh-badge--${variant}`,
375
+ `ansh-badge--${size}`,
376
+ className
377
+ ),
378
+ ...rest,
379
+ children: [
380
+ dot ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-badge__dot", "aria-hidden": "true" }) : null,
381
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-badge__icon", children: icon }) : null,
382
+ children
383
+ ]
384
+ }
385
+ );
386
+ }
387
+ function initials(name) {
388
+ const words = name.trim().split(/\s+/).filter(Boolean);
389
+ if (words.length === 0) return "?";
390
+ if (words.length === 1) return words[0].slice(0, 2).toUpperCase();
391
+ return (words[0][0] + words[words.length - 1][0]).toUpperCase();
392
+ }
393
+ function hash(text) {
394
+ let value = 0;
395
+ for (let i = 0; i < text.length; i++) {
396
+ value = value * 31 + text.charCodeAt(i) | 0;
397
+ }
398
+ return Math.abs(value);
399
+ }
400
+ function Avatar({
401
+ src,
402
+ name,
403
+ size = "md",
404
+ shape = "circle",
405
+ status,
406
+ className,
407
+ ...rest
408
+ }) {
409
+ const [failed, setFailed] = react.useState(false);
410
+ const { background, foreground } = react.useMemo(() => {
411
+ const hue = hash(name) % 360;
412
+ const backgroundHex = core.toHex(core.parseColor(`oklch(72% 0.13 ${hue})`));
413
+ return {
414
+ background: backgroundHex,
415
+ foreground: core.toHex(core.pickReadable(backgroundHex, "#ffffff", "#101828"))
416
+ };
417
+ }, [name]);
418
+ const showImage = src && !failed;
419
+ return /* @__PURE__ */ jsxRuntime.jsxs(
420
+ "span",
421
+ {
422
+ className: chunkSFU5EPSN_cjs.cx("ansh-avatar", `ansh-avatar--${size}`, `ansh-avatar--${shape}`, className),
423
+ ...rest,
424
+ children: [
425
+ showImage ? /* @__PURE__ */ jsxRuntime.jsx(
426
+ "img",
427
+ {
428
+ src,
429
+ alt: name,
430
+ className: "ansh-avatar__image",
431
+ onError: () => setFailed(true)
432
+ }
433
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
434
+ "span",
435
+ {
436
+ className: "ansh-avatar__fallback",
437
+ style: { background, color: foreground },
438
+ "aria-hidden": "true",
439
+ children: initials(name)
440
+ }
441
+ ),
442
+ !showImage ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-visually-hidden", children: name }) : null,
443
+ status ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: chunkSFU5EPSN_cjs.cx("ansh-avatar__status", `ansh-avatar__status--${status}`), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-visually-hidden", children: status }) }) : null
444
+ ]
445
+ }
446
+ );
447
+ }
448
+ function AvatarGroup({ max = 4, size, className, children }) {
449
+ const items = Array.isArray(children) ? children : [children];
450
+ const shown = items.slice(0, max);
451
+ const overflow = items.length - shown.length;
452
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: chunkSFU5EPSN_cjs.cx("ansh-avatar-group", size && `ansh-avatar-group--${size}`, className), children: [
453
+ shown,
454
+ overflow > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
455
+ "span",
456
+ {
457
+ className: chunkSFU5EPSN_cjs.cx(
458
+ "ansh-avatar",
459
+ size && `ansh-avatar--${size}`,
460
+ "ansh-avatar--circle",
461
+ "ansh-avatar--more"
462
+ ),
463
+ children: [
464
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ansh-avatar__fallback", "aria-hidden": "true", children: [
465
+ "+",
466
+ overflow
467
+ ] }),
468
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ansh-visually-hidden", children: [
469
+ "and ",
470
+ overflow,
471
+ " more"
472
+ ] })
473
+ ]
474
+ }
475
+ ) : null
476
+ ] });
477
+ }
478
+ function Kbd({ children, className }) {
479
+ const keys = children.split("+").map((key) => key.trim());
480
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: chunkSFU5EPSN_cjs.cx("ansh-kbd-group", className), children: keys.map((key, index) => /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
481
+ index > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-kbd__plus", "aria-hidden": "true", children: "+" }) : null,
482
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "ansh-kbd", children: key })
483
+ ] }, `${key}-${index}`)) });
484
+ }
485
+ function Stat({
486
+ label,
487
+ value,
488
+ delta,
489
+ deltaLabel,
490
+ invertDelta = false,
491
+ hint,
492
+ icon,
493
+ className
494
+ }) {
495
+ const positive = delta !== void 0 && delta > 0;
496
+ const negative = delta !== void 0 && delta < 0;
497
+ const good = invertDelta ? negative : positive;
498
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkSFU5EPSN_cjs.cx("ansh-stat", className), children: [
499
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-stat__head", children: [
500
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-stat__label", children: label }),
501
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-stat__icon", children: icon }) : null
502
+ ] }),
503
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-stat__value", children: value }),
504
+ delta !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
505
+ "div",
506
+ {
507
+ className: chunkSFU5EPSN_cjs.cx(
508
+ "ansh-stat__delta",
509
+ delta !== 0 && (good ? "ansh-stat__delta--good" : "ansh-stat__delta--bad")
510
+ ),
511
+ children: [
512
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-stat__arrow", "aria-hidden": "true", children: positive ? "\u2191" : negative ? "\u2193" : "\u2192" }),
513
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: deltaLabel ?? `${delta > 0 ? "+" : ""}${delta}%` }),
514
+ hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-stat__hint", children: hint }) : null
515
+ ]
516
+ }
517
+ ) : hint ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-stat__hint", children: hint }) : null
518
+ ] });
519
+ }
520
+ function EmptyState({
521
+ title,
522
+ description,
523
+ icon,
524
+ action,
525
+ size = "md",
526
+ className
527
+ }) {
528
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkSFU5EPSN_cjs.cx("ansh-empty", `ansh-empty--${size}`, className), children: [
529
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-empty__icon", "aria-hidden": "true", children: icon }) : null,
530
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ansh-empty__title", children: title }),
531
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ansh-empty__description", children: description }) : null,
532
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-empty__action", children: action }) : null
533
+ ] });
534
+ }
535
+ function DescriptionList({
536
+ items,
537
+ orientation = "horizontal",
538
+ className
539
+ }) {
540
+ return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: chunkSFU5EPSN_cjs.cx("ansh-dl", `ansh-dl--${orientation}`, className), children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-dl__row", children: [
541
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "ansh-dl__term", children: item.term }),
542
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "ansh-dl__description", children: item.description })
543
+ ] }, index)) });
544
+ }
545
+ function Timeline({
546
+ items,
547
+ className
548
+ }) {
549
+ return /* @__PURE__ */ jsxRuntime.jsx("ol", { className: chunkSFU5EPSN_cjs.cx("ansh-timeline", className), children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
550
+ "li",
551
+ {
552
+ className: chunkSFU5EPSN_cjs.cx("ansh-timeline__item", item.tone && `ansh-timeline__item--${item.tone}`),
553
+ children: [
554
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-timeline__marker", "aria-hidden": "true", children: item.icon }),
555
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-timeline__body", children: [
556
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-timeline__head", children: [
557
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-timeline__title", children: item.title }),
558
+ item.timestamp ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-timeline__time", children: item.timestamp }) : null
559
+ ] }),
560
+ item.description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ansh-timeline__description", children: item.description }) : null
561
+ ] })
562
+ ]
563
+ },
564
+ item.id
565
+ )) });
566
+ }
567
+ function CodeBlock({
568
+ code,
569
+ language = "tsx",
570
+ copyable = true,
571
+ lineNumbers = false,
572
+ filename,
573
+ className
574
+ }) {
575
+ const [copied, setCopied] = react.useState(false);
576
+ const lines = react.useMemo(() => code.split("\n"), [code]);
577
+ const copy = async () => {
578
+ try {
579
+ await navigator.clipboard.writeText(code);
580
+ setCopied(true);
581
+ setTimeout(() => setCopied(false), 1600);
582
+ } catch {
583
+ }
584
+ };
585
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkSFU5EPSN_cjs.cx("ansh-code", className), children: [
586
+ filename || copyable ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-code__bar", children: [
587
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-code__filename", children: filename ?? language }),
588
+ copyable ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "ansh-code__copy ansh-focusable", onClick: copy, children: [
589
+ copied ? "Copied" : "Copy",
590
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-visually-hidden", children: " code to clipboard" })
591
+ ] }) : null
592
+ ] }) : null,
593
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: chunkSFU5EPSN_cjs.cx("ansh-code__pre", lineNumbers && "ansh-code__pre--numbered"), children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: `language-${language}`, children: lineNumbers ? lines.map((line, index) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ansh-code__line", children: [
594
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-code__lineno", "aria-hidden": "true", children: index + 1 }),
595
+ line,
596
+ "\n"
597
+ ] }, index)) : code }) })
598
+ ] });
599
+ }
600
+ function Progress({
601
+ value,
602
+ max = 100,
603
+ size = "md",
604
+ tone = "accent",
605
+ label,
606
+ showLabel = false,
607
+ formatValue,
608
+ className
609
+ }) {
610
+ const indeterminate = value === void 0;
611
+ const clamped = indeterminate ? 0 : Math.min(Math.max(value, 0), max);
612
+ const percent = clamped / max * 100;
613
+ const text = formatValue ? formatValue(clamped, max) : `${Math.round(percent)}%`;
614
+ return /* @__PURE__ */ jsxRuntime.jsxs(
615
+ "div",
616
+ {
617
+ className: chunkSFU5EPSN_cjs.cx("ansh-progress", `ansh-progress--${size}`, `ansh-progress--${tone}`, className),
618
+ children: [
619
+ showLabel ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-progress__labels", children: [
620
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-progress__label", children: label }),
621
+ !indeterminate ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-progress__value", children: text }) : null
622
+ ] }) : null,
623
+ /* @__PURE__ */ jsxRuntime.jsx(
624
+ "div",
625
+ {
626
+ className: chunkSFU5EPSN_cjs.cx(
627
+ "ansh-progress__track",
628
+ indeterminate && "ansh-progress__track--indeterminate"
629
+ ),
630
+ role: "progressbar",
631
+ "aria-label": label,
632
+ ...indeterminate ? null : {
633
+ "aria-valuenow": clamped,
634
+ "aria-valuemin": 0,
635
+ "aria-valuemax": max,
636
+ "aria-valuetext": text
637
+ },
638
+ children: /* @__PURE__ */ jsxRuntime.jsx(
639
+ "div",
640
+ {
641
+ className: "ansh-progress__fill",
642
+ style: indeterminate ? void 0 : { width: `${percent}%` }
643
+ }
644
+ )
645
+ }
646
+ )
647
+ ]
648
+ }
649
+ );
650
+ }
651
+ function CircularProgress({
652
+ value,
653
+ max = 100,
654
+ size = 48,
655
+ thickness = 4,
656
+ tone = "accent",
657
+ label,
658
+ formatValue,
659
+ className,
660
+ children
661
+ }) {
662
+ const indeterminate = value === void 0;
663
+ const clamped = indeterminate ? 25 : Math.min(Math.max(value, 0), max);
664
+ const fraction = clamped / max;
665
+ const radius = (size - thickness) / 2;
666
+ const circumference = 2 * Math.PI * radius;
667
+ const text = formatValue ? formatValue(clamped, max) : `${Math.round(fraction * 100)}%`;
668
+ return /* @__PURE__ */ jsxRuntime.jsxs(
669
+ "div",
670
+ {
671
+ className: chunkSFU5EPSN_cjs.cx(
672
+ "ansh-ring",
673
+ `ansh-ring--${tone}`,
674
+ indeterminate && "ansh-ring--indeterminate",
675
+ className
676
+ ),
677
+ style: { width: size, height: size },
678
+ role: "progressbar",
679
+ "aria-label": label,
680
+ ...indeterminate ? null : {
681
+ "aria-valuenow": clamped,
682
+ "aria-valuemin": 0,
683
+ "aria-valuemax": max,
684
+ "aria-valuetext": text
685
+ },
686
+ children: [
687
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, "aria-hidden": "true", children: [
688
+ /* @__PURE__ */ jsxRuntime.jsx(
689
+ "circle",
690
+ {
691
+ className: "ansh-ring__track",
692
+ cx: size / 2,
693
+ cy: size / 2,
694
+ r: radius,
695
+ fill: "none",
696
+ strokeWidth: thickness
697
+ }
698
+ ),
699
+ /* @__PURE__ */ jsxRuntime.jsx(
700
+ "circle",
701
+ {
702
+ className: "ansh-ring__fill",
703
+ cx: size / 2,
704
+ cy: size / 2,
705
+ r: radius,
706
+ fill: "none",
707
+ strokeWidth: thickness,
708
+ strokeLinecap: "round",
709
+ strokeDasharray: circumference,
710
+ strokeDashoffset: circumference * (1 - fraction),
711
+ transform: `rotate(-90 ${size / 2} ${size / 2})`
712
+ }
713
+ )
714
+ ] }),
715
+ children ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-ring__content", children }) : null
716
+ ]
717
+ }
718
+ );
719
+ }
720
+ function Meter({
721
+ value,
722
+ min = 0,
723
+ max = 100,
724
+ low,
725
+ high,
726
+ inverted = false,
727
+ label,
728
+ showValue = true,
729
+ formatValue,
730
+ className
731
+ }) {
732
+ const clamped = Math.min(Math.max(value, min), max);
733
+ const percent = (clamped - min) / (max - min) * 100;
734
+ let tone = "success";
735
+ if (low !== void 0 && clamped < low) tone = inverted ? "success" : "danger";
736
+ else if (high !== void 0 && clamped > high) tone = inverted ? "danger" : "success";
737
+ else if (low !== void 0 || high !== void 0) tone = "warning";
738
+ const text = formatValue ? formatValue(clamped) : String(clamped);
739
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkSFU5EPSN_cjs.cx("ansh-meter", `ansh-meter--${tone}`, className), children: [
740
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-progress__labels", children: [
741
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-progress__label", children: label }),
742
+ showValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-progress__value", children: text }) : null
743
+ ] }),
744
+ /* @__PURE__ */ jsxRuntime.jsx(
745
+ "div",
746
+ {
747
+ className: "ansh-progress__track",
748
+ role: "meter",
749
+ "aria-label": label,
750
+ "aria-valuenow": clamped,
751
+ "aria-valuemin": min,
752
+ "aria-valuemax": max,
753
+ "aria-valuetext": text,
754
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-progress__fill", style: { width: `${percent}%` } })
755
+ }
756
+ )
757
+ ] });
758
+ }
759
+
760
+ exports.Avatar = Avatar;
761
+ exports.AvatarGroup = AvatarGroup;
762
+ exports.Badge = Badge;
763
+ exports.CircularProgress = CircularProgress;
764
+ exports.CodeBlock = CodeBlock;
765
+ exports.DataTable = DataTable;
766
+ exports.DescriptionList = DescriptionList;
767
+ exports.EmptyState = EmptyState;
768
+ exports.Kbd = Kbd;
769
+ exports.Meter = Meter;
770
+ exports.Pagination = Pagination;
771
+ exports.Progress = Progress;
772
+ exports.Stat = Stat;
773
+ exports.Table = Table;
774
+ exports.Timeline = Timeline;
775
+ //# sourceMappingURL=chunk-OJN5JBNP.cjs.map
776
+ //# sourceMappingURL=chunk-OJN5JBNP.cjs.map