@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,606 @@
1
+ import { useControllableState } from './chunk-LXCIXR5T.js';
2
+ import { cx } from './chunk-H34OXXJU.js';
3
+ import { useId, useRef, useState, useEffect } from 'react';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ function Tabs({
7
+ items,
8
+ value,
9
+ defaultValue,
10
+ onChange,
11
+ variant = "underline",
12
+ orientation = "horizontal",
13
+ size = "md",
14
+ fitted = false,
15
+ activateOnFocus = true,
16
+ label,
17
+ className,
18
+ children
19
+ }) {
20
+ const [active, setActive] = useControllableState({
21
+ value,
22
+ defaultValue: defaultValue ?? items.find((item) => !item.disabled)?.id ?? "",
23
+ onChange
24
+ });
25
+ const baseId = useId();
26
+ const tabRefs = useRef([]);
27
+ const activeIndex = items.findIndex((item) => item.id === active);
28
+ const activeItem = items[activeIndex];
29
+ const move = (delta) => {
30
+ if (items.length === 0) return;
31
+ let next = activeIndex < 0 ? 0 : activeIndex;
32
+ for (let attempts = 0; attempts < items.length; attempts++) {
33
+ next = (next + delta + items.length) % items.length;
34
+ if (!items[next]?.disabled) break;
35
+ }
36
+ tabRefs.current[next]?.focus();
37
+ if (activateOnFocus) setActive(items[next].id);
38
+ };
39
+ const onKeyDown = (event) => {
40
+ const forward = orientation === "horizontal" ? "ArrowRight" : "ArrowDown";
41
+ const backward = orientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
42
+ switch (event.key) {
43
+ case forward:
44
+ event.preventDefault();
45
+ move(1);
46
+ break;
47
+ case backward:
48
+ event.preventDefault();
49
+ move(-1);
50
+ break;
51
+ case "Home": {
52
+ event.preventDefault();
53
+ const first = items.findIndex((item) => !item.disabled);
54
+ if (first >= 0) {
55
+ tabRefs.current[first]?.focus();
56
+ if (activateOnFocus) setActive(items[first].id);
57
+ }
58
+ break;
59
+ }
60
+ case "End": {
61
+ event.preventDefault();
62
+ for (let i = items.length - 1; i >= 0; i--) {
63
+ if (!items[i]?.disabled) {
64
+ tabRefs.current[i]?.focus();
65
+ if (activateOnFocus) setActive(items[i].id);
66
+ break;
67
+ }
68
+ }
69
+ break;
70
+ }
71
+ }
72
+ };
73
+ return /* @__PURE__ */ jsxs(
74
+ "div",
75
+ {
76
+ className: cx(
77
+ "ansh-tabs",
78
+ `ansh-tabs--${variant}`,
79
+ `ansh-tabs--${orientation}`,
80
+ `ansh-tabs--${size}`,
81
+ className
82
+ ),
83
+ children: [
84
+ /* @__PURE__ */ jsx(
85
+ "div",
86
+ {
87
+ role: "tablist",
88
+ "aria-label": label,
89
+ "aria-orientation": orientation,
90
+ className: cx("ansh-tabs__list", fitted && "ansh-tabs__list--fitted"),
91
+ onKeyDown,
92
+ children: items.map((item, index) => {
93
+ const selected = item.id === active;
94
+ return /* @__PURE__ */ jsxs(
95
+ "button",
96
+ {
97
+ ref: (node) => {
98
+ tabRefs.current[index] = node;
99
+ },
100
+ type: "button",
101
+ role: "tab",
102
+ id: `${baseId}-tab-${item.id}`,
103
+ "aria-selected": selected,
104
+ "aria-controls": `${baseId}-panel-${item.id}`,
105
+ tabIndex: selected ? 0 : -1,
106
+ disabled: item.disabled,
107
+ className: cx(
108
+ "ansh-tabs__tab",
109
+ selected && "ansh-tabs__tab--active",
110
+ "ansh-focusable"
111
+ ),
112
+ onClick: () => setActive(item.id),
113
+ children: [
114
+ item.icon ? /* @__PURE__ */ jsx("span", { className: "ansh-tabs__icon", children: item.icon }) : null,
115
+ /* @__PURE__ */ jsx("span", { children: item.label }),
116
+ item.badge !== void 0 ? /* @__PURE__ */ jsx("span", { className: "ansh-tabs__badge", children: item.badge }) : null
117
+ ]
118
+ },
119
+ item.id
120
+ );
121
+ })
122
+ }
123
+ ),
124
+ activeItem?.content !== void 0 || children ? /* @__PURE__ */ jsx(
125
+ "div",
126
+ {
127
+ role: "tabpanel",
128
+ id: `${baseId}-panel-${active}`,
129
+ "aria-labelledby": `${baseId}-tab-${active}`,
130
+ tabIndex: 0,
131
+ className: "ansh-tabs__panel ansh-focusable",
132
+ children: activeItem?.content ?? children
133
+ }
134
+ ) : null
135
+ ]
136
+ }
137
+ );
138
+ }
139
+ function Breadcrumbs({
140
+ items,
141
+ maxItems = Number.POSITIVE_INFINITY,
142
+ separator,
143
+ className
144
+ }) {
145
+ const [expanded, setExpanded] = useState(false);
146
+ const collapsed = !expanded && items.length > maxItems && maxItems >= 2;
147
+ const shown = collapsed ? [items[0], ...items.slice(-2)] : items;
148
+ const gapAfter = collapsed ? 0 : -1;
149
+ const chevron = separator ?? /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
150
+ "path",
151
+ {
152
+ d: "M4.5 2.5L8 6l-3.5 3.5",
153
+ stroke: "currentColor",
154
+ strokeWidth: "1.5",
155
+ fill: "none",
156
+ strokeLinecap: "round",
157
+ strokeLinejoin: "round"
158
+ }
159
+ ) });
160
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: cx("ansh-breadcrumbs", className), children: /* @__PURE__ */ jsx("ol", { className: "ansh-breadcrumbs__list", children: shown.map((crumb, index) => {
161
+ const isLast = index === shown.length - 1;
162
+ return /* @__PURE__ */ jsxs("li", { className: "ansh-breadcrumbs__item", children: [
163
+ index > 0 ? /* @__PURE__ */ jsx("span", { className: "ansh-breadcrumbs__separator", "aria-hidden": "true", children: chevron }) : null,
164
+ isLast ? /* @__PURE__ */ jsxs("span", { className: "ansh-breadcrumbs__current", "aria-current": "page", children: [
165
+ crumb.icon,
166
+ crumb.label
167
+ ] }) : /* @__PURE__ */ jsxs(
168
+ "a",
169
+ {
170
+ href: crumb.href ?? "#",
171
+ className: "ansh-breadcrumbs__link ansh-focusable",
172
+ onClick: crumb.onClick ? (event) => {
173
+ event.preventDefault();
174
+ crumb.onClick();
175
+ } : void 0,
176
+ children: [
177
+ crumb.icon,
178
+ crumb.label
179
+ ]
180
+ }
181
+ ),
182
+ index === gapAfter ? /* @__PURE__ */ jsxs(Fragment, { children: [
183
+ /* @__PURE__ */ jsx("span", { className: "ansh-breadcrumbs__separator", "aria-hidden": "true", children: chevron }),
184
+ /* @__PURE__ */ jsx(
185
+ "button",
186
+ {
187
+ type: "button",
188
+ className: "ansh-breadcrumbs__more ansh-focusable",
189
+ "aria-label": `Show ${items.length - 3} hidden breadcrumbs`,
190
+ "aria-expanded": false,
191
+ onClick: () => setExpanded(true),
192
+ children: "\u2026"
193
+ }
194
+ )
195
+ ] }) : null
196
+ ] }, index);
197
+ }) }) });
198
+ }
199
+ function Stepper({
200
+ steps,
201
+ current,
202
+ onStepChange,
203
+ orientation = "horizontal",
204
+ className
205
+ }) {
206
+ return /* @__PURE__ */ jsx(
207
+ "nav",
208
+ {
209
+ className: cx("ansh-stepper", `ansh-stepper--${orientation}`, className),
210
+ "aria-label": "Progress",
211
+ children: /* @__PURE__ */ jsx("ol", { className: "ansh-stepper__list", children: steps.map((step, index) => {
212
+ const complete = index < current;
213
+ const active = index === current;
214
+ const state = step.error ? "error" : complete ? "complete" : active ? "current" : "upcoming";
215
+ const interactive = step.clickable && onStepChange && index !== current;
216
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
217
+ /* @__PURE__ */ jsx(
218
+ "span",
219
+ {
220
+ className: cx("ansh-stepper__marker", `ansh-stepper__marker--${state}`),
221
+ "aria-hidden": "true",
222
+ children: step.error ? "!" : complete ? /* @__PURE__ */ jsx("svg", { viewBox: "0 0 14 14", width: "12", height: "12", children: /* @__PURE__ */ jsx(
223
+ "path",
224
+ {
225
+ d: "M2.5 7.5l3 3 6-6.5",
226
+ stroke: "currentColor",
227
+ strokeWidth: "2",
228
+ strokeLinecap: "round",
229
+ strokeLinejoin: "round",
230
+ fill: "none"
231
+ }
232
+ ) }) : index + 1
233
+ }
234
+ ),
235
+ /* @__PURE__ */ jsxs("span", { className: "ansh-stepper__text", children: [
236
+ /* @__PURE__ */ jsx("span", { className: "ansh-stepper__label", children: step.label }),
237
+ step.description ? /* @__PURE__ */ jsx("span", { className: "ansh-stepper__description", children: step.description }) : null,
238
+ /* @__PURE__ */ jsx("span", { className: "ansh-visually-hidden", children: step.error ? " \u2014 has errors" : complete ? " \u2014 completed" : active ? " \u2014 current step" : " \u2014 not started" })
239
+ ] })
240
+ ] });
241
+ return /* @__PURE__ */ jsx(
242
+ "li",
243
+ {
244
+ className: cx("ansh-stepper__item", `ansh-stepper__item--${state}`),
245
+ "aria-current": active ? "step" : void 0,
246
+ children: interactive ? /* @__PURE__ */ jsx(
247
+ "button",
248
+ {
249
+ type: "button",
250
+ className: "ansh-stepper__button ansh-focusable",
251
+ onClick: () => onStepChange(index),
252
+ children: inner
253
+ }
254
+ ) : /* @__PURE__ */ jsx("span", { className: "ansh-stepper__button", children: inner })
255
+ },
256
+ step.id
257
+ );
258
+ }) })
259
+ }
260
+ );
261
+ }
262
+ function NavigationMenu({
263
+ items,
264
+ label = "Main navigation",
265
+ className
266
+ }) {
267
+ const [openId, setOpenId] = useState(null);
268
+ const timerRef = useRef(void 0);
269
+ const rootRef = useRef(null);
270
+ const baseId = useId();
271
+ const schedule = (next, delay) => {
272
+ clearTimeout(timerRef.current);
273
+ timerRef.current = setTimeout(() => setOpenId(next), delay);
274
+ };
275
+ useEffect(() => () => clearTimeout(timerRef.current), []);
276
+ useEffect(() => {
277
+ if (!openId) return;
278
+ const root = rootRef.current;
279
+ if (!root) return;
280
+ const onFocusOut = (event) => {
281
+ const next = event.relatedTarget;
282
+ if (next && root.contains(next)) return;
283
+ setOpenId(null);
284
+ };
285
+ const onKeyDown = (event) => {
286
+ if (event.key !== "Escape") return;
287
+ setOpenId(null);
288
+ root.querySelector(`[aria-expanded="true"]`)?.focus();
289
+ };
290
+ root.addEventListener("focusout", onFocusOut);
291
+ document.addEventListener("keydown", onKeyDown);
292
+ return () => {
293
+ root.removeEventListener("focusout", onFocusOut);
294
+ document.removeEventListener("keydown", onKeyDown);
295
+ };
296
+ }, [openId]);
297
+ return /* @__PURE__ */ jsx(
298
+ "nav",
299
+ {
300
+ ref: rootRef,
301
+ className: cx("ansh-navmenu", className),
302
+ "aria-label": label,
303
+ onMouseLeave: () => schedule(null, 200),
304
+ children: /* @__PURE__ */ jsx("ul", { className: "ansh-navmenu__list", children: items.map((item) => {
305
+ const hasPanel = Boolean(item.columns?.length);
306
+ const open = openId === item.id;
307
+ const panelId = `${baseId}-${item.id}`;
308
+ if (!hasPanel) {
309
+ return /* @__PURE__ */ jsx("li", { className: "ansh-navmenu__item", children: /* @__PURE__ */ jsx("a", { href: item.href ?? "#", className: "ansh-navmenu__link ansh-focusable", children: item.label }) }, item.id);
310
+ }
311
+ return /* @__PURE__ */ jsxs(
312
+ "li",
313
+ {
314
+ className: cx("ansh-navmenu__item", open && "ansh-navmenu__item--open"),
315
+ onMouseEnter: () => schedule(item.id, 80),
316
+ children: [
317
+ /* @__PURE__ */ jsxs(
318
+ "button",
319
+ {
320
+ type: "button",
321
+ className: "ansh-navmenu__link ansh-navmenu__link--trigger ansh-focusable",
322
+ "aria-expanded": open,
323
+ "aria-controls": panelId,
324
+ onClick: () => setOpenId(open ? null : item.id),
325
+ onKeyDown: (event) => {
326
+ if (event.key === "ArrowDown") {
327
+ event.preventDefault();
328
+ setOpenId(item.id);
329
+ requestAnimationFrame(() => {
330
+ document.getElementById(panelId)?.querySelector("a, button")?.focus();
331
+ });
332
+ }
333
+ },
334
+ children: [
335
+ item.label,
336
+ /* @__PURE__ */ jsx(
337
+ "span",
338
+ {
339
+ className: cx("ansh-navmenu__chevron", open && "ansh-navmenu__chevron--open"),
340
+ "aria-hidden": "true",
341
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: "10", height: "10", children: /* @__PURE__ */ jsx(
342
+ "path",
343
+ {
344
+ d: "M3 4.5L6 7.5l3-3",
345
+ stroke: "currentColor",
346
+ strokeWidth: "1.5",
347
+ fill: "none",
348
+ strokeLinecap: "round",
349
+ strokeLinejoin: "round"
350
+ }
351
+ ) })
352
+ }
353
+ )
354
+ ]
355
+ }
356
+ ),
357
+ /* @__PURE__ */ jsx(
358
+ "div",
359
+ {
360
+ id: panelId,
361
+ className: "ansh-navmenu__panel",
362
+ hidden: !open,
363
+ onMouseEnter: () => clearTimeout(timerRef.current),
364
+ children: /* @__PURE__ */ jsxs("div", { className: "ansh-navmenu__grid", children: [
365
+ item.columns.map((column) => /* @__PURE__ */ jsxs("div", { className: "ansh-navmenu__column", children: [
366
+ column.heading ? /* @__PURE__ */ jsx("p", { className: "ansh-navmenu__heading", children: column.heading }) : null,
367
+ /* @__PURE__ */ jsx("ul", { className: "ansh-navmenu__links", children: column.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
368
+ "a",
369
+ {
370
+ href: link.href ?? "#",
371
+ className: "ansh-navmenu__entry ansh-focusable",
372
+ onClick: link.onClick ? (event) => {
373
+ event.preventDefault();
374
+ link.onClick();
375
+ setOpenId(null);
376
+ } : () => setOpenId(null),
377
+ children: [
378
+ link.icon ? /* @__PURE__ */ jsx("span", { className: "ansh-navmenu__icon", "aria-hidden": "true", children: link.icon }) : null,
379
+ /* @__PURE__ */ jsxs("span", { className: "ansh-navmenu__entry-text", children: [
380
+ /* @__PURE__ */ jsx("span", { className: "ansh-navmenu__entry-label", children: link.label }),
381
+ link.description ? /* @__PURE__ */ jsx("span", { className: "ansh-navmenu__entry-description", children: link.description }) : null
382
+ ] })
383
+ ]
384
+ }
385
+ ) }, link.id)) })
386
+ ] }, column.id)),
387
+ item.feature ? /* @__PURE__ */ jsx("div", { className: "ansh-navmenu__feature", children: item.feature }) : null
388
+ ] })
389
+ }
390
+ )
391
+ ]
392
+ },
393
+ item.id
394
+ );
395
+ }) })
396
+ }
397
+ );
398
+ }
399
+ function Collapsible({
400
+ open,
401
+ defaultOpen = false,
402
+ onOpenChange,
403
+ trigger,
404
+ bare = false,
405
+ className,
406
+ children
407
+ }) {
408
+ const [isOpen, setOpen] = useControllableState({
409
+ value: open,
410
+ defaultValue: defaultOpen,
411
+ onChange: onOpenChange
412
+ });
413
+ const id = useId();
414
+ return /* @__PURE__ */ jsxs("div", { className: cx("ansh-collapsible", className), "data-state": isOpen ? "open" : "closed", children: [
415
+ /* @__PURE__ */ jsxs(
416
+ "button",
417
+ {
418
+ type: "button",
419
+ className: cx(
420
+ bare ? "ansh-collapsible__bare" : "ansh-collapsible__trigger",
421
+ "ansh-focusable"
422
+ ),
423
+ "aria-expanded": isOpen,
424
+ "aria-controls": id,
425
+ onClick: () => setOpen(!isOpen),
426
+ children: [
427
+ trigger,
428
+ /* @__PURE__ */ jsx(
429
+ "span",
430
+ {
431
+ className: cx("ansh-collapsible__chevron", isOpen && "ansh-collapsible__chevron--open"),
432
+ "aria-hidden": "true",
433
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", children: /* @__PURE__ */ jsx(
434
+ "path",
435
+ {
436
+ d: "M3 4.5L6 7.5l3-3",
437
+ stroke: "currentColor",
438
+ strokeWidth: "1.5",
439
+ fill: "none",
440
+ strokeLinecap: "round",
441
+ strokeLinejoin: "round"
442
+ }
443
+ ) })
444
+ }
445
+ )
446
+ ]
447
+ }
448
+ ),
449
+ /* @__PURE__ */ jsx(
450
+ "div",
451
+ {
452
+ className: "ansh-collapsible__region",
453
+ id,
454
+ role: "region",
455
+ "data-state": isOpen ? "open" : "closed",
456
+ children: /* @__PURE__ */ jsx("div", { className: "ansh-collapsible__inner", ...isOpen ? null : { inert: true }, children })
457
+ }
458
+ )
459
+ ] });
460
+ }
461
+ function Accordion({
462
+ items,
463
+ multiple = false,
464
+ value,
465
+ defaultValue = [],
466
+ onChange,
467
+ variant = "bordered",
468
+ className
469
+ }) {
470
+ const [openIds, setOpenIds] = useControllableState({
471
+ value,
472
+ defaultValue,
473
+ onChange
474
+ });
475
+ const baseId = useId();
476
+ const headerRefs = useRef([]);
477
+ const toggle = (id) => {
478
+ if (openIds.includes(id)) {
479
+ setOpenIds(openIds.filter((entry) => entry !== id));
480
+ } else {
481
+ setOpenIds(multiple ? [...openIds, id] : [id]);
482
+ }
483
+ };
484
+ const onKeyDown = (index) => (event) => {
485
+ const enabled = items.map((item, i) => ({ item, i })).filter(({ item }) => !item.disabled).map(({ i }) => i);
486
+ const position = enabled.indexOf(index);
487
+ let next;
488
+ switch (event.key) {
489
+ case "ArrowDown":
490
+ next = enabled[(position + 1) % enabled.length];
491
+ break;
492
+ case "ArrowUp":
493
+ next = enabled[(position - 1 + enabled.length) % enabled.length];
494
+ break;
495
+ case "Home":
496
+ next = enabled[0];
497
+ break;
498
+ case "End":
499
+ next = enabled[enabled.length - 1];
500
+ break;
501
+ default:
502
+ return;
503
+ }
504
+ event.preventDefault();
505
+ if (next !== void 0) headerRefs.current[next]?.focus();
506
+ };
507
+ return /* @__PURE__ */ jsx("div", { className: cx("ansh-accordion", `ansh-accordion--${variant}`, className), children: items.map((item, index) => {
508
+ const open = openIds.includes(item.id);
509
+ const panelId = `${baseId}-panel-${item.id}`;
510
+ const headerId = `${baseId}-header-${item.id}`;
511
+ return /* @__PURE__ */ jsxs(
512
+ "div",
513
+ {
514
+ className: cx("ansh-accordion__item", open && "ansh-accordion__item--open"),
515
+ "data-state": open ? "open" : "closed",
516
+ children: [
517
+ /* @__PURE__ */ jsx("h3", { className: "ansh-accordion__heading", children: /* @__PURE__ */ jsxs(
518
+ "button",
519
+ {
520
+ ref: (node) => {
521
+ headerRefs.current[index] = node;
522
+ },
523
+ type: "button",
524
+ id: headerId,
525
+ className: "ansh-accordion__trigger ansh-focusable",
526
+ "aria-expanded": open,
527
+ "aria-controls": panelId,
528
+ disabled: item.disabled,
529
+ onClick: () => toggle(item.id),
530
+ onKeyDown: onKeyDown(index),
531
+ children: [
532
+ item.icon ? /* @__PURE__ */ jsx("span", { className: "ansh-accordion__icon", children: item.icon }) : null,
533
+ /* @__PURE__ */ jsxs("span", { className: "ansh-accordion__text", children: [
534
+ /* @__PURE__ */ jsx("span", { className: "ansh-accordion__title", children: item.title }),
535
+ item.subtitle ? /* @__PURE__ */ jsx("span", { className: "ansh-accordion__subtitle", children: item.subtitle }) : null
536
+ ] }),
537
+ /* @__PURE__ */ jsx(
538
+ "span",
539
+ {
540
+ className: cx("ansh-accordion__chevron", open && "ansh-accordion__chevron--open"),
541
+ "aria-hidden": "true",
542
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", children: /* @__PURE__ */ jsx(
543
+ "path",
544
+ {
545
+ d: "M3 4.5L6 7.5l3-3",
546
+ stroke: "currentColor",
547
+ strokeWidth: "1.5",
548
+ fill: "none",
549
+ strokeLinecap: "round",
550
+ strokeLinejoin: "round"
551
+ }
552
+ ) })
553
+ }
554
+ )
555
+ ]
556
+ }
557
+ ) }),
558
+ /* @__PURE__ */ jsx(
559
+ "div",
560
+ {
561
+ className: "ansh-accordion__region",
562
+ id: panelId,
563
+ role: "region",
564
+ "aria-labelledby": headerId,
565
+ "data-state": open ? "open" : "closed",
566
+ children: /* @__PURE__ */ jsx("div", { className: "ansh-accordion__panel", ...open ? null : { inert: true }, children: item.content })
567
+ }
568
+ )
569
+ ]
570
+ },
571
+ item.id
572
+ );
573
+ }) });
574
+ }
575
+ function DisclosureList({
576
+ items,
577
+ initial = 3,
578
+ moreLabel = (hidden) => `Show ${hidden} more`,
579
+ lessLabel = "Show less",
580
+ className
581
+ }) {
582
+ const [expanded, setExpanded] = useState(false);
583
+ const id = useId();
584
+ const hidden = items.length - initial;
585
+ if (hidden <= 0) {
586
+ return /* @__PURE__ */ jsx("ul", { className: cx("ansh-disclosure-list", className), children: items.map((item, index) => /* @__PURE__ */ jsx("li", { children: item }, index)) });
587
+ }
588
+ return /* @__PURE__ */ jsxs("div", { className, children: [
589
+ /* @__PURE__ */ jsx("ul", { className: "ansh-disclosure-list", id, children: (expanded ? items : items.slice(0, initial)).map((item, index) => /* @__PURE__ */ jsx("li", { children: item }, index)) }),
590
+ /* @__PURE__ */ jsx(
591
+ "button",
592
+ {
593
+ type: "button",
594
+ className: "ansh-disclosure-list__toggle ansh-focusable",
595
+ "aria-expanded": expanded,
596
+ "aria-controls": id,
597
+ onClick: () => setExpanded((v) => !v),
598
+ children: expanded ? lessLabel : moreLabel(hidden)
599
+ }
600
+ )
601
+ ] });
602
+ }
603
+
604
+ export { Accordion, Breadcrumbs, Collapsible, DisclosureList, NavigationMenu, Stepper, Tabs };
605
+ //# sourceMappingURL=chunk-OLTS6G5M.js.map
606
+ //# sourceMappingURL=chunk-OLTS6G5M.js.map