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