twico-ui 1.3.2 → 1.5.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.
package/dist/index.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  "use client";
2
- import * as React23 from 'react';
3
- import React23__default from 'react';
2
+ import * as React24 from 'react';
3
+ import React24__default from 'react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
  import { createPortal } from 'react-dom';
6
6
 
7
7
  // components/navigation/Accordion.jsx
8
- var SUPPORTS_STYLE_HOIST = parseInt(String(React23.version), 10) >= 19;
8
+ var SUPPORTS_STYLE_HOIST = parseInt(String(React24.version), 10) >= 19;
9
9
  function useScopedStyles(id, css) {
10
- React23.useInsertionEffect(() => {
10
+ React24.useInsertionEffect(() => {
11
11
  if (SUPPORTS_STYLE_HOIST) return;
12
12
  if (typeof document === "undefined" || document.getElementById(id)) return;
13
13
  const el = document.createElement("style");
@@ -15,7 +15,7 @@ function useScopedStyles(id, css) {
15
15
  el.textContent = css;
16
16
  document.head.appendChild(el);
17
17
  }, [id, css]);
18
- return SUPPORTS_STYLE_HOIST ? React23.createElement("style", { href: id, precedence: "twc-ui" }, css) : null;
18
+ return SUPPORTS_STYLE_HOIST ? React24.createElement("style", { href: id, precedence: "twc-ui" }, css) : null;
19
19
  }
20
20
  var ACCORDION_CSS = `
21
21
  .twc-accordion { display: flex; flex-direction: column; font-family: var(--font-sans);
@@ -29,7 +29,9 @@ var ACCORDION_CSS = `
29
29
  color: var(--color-text); text-align: start;
30
30
  transition: background-color var(--duration-fast) var(--ease-standard);
31
31
  }
32
- .twc-accordion__trigger:hover { background: var(--color-surface-sunken); }
32
+ .twc-accordion__heading { margin: 0; font: inherit; }
33
+ .twc-accordion__trigger:hover:not(:disabled) { background: var(--color-surface-sunken); }
34
+ .twc-accordion__trigger:disabled { opacity: 0.45; cursor: not-allowed; }
33
35
  .twc-accordion__trigger:focus-visible { outline: none; box-shadow: var(--ring); }
34
36
  .twc-accordion__label { flex: 1; }
35
37
  .twc-accordion__chevron { flex: none; color: var(--color-text-subtle); transition: transform var(--duration-base) var(--ease-spring); }
@@ -48,14 +50,19 @@ function Accordion({
48
50
  defaultOpen = [],
49
51
  open: openProp,
50
52
  onOpenChange,
53
+ headingLevel = 3,
51
54
  className = "",
55
+ onKeyDown: onKeyDownProp,
52
56
  ...rest
53
57
  }) {
54
58
  const __twcStyles = useScopedStyles("twc-accordion-styles", ACCORDION_CSS);
55
- const [internal, setInternal] = React23__default.useState(() => new Set(defaultOpen));
59
+ const rootRef = React24__default.useRef(null);
60
+ const [internal, setInternal] = React24__default.useState(() => new Set(defaultOpen));
56
61
  const open = openProp !== void 0 ? new Set(openProp) : internal;
57
- const baseId = React23__default.useId();
62
+ const baseId = React24__default.useId();
58
63
  function toggle(val) {
64
+ const item = items.find((x) => x.value === val);
65
+ if (item?.disabled) return;
59
66
  const next = new Set(open);
60
67
  if (next.has(val)) next.delete(val);
61
68
  else {
@@ -65,18 +72,47 @@ function Accordion({
65
72
  if (openProp === void 0) setInternal(next);
66
73
  onOpenChange?.([...next]);
67
74
  }
68
- return /* @__PURE__ */ jsxs("div", { className: `twc-accordion ${className}`, ...rest, children: [
75
+ function handleKeyDown(e) {
76
+ onKeyDownProp?.(e);
77
+ if (!(e.target instanceof HTMLElement) || !e.target.classList.contains("twc-accordion__trigger")) return;
78
+ const triggers = Array.from(rootRef.current.querySelectorAll(".twc-accordion__trigger")).filter((b) => !b.disabled);
79
+ const i = triggers.indexOf(e.target);
80
+ if (i < 0) return;
81
+ const len2 = triggers.length;
82
+ let next;
83
+ switch (e.key) {
84
+ case "ArrowDown":
85
+ next = (i + 1) % len2;
86
+ break;
87
+ case "ArrowUp":
88
+ next = (i - 1 + len2) % len2;
89
+ break;
90
+ case "Home":
91
+ next = 0;
92
+ break;
93
+ case "End":
94
+ next = len2 - 1;
95
+ break;
96
+ default:
97
+ return;
98
+ }
99
+ e.preventDefault();
100
+ triggers[next].focus();
101
+ }
102
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: `twc-accordion ${className}`, onKeyDown: handleKeyDown, ...rest, children: [
69
103
  __twcStyles,
70
104
  items.map((it, i) => {
71
105
  const isOpen = open.has(it.value);
72
106
  const triggerId = `${baseId}-trigger-${i}`;
73
107
  const panelId = `${baseId}-panel-${i}`;
108
+ const lvl = Math.min(6, Math.max(1, it.headingLevel ?? headingLevel));
109
+ const Heading2 = `h${lvl}`;
74
110
  return /* @__PURE__ */ jsxs("div", { className: "twc-accordion__item", children: [
75
- /* @__PURE__ */ jsxs("button", { type: "button", id: triggerId, className: "twc-accordion__trigger", "data-open": isOpen || void 0, "aria-expanded": isOpen, "aria-controls": panelId, onClick: () => toggle(it.value), children: [
111
+ /* @__PURE__ */ jsx(Heading2, { className: "twc-accordion__heading", children: /* @__PURE__ */ jsxs("button", { type: "button", id: triggerId, className: "twc-accordion__trigger", "data-open": isOpen || void 0, disabled: it.disabled || void 0, "aria-disabled": it.disabled || void 0, "data-disabled": it.disabled || void 0, "aria-expanded": isOpen, "aria-controls": panelId, onClick: () => toggle(it.value), children: [
76
112
  it.icon,
77
113
  /* @__PURE__ */ jsx("span", { className: "twc-accordion__label", children: it.label }),
78
114
  /* @__PURE__ */ jsx("span", { className: "twc-accordion__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) }) })
79
- ] }),
115
+ ] }) }),
80
116
  /* @__PURE__ */ jsx("div", { className: "twc-accordion__panel", id: panelId, role: "region", "aria-labelledby": triggerId, "data-open": isOpen || void 0, children: /* @__PURE__ */ jsx("div", { className: "twc-accordion__panel-inner", children: /* @__PURE__ */ jsx("div", { className: "twc-accordion__content", children: it.content }) }) })
81
117
  ] }, it.value);
82
118
  })
@@ -132,11 +168,15 @@ function Alert({
132
168
  title,
133
169
  icon,
134
170
  onClose,
171
+ live,
172
+ closeLabel = "Dismiss",
135
173
  className = "",
136
174
  ...rest
137
175
  }) {
138
176
  const __twcStyles = useScopedStyles("twc-alert-styles", ALERT_CSS);
139
- return /* @__PURE__ */ jsxs("div", { className: `twc-alert ${className}`, "data-tone": tone, "data-variant": variant, role: "alert", ...rest, children: [
177
+ const resolvedLive = live ?? (tone === "danger" || tone === "warning" ? "assertive" : tone === "success" || tone === "info" ? "polite" : "off");
178
+ const liveProps = resolvedLive === "assertive" ? { role: "alert" } : resolvedLive === "polite" ? { role: "status" } : {};
179
+ return /* @__PURE__ */ jsxs("div", { className: `twc-alert ${className}`, "data-tone": tone, "data-variant": variant, ...liveProps, ...rest, children: [
140
180
  __twcStyles,
141
181
  /* @__PURE__ */ jsx("span", { className: "twc-alert__icon", "aria-hidden": "true", children: icon || /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
142
182
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
@@ -146,7 +186,7 @@ function Alert({
146
186
  title ? /* @__PURE__ */ jsx("div", { className: "twc-alert__title", children: title }) : null,
147
187
  children ? /* @__PURE__ */ jsx("div", { className: "twc-alert__desc", children }) : null
148
188
  ] }),
149
- onClose ? /* @__PURE__ */ jsx("button", { className: "twc-alert__close", onClick: onClose, "aria-label": "Dismiss", type: "button", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
189
+ onClose ? /* @__PURE__ */ jsx("button", { className: "twc-alert__close", onClick: onClose, "aria-label": closeLabel, type: "button", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
150
190
  ] });
151
191
  }
152
192
  var AVATAR_CSS = `
@@ -187,22 +227,29 @@ function initials(name) {
187
227
  function safeSrc(url) {
188
228
  if (url == null) return void 0;
189
229
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
190
- return s.startsWith("javascript:") || s.startsWith("vbscript:") ? void 0 : url;
230
+ if (s.startsWith("javascript:") || s.startsWith("vbscript:")) return void 0;
231
+ if (s.startsWith("data:") && !s.startsWith("data:image/")) return void 0;
232
+ return url;
191
233
  }
234
+ var STATUS_LABELS = { online: "Online", busy: "Busy", away: "Away", offline: "Offline" };
192
235
  function Avatar({
193
236
  src,
194
237
  name,
195
238
  size = "md",
196
239
  square = false,
197
240
  status,
241
+ statusLabel,
242
+ statusLabels,
198
243
  ring = false,
199
244
  className = "",
200
245
  ...rest
201
246
  }) {
202
247
  const __twcStyles = useScopedStyles("twc-avatar-styles", AVATAR_CSS);
203
- const [errored, setErrored] = React23__default.useState(false);
248
+ const [errored, setErrored] = React24__default.useState(false);
204
249
  const cleanSrc = safeSrc(src);
205
250
  const showImg = cleanSrc && !errored;
251
+ const _statusLabel = status ? statusLabel ?? statusLabels?.[status] ?? STATUS_LABELS[status] : void 0;
252
+ const baseName = name || "avatar";
206
253
  return /* @__PURE__ */ jsxs(
207
254
  "span",
208
255
  {
@@ -210,12 +257,12 @@ function Avatar({
210
257
  "data-size": size,
211
258
  "data-square": square || void 0,
212
259
  role: "img",
213
- "aria-label": name || "avatar",
260
+ "aria-label": _statusLabel ? `${baseName}, ${_statusLabel}` : baseName,
214
261
  ...rest,
215
262
  children: [
216
263
  __twcStyles,
217
264
  showImg ? /* @__PURE__ */ jsx("img", { className: "twc-avatar__img", src: cleanSrc, alt: name || "", onError: () => setErrored(true) }, cleanSrc) : initials(name),
218
- status ? /* @__PURE__ */ jsx("span", { className: "twc-avatar__status", "data-status": status }) : null
265
+ status ? /* @__PURE__ */ jsx("span", { className: "twc-avatar__status", "data-status": status, title: _statusLabel }) : null
219
266
  ]
220
267
  }
221
268
  );
@@ -256,6 +303,11 @@ var MENU_CSS = `
256
303
  .twc-menu__item-label { flex: 1 1 auto; min-width: 0; }
257
304
  .twc-menu__shortcut { margin-inline-start: auto; padding-inline-start: var(--space-3); font-size: var(--text-xs); color: var(--color-text-subtle); font-family: var(--font-mono); }
258
305
  `;
306
+ var safeHref = (url) => {
307
+ if (url == null) return void 0;
308
+ const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
309
+ return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
310
+ };
259
311
  function Menu({
260
312
  trigger,
261
313
  items,
@@ -265,26 +317,29 @@ function Menu({
265
317
  open: openProp,
266
318
  defaultOpen = false,
267
319
  onOpenChange,
320
+ "aria-label": ariaLabel,
321
+ "aria-labelledby": ariaLabelledby,
268
322
  className = "",
269
323
  ...rest
270
324
  }) {
271
325
  const __twcStyles = useScopedStyles("twc-menu-styles", MENU_CSS);
272
- const [openState, setOpenState] = React23__default.useState(defaultOpen);
273
- const [render, setRender] = React23__default.useState(false);
274
- const [pos, setPos] = React23__default.useState(null);
275
- const [active, setActive] = React23__default.useState(-1);
276
- const wrapRef = React23__default.useRef(null);
277
- const menuRef = React23__default.useRef(null);
278
- const menuId = React23__default.useId();
326
+ const [openState, setOpenState] = React24__default.useState(defaultOpen);
327
+ const [render, setRender] = React24__default.useState(false);
328
+ const [pos, setPos] = React24__default.useState(null);
329
+ const [active, setActive] = React24__default.useState(-1);
330
+ const wrapRef = React24__default.useRef(null);
331
+ const menuRef = React24__default.useRef(null);
332
+ const menuId = React24__default.useId();
333
+ const headerId = `${menuId}-header`;
279
334
  const controlled = openProp !== void 0;
280
335
  const open = controlled ? !!openProp : openState;
281
- const openRef = React23__default.useRef(open);
336
+ const openRef = React24__default.useRef(open);
282
337
  openRef.current = open;
283
- const controlledRef = React23__default.useRef(controlled);
338
+ const controlledRef = React24__default.useRef(controlled);
284
339
  controlledRef.current = controlled;
285
- const onOpenChangeRef = React23__default.useRef(onOpenChange);
340
+ const onOpenChangeRef = React24__default.useRef(onOpenChange);
286
341
  onOpenChangeRef.current = onOpenChange;
287
- const setOpen = React23__default.useCallback((next) => {
342
+ const setOpen = React24__default.useCallback((next) => {
288
343
  const value = typeof next === "function" ? next(openRef.current) : next;
289
344
  if (value === openRef.current) return;
290
345
  if (!controlledRef.current) setOpenState(value);
@@ -292,7 +347,7 @@ function Menu({
292
347
  }, []);
293
348
  const RD = { createPortal: typeof createPortal === "function" ? createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
294
349
  const interactiveIdx = items.map((it, i) => !it.separator && !it.heading ? i : -1).filter((i) => i >= 0);
295
- const place = React23__default.useCallback(() => {
350
+ const place = React24__default.useCallback(() => {
296
351
  const t = wrapRef.current;
297
352
  if (!t) return;
298
353
  const r = t.getBoundingClientRect();
@@ -307,7 +362,7 @@ function Menu({
307
362
  const avail = (flip ? r.top : vh - r.bottom) - gap - M;
308
363
  setPos({ top, bottom, left, width: w, flip, maxHeight: Math.max(120, avail) });
309
364
  }, [align, width]);
310
- React23__default.useEffect(() => {
365
+ React24__default.useEffect(() => {
311
366
  if (!open) return;
312
367
  place();
313
368
  const onMove = () => place();
@@ -325,7 +380,7 @@ function Menu({
325
380
  document.removeEventListener("mousedown", onDown);
326
381
  };
327
382
  }, [open, place]);
328
- React23__default.useEffect(() => {
383
+ React24__default.useEffect(() => {
329
384
  if (open) {
330
385
  setRender(true);
331
386
  return;
@@ -371,8 +426,12 @@ function Menu({
371
426
  e.preventDefault();
372
427
  const it = items[active];
373
428
  if (it && !it.disabled) {
374
- it.onClick?.();
375
- setOpen(false);
429
+ const el = typeof document !== "undefined" ? document.getElementById(`${menuId}-item-${active}`) : null;
430
+ if (el && el.tagName === "A") el.click();
431
+ else {
432
+ it.onClick?.();
433
+ setOpen(false);
434
+ }
376
435
  }
377
436
  }
378
437
  }
@@ -386,29 +445,32 @@ function Menu({
386
445
  "data-align": align,
387
446
  "data-flip": pos.flip || void 0,
388
447
  role: "menu",
448
+ "aria-label": ariaLabel,
449
+ "aria-labelledby": ariaLabelledby ?? (ariaLabel ? void 0 : header ? headerId : void 0),
389
450
  style: { top: pos.top, bottom: pos.bottom, left: pos.left, minWidth: pos.width, width: pos.width, maxHeight: pos.maxHeight },
390
451
  children: [
391
452
  __twcStyles,
392
- header ? /* @__PURE__ */ jsx("div", { className: "twc-menu__header", children: header }) : null,
453
+ header ? /* @__PURE__ */ jsx("div", { className: "twc-menu__header", id: headerId, children: header }) : null,
393
454
  items.map((it, i) => {
394
455
  if (it.separator) return /* @__PURE__ */ jsx("div", { className: "twc-menu__sep", role: "separator" }, `s${i}`);
395
456
  if (it.label && it.heading) return /* @__PURE__ */ jsx("div", { className: "twc-menu__label", children: it.label }, `h${i}`);
457
+ const href = !it.disabled ? safeHref(it.href) : void 0;
458
+ const Tag2 = href ? "a" : "button";
396
459
  return /* @__PURE__ */ jsxs(
397
- "button",
460
+ Tag2,
398
461
  {
399
- type: "button",
400
462
  id: `${menuId}-item-${i}`,
401
463
  className: "twc-menu__item",
402
464
  role: "menuitem",
403
465
  tabIndex: -1,
404
466
  "data-danger": it.danger || void 0,
405
467
  "data-active": active === i || void 0,
406
- disabled: it.disabled,
407
468
  onMouseEnter: () => setActive(i),
408
469
  onClick: () => {
409
470
  it.onClick?.();
410
471
  setOpen(false);
411
472
  },
473
+ ...Tag2 === "button" ? { type: "button", disabled: it.disabled } : { href, target: it.target, rel: it.rel },
412
474
  children: [
413
475
  it.icon,
414
476
  /* @__PURE__ */ jsx("span", { className: "twc-menu__item-label", children: it.label }),
@@ -422,7 +484,7 @@ function Menu({
422
484
  }
423
485
  ) : null;
424
486
  const activeDescId = open && active >= 0 ? `${menuId}-item-${active}` : void 0;
425
- const triggerEl = React23__default.isValidElement(trigger) ? React23__default.cloneElement(trigger, {
487
+ const triggerEl = React24__default.isValidElement(trigger) ? React24__default.cloneElement(trigger, {
426
488
  onClick: (e) => {
427
489
  trigger.props.onClick?.(e);
428
490
  toggle();
@@ -505,7 +567,7 @@ function AvatarMenu({
505
567
  ]
506
568
  }
507
569
  );
508
- return /* @__PURE__ */ jsx(Menu, { className, trigger, items, header, align, width: 240, ...rest });
570
+ return /* @__PURE__ */ jsx(Menu, { className, trigger, items, header, align, width: 240, "aria-label": `${name || "Account"} menu`, ...rest });
509
571
  }
510
572
  var BADGE_CSS = `
511
573
  .twc-badge {
@@ -572,7 +634,7 @@ var BREADCRUMB_CSS = `
572
634
  .twc-breadcrumb__ellipsis { border: none; background: transparent; cursor: pointer; color: var(--color-text-subtle); padding: 3px 7px; border-radius: var(--radius-sm); font: inherit; }
573
635
  .twc-breadcrumb__ellipsis:hover { background: var(--color-surface-sunken); color: var(--color-text); }
574
636
  `;
575
- function safeHref(url) {
637
+ function safeHref2(url) {
576
638
  if (url == null) return void 0;
577
639
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
578
640
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -586,7 +648,7 @@ function Breadcrumb({
586
648
  ...rest
587
649
  }) {
588
650
  const __twcStyles = useScopedStyles("twc-breadcrumb-styles", BREADCRUMB_CSS);
589
- const [expanded, setExpanded] = React23__default.useState(false);
651
+ const [expanded, setExpanded] = React24__default.useState(false);
590
652
  const sep = separator || /* @__PURE__ */ jsx(ChevronSep, {});
591
653
  let display = items;
592
654
  if (maxItems > 0 && items.length > maxItems && !expanded) {
@@ -599,7 +661,7 @@ function Breadcrumb({
599
661
  __twcStyles,
600
662
  display.map((it, i) => {
601
663
  const last = i === display.length - 1;
602
- return /* @__PURE__ */ jsxs(React23__default.Fragment, { children: [
664
+ return /* @__PURE__ */ jsxs(React24__default.Fragment, { children: [
603
665
  it.ellipsis ? /* @__PURE__ */ jsx("button", { className: "twc-breadcrumb__ellipsis", "aria-label": "Show more", onClick: () => setExpanded(true), children: "\u2026" }) : last ? /* @__PURE__ */ jsxs(
604
666
  "span",
605
667
  {
@@ -615,7 +677,7 @@ function Breadcrumb({
615
677
  "a",
616
678
  {
617
679
  className: "twc-breadcrumb__item",
618
- href: safeHref(it.href) || "#",
680
+ href: safeHref2(it.href) || "#",
619
681
  onClick: it.onClick,
620
682
  children: [
621
683
  it.icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
@@ -718,7 +780,7 @@ var CSS2 = `
718
780
  animation: twico-ripple var(--duration-slow) var(--ease-out) forwards;
719
781
  }
720
782
  `;
721
- function safeHref2(url) {
783
+ function safeHref3(url) {
722
784
  if (url == null) return void 0;
723
785
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
724
786
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -740,7 +802,7 @@ function Button({
740
802
  ...rest
741
803
  }) {
742
804
  const __twcStyles = useScopedStyles("twc-btn-styles", CSS2);
743
- const [ripples, setRipples] = React23__default.useState([]);
805
+ const [ripples, setRipples] = React24__default.useState([]);
744
806
  const Tag2 = as;
745
807
  const inert = Tag2 === "a" && (disabled || loading);
746
808
  function handleClick(e) {
@@ -769,7 +831,7 @@ function Button({
769
831
  "data-block": fullWidth || void 0,
770
832
  disabled: Tag2 === "button" ? disabled || loading : void 0,
771
833
  type: Tag2 === "button" ? "button" : void 0,
772
- href: inert ? void 0 : safeHref2(href),
834
+ href: inert ? void 0 : safeHref3(href),
773
835
  "aria-disabled": inert || void 0,
774
836
  tabIndex: inert ? -1 : void 0,
775
837
  "aria-busy": loading || void 0,
@@ -877,6 +939,15 @@ var CAROUSEL_CSS = `
877
939
  .twc-carousel__dot { width: 8px; height: 8px; border-radius: var(--radius-full); border: none; padding: 0; cursor: pointer;
878
940
  background: var(--color-border-strong); transition: width var(--duration-base) var(--ease-spring), background-color var(--duration-fast); }
879
941
  .twc-carousel__dot[data-active="true"] { width: 22px; background: var(--color-primary); }
942
+ .twc-carousel__pause { position: absolute; top: 12px; inset-inline-end: 12px; z-index: 2;
943
+ display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--radius-full);
944
+ background: color-mix(in srgb, var(--color-surface) 88%, transparent); color: var(--color-text);
945
+ border: var(--border-thin) solid var(--color-border); box-shadow: var(--shadow-sm); cursor: pointer;
946
+ backdrop-filter: blur(6px); transition: background-color var(--duration-fast) var(--ease-standard); }
947
+ .twc-carousel__pause:hover { background: var(--color-surface); }
948
+ .twc-carousel__pause svg { width: 15px; height: 15px; display: block; }
949
+ .twc-carousel__live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
950
+ overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
880
951
  `;
881
952
  function Carousel({
882
953
  children,
@@ -885,35 +956,76 @@ function Carousel({
885
956
  onIndexChange,
886
957
  showArrows = true,
887
958
  showDots = true,
959
+ showPauseButton = true,
888
960
  loop = true,
889
961
  autoPlay = false,
890
962
  interval = 4e3,
963
+ label,
964
+ pauseLabel = "Pause",
965
+ playLabel = "Play",
891
966
  className = "",
967
+ onKeyDown: onKeyDownProp,
968
+ "aria-label": ariaLabelProp,
969
+ "aria-labelledby": ariaLabelledbyProp,
892
970
  ...rest
893
971
  }) {
894
972
  const __twcStyles = useScopedStyles("twc-carousel-styles", CAROUSEL_CSS);
895
- const slides = React23__default.Children.toArray(children);
973
+ const slides = React24__default.Children.toArray(children);
896
974
  const count = slides.length;
897
- const [internal, setInternal] = React23__default.useState(defaultIndex);
975
+ const [internal, setInternal] = React24__default.useState(defaultIndex);
898
976
  const index = indexProp !== void 0 ? indexProp : internal;
899
- const [paused, setPaused] = React23__default.useState(false);
900
- const setIndex = React23__default.useCallback((i) => {
977
+ const [paused, setPaused] = React24__default.useState(false);
978
+ const [userPaused, setUserPaused] = React24__default.useState(false);
979
+ const [prefersReduced, setPrefersReduced] = React24__default.useState(false);
980
+ React24__default.useEffect(() => {
981
+ if (typeof window === "undefined" || !window.matchMedia) return void 0;
982
+ const mql = window.matchMedia("(prefers-reduced-motion: reduce)");
983
+ const on = () => setPrefersReduced(mql.matches);
984
+ on();
985
+ mql.addEventListener("change", on);
986
+ return () => mql.removeEventListener("change", on);
987
+ }, []);
988
+ const setIndex = React24__default.useCallback((i) => {
901
989
  if (indexProp === void 0) setInternal(i);
902
990
  onIndexChange?.(i);
903
991
  }, [indexProp, onIndexChange]);
904
- const go = React23__default.useCallback((i) => {
992
+ const go = React24__default.useCallback((i) => {
905
993
  setIndex(loop ? (i + count) % count : Math.min(Math.max(i, 0), count - 1));
906
994
  }, [count, loop, setIndex]);
907
- React23__default.useEffect(() => {
908
- if (!autoPlay || paused || count <= 1) return;
995
+ const autoRotating = autoPlay && !paused && !userPaused && !prefersReduced && count > 1;
996
+ React24__default.useEffect(() => {
997
+ if (!autoRotating) return void 0;
909
998
  const t = setInterval(() => {
910
999
  const next = loop ? (index + 1) % count : index + 1 >= count ? index : index + 1;
911
1000
  if (next !== index) setIndex(next);
912
1001
  }, interval);
913
1002
  return () => clearInterval(t);
914
- }, [autoPlay, paused, count, interval, loop, index, setIndex]);
1003
+ }, [autoRotating, count, interval, loop, index, setIndex]);
915
1004
  const atStart = !loop && index === 0;
916
1005
  const atEnd = !loop && index === count - 1;
1006
+ const handleKeyDown = (e) => {
1007
+ onKeyDownProp?.(e);
1008
+ if (e.defaultPrevented) return;
1009
+ if (e.target.closest && e.target.closest('input, textarea, select, [contenteditable="true"]')) return;
1010
+ switch (e.key) {
1011
+ case "ArrowLeft":
1012
+ go(index - 1);
1013
+ break;
1014
+ case "ArrowRight":
1015
+ go(index + 1);
1016
+ break;
1017
+ case "Home":
1018
+ go(0);
1019
+ break;
1020
+ case "End":
1021
+ go(count - 1);
1022
+ break;
1023
+ default:
1024
+ return;
1025
+ }
1026
+ e.preventDefault();
1027
+ };
1028
+ const ariaLabel = ariaLabelledbyProp ? void 0 : ariaLabelProp ?? label ?? "Carousel";
917
1029
  return /* @__PURE__ */ jsxs(
918
1030
  "div",
919
1031
  {
@@ -922,12 +1034,17 @@ function Carousel({
922
1034
  onMouseLeave: () => setPaused(false),
923
1035
  onFocusCapture: () => setPaused(true),
924
1036
  onBlurCapture: () => setPaused(false),
1037
+ onKeyDown: handleKeyDown,
925
1038
  role: "region",
926
1039
  "aria-roledescription": "carousel",
1040
+ "aria-label": ariaLabel,
1041
+ "aria-labelledby": ariaLabelledbyProp,
927
1042
  ...rest,
928
1043
  children: [
929
1044
  __twcStyles,
930
- /* @__PURE__ */ jsx("div", { className: "twc-carousel__viewport", children: /* @__PURE__ */ jsx("div", { className: "twc-carousel__track", style: { transform: `translateX(-${index * 100}%)` }, children: slides.map((s, i) => /* @__PURE__ */ jsx("div", { className: "twc-carousel__slide", role: "group", "aria-roledescription": "slide", "aria-label": `${i + 1} of ${count}`, "aria-hidden": i !== index || void 0, inert: i !== index || void 0, children: s }, i)) }) }),
1045
+ /* @__PURE__ */ jsx("div", { className: "twc-carousel__viewport", tabIndex: 0, children: /* @__PURE__ */ jsx("div", { className: "twc-carousel__track", style: { transform: `translateX(-${index * 100}%)` }, children: slides.map((s, i) => /* @__PURE__ */ jsx("div", { className: "twc-carousel__slide", role: "group", "aria-roledescription": "slide", "aria-label": `${i + 1} of ${count}`, "aria-hidden": i !== index || void 0, inert: i !== index || void 0, children: s }, i)) }) }),
1046
+ /* @__PURE__ */ jsx("div", { className: "twc-carousel__live", "aria-live": autoRotating ? "off" : "polite", "aria-atomic": "true", children: count > 1 ? `Slide ${index + 1} of ${count}` : null }),
1047
+ autoPlay && showPauseButton && count > 1 ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-carousel__pause", "aria-label": userPaused ? playLabel : pauseLabel, onClick: () => setUserPaused((v) => !v), children: userPaused ? /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M8 5v14l11-7z" }) }) : /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M6 5h4v14H6zM14 5h4v14h-4z" }) }) }) : null,
931
1048
  showArrows && count > 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
932
1049
  /* @__PURE__ */ jsx("button", { className: "twc-carousel__arrow", "data-dir": "prev", "aria-label": "Previous", disabled: atStart, onClick: () => go(index - 1), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
933
1050
  /* @__PURE__ */ jsx("button", { className: "twc-carousel__arrow", "data-dir": "next", "aria-label": "Next", disabled: atEnd, onClick: () => go(index + 1), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) }) })
@@ -950,6 +1067,7 @@ var CHART_CSS = `
950
1067
  .twc-chart__leg { display: inline-flex; align-items: center; gap: 6px; }
951
1068
  .twc-chart__leg-sw { width: 10px; height: 10px; border-radius: 3px; }
952
1069
  @keyframes twc-chart-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
1070
+ .twc-chart__sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
953
1071
  `;
954
1072
  var SERIES_COLORS = ["var(--brand-500)", "var(--sky-500)", "var(--emerald-500)", "var(--amber-500)", "var(--rose-500)"];
955
1073
  function Chart({
@@ -964,10 +1082,14 @@ function Chart({
964
1082
  valueFormat,
965
1083
  ariaLabel,
966
1084
  "aria-label": ariaLabelProp,
1085
+ tableFallback = true,
1086
+ caption,
967
1087
  className = "",
968
1088
  ...rest
969
1089
  }) {
970
1090
  const __twcStyles = useScopedStyles("twc-chart-styles", CHART_CSS);
1091
+ const uid = React24__default.useId();
1092
+ const tableId = tableFallback ? `${uid}-table` : void 0;
971
1093
  const keys = series || ["value"];
972
1094
  const palette = colors && colors.length ? colors : SERIES_COLORS;
973
1095
  const W = 600, H = height, padL = showAxis ? 40 : 8, padR = 8, padT = 12, padB = showAxis ? 26 : 8;
@@ -980,7 +1102,7 @@ function Chart({
980
1102
  const svgAriaLabel = ariaLabelProp ?? ariaLabel ?? `${type} chart`;
981
1103
  return /* @__PURE__ */ jsxs("div", { className: `twc-chart ${className}`, ...rest, children: [
982
1104
  __twcStyles,
983
- /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": svgAriaLabel, preserveAspectRatio: "none", children: [
1105
+ /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": svgAriaLabel, "aria-describedby": tableId, preserveAspectRatio: "none", children: [
984
1106
  showGrid ? Array.from({ length: ticks + 1 }).map((_, i) => {
985
1107
  const gy = padT + innerH / ticks * i;
986
1108
  return /* @__PURE__ */ jsx("line", { className: "twc-chart__grid", x1: padL, y1: gy, x2: W - padR, y2: gy }, i);
@@ -1030,6 +1152,17 @@ function Chart({
1030
1152
  return /* @__PURE__ */ jsx("text", { className: "twc-chart__axis", x: cx, y: H - 8, textAnchor: "middle", children: d.label }, i);
1031
1153
  }) : null
1032
1154
  ] }),
1155
+ tableFallback ? /* @__PURE__ */ jsxs("table", { className: "twc-chart__sr", id: tableId, children: [
1156
+ /* @__PURE__ */ jsx("caption", { children: caption ?? svgAriaLabel }),
1157
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
1158
+ /* @__PURE__ */ jsx("th", { scope: "col" }),
1159
+ keys.map((k) => /* @__PURE__ */ jsx("th", { scope: "col", children: k }, k))
1160
+ ] }) }),
1161
+ /* @__PURE__ */ jsx("tbody", { children: data.map((d, i) => /* @__PURE__ */ jsxs("tr", { children: [
1162
+ /* @__PURE__ */ jsx("th", { scope: "row", children: d.label }),
1163
+ keys.map((k) => /* @__PURE__ */ jsx("td", { children: fmt(Number(d[k]) || 0) }, k))
1164
+ ] }, i)) })
1165
+ ] }) : null,
1033
1166
  showLegend && keys.length > 1 ? /* @__PURE__ */ jsx("div", { className: "twc-chart__legend", children: keys.map((k, si) => /* @__PURE__ */ jsxs("span", { className: "twc-chart__leg", children: [
1034
1167
  /* @__PURE__ */ jsx("span", { className: "twc-chart__leg-sw", style: { background: palette[si % palette.length] } }),
1035
1168
  k
@@ -1102,12 +1235,12 @@ function Checkbox({
1102
1235
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
1103
1236
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
1104
1237
  `);
1105
- const autoId = React23__default.useId();
1238
+ const autoId = React24__default.useId();
1106
1239
  const fieldId = id || autoId;
1107
1240
  const errId = `${fieldId}-error`;
1108
1241
  const invalid = Boolean(error);
1109
- const ref = React23__default.useRef(null);
1110
- React23__default.useEffect(() => {
1242
+ const ref = React24__default.useRef(null);
1243
+ React24__default.useEffect(() => {
1111
1244
  if (ref.current) ref.current.indeterminate = indeterminate;
1112
1245
  }, [indeterminate]);
1113
1246
  const describedBy = [rest["aria-describedby"], error ? errId : null].filter(Boolean).join(" ") || void 0;
@@ -1244,20 +1377,20 @@ function ColorPicker({
1244
1377
  }) {
1245
1378
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS);
1246
1379
  const __twcStyles1 = useScopedStyles("twc-colorpicker-styles", COLORPICKER_CSS);
1247
- const [internal, setInternal] = React23__default.useState(defaultValue);
1380
+ const [internal, setInternal] = React24__default.useState(defaultValue);
1248
1381
  const hex = (value !== void 0 ? value : internal) || "#000000";
1249
- const lastValidRef = React23__default.useRef(hex);
1382
+ const lastValidRef = React24__default.useRef(hex);
1250
1383
  if (/^#[0-9a-f]{6}$/i.test(hex)) lastValidRef.current = hex;
1251
- const [open, setOpen] = React23__default.useState(false);
1252
- const [hsv, setHsv] = React23__default.useState(() => hexToHsv(hex) || { h: 239, s: 60, v: 94 });
1253
- const [coords, setCoords] = React23__default.useState(null);
1254
- const wrapRef = React23__default.useRef(null);
1255
- const triggerRef = React23__default.useRef(null);
1256
- const popRef = React23__default.useRef(null);
1257
- const areaRef = React23__default.useRef(null);
1258
- const hueRef = React23__default.useRef(null);
1384
+ const [open, setOpen] = React24__default.useState(false);
1385
+ const [hsv, setHsv] = React24__default.useState(() => hexToHsv(hex) || { h: 239, s: 60, v: 94 });
1386
+ const [coords, setCoords] = React24__default.useState(null);
1387
+ const wrapRef = React24__default.useRef(null);
1388
+ const triggerRef = React24__default.useRef(null);
1389
+ const popRef = React24__default.useRef(null);
1390
+ const areaRef = React24__default.useRef(null);
1391
+ const hueRef = React24__default.useRef(null);
1259
1392
  const POP_W = 240;
1260
- const place = React23__default.useCallback(() => {
1393
+ const place = React24__default.useCallback(() => {
1261
1394
  const el = triggerRef.current;
1262
1395
  if (!el) return;
1263
1396
  const r = el.getBoundingClientRect();
@@ -1268,7 +1401,7 @@ function ColorPicker({
1268
1401
  left = Math.max(8, left);
1269
1402
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
1270
1403
  }, []);
1271
- React23__default.useEffect(() => {
1404
+ React24__default.useEffect(() => {
1272
1405
  if (!open) return void 0;
1273
1406
  place();
1274
1407
  const onMove = () => place();
@@ -1279,17 +1412,17 @@ function ColorPicker({
1279
1412
  window.removeEventListener("resize", onMove);
1280
1413
  };
1281
1414
  }, [open, place]);
1282
- const labelId = React23__default.useId();
1415
+ const labelId = React24__default.useId();
1283
1416
  const descId = `${labelId}-desc`;
1284
1417
  const invalid = Boolean(error);
1285
- React23__default.useEffect(() => {
1418
+ React24__default.useEffect(() => {
1286
1419
  if (disabled) setOpen(false);
1287
1420
  }, [disabled]);
1288
- React23__default.useEffect(() => {
1421
+ React24__default.useEffect(() => {
1289
1422
  const v = hexToHsv(hex);
1290
1423
  if (v && hsvToHex(v.h, v.s, v.v).toLowerCase() !== hsvToHex(hsv.h, hsv.s, hsv.v).toLowerCase()) setHsv(v);
1291
1424
  }, [hex]);
1292
- React23__default.useEffect(() => {
1425
+ React24__default.useEffect(() => {
1293
1426
  if (!open) return;
1294
1427
  const onDown = (e) => {
1295
1428
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -1306,8 +1439,8 @@ function ColorPicker({
1306
1439
  document.removeEventListener("keydown", onKey);
1307
1440
  };
1308
1441
  }, [open]);
1309
- const prevOpen = React23__default.useRef(false);
1310
- React23__default.useEffect(() => {
1442
+ const prevOpen = React24__default.useRef(false);
1443
+ React24__default.useEffect(() => {
1311
1444
  let id;
1312
1445
  if (!prevOpen.current && open) {
1313
1446
  id = setTimeout(() => areaRef.current?.focus({ preventScroll: true }), 20);
@@ -1627,29 +1760,29 @@ function Combobox({
1627
1760
  ...rest
1628
1761
  }) {
1629
1762
  const __twcStyles = useScopedStyles("twc-combo-styles", COMBO_CSS);
1630
- const groups = React23__default.useMemo(() => normalizeGroups(options), [options]);
1631
- const flat = React23__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
1632
- const autoId = React23__default.useId();
1763
+ const groups = React24__default.useMemo(() => normalizeGroups(options), [options]);
1764
+ const flat = React24__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
1765
+ const autoId = React24__default.useId();
1633
1766
  const fieldId = id || autoId;
1634
- const [internal, setInternal] = React23__default.useState(defaultValue);
1767
+ const [internal, setInternal] = React24__default.useState(defaultValue);
1635
1768
  const current = value !== void 0 ? value : internal;
1636
1769
  const selected = flat.find((o) => o.value === current);
1637
- const [open, setOpen] = React23__default.useState(false);
1638
- const [query, setQuery] = React23__default.useState("");
1639
- const [active, setActive] = React23__default.useState(0);
1640
- const [coords, setCoords] = React23__default.useState(null);
1641
- const wrapRef = React23__default.useRef(null);
1642
- const controlRef = React23__default.useRef(null);
1643
- const inputRef = React23__default.useRef(null);
1644
- const popRef = React23__default.useRef(null);
1645
- const listRef = React23__default.useRef(null);
1646
- const activeRef = React23__default.useRef(null);
1647
- const fGroups = React23__default.useMemo(
1770
+ const [open, setOpen] = React24__default.useState(false);
1771
+ const [query, setQuery] = React24__default.useState("");
1772
+ const [active, setActive] = React24__default.useState(0);
1773
+ const [coords, setCoords] = React24__default.useState(null);
1774
+ const wrapRef = React24__default.useRef(null);
1775
+ const controlRef = React24__default.useRef(null);
1776
+ const inputRef = React24__default.useRef(null);
1777
+ const popRef = React24__default.useRef(null);
1778
+ const listRef = React24__default.useRef(null);
1779
+ const activeRef = React24__default.useRef(null);
1780
+ const fGroups = React24__default.useMemo(
1648
1781
  () => groups.map((g) => ({ group: g.group, options: g.options.filter((o) => matches(o, query.trim())) })).filter((g) => g.options.length),
1649
1782
  [groups, query]
1650
1783
  );
1651
- const visible = React23__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
1652
- const place = React23__default.useCallback(() => {
1784
+ const visible = React24__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
1785
+ const place = React24__default.useCallback(() => {
1653
1786
  const el = controlRef.current;
1654
1787
  if (!el) return;
1655
1788
  const r = el.getBoundingClientRect();
@@ -1664,7 +1797,7 @@ function Combobox({
1664
1797
  flip
1665
1798
  });
1666
1799
  }, [placement, minWidth]);
1667
- React23__default.useEffect(() => {
1800
+ React24__default.useEffect(() => {
1668
1801
  if (!open || !portal) return;
1669
1802
  place();
1670
1803
  const onMove = () => place();
@@ -1675,7 +1808,7 @@ function Combobox({
1675
1808
  window.removeEventListener("resize", onMove);
1676
1809
  };
1677
1810
  }, [open, portal, place]);
1678
- React23__default.useEffect(() => {
1811
+ React24__default.useEffect(() => {
1679
1812
  if (!open) return;
1680
1813
  const onDown = (e) => {
1681
1814
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -1685,10 +1818,10 @@ function Combobox({
1685
1818
  document.addEventListener("mousedown", onDown);
1686
1819
  return () => document.removeEventListener("mousedown", onDown);
1687
1820
  }, [open]);
1688
- React23__default.useEffect(() => {
1821
+ React24__default.useEffect(() => {
1689
1822
  setActive(0);
1690
1823
  }, [query]);
1691
- React23__default.useEffect(() => {
1824
+ React24__default.useEffect(() => {
1692
1825
  if (open) ensureVisible(listRef.current, activeRef.current);
1693
1826
  }, [active, open]);
1694
1827
  function openMenu() {
@@ -1731,7 +1864,7 @@ function Combobox({
1731
1864
  const descId = `${fieldId}-desc`;
1732
1865
  const describedBy = error || hint ? descId : void 0;
1733
1866
  let counter = -1;
1734
- const popInner = /* @__PURE__ */ jsx("div", { className: "twc-pop__list", ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React23__default.Fragment, { children: [
1867
+ const popInner = /* @__PURE__ */ jsx("div", { className: "twc-pop__list", ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React24__default.Fragment, { children: [
1735
1868
  g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
1736
1869
  g.options.map((o) => {
1737
1870
  counter += 1;
@@ -1869,6 +2002,52 @@ function Combobox({
1869
2002
  error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
1870
2003
  ] });
1871
2004
  }
2005
+ var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
2006
+ var FOCUSABLE = 'a[href]:not([tabindex="-1"]), button:not([disabled]):not([tabindex="-1"]), textarea:not([disabled]):not([tabindex="-1"]), input:not([disabled]):not([tabindex="-1"]), select:not([disabled]):not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])';
2007
+ function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
2008
+ React24__default.useEffect(() => {
2009
+ if (!active || !canUseDOM) return void 0;
2010
+ const node = ref.current;
2011
+ if (!node) return void 0;
2012
+ const prevFocused = document.activeElement;
2013
+ const first = node.querySelector(FOCUSABLE);
2014
+ (first || node).focus();
2015
+ return () => {
2016
+ if (restoreFocus && prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
2017
+ };
2018
+ }, [active]);
2019
+ React24__default.useEffect(() => {
2020
+ if (!active || !canUseDOM) return void 0;
2021
+ const node = ref.current;
2022
+ const onKey = (e) => {
2023
+ if (e.key !== "Tab" || !node) return;
2024
+ const f = Array.from(node.querySelectorAll(FOCUSABLE)).filter((el) => el.offsetParent !== null);
2025
+ if (!f.length) {
2026
+ e.preventDefault();
2027
+ node.focus();
2028
+ return;
2029
+ }
2030
+ const first = f[0], last = f[f.length - 1], ae = document.activeElement;
2031
+ if (e.shiftKey) {
2032
+ if (ae === first || ae === node || !node.contains(ae)) {
2033
+ e.preventDefault();
2034
+ last.focus();
2035
+ }
2036
+ } else if (ae === last || !node.contains(ae)) {
2037
+ e.preventDefault();
2038
+ first.focus();
2039
+ }
2040
+ };
2041
+ document.addEventListener("keydown", onKey);
2042
+ return () => document.removeEventListener("keydown", onKey);
2043
+ }, [active]);
2044
+ }
2045
+ function usePortal() {
2046
+ return React24__default.useCallback((node) => {
2047
+ if (typeof document === "undefined") return null;
2048
+ return typeof createPortal === "function" ? createPortal(node, document.body) : node;
2049
+ }, []);
2050
+ }
1872
2051
  var COMMAND_CSS = `
1873
2052
  .twc-cmdk__overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: var(--color-overlay); backdrop-filter: blur(3px);
1874
2053
  display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
@@ -1914,14 +2093,15 @@ function CommandPalette({
1914
2093
  ...rest
1915
2094
  }) {
1916
2095
  const __twcStyles = useScopedStyles("twc-cmdk-styles", COMMAND_CSS);
1917
- const [query, setQuery] = React23__default.useState("");
1918
- const [active, setActive] = React23__default.useState(0);
1919
- const inputRef = React23__default.useRef(null);
1920
- const listRef = React23__default.useRef(null);
1921
- const paletteRef = React23__default.useRef(null);
1922
- const baseId = React23__default.useId();
1923
- const [mounted, setMounted] = React23__default.useState(open);
1924
- React23__default.useEffect(() => {
2096
+ const renderPortal = usePortal();
2097
+ const [query, setQuery] = React24__default.useState("");
2098
+ const [active, setActive] = React24__default.useState(0);
2099
+ const inputRef = React24__default.useRef(null);
2100
+ const listRef = React24__default.useRef(null);
2101
+ const paletteRef = React24__default.useRef(null);
2102
+ const baseId = React24__default.useId();
2103
+ const [mounted, setMounted] = React24__default.useState(open);
2104
+ React24__default.useEffect(() => {
1925
2105
  if (open) {
1926
2106
  setMounted(true);
1927
2107
  return;
@@ -1929,7 +2109,7 @@ function CommandPalette({
1929
2109
  const t = setTimeout(() => setMounted(false), 170);
1930
2110
  return () => clearTimeout(t);
1931
2111
  }, [open]);
1932
- React23__default.useEffect(() => {
2112
+ React24__default.useEffect(() => {
1933
2113
  if (!open) return void 0;
1934
2114
  const prev = document.body.style.overflow;
1935
2115
  document.body.style.overflow = "hidden";
@@ -1937,58 +2117,26 @@ function CommandPalette({
1937
2117
  document.body.style.overflow = prev;
1938
2118
  };
1939
2119
  }, [open]);
1940
- React23__default.useEffect(() => {
2120
+ React24__default.useEffect(() => {
1941
2121
  if (open) {
1942
2122
  setQuery("");
1943
2123
  setActive(0);
1944
- const t = setTimeout(() => inputRef.current?.focus(), 30);
1945
- return () => clearTimeout(t);
1946
2124
  }
1947
2125
  }, [open]);
1948
- React23__default.useEffect(() => {
1949
- if (!open) return;
1950
- const prevFocused = document.activeElement;
1951
- return () => {
1952
- if (prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
1953
- };
1954
- }, [open]);
1955
- React23__default.useEffect(() => {
1956
- if (!open) return;
1957
- const focusables = (node) => node ? Array.from(
1958
- node.querySelectorAll(
1959
- 'a[href]:not([tabindex="-1"]), button:not([disabled]):not([tabindex="-1"]), textarea:not([disabled]):not([tabindex="-1"]), input:not([disabled]):not([tabindex="-1"]), select:not([disabled]):not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])'
1960
- )
1961
- ).filter((el) => el.offsetParent !== null) : [];
2126
+ useFocusTrap(paletteRef, open && mounted);
2127
+ React24__default.useEffect(() => {
2128
+ if (!open) return void 0;
1962
2129
  const onKey = (e) => {
1963
2130
  if (e.key === "Escape") {
1964
2131
  e.preventDefault();
1965
2132
  onClose?.();
1966
- return;
1967
- }
1968
- if (e.key !== "Tab") return;
1969
- const node = paletteRef.current;
1970
- const f = focusables(node);
1971
- if (!f.length) {
1972
- e.preventDefault();
1973
- node?.focus();
1974
- return;
1975
- }
1976
- const first = f[0], last = f[f.length - 1], ae = document.activeElement;
1977
- if (e.shiftKey) {
1978
- if (ae === first || ae === node || !node.contains(ae)) {
1979
- e.preventDefault();
1980
- last.focus();
1981
- }
1982
- } else if (ae === last || !node.contains(ae)) {
1983
- e.preventDefault();
1984
- first.focus();
1985
2133
  }
1986
2134
  };
1987
2135
  document.addEventListener("keydown", onKey);
1988
2136
  return () => document.removeEventListener("keydown", onKey);
1989
2137
  }, [open, onClose]);
1990
2138
  const q = query.trim().toLowerCase();
1991
- const filtered = React23__default.useMemo(() => commands.filter(
2139
+ const filtered = React24__default.useMemo(() => commands.filter(
1992
2140
  (c) => !q || c.label.toLowerCase().includes(q) || (c.keywords || "").toLowerCase().includes(q) || (c.group || "").toLowerCase().includes(q)
1993
2141
  ), [commands, q]);
1994
2142
  const groups = [];
@@ -2003,7 +2151,7 @@ function CommandPalette({
2003
2151
  g.items.push(c);
2004
2152
  flat.push(c);
2005
2153
  });
2006
- React23__default.useEffect(() => {
2154
+ React24__default.useEffect(() => {
2007
2155
  setActive(0);
2008
2156
  }, [query]);
2009
2157
  const run = (cmd) => {
@@ -2023,11 +2171,11 @@ function CommandPalette({
2023
2171
  if (cmd) run(cmd);
2024
2172
  }
2025
2173
  }
2026
- React23__default.useEffect(() => {
2174
+ React24__default.useEffect(() => {
2027
2175
  const node = listRef.current?.querySelector('[data-active="true"]');
2028
2176
  if (node) node.scrollIntoView({ block: "nearest" });
2029
2177
  }, [active]);
2030
- if (!mounted || typeof document === "undefined") return null;
2178
+ if (!mounted) return null;
2031
2179
  const state = open ? "open" : "closed";
2032
2180
  const listId = `${baseId}-list`;
2033
2181
  const optionId = (i) => `${baseId}-opt-${i}`;
@@ -2093,8 +2241,7 @@ function CommandPalette({
2093
2241
  ] }, g.key || "_")) })
2094
2242
  ] })
2095
2243
  ] });
2096
- const RD = typeof createPortal === "function" ? createPortal : null;
2097
- return RD ? RD(overlay, document.body) : overlay;
2244
+ return renderPortal(overlay);
2098
2245
  }
2099
2246
  var CURRENCIES = {
2100
2247
  USD: { code: "USD", symbol: "$", precision: 2, label: "US Dollar" },
@@ -2197,11 +2344,11 @@ function Currency({
2197
2344
  const prec = precision != null ? precision : meta.precision;
2198
2345
  const sym = symbol != null ? symbol : meta.symbol;
2199
2346
  const cur = code != null ? code : meta.code;
2200
- const autoId = React23__default.useId();
2347
+ const autoId = React24__default.useId();
2201
2348
  const fieldId = id || autoId;
2202
2349
  const invalid = Boolean(error);
2203
2350
  const controlled = value !== void 0;
2204
- const [internal, setInternal] = React23__default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2351
+ const [internal, setInternal] = React24__default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2205
2352
  const shown = controlled ? clampPrecision(String(value ?? ""), prec) : internal;
2206
2353
  const describedBy = [error ? `${fieldId}-error` : hint ? `${fieldId}-hint` : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
2207
2354
  function handleChange(e) {
@@ -2375,32 +2522,32 @@ function Select({
2375
2522
  ...rest
2376
2523
  }) {
2377
2524
  const __twcStyles = useScopedStyles("twc-select-styles", SELECT_CSS);
2378
- const groups = React23__default.useMemo(() => normalizeGroups2(options), [options]);
2379
- const flat = React23__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
2380
- const autoId = React23__default.useId();
2525
+ const groups = React24__default.useMemo(() => normalizeGroups2(options), [options]);
2526
+ const flat = React24__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
2527
+ const autoId = React24__default.useId();
2381
2528
  const fieldId = id || autoId;
2382
- const [internal, setInternal] = React23__default.useState(defaultValue);
2529
+ const [internal, setInternal] = React24__default.useState(defaultValue);
2383
2530
  const current = value !== void 0 ? value : internal;
2384
- const [open, setOpen] = React23__default.useState(false);
2385
- const [render, setRender] = React23__default.useState(false);
2386
- const [active, setActive] = React23__default.useState(0);
2387
- const [coords, setCoords] = React23__default.useState(null);
2388
- const [query, setQuery] = React23__default.useState("");
2389
- const wrapRef = React23__default.useRef(null);
2390
- const triggerRef = React23__default.useRef(null);
2391
- const popRef = React23__default.useRef(null);
2392
- const listRef = React23__default.useRef(null);
2393
- const activeRef = React23__default.useRef(null);
2394
- const searchRef = React23__default.useRef(null);
2531
+ const [open, setOpen] = React24__default.useState(false);
2532
+ const [render, setRender] = React24__default.useState(false);
2533
+ const [active, setActive] = React24__default.useState(0);
2534
+ const [coords, setCoords] = React24__default.useState(null);
2535
+ const [query, setQuery] = React24__default.useState("");
2536
+ const wrapRef = React24__default.useRef(null);
2537
+ const triggerRef = React24__default.useRef(null);
2538
+ const popRef = React24__default.useRef(null);
2539
+ const listRef = React24__default.useRef(null);
2540
+ const activeRef = React24__default.useRef(null);
2541
+ const searchRef = React24__default.useRef(null);
2395
2542
  const showSearch = searchable === void 0 ? flat.length > 5 : searchable;
2396
- const fGroups = React23__default.useMemo(() => {
2543
+ const fGroups = React24__default.useMemo(() => {
2397
2544
  const q = query.trim().toLowerCase();
2398
2545
  if (!q) return groups;
2399
2546
  return groups.map((g) => ({ group: g.group, options: g.options.filter((o) => o.label.toLowerCase().includes(q) || o.description && o.description.toLowerCase().includes(q)) })).filter((g) => g.options.length);
2400
2547
  }, [groups, query]);
2401
- const visible = React23__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
2548
+ const visible = React24__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
2402
2549
  const selected = flat.find((o) => o.value === current);
2403
- const place = React23__default.useCallback(() => {
2550
+ const place = React24__default.useCallback(() => {
2404
2551
  const el = triggerRef.current;
2405
2552
  if (!el) return;
2406
2553
  const r = el.getBoundingClientRect();
@@ -2415,7 +2562,7 @@ function Select({
2415
2562
  flip
2416
2563
  });
2417
2564
  }, [placement, minWidth]);
2418
- React23__default.useEffect(() => {
2565
+ React24__default.useEffect(() => {
2419
2566
  if (!open || !portal) return;
2420
2567
  place();
2421
2568
  const onMove = () => place();
@@ -2426,7 +2573,7 @@ function Select({
2426
2573
  window.removeEventListener("resize", onMove);
2427
2574
  };
2428
2575
  }, [open, portal, place]);
2429
- React23__default.useEffect(() => {
2576
+ React24__default.useEffect(() => {
2430
2577
  if (!open) return;
2431
2578
  const idx = flat.findIndex((o) => o.value === current);
2432
2579
  setActive(idx >= 0 ? idx : 0);
@@ -2442,13 +2589,13 @@ function Select({
2442
2589
  document.addEventListener("mousedown", onDown);
2443
2590
  return () => document.removeEventListener("mousedown", onDown);
2444
2591
  }, [open]);
2445
- React23__default.useEffect(() => {
2592
+ React24__default.useEffect(() => {
2446
2593
  setActive(0);
2447
2594
  }, [query]);
2448
- React23__default.useEffect(() => {
2595
+ React24__default.useEffect(() => {
2449
2596
  if (open) ensureVisible2(listRef.current, activeRef.current);
2450
2597
  }, [active, open]);
2451
- React23__default.useEffect(() => {
2598
+ React24__default.useEffect(() => {
2452
2599
  if (open) {
2453
2600
  setRender(true);
2454
2601
  return;
@@ -2456,8 +2603,8 @@ function Select({
2456
2603
  const t = setTimeout(() => setRender(false), 170);
2457
2604
  return () => clearTimeout(t);
2458
2605
  }, [open]);
2459
- const prevOpen = React23__default.useRef(false);
2460
- React23__default.useEffect(() => {
2606
+ const prevOpen = React24__default.useRef(false);
2607
+ React24__default.useEffect(() => {
2461
2608
  if (prevOpen.current && !open) {
2462
2609
  const ae = typeof document !== "undefined" ? document.activeElement : null;
2463
2610
  if (popRef.current && ae && popRef.current.contains(ae)) triggerRef.current?.focus();
@@ -2530,7 +2677,7 @@ function Select({
2530
2677
  }
2531
2678
  )
2532
2679
  ] }) : null,
2533
- /* @__PURE__ */ jsx("div", { className: "twc-pop__list", ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React23__default.Fragment, { children: [
2680
+ /* @__PURE__ */ jsx("div", { className: "twc-pop__list", ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React24__default.Fragment, { children: [
2534
2681
  g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
2535
2682
  g.options.map((o) => {
2536
2683
  counter += 1;
@@ -2704,19 +2851,19 @@ function CurrencyField({
2704
2851
  ...rest
2705
2852
  }) {
2706
2853
  const __twcStyles = useScopedStyles("twc-curf-styles", CURF_CSS);
2707
- const autoId = React23__default.useId();
2854
+ const autoId = React24__default.useId();
2708
2855
  const fieldId = id || autoId;
2709
2856
  const invalid = Boolean(error);
2710
2857
  const curControlled = currency !== void 0;
2711
- const [curInternal, setCurInternal] = React23__default.useState(defaultCurrency);
2858
+ const [curInternal, setCurInternal] = React24__default.useState(defaultCurrency);
2712
2859
  const cur = curControlled ? currency : curInternal;
2713
2860
  const meta = CURRENCIES[cur] || CURRENCIES.USD;
2714
2861
  const prec = meta.precision;
2715
2862
  const valControlled = value !== void 0;
2716
- const [valInternal, setValInternal] = React23__default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2863
+ const [valInternal, setValInternal] = React24__default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2717
2864
  const shown = valControlled ? clampPrecision(String(value ?? ""), prec) : valInternal;
2718
2865
  const describedBy = [error ? `${fieldId}-error` : hint ? `${fieldId}-hint` : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
2719
- const options = React23__default.useMemo(() => {
2866
+ const options = React24__default.useMemo(() => {
2720
2867
  if (!currencies) return CURRENCY_OPTIONS;
2721
2868
  return currencies.map((c) => typeof c === "string" ? { value: c, label: `${c} \u2014 ${(CURRENCIES[c] || {}).label || c}` } : c);
2722
2869
  }, [currencies]);
@@ -2851,12 +2998,12 @@ function Input({
2851
2998
  ...rest
2852
2999
  }) {
2853
3000
  const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS2);
2854
- const autoId = React23__default.useId();
3001
+ const autoId = React24__default.useId();
2855
3002
  const fieldId = id || autoId;
2856
3003
  const descId = `${fieldId}-desc`;
2857
3004
  const invalid = Boolean(error);
2858
3005
  const isPassword = type === "password";
2859
- const [revealed, setRevealed] = React23__default.useState(false);
3006
+ const [revealed, setRevealed] = React24__default.useState(false);
2860
3007
  const effectiveType = isPassword && revealed ? "text" : type;
2861
3008
  const suffix = rightIcon ? /* @__PURE__ */ jsx("span", { className: "twc-input__affix", children: rightIcon }) : isPassword ? /* @__PURE__ */ jsx(
2862
3009
  "button",
@@ -3037,28 +3184,28 @@ function MultiSelect({
3037
3184
  ...rest
3038
3185
  }) {
3039
3186
  const __twcStyles = useScopedStyles("twc-ms-styles", MULTI_CSS);
3040
- const groups = React23__default.useMemo(() => normalizeGroups3(options), [options]);
3041
- const flat = React23__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
3042
- const autoId = React23__default.useId();
3187
+ const groups = React24__default.useMemo(() => normalizeGroups3(options), [options]);
3188
+ const flat = React24__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
3189
+ const autoId = React24__default.useId();
3043
3190
  const fieldId = id || autoId;
3044
- const [internal, setInternal] = React23__default.useState(defaultValue);
3191
+ const [internal, setInternal] = React24__default.useState(defaultValue);
3045
3192
  const selected = value !== void 0 ? value : internal;
3046
- const [open, setOpen] = React23__default.useState(false);
3047
- const [query, setQuery] = React23__default.useState("");
3048
- const [active, setActive] = React23__default.useState(0);
3049
- const [coords, setCoords] = React23__default.useState(null);
3050
- const wrapRef = React23__default.useRef(null);
3051
- const controlRef = React23__default.useRef(null);
3052
- const inputRef = React23__default.useRef(null);
3053
- const popRef = React23__default.useRef(null);
3054
- const listRef = React23__default.useRef(null);
3055
- const activeRef = React23__default.useRef(null);
3056
- const fGroups = React23__default.useMemo(
3193
+ const [open, setOpen] = React24__default.useState(false);
3194
+ const [query, setQuery] = React24__default.useState("");
3195
+ const [active, setActive] = React24__default.useState(0);
3196
+ const [coords, setCoords] = React24__default.useState(null);
3197
+ const wrapRef = React24__default.useRef(null);
3198
+ const controlRef = React24__default.useRef(null);
3199
+ const inputRef = React24__default.useRef(null);
3200
+ const popRef = React24__default.useRef(null);
3201
+ const listRef = React24__default.useRef(null);
3202
+ const activeRef = React24__default.useRef(null);
3203
+ const fGroups = React24__default.useMemo(
3057
3204
  () => groups.map((g) => ({ group: g.group, options: g.options.filter((o) => matches2(o, query.trim())) })).filter((g) => g.options.length),
3058
3205
  [groups, query]
3059
3206
  );
3060
- const visible = React23__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
3061
- const place = React23__default.useCallback(() => {
3207
+ const visible = React24__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
3208
+ const place = React24__default.useCallback(() => {
3062
3209
  const el = controlRef.current;
3063
3210
  if (!el) return;
3064
3211
  const r = el.getBoundingClientRect();
@@ -3073,7 +3220,7 @@ function MultiSelect({
3073
3220
  flip
3074
3221
  });
3075
3222
  }, [placement, minWidth]);
3076
- React23__default.useEffect(() => {
3223
+ React24__default.useEffect(() => {
3077
3224
  if (!open || !portal) return;
3078
3225
  place();
3079
3226
  const onMove = () => place();
@@ -3084,7 +3231,7 @@ function MultiSelect({
3084
3231
  window.removeEventListener("resize", onMove);
3085
3232
  };
3086
3233
  }, [open, portal, place]);
3087
- React23__default.useEffect(() => {
3234
+ React24__default.useEffect(() => {
3088
3235
  if (!open) return;
3089
3236
  const onDown = (e) => {
3090
3237
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -3095,10 +3242,10 @@ function MultiSelect({
3095
3242
  document.addEventListener("mousedown", onDown);
3096
3243
  return () => document.removeEventListener("mousedown", onDown);
3097
3244
  }, [open]);
3098
- React23__default.useEffect(() => {
3245
+ React24__default.useEffect(() => {
3099
3246
  setActive(0);
3100
3247
  }, [query]);
3101
- React23__default.useEffect(() => {
3248
+ React24__default.useEffect(() => {
3102
3249
  if (open) ensureVisible3(listRef.current, activeRef.current);
3103
3250
  }, [active, open]);
3104
3251
  function commit(next) {
@@ -3135,7 +3282,7 @@ function MultiSelect({
3135
3282
  const descId = `${fieldId}-desc`;
3136
3283
  const describedBy = error || hint ? descId : void 0;
3137
3284
  let counter = -1;
3138
- const popInner = /* @__PURE__ */ jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children: visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React23__default.Fragment, { children: [
3285
+ const popInner = /* @__PURE__ */ jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children: visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React24__default.Fragment, { children: [
3139
3286
  g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
3140
3287
  g.options.map((o) => {
3141
3288
  counter += 1;
@@ -3279,6 +3426,15 @@ function MultiSelect({
3279
3426
  error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
3280
3427
  ] });
3281
3428
  }
3429
+
3430
+ // components/_warn.js
3431
+ var seen = /* @__PURE__ */ new Set();
3432
+ function warnOnce(key, message) {
3433
+ if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production") return;
3434
+ if (seen.has(key)) return;
3435
+ seen.add(key);
3436
+ if (typeof console !== "undefined" && console.warn) console.warn(message);
3437
+ }
3282
3438
  var PAGINATION_CSS = `
3283
3439
  .twc-pagination { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-sans); }
3284
3440
  .twc-page {
@@ -3341,15 +3497,18 @@ function Pagination({
3341
3497
  siblings = 1,
3342
3498
  boundaries = 1,
3343
3499
  size = "md",
3344
- showJumper = false,
3500
+ showJumper,
3345
3501
  showPageJumper,
3346
3502
  jumperLabel = "Go to",
3347
3503
  className = "",
3348
3504
  ...rest
3349
3505
  }) {
3506
+ if (process.env.NODE_ENV !== "production" && showJumper !== void 0 && showPageJumper === void 0) {
3507
+ warnOnce("Pagination.showJumper", "Pagination: `showJumper` is deprecated and will be removed in 2.0 \u2014 use `showPageJumper`.");
3508
+ }
3350
3509
  const jumperEnabled = showPageJumper ?? showJumper;
3351
3510
  const __twcStyles = useScopedStyles("twc-pagination-styles", PAGINATION_CSS);
3352
- const [internal, setInternal] = React23__default.useState(defaultPage);
3511
+ const [internal, setInternal] = React24__default.useState(defaultPage);
3353
3512
  const page = pageProp !== void 0 ? pageProp : internal;
3354
3513
  const pages = buildPages(page, total, siblings, boundaries);
3355
3514
  const go = (p) => {
@@ -3357,7 +3516,7 @@ function Pagination({
3357
3516
  if (pageProp === void 0) setInternal(p);
3358
3517
  onChange?.(p);
3359
3518
  };
3360
- const [jump, setJump] = React23__default.useState("");
3519
+ const [jump, setJump] = React24__default.useState("");
3361
3520
  const submitJump = () => {
3362
3521
  const n = parseInt(jump, 10);
3363
3522
  if (!Number.isNaN(n)) go(Math.min(Math.max(n, 1), total));
@@ -3780,6 +3939,7 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
3780
3939
  .twc-dt__sw[data-on="true"]::after { transform: translateX(14px); }
3781
3940
  .twc-dt__panel-head { display: flex; align-items: center; justify-content: space-between; padding: 6px 8px 8px; }
3782
3941
  .twc-dt__panel-title { font-size: var(--text-xs); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-text-subtle); }
3942
+ .twc-dt__panel-count { font-weight: 600; color: var(--color-text-muted); text-transform: none; letter-spacing: 0; margin-inline-start: 6px; font-variant-numeric: tabular-nums; }
3783
3943
  .twc-dt__link { border: none; background: transparent; color: var(--color-primary); font-family: inherit; font-size: var(--text-xs); font-weight: 600; cursor: pointer; padding: 2px 4px; border-radius: var(--radius-sm); }
3784
3944
  .twc-dt__link:hover { background: var(--color-primary-subtle); }
3785
3945
 
@@ -3967,9 +4127,9 @@ function runDatatableQuery(rows, query, options = {}) {
3967
4127
  return { rows: page, total, filtered: out };
3968
4128
  }
3969
4129
  function useFloating() {
3970
- const [pos, setPos] = React23__default.useState(null);
3971
- const cfg = React23__default.useRef(null);
3972
- const place = React23__default.useCallback(() => {
4130
+ const [pos, setPos] = React24__default.useState(null);
4131
+ const cfg = React24__default.useRef(null);
4132
+ const place = React24__default.useCallback(() => {
3973
4133
  const c = cfg.current;
3974
4134
  if (!c || !c.el || !c.el.isConnected) return null;
3975
4135
  const r = c.el.getBoundingClientRect();
@@ -3980,17 +4140,17 @@ function useFloating() {
3980
4140
  const top = r.bottom + 6;
3981
4141
  return { top, left, width: c.width, anchorX: r.left + r.width / 2, maxHeight: Math.max(180, vh - top - M) };
3982
4142
  }, []);
3983
- const open = React23__default.useCallback((el, align = "left", width = 220) => {
4143
+ const open = React24__default.useCallback((el, align = "left", width = 220) => {
3984
4144
  cfg.current = { el, align, width };
3985
4145
  const p = place();
3986
4146
  if (p) setPos(p);
3987
4147
  }, [place]);
3988
- const close = React23__default.useCallback(() => {
4148
+ const close = React24__default.useCallback(() => {
3989
4149
  cfg.current = null;
3990
4150
  setPos(null);
3991
4151
  }, []);
3992
4152
  const isOpen = pos != null;
3993
- React23__default.useEffect(() => {
4153
+ React24__default.useEffect(() => {
3994
4154
  if (!isOpen) return void 0;
3995
4155
  const update = () => {
3996
4156
  const p = place();
@@ -4014,9 +4174,9 @@ function Caret({ pos }) {
4014
4174
  return /* @__PURE__ */ jsx("span", { className: "twc-dt__caret", style: { left } });
4015
4175
  }
4016
4176
  function EditCell({ col, value, options, onChange, onCommit, onCommitValue, onCancel, onKeyDown }) {
4017
- const ref = React23__default.useRef(null);
4177
+ const ref = React24__default.useRef(null);
4018
4178
  const isSelect = col.editType === "select" || options && col.editType !== "text";
4019
- React23__default.useEffect(() => {
4179
+ React24__default.useEffect(() => {
4020
4180
  if (isSelect) {
4021
4181
  const t = setTimeout(() => ref.current?.querySelector(".twc-sel__trigger")?.click(), 0);
4022
4182
  return () => clearTimeout(t);
@@ -4177,7 +4337,7 @@ function Datatable({
4177
4337
  loading = false,
4178
4338
  rowKey,
4179
4339
  checkboxSelection = false,
4180
- density: densityProp = "standard",
4340
+ density: densityProp = "comfortable",
4181
4341
  pageSize = 10,
4182
4342
  pageSizeOptions = [5, 10, 25, 50],
4183
4343
  height = 440,
@@ -4185,7 +4345,9 @@ function Datatable({
4185
4345
  rowCount,
4186
4346
  onServerChange,
4187
4347
  batchActions = [],
4188
- showExport = true,
4348
+ showExport = false,
4349
+ showDensity = false,
4350
+ showPivot = false,
4189
4351
  exportFilename = "export",
4190
4352
  aggregationValues = null,
4191
4353
  disableColumnReorder = false,
@@ -4217,7 +4379,7 @@ function Datatable({
4217
4379
  ...rest
4218
4380
  }) {
4219
4381
  const __twcStyles = useScopedStyles("twc-dt-styles", DT_CSS);
4220
- const cols = React23__default.useMemo(() => {
4382
+ const cols = React24__default.useMemo(() => {
4221
4383
  const out = columns.map((c) => {
4222
4384
  const isActions = c.type === "actions";
4223
4385
  return {
@@ -4252,7 +4414,7 @@ function Datatable({
4252
4414
  }
4253
4415
  return out;
4254
4416
  }, [columns, rowPinning]);
4255
- const _autoKey = React23__default.useRef();
4417
+ const _autoKey = React24__default.useRef();
4256
4418
  if (!_autoKey.current) _autoKey.current = { map: /* @__PURE__ */ new WeakMap(), n: 0 };
4257
4419
  const keyOf = rowKey || ((r, i) => {
4258
4420
  if (r != null && r.id != null) return r.id;
@@ -4267,17 +4429,17 @@ function Datatable({
4267
4429
  }
4268
4430
  return i;
4269
4431
  });
4270
- const [sort, setSort] = React23__default.useState(null);
4271
- const [filters, setFilters] = React23__default.useState([]);
4272
- const [hidden, setHidden] = React23__default.useState(() => /* @__PURE__ */ new Set());
4273
- const [showRowNum, setShowRowNum] = React23__default.useState(rowNumbers);
4274
- const [wrapped, setWrapped] = React23__default.useState(() => new Set((columns || []).filter((c) => c.wrapText).map((c) => c.field)));
4432
+ const [sort, setSort] = React24__default.useState(null);
4433
+ const [filters, setFilters] = React24__default.useState([]);
4434
+ const [hidden, setHidden] = React24__default.useState(() => /* @__PURE__ */ new Set());
4435
+ const [showRowNum, setShowRowNum] = React24__default.useState(rowNumbers);
4436
+ const [wrapped, setWrapped] = React24__default.useState(() => new Set((columns || []).filter((c) => c.wrapText).map((c) => c.field)));
4275
4437
  const toggleWrap = (field) => setWrapped((w) => {
4276
4438
  const n = new Set(w);
4277
4439
  n.has(field) ? n.delete(field) : n.add(field);
4278
4440
  return n;
4279
4441
  });
4280
- const [pins, setPins] = React23__default.useState(() => {
4442
+ const [pins, setPins] = React24__default.useState(() => {
4281
4443
  const left = [], right = [];
4282
4444
  columns.forEach((c) => {
4283
4445
  if (c.pinned === "left") left.push(c.field);
@@ -4285,34 +4447,34 @@ function Datatable({
4285
4447
  });
4286
4448
  return { left, right };
4287
4449
  });
4288
- const [density, setDensity] = React23__default.useState(densityProp);
4289
- const [quick, setQuick] = React23__default.useState("");
4290
- const [selected, setSelected] = React23__default.useState(() => /* @__PURE__ */ new Set());
4291
- const [activeRow, setActiveRow] = React23__default.useState(null);
4292
- const [activeCell, setActiveCell] = React23__default.useState(null);
4293
- const [page, setPage] = React23__default.useState(0);
4294
- const [rowsPerPage, setRowsPerPage] = React23__default.useState(pageSize > 0 ? pageSize : 10);
4295
- const [colQuery, setColQuery] = React23__default.useState("");
4296
- const [widths, setWidths] = React23__default.useState({});
4297
- const [order, setOrder] = React23__default.useState(() => columns.map((c) => c.field));
4298
- const [drag, setDrag] = React23__default.useState({ from: null, over: null, after: false });
4299
- const [aggOn, setAggOn] = React23__default.useState(showAggregation);
4300
- const [focus, setFocus] = React23__default.useState({ r: 0, c: 0 });
4301
- const gridRef = React23__default.useRef(null);
4302
- const [groupBy, setGroupBy] = React23__default.useState(rowGrouping || []);
4303
- const [collapsed, setCollapsed] = React23__default.useState(() => /* @__PURE__ */ new Set());
4304
- const [pinnedRows, setPinnedRows] = React23__default.useState({ top: [], bottom: [] });
4305
- const [headH, setHeadH] = React23__default.useState(41);
4306
- const theadRef = React23__default.useRef(null);
4307
- const [rowOrder, setRowOrder] = React23__default.useState(null);
4308
- const [rowHeights, setRowHeights] = React23__default.useState({});
4309
- const [rowDrag, setRowDrag] = React23__default.useState({ from: null, over: null, after: false });
4310
- const [rowGrab, setRowGrab] = React23__default.useState(null);
4311
- const [reorderMsg, setReorderMsg] = React23__default.useState("");
4312
- const rowFocusRef = React23__default.useRef(null);
4313
- const rootRef = React23__default.useRef(null);
4314
- const [compact, setCompact] = React23__default.useState(false);
4315
- React23__default.useEffect(() => {
4450
+ const [density, setDensity] = React24__default.useState(densityProp);
4451
+ const [quick, setQuick] = React24__default.useState("");
4452
+ const [selected, setSelected] = React24__default.useState(() => /* @__PURE__ */ new Set());
4453
+ const [activeRow, setActiveRow] = React24__default.useState(null);
4454
+ const [activeCell, setActiveCell] = React24__default.useState(null);
4455
+ const [page, setPage] = React24__default.useState(0);
4456
+ const [rowsPerPage, setRowsPerPage] = React24__default.useState(pageSize > 0 ? pageSize : 10);
4457
+ const [colQuery, setColQuery] = React24__default.useState("");
4458
+ const [widths, setWidths] = React24__default.useState({});
4459
+ const [order, setOrder] = React24__default.useState(() => columns.map((c) => c.field));
4460
+ const [drag, setDrag] = React24__default.useState({ from: null, over: null, after: false });
4461
+ const [aggOn, setAggOn] = React24__default.useState(showAggregation);
4462
+ const [focus, setFocus] = React24__default.useState({ r: 0, c: 0 });
4463
+ const gridRef = React24__default.useRef(null);
4464
+ const [groupBy, setGroupBy] = React24__default.useState(rowGrouping || []);
4465
+ const [collapsed, setCollapsed] = React24__default.useState(() => /* @__PURE__ */ new Set());
4466
+ const [pinnedRows, setPinnedRows] = React24__default.useState({ top: [], bottom: [] });
4467
+ const [headH, setHeadH] = React24__default.useState(41);
4468
+ const theadRef = React24__default.useRef(null);
4469
+ const [rowOrder, setRowOrder] = React24__default.useState(null);
4470
+ const [rowHeights, setRowHeights] = React24__default.useState({});
4471
+ const [rowDrag, setRowDrag] = React24__default.useState({ from: null, over: null, after: false });
4472
+ const [rowGrab, setRowGrab] = React24__default.useState(null);
4473
+ const [reorderMsg, setReorderMsg] = React24__default.useState("");
4474
+ const rowFocusRef = React24__default.useRef(null);
4475
+ const rootRef = React24__default.useRef(null);
4476
+ const [compact, setCompact] = React24__default.useState(false);
4477
+ React24__default.useEffect(() => {
4316
4478
  const el = rootRef.current;
4317
4479
  if (!el) return void 0;
4318
4480
  const measure = () => setCompact((el.clientWidth || 0) < 720);
@@ -4325,11 +4487,11 @@ function Datatable({
4325
4487
  else if (typeof window !== "undefined") window.removeEventListener("resize", measure);
4326
4488
  };
4327
4489
  }, []);
4328
- const scrollRef = React23__default.useRef(null);
4329
- const [scrollTop, setScrollTop] = React23__default.useState(0);
4330
- const [viewportH, setViewportH] = React23__default.useState(0);
4331
- const [pivotOn, setPivotOn] = React23__default.useState(pivotMode);
4332
- const [aggConfig, setAggConfig] = React23__default.useState(() => {
4490
+ const scrollRef = React24__default.useRef(null);
4491
+ const [scrollTop, setScrollTop] = React24__default.useState(0);
4492
+ const [viewportH, setViewportH] = React24__default.useState(0);
4493
+ const [pivotOn, setPivotOn] = React24__default.useState(pivotMode);
4494
+ const [aggConfig, setAggConfig] = React24__default.useState(() => {
4333
4495
  const m = {};
4334
4496
  (columns || []).forEach((c) => {
4335
4497
  if (typeof c.aggregation === "string") m[c.field] = c.aggregation;
@@ -4337,13 +4499,13 @@ function Datatable({
4337
4499
  return m;
4338
4500
  });
4339
4501
  const aggOf = (c) => aggConfig[c.field] || (typeof c.aggregation === "function" ? c.aggregation : null);
4340
- const [pivotConfig, setPivotConfig] = React23__default.useState(() => ({
4502
+ const [pivotConfig, setPivotConfig] = React24__default.useState(() => ({
4341
4503
  rows: pivot && pivot.rows || [],
4342
4504
  columns: pivot && pivot.columns || [],
4343
4505
  values: pivot && pivot.values || []
4344
4506
  }));
4345
4507
  const pivotActive = pivotOn && pivotConfig.rows.length > 0 && pivotConfig.values.length > 0;
4346
- React23__default.useEffect(() => {
4508
+ React24__default.useEffect(() => {
4347
4509
  setOrder((prev) => {
4348
4510
  const fields = columns.map((c) => c.field);
4349
4511
  const kept = prev.filter((f) => fields.includes(f));
@@ -4351,32 +4513,32 @@ function Datatable({
4351
4513
  return [...kept, ...added];
4352
4514
  });
4353
4515
  }, [columns]);
4354
- React23__default.useEffect(() => {
4516
+ React24__default.useEffect(() => {
4355
4517
  setDensity(densityProp);
4356
4518
  }, [densityProp]);
4357
- React23__default.useEffect(() => {
4519
+ React24__default.useEffect(() => {
4358
4520
  setAggOn(showAggregation);
4359
4521
  }, [showAggregation]);
4360
4522
  const rowGroupingKey = (rowGrouping || []).join("\0");
4361
- const rowGroupingKeyRef = React23__default.useRef(rowGroupingKey);
4362
- React23__default.useEffect(() => {
4523
+ const rowGroupingKeyRef = React24__default.useRef(rowGroupingKey);
4524
+ React24__default.useEffect(() => {
4363
4525
  if (rowGroupingKeyRef.current === rowGroupingKey) return;
4364
4526
  rowGroupingKeyRef.current = rowGroupingKey;
4365
4527
  setGroupBy(rowGrouping || []);
4366
4528
  }, [rowGroupingKey]);
4367
4529
  const widthOf = (c) => widths[c.field] ?? c.width ?? 160;
4368
- const [colMenu, setColMenu] = React23__default.useState(null);
4530
+ const [colMenu, setColMenu] = React24__default.useState(null);
4369
4531
  const [menuPos, openMenu, closeMenu] = useFloating();
4370
- const [panel, setPanel] = React23__default.useState(null);
4532
+ const [panel, setPanel] = React24__default.useState(null);
4371
4533
  const [panelPos, openPanel, closePanel] = useFloating();
4372
- const [rowMenu, setRowMenu] = React23__default.useState(null);
4534
+ const [rowMenu, setRowMenu] = React24__default.useState(null);
4373
4535
  const [rowMenuPos, openRowMenu, closeRowMenu] = useFloating();
4374
- const [exportOpen, setExportOpen] = React23__default.useState(false);
4536
+ const [exportOpen, setExportOpen] = React24__default.useState(false);
4375
4537
  const [exportPos, openExport, closeExport] = useFloating();
4376
- const menuTriggerRef = React23__default.useRef(null);
4377
- const colMenuRef = React23__default.useRef(null);
4378
- const rowMenuRef = React23__default.useRef(null);
4379
- const exportMenuRef = React23__default.useRef(null);
4538
+ const menuTriggerRef = React24__default.useRef(null);
4539
+ const colMenuRef = React24__default.useRef(null);
4540
+ const rowMenuRef = React24__default.useRef(null);
4541
+ const exportMenuRef = React24__default.useRef(null);
4380
4542
  function focusFirstItem(container) {
4381
4543
  if (!container) return;
4382
4544
  const first = container.querySelector('[role="menuitem"]:not([disabled])');
@@ -4415,16 +4577,16 @@ function Datatable({
4415
4577
  restoreTriggerFocus();
4416
4578
  }
4417
4579
  }
4418
- React23__default.useEffect(() => {
4580
+ React24__default.useEffect(() => {
4419
4581
  if (colMenu) focusFirstItem(colMenuRef.current);
4420
4582
  }, [colMenu]);
4421
- React23__default.useEffect(() => {
4583
+ React24__default.useEffect(() => {
4422
4584
  if (rowMenu) focusFirstItem(rowMenuRef.current);
4423
4585
  }, [rowMenu]);
4424
- React23__default.useEffect(() => {
4586
+ React24__default.useEffect(() => {
4425
4587
  if (exportOpen) focusFirstItem(exportMenuRef.current);
4426
4588
  }, [exportOpen]);
4427
- React23__default.useEffect(() => {
4589
+ React24__default.useEffect(() => {
4428
4590
  if (!colMenu && !panel && !rowMenu) return;
4429
4591
  const closeAll = () => {
4430
4592
  setColMenu(null);
@@ -4447,7 +4609,7 @@ function Datatable({
4447
4609
  document.removeEventListener("keydown", onKey);
4448
4610
  };
4449
4611
  }, [colMenu, panel, rowMenu]);
4450
- React23__default.useEffect(() => {
4612
+ React24__default.useEffect(() => {
4451
4613
  if (!exportOpen) return;
4452
4614
  const close = () => {
4453
4615
  setExportOpen(false);
@@ -4466,9 +4628,9 @@ function Datatable({
4466
4628
  document.removeEventListener("keydown", onKey);
4467
4629
  };
4468
4630
  }, [exportOpen]);
4469
- const colByField = React23__default.useMemo(() => Object.fromEntries(cols.map((c) => [c.field, c])), [cols]);
4631
+ const colByField = React24__default.useMemo(() => Object.fromEntries(cols.map((c) => [c.field, c])), [cols]);
4470
4632
  const visibleCols = cols.filter((c) => !hidden.has(c.field));
4471
- const ordered = React23__default.useMemo(() => {
4633
+ const ordered = React24__default.useMemo(() => {
4472
4634
  const orderIdx = (f) => {
4473
4635
  const i = order.indexOf(f);
4474
4636
  return i === -1 ? 9999 : i;
@@ -4503,7 +4665,7 @@ function Datatable({
4503
4665
  }
4504
4666
  return {};
4505
4667
  };
4506
- const processed = React23__default.useMemo(() => {
4668
+ const processed = React24__default.useMemo(() => {
4507
4669
  if (serverMode) {
4508
4670
  if (rowOrder) {
4509
4671
  const idx = new Map(rowOrder.map((k, i) => [k, i]));
@@ -4542,10 +4704,10 @@ function Datatable({
4542
4704
  const totalRows = serverMode ? serverTotal : processed.length;
4543
4705
  const totalPages = paginated ? Math.max(1, Math.ceil(totalRows / rowsPerPage)) : 1;
4544
4706
  const paged = !paginated || serverMode ? processed : processed.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
4545
- React23__default.useEffect(() => {
4707
+ React24__default.useEffect(() => {
4546
4708
  if (page > totalPages - 1) setPage(0);
4547
4709
  }, [totalPages]);
4548
- const activeGroupBy = React23__default.useMemo(() => groupBy.filter((f) => colByField[f]), [groupBy, colByField]);
4710
+ const activeGroupBy = React24__default.useMemo(() => groupBy.filter((f) => colByField[f]), [groupBy, colByField]);
4549
4711
  function subtotalText(rowsIn) {
4550
4712
  const parts = [];
4551
4713
  for (const c of ordered) {
@@ -4572,7 +4734,7 @@ function Datatable({
4572
4734
  if (agg === "max") return Math.max(...nums);
4573
4735
  return null;
4574
4736
  }
4575
- const displayItems = React23__default.useMemo(() => {
4737
+ const displayItems = React24__default.useMemo(() => {
4576
4738
  if (!activeGroupBy.length) return null;
4577
4739
  const build = (rowsIn, depth, prefix) => {
4578
4740
  if (depth >= activeGroupBy.length) return rowsIn.map((row) => ({ kind: "leaf", row }));
@@ -4614,7 +4776,7 @@ function Datatable({
4614
4776
  return { top, bottom };
4615
4777
  });
4616
4778
  }
4617
- React23__default.useEffect(() => {
4779
+ React24__default.useEffect(() => {
4618
4780
  if (!rowPinning) return;
4619
4781
  const measure = () => {
4620
4782
  if (theadRef.current) setHeadH(theadRef.current.offsetHeight || 41);
@@ -4628,12 +4790,12 @@ function Datatable({
4628
4790
  const pinnedTopRows = canPinRows ? pinnedRows.top.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
4629
4791
  const pinnedBottomRows = canPinRows ? pinnedRows.bottom.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
4630
4792
  const middleRows = canPinRows ? leafRows.filter((r, i) => !pinSideOf(keyOf(r, i))) : leafRows;
4631
- const keyIndex = React23__default.useMemo(() => {
4793
+ const keyIndex = React24__default.useMemo(() => {
4632
4794
  const m = /* @__PURE__ */ new Map();
4633
4795
  leafRows.forEach((r, i) => m.set(keyOf(r, i), i));
4634
4796
  return m;
4635
4797
  }, [leafRows]);
4636
- const keyIndexMid = React23__default.useMemo(() => {
4798
+ const keyIndexMid = React24__default.useMemo(() => {
4637
4799
  const m = /* @__PURE__ */ new Map();
4638
4800
  middleRows.forEach((r, i) => m.set(keyOf(r, keyIndex.get(keyOf(r)) ?? i), i));
4639
4801
  return m;
@@ -4718,19 +4880,19 @@ function Datatable({
4718
4880
  setReorderMsg("Reorder cancelled.");
4719
4881
  }
4720
4882
  }
4721
- React23__default.useEffect(() => {
4883
+ React24__default.useEffect(() => {
4722
4884
  if (rowFocusRef.current == null) return;
4723
4885
  const key = rowFocusRef.current;
4724
4886
  rowFocusRef.current = null;
4725
4887
  const root = gridRef.current;
4726
4888
  if (!root) return;
4727
- const sel = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(String(key)) : String(key).replace(/"/g, '\\"');
4889
+ const sel = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(String(key)) : String(key).replace(/[\\"]/g, "\\$&");
4728
4890
  const el = root.querySelector(`.twc-dt__row-handle[data-row-key="${sel}"]`);
4729
4891
  if (el) el.focus();
4730
4892
  });
4731
4893
  const estRowH = rowHeight ?? (density === "compact" ? 36 : density === "comfortable" ? 56 : 44);
4732
4894
  const virtualizing = virtualized && !paginated && !activeGroupBy.length && !loading;
4733
- React23__default.useEffect(() => {
4895
+ React24__default.useEffect(() => {
4734
4896
  if (!virtualizing) return;
4735
4897
  const el = scrollRef.current;
4736
4898
  if (!el) return;
@@ -4740,13 +4902,13 @@ function Datatable({
4740
4902
  if (ro) ro.observe(el);
4741
4903
  return () => ro && ro.disconnect();
4742
4904
  }, [virtualizing, height]);
4743
- const onScrollVirtual = React23__default.useCallback((e) => {
4905
+ const onScrollVirtual = React24__default.useCallback((e) => {
4744
4906
  setScrollTop(e.currentTarget.scrollTop);
4745
4907
  }, []);
4746
4908
  const vh = viewportH || (typeof height === "number" ? height : 440);
4747
- const rowHRef = React23__default.useRef(/* @__PURE__ */ new Map());
4748
- const [measureTick, setMeasureTick] = React23__default.useState(0);
4749
- const offsets = React23__default.useMemo(() => {
4909
+ const rowHRef = React24__default.useRef(/* @__PURE__ */ new Map());
4910
+ const [measureTick, setMeasureTick] = React24__default.useState(0);
4911
+ const offsets = React24__default.useMemo(() => {
4750
4912
  if (!virtualizing) return null;
4751
4913
  const total = middleRows.length;
4752
4914
  const arr = new Float64Array(total + 1);
@@ -4756,7 +4918,7 @@ function Datatable({
4756
4918
  }
4757
4919
  return arr;
4758
4920
  }, [virtualizing, middleRows, estRowH, measureTick]);
4759
- const vWindow = React23__default.useMemo(() => {
4921
+ const vWindow = React24__default.useMemo(() => {
4760
4922
  if (!virtualizing || !offsets) return null;
4761
4923
  const total = middleRows.length;
4762
4924
  const totalH = offsets[total];
@@ -4785,7 +4947,7 @@ function Datatable({
4785
4947
  if (start > end) start = end;
4786
4948
  return { start, end, padTop: offsets[start], padBottom: Math.max(0, totalH - offsets[end]) };
4787
4949
  }, [virtualizing, offsets, middleRows.length, vh, scrollTop, overscan]);
4788
- React23__default.useLayoutEffect(() => {
4950
+ React24__default.useLayoutEffect(() => {
4789
4951
  if (!virtualizing) return;
4790
4952
  const el = scrollRef.current;
4791
4953
  if (!el) return;
@@ -4800,9 +4962,9 @@ function Datatable({
4800
4962
  }
4801
4963
  if (changed) setMeasureTick((t) => t + 1);
4802
4964
  });
4803
- const onServerChangeRef = React23__default.useRef(onServerChange);
4965
+ const onServerChangeRef = React24__default.useRef(onServerChange);
4804
4966
  onServerChangeRef.current = onServerChange;
4805
- React23__default.useEffect(() => {
4967
+ React24__default.useEffect(() => {
4806
4968
  if (!serverMode) return;
4807
4969
  const t = setTimeout(() => {
4808
4970
  onServerChangeRef.current?.({
@@ -4837,7 +4999,7 @@ function Datatable({
4837
4999
  return n;
4838
5000
  });
4839
5001
  }
4840
- const movableMidFields = React23__default.useMemo(
5002
+ const movableMidFields = React24__default.useMemo(
4841
5003
  () => ordered.filter((c) => !pins.left.includes(c.field) && !pins.right.includes(c.field)).map((c) => c.field),
4842
5004
  [ordered, pins]
4843
5005
  );
@@ -4868,7 +5030,7 @@ function Datatable({
4868
5030
  }
4869
5031
  return [...set].sort((a, b) => a.localeCompare(b)).map((v) => ({ value: v, label: v }));
4870
5032
  }
4871
- const [resizing, setResizing] = React23__default.useState(false);
5033
+ const [resizing, setResizing] = React24__default.useState(false);
4872
5034
  function startResize(e, field) {
4873
5035
  e.preventDefault();
4874
5036
  e.stopPropagation();
@@ -4975,7 +5137,7 @@ function Datatable({
4975
5137
  if (!agg) return null;
4976
5138
  if (aggregationValues && col.field in aggregationValues) {
4977
5139
  const pre = aggregationValues[col.field];
4978
- if (pre && typeof pre === "object" && !React23__default.isValidElement(pre)) {
5140
+ if (pre && typeof pre === "object" && !React24__default.isValidElement(pre)) {
4979
5141
  if (typeof agg === "string" && agg in pre) return pre[agg];
4980
5142
  } else {
4981
5143
  return pre;
@@ -5093,14 +5255,14 @@ function Datatable({
5093
5255
  focusCell(r, c);
5094
5256
  }
5095
5257
  }
5096
- React23__default.useEffect(() => {
5258
+ React24__default.useEffect(() => {
5097
5259
  setFocus((f) => ({ r: Math.min(f.r, Math.max(0, leafRows.length - 1)), c: Math.min(f.c, Math.max(0, ordered.length - 1)) }));
5098
5260
  }, [leafRows.length, ordered.length, page]);
5099
- const selectedRows = React23__default.useMemo(() => rows.filter((r, i) => selected.has(keyOf(r, i))), [rows, selected]);
5261
+ const selectedRows = React24__default.useMemo(() => rows.filter((r, i) => selected.has(keyOf(r, i))), [rows, selected]);
5100
5262
  function clearSelection() {
5101
5263
  setSelected(/* @__PURE__ */ new Set());
5102
5264
  }
5103
- const [editing, setEditing] = React23__default.useState(null);
5265
+ const [editing, setEditing] = React24__default.useState(null);
5104
5266
  const isColEditable = (c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false));
5105
5267
  function beginEdit(rowK, col, row) {
5106
5268
  if (!isColEditable(col)) return;
@@ -5135,17 +5297,17 @@ function Datatable({
5135
5297
  cancelEdit();
5136
5298
  }
5137
5299
  }
5138
- const batchEditableCols = React23__default.useMemo(
5300
+ const batchEditableCols = React24__default.useMemo(
5139
5301
  () => cols.filter((c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false))),
5140
5302
  [cols, editMode]
5141
5303
  );
5142
- const [batchEdit, setBatchEdit] = React23__default.useState(null);
5304
+ const [batchEdit, setBatchEdit] = React24__default.useState(null);
5143
5305
  const [batchEditPos, openBatchEdit, closeBatchEdit] = useFloating();
5144
5306
  function openBatchEditor(el) {
5145
5307
  setBatchEdit({ fields: {}, values: {} });
5146
5308
  openBatchEdit(el, "left", 320);
5147
5309
  }
5148
- React23__default.useEffect(() => {
5310
+ React24__default.useEffect(() => {
5149
5311
  if (!batchEdit) return;
5150
5312
  const close = () => {
5151
5313
  setBatchEdit(null);
@@ -5164,7 +5326,7 @@ function Datatable({
5164
5326
  document.removeEventListener("keydown", onKey);
5165
5327
  };
5166
5328
  }, [batchEdit]);
5167
- React23__default.useEffect(() => {
5329
+ React24__default.useEffect(() => {
5168
5330
  if (batchEdit && selected.size === 0) {
5169
5331
  setBatchEdit(null);
5170
5332
  closeBatchEdit();
@@ -5201,7 +5363,7 @@ function Datatable({
5201
5363
  setBatchEdit(null);
5202
5364
  closeBatchEdit();
5203
5365
  }
5204
- React23__default.useEffect(() => {
5366
+ React24__default.useEffect(() => {
5205
5367
  if (!editing) return;
5206
5368
  const onDown = (e) => {
5207
5369
  if (e.target.closest(".twc-dt__editor-wrap") || e.target.closest(".twc-pop")) return;
@@ -5274,6 +5436,8 @@ function Datatable({
5274
5436
  };
5275
5437
  const shownColRows = cols.filter((c) => c.field !== "__pinactions__" && c.headerName.toLowerCase().includes(colQuery.trim().toLowerCase())).sort((a, b) => orderIdxOf(a.field) - orderIdxOf(b.field));
5276
5438
  const rowNumMatch = rowNumbers && "row number".includes(colQuery.trim().toLowerCase());
5439
+ const manageableCols = cols.filter((c) => c.field !== "__pinactions__");
5440
+ const visibleColCount = manageableCols.filter((c) => !hidden.has(c.field)).length;
5277
5441
  const rppOptions = Array.from(new Set([...pageSizeOptions || [], pageSize].filter((n) => n > 0))).sort((a, b) => a - b).map((n) => ({ value: String(n), label: String(n) }));
5278
5442
  const totalCols = ordered.length + (checkboxSelection ? 1 : 0) + (showRowNum ? 1 : 0);
5279
5443
  function renderGroupRow(item) {
@@ -5471,12 +5635,12 @@ function Datatable({
5471
5635
  const vlabel = (v) => v.label || (colByField[v.field]?.headerName || v.field);
5472
5636
  const rowFieldLabel = rFields.map((f) => colByField[f]?.headerName || f).join(" / ");
5473
5637
  const leafPaths = [];
5474
- const seen = /* @__PURE__ */ new Set();
5638
+ const seen2 = /* @__PURE__ */ new Set();
5475
5639
  for (const r of rows) {
5476
5640
  const path = colPathOf(r);
5477
5641
  const key = path.join("\0");
5478
- if (!seen.has(key)) {
5479
- seen.add(key);
5642
+ if (!seen2.has(key)) {
5643
+ seen2.add(key);
5480
5644
  leafPaths.push(path);
5481
5645
  }
5482
5646
  }
@@ -5636,11 +5800,11 @@ function Datatable({
5636
5800
  ]
5637
5801
  }
5638
5802
  ),
5639
- /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-dt__tbtn", "data-tip": "Change row density", onClick: () => setDensity((d) => d === "compact" ? "standard" : d === "standard" ? "comfortable" : "compact"), children: [
5803
+ showDensity ? /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-dt__tbtn", "data-tip": "Change row density", onClick: () => setDensity((d) => d === "compact" ? "standard" : d === "standard" ? "comfortable" : "compact"), children: [
5640
5804
  /* @__PURE__ */ jsx(Svg, { d: I.density }),
5641
5805
  /* @__PURE__ */ jsx("span", { className: "twc-dt__tlabel", children: density[0].toUpperCase() + density.slice(1) })
5642
- ] }),
5643
- /* @__PURE__ */ jsxs(
5806
+ ] }) : null,
5807
+ showAggregation ? /* @__PURE__ */ jsxs(
5644
5808
  "button",
5645
5809
  {
5646
5810
  type: "button",
@@ -5665,8 +5829,8 @@ function Datatable({
5665
5829
  aggOn && hasAggregation ? /* @__PURE__ */ jsx("span", { className: "twc-dt__tbadge", children: ordered.filter((c) => aggOf(c)).length }) : null
5666
5830
  ]
5667
5831
  }
5668
- ),
5669
- /* @__PURE__ */ jsxs(
5832
+ ) : null,
5833
+ showPivot || pivotMode || pivot != null || pivotActive ? /* @__PURE__ */ jsxs(
5670
5834
  "button",
5671
5835
  {
5672
5836
  type: "button",
@@ -5691,7 +5855,7 @@ function Datatable({
5691
5855
  pivotActive ? /* @__PURE__ */ jsx("span", { className: "twc-dt__tdot", "aria-label": "on", role: "img" }) : null
5692
5856
  ]
5693
5857
  }
5694
- ),
5858
+ ) : null,
5695
5859
  showExport ? /* @__PURE__ */ jsxs("span", { className: "twc-dt__export", children: [
5696
5860
  /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-dt__export-main", "data-tip": "Export to CSV", onClick: () => exportData("csv"), "aria-label": "Export to CSV", children: [
5697
5861
  /* @__PURE__ */ jsx(Svg, { d: I.download }),
@@ -6004,7 +6168,7 @@ function Datatable({
6004
6168
  } }) })
6005
6169
  ] }) : null
6006
6170
  ] }),
6007
- paginated ? /* @__PURE__ */ jsx("div", { className: "twc-dt__footer-row", "data-pager": "true", children: /* @__PURE__ */ jsx(Pagination, { size: "sm", page: page + 1, total: totalPages, boundaries: 3, showJumper: showPageJumper && totalPages > 5, onChange: (p) => setPage(p - 1) }) }) : null
6171
+ paginated ? /* @__PURE__ */ jsx("div", { className: "twc-dt__footer-row", "data-pager": "true", children: /* @__PURE__ */ jsx(Pagination, { size: "sm", page: page + 1, total: totalPages, boundaries: 3, showPageJumper: showPageJumper && totalPages > 5, onChange: (p) => setPage(p - 1) }) }) : null
6008
6172
  ] }) : null,
6009
6173
  exportOpen && exportPos ? /* @__PURE__ */ jsxs(
6010
6174
  "div",
@@ -6260,7 +6424,14 @@ function Datatable({
6260
6424
  ) : null,
6261
6425
  panel === "columns" && panelPos ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__pop twc-dt__cols", style: { top: panelPos.top, left: panelPos.left }, role: "dialog", "aria-label": "Column settings", children: [
6262
6426
  /* @__PURE__ */ jsxs("div", { className: "twc-dt__panel-head", children: [
6263
- /* @__PURE__ */ jsx("span", { className: "twc-dt__panel-title", children: "Columns" }),
6427
+ /* @__PURE__ */ jsxs("span", { className: "twc-dt__panel-title", children: [
6428
+ "Columns ",
6429
+ /* @__PURE__ */ jsxs("span", { className: "twc-dt__panel-count", title: `${visibleColCount} of ${manageableCols.length} columns shown`, children: [
6430
+ visibleColCount,
6431
+ "/",
6432
+ manageableCols.length
6433
+ ] })
6434
+ ] }),
6264
6435
  /* @__PURE__ */ jsxs("div", { children: [
6265
6436
  /* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__link", onClick: () => setHidden(/* @__PURE__ */ new Set()), children: "Show all" }),
6266
6437
  /* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__link", onClick: () => setHidden(new Set(cols.filter((c) => c.hideable).map((c) => c.field))), children: "Hide all" })
@@ -6714,23 +6885,23 @@ function DatePicker({
6714
6885
  }) {
6715
6886
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS3);
6716
6887
  const __twcStyles1 = useScopedStyles("twc-datepicker-styles", DATEPICKER_CSS);
6717
- const autoId = React23__default.useId();
6888
+ const autoId = React24__default.useId();
6718
6889
  const fieldId = id || autoId;
6719
6890
  const descId = `${fieldId}-desc`;
6720
6891
  const invalid = Boolean(error);
6721
- const [internal, setInternal] = React23__default.useState(defaultValue);
6892
+ const [internal, setInternal] = React24__default.useState(defaultValue);
6722
6893
  const selected = value !== void 0 ? value : internal;
6723
- const [open, setOpen] = React23__default.useState(false);
6724
- const [view, setView] = React23__default.useState(selected || /* @__PURE__ */ new Date());
6725
- const [mode, setMode] = React23__default.useState("days");
6726
- const [focusDate, setFocusDate] = React23__default.useState(null);
6727
- const [coords, setCoords] = React23__default.useState(null);
6728
- const wrapRef = React23__default.useRef(null);
6729
- const triggerRef = React23__default.useRef(null);
6730
- const popRef = React23__default.useRef(null);
6731
- const gridRef = React23__default.useRef(null);
6894
+ const [open, setOpen] = React24__default.useState(false);
6895
+ const [view, setView] = React24__default.useState(selected || /* @__PURE__ */ new Date());
6896
+ const [mode, setMode] = React24__default.useState("days");
6897
+ const [focusDate, setFocusDate] = React24__default.useState(null);
6898
+ const [coords, setCoords] = React24__default.useState(null);
6899
+ const wrapRef = React24__default.useRef(null);
6900
+ const triggerRef = React24__default.useRef(null);
6901
+ const popRef = React24__default.useRef(null);
6902
+ const gridRef = React24__default.useRef(null);
6732
6903
  const POP_W = 280;
6733
- const place = React23__default.useCallback(() => {
6904
+ const place = React24__default.useCallback(() => {
6734
6905
  const el = triggerRef.current;
6735
6906
  if (!el) return;
6736
6907
  const r = el.getBoundingClientRect();
@@ -6741,7 +6912,7 @@ function DatePicker({
6741
6912
  left = Math.max(8, left);
6742
6913
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
6743
6914
  }, []);
6744
- React23__default.useEffect(() => {
6915
+ React24__default.useEffect(() => {
6745
6916
  if (!open) return void 0;
6746
6917
  place();
6747
6918
  const onMove = () => place();
@@ -6752,7 +6923,7 @@ function DatePicker({
6752
6923
  window.removeEventListener("resize", onMove);
6753
6924
  };
6754
6925
  }, [open, place]);
6755
- React23__default.useEffect(() => {
6926
+ React24__default.useEffect(() => {
6756
6927
  if (!open) return;
6757
6928
  setView(selected || /* @__PURE__ */ new Date());
6758
6929
  setMode("days");
@@ -6772,8 +6943,8 @@ function DatePicker({
6772
6943
  document.removeEventListener("keydown", onKey);
6773
6944
  };
6774
6945
  }, [open]);
6775
- const prevOpen = React23__default.useRef(false);
6776
- React23__default.useEffect(() => {
6946
+ const prevOpen = React24__default.useRef(false);
6947
+ React24__default.useEffect(() => {
6777
6948
  let id2;
6778
6949
  if (!prevOpen.current && open) {
6779
6950
  id2 = setTimeout(() => gridRef.current?.querySelector('[tabindex="0"]')?.focus({ preventScroll: true }), 30);
@@ -6784,9 +6955,9 @@ function DatePicker({
6784
6955
  prevOpen.current = open;
6785
6956
  return () => clearTimeout(id2);
6786
6957
  }, [open]);
6787
- const months = React23__default.useMemo(() => locale === void 0 ? MONTHS : monthNames(locale), [locale]);
6788
- const monthsShort = React23__default.useMemo(() => locale === void 0 ? MONTHS.map((n) => n.slice(0, 3)) : monthShortNames(locale), [locale]);
6789
- const dows = React23__default.useMemo(
6958
+ const months = React24__default.useMemo(() => locale === void 0 ? MONTHS : monthNames(locale), [locale]);
6959
+ const monthsShort = React24__default.useMemo(() => locale === void 0 ? MONTHS.map((n) => n.slice(0, 3)) : monthShortNames(locale), [locale]);
6960
+ const dows = React24__default.useMemo(
6790
6961
  () => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW[(i + weekStartsOn) % 7]) : weekdayNames(locale, weekStartsOn),
6791
6962
  [locale, weekStartsOn]
6792
6963
  );
@@ -6814,7 +6985,7 @@ function DatePicker({
6814
6985
  };
6815
6986
  const cells = Array.from({ length: 42 }, (_, i) => new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i));
6816
6987
  const tabbableDate = (focusDate && cells.some((c) => sameDay(c, focusDate)) ? focusDate : null) || (selected && cells.some((c) => sameDay(c, selected)) ? selected : null) || (cells.some((c) => sameDay(c, today)) ? today : null) || new Date(y, m, 1);
6817
- React23__default.useEffect(() => {
6988
+ React24__default.useEffect(() => {
6818
6989
  if (!open || mode !== "days" || !focusDate) return;
6819
6990
  gridRef.current?.querySelector(`[data-key="${keyOf(focusDate)}"]`)?.focus();
6820
6991
  }, [focusDate, open, mode]);
@@ -7037,23 +7208,23 @@ function DateRangePicker({
7037
7208
  }) {
7038
7209
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS4);
7039
7210
  const __twcStyles1 = useScopedStyles("twc-drp-styles", RANGE_CSS);
7040
- const [internal, setInternal] = React23__default.useState(defaultValue);
7211
+ const [internal, setInternal] = React24__default.useState(defaultValue);
7041
7212
  const range = value !== void 0 ? value : internal;
7042
- const [open, setOpen] = React23__default.useState(false);
7043
- const [view, setView] = React23__default.useState(range.start || /* @__PURE__ */ new Date());
7044
- const [hover, setHover] = React23__default.useState(null);
7045
- const [coords, setCoords] = React23__default.useState(null);
7046
- const wrapRef = React23__default.useRef(null);
7047
- const triggerRef = React23__default.useRef(null);
7048
- const popRef = React23__default.useRef(null);
7049
- const labelId = React23__default.useId();
7213
+ const [open, setOpen] = React24__default.useState(false);
7214
+ const [view, setView] = React24__default.useState(range.start || /* @__PURE__ */ new Date());
7215
+ const [hover, setHover] = React24__default.useState(null);
7216
+ const [coords, setCoords] = React24__default.useState(null);
7217
+ const wrapRef = React24__default.useRef(null);
7218
+ const triggerRef = React24__default.useRef(null);
7219
+ const popRef = React24__default.useRef(null);
7220
+ const labelId = React24__default.useId();
7050
7221
  const descId = `${labelId}-desc`;
7051
7222
  const invalid = Boolean(error);
7052
- React23__default.useEffect(() => {
7223
+ React24__default.useEffect(() => {
7053
7224
  if (disabled) setOpen(false);
7054
7225
  }, [disabled]);
7055
7226
  const POP_W = 420;
7056
- const place = React23__default.useCallback(() => {
7227
+ const place = React24__default.useCallback(() => {
7057
7228
  const el = triggerRef.current;
7058
7229
  if (!el) return;
7059
7230
  const r = el.getBoundingClientRect();
@@ -7064,7 +7235,7 @@ function DateRangePicker({
7064
7235
  left = Math.max(8, left);
7065
7236
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
7066
7237
  }, []);
7067
- React23__default.useEffect(() => {
7238
+ React24__default.useEffect(() => {
7068
7239
  if (!open) return void 0;
7069
7240
  place();
7070
7241
  const onMove = () => place();
@@ -7075,7 +7246,7 @@ function DateRangePicker({
7075
7246
  window.removeEventListener("resize", onMove);
7076
7247
  };
7077
7248
  }, [open, place]);
7078
- React23__default.useEffect(() => {
7249
+ React24__default.useEffect(() => {
7079
7250
  if (!open) return;
7080
7251
  const onDown = (e) => {
7081
7252
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -7113,8 +7284,8 @@ function DateRangePicker({
7113
7284
  setView(start);
7114
7285
  setOpen(false);
7115
7286
  };
7116
- const months = React23__default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
7117
- const dows = React23__default.useMemo(
7287
+ const months = React24__default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
7288
+ const dows = React24__default.useMemo(
7118
7289
  () => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW2[(i + weekStartsOn) % 7]) : weekdayNames2(locale, weekStartsOn),
7119
7290
  [locale, weekStartsOn]
7120
7291
  );
@@ -7295,13 +7466,14 @@ function Dialog({
7295
7466
  className = "",
7296
7467
  ...rest
7297
7468
  }) {
7298
- const autoId = React23__default.useId();
7469
+ const autoId = React24__default.useId();
7299
7470
  const titleId = `${autoId}-title`;
7300
7471
  const descId = `${autoId}-desc`;
7301
- const dialogRef = React23__default.useRef(null);
7472
+ const dialogRef = React24__default.useRef(null);
7302
7473
  const __twcStyles = useScopedStyles("twc-dialog-styles", DIALOG_CSS);
7303
- const [mounted, setMounted] = React23__default.useState(open);
7304
- React23__default.useEffect(() => {
7474
+ const renderPortal = usePortal();
7475
+ const [mounted, setMounted] = React24__default.useState(open);
7476
+ React24__default.useEffect(() => {
7305
7477
  if (open) {
7306
7478
  setMounted(true);
7307
7479
  return;
@@ -7309,7 +7481,7 @@ function Dialog({
7309
7481
  const t = setTimeout(() => setMounted(false), 170);
7310
7482
  return () => clearTimeout(t);
7311
7483
  }, [open]);
7312
- React23__default.useEffect(() => {
7484
+ React24__default.useEffect(() => {
7313
7485
  if (!open) return void 0;
7314
7486
  const prev = document.body.style.overflow;
7315
7487
  document.body.style.overflow = "hidden";
@@ -7317,48 +7489,13 @@ function Dialog({
7317
7489
  document.body.style.overflow = prev;
7318
7490
  };
7319
7491
  }, [open]);
7320
- React23__default.useEffect(() => {
7321
- if (!open || !mounted) return void 0;
7322
- const node = dialogRef.current;
7323
- const prevFocused = document.activeElement;
7324
- const first = node?.querySelector(
7325
- 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
7326
- );
7327
- (first || node)?.focus();
7328
- return () => {
7329
- if (prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
7330
- };
7331
- }, [open, mounted]);
7332
- React23__default.useEffect(() => {
7333
- if (!open) return;
7334
- const node = dialogRef.current;
7335
- const focusables = () => node ? Array.from(
7336
- node.querySelectorAll(
7337
- 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
7338
- )
7339
- ).filter((el) => el.offsetParent !== null) : [];
7492
+ useFocusTrap(dialogRef, open && mounted);
7493
+ React24__default.useEffect(() => {
7494
+ if (!open) return void 0;
7340
7495
  const onKey = (e) => {
7341
7496
  if (e.key === "Escape") {
7342
7497
  e.preventDefault();
7343
7498
  onClose?.();
7344
- return;
7345
- }
7346
- if (e.key !== "Tab") return;
7347
- const f = focusables();
7348
- if (!f.length) {
7349
- e.preventDefault();
7350
- node?.focus();
7351
- return;
7352
- }
7353
- const first = f[0], last = f[f.length - 1], ae = document.activeElement;
7354
- if (e.shiftKey) {
7355
- if (ae === first || ae === node || !node.contains(ae)) {
7356
- e.preventDefault();
7357
- last.focus();
7358
- }
7359
- } else if (ae === last || !node.contains(ae)) {
7360
- e.preventDefault();
7361
- first.focus();
7362
7499
  }
7363
7500
  };
7364
7501
  document.addEventListener("keydown", onKey);
@@ -7382,9 +7519,7 @@ function Dialog({
7382
7519
  footer ? /* @__PURE__ */ jsx("div", { className: "twc-dialog__footer", children: footer }) : null
7383
7520
  ] })
7384
7521
  ] });
7385
- if (typeof document === "undefined") return null;
7386
- const RD = typeof createPortal === "function" ? createPortal : null;
7387
- return RD ? RD(overlay, document.body) : overlay;
7522
+ return renderPortal(overlay);
7388
7523
  }
7389
7524
  var DIVIDER_CSS = `
7390
7525
  .twc-divider { border: none; background: var(--color-divider); }
@@ -7399,6 +7534,10 @@ var DIVIDER_CSS = `
7399
7534
  so ::before/::after land on the correct inline edge under RTL \u2014 no physical override needed. */
7400
7535
  .twc-divider-label[data-align="start"]::before { flex: 0 0 var(--space-6); }
7401
7536
  .twc-divider-label[data-align="end"]::after { flex: 0 0 var(--space-6); }
7537
+ /* Vertical labeled divider: stack the two segments above/below the label. */
7538
+ .twc-divider-label[data-orientation="vertical"] { flex-direction: column; align-self: stretch; min-height: 1em; margin: 0 var(--space-3); }
7539
+ .twc-divider-label[data-orientation="vertical"]::before,
7540
+ .twc-divider-label[data-orientation="vertical"]::after { width: 1px; height: auto; flex: 1; }
7402
7541
  `;
7403
7542
  function Divider({
7404
7543
  orientation = "horizontal",
@@ -7411,7 +7550,7 @@ function Divider({
7411
7550
  const __twcStyles = useScopedStyles("twc-divider-styles", DIVIDER_CSS);
7412
7551
  const resolvedAlign = align === "left" ? "start" : align === "right" ? "end" : align;
7413
7552
  if (children) {
7414
- return /* @__PURE__ */ jsxs("div", { className: `twc-divider-label ${className}`, "data-align": resolvedAlign, role: "separator", ...rest, children: [
7553
+ return /* @__PURE__ */ jsxs("div", { className: `twc-divider-label ${className}`, "data-align": resolvedAlign, "data-orientation": orientation, role: "separator", "aria-orientation": orientation, ...rest, children: [
7415
7554
  __twcStyles,
7416
7555
  children
7417
7556
  ] });
@@ -7498,13 +7637,14 @@ function Drawer({
7498
7637
  style,
7499
7638
  ...rest
7500
7639
  }) {
7501
- const autoId = React23__default.useId();
7640
+ const autoId = React24__default.useId();
7502
7641
  const titleId = `${autoId}-title`;
7503
7642
  const descId = `${autoId}-desc`;
7504
- const panelRef = React23__default.useRef(null);
7643
+ const panelRef = React24__default.useRef(null);
7505
7644
  const __twcStyles = useScopedStyles("twc-drawer-styles", DRAWER_CSS);
7506
- const [mounted, setMounted] = React23__default.useState(open);
7507
- React23__default.useEffect(() => {
7645
+ const renderPortal = usePortal();
7646
+ const [mounted, setMounted] = React24__default.useState(open);
7647
+ React24__default.useEffect(() => {
7508
7648
  if (open) {
7509
7649
  setMounted(true);
7510
7650
  return;
@@ -7512,7 +7652,7 @@ function Drawer({
7512
7652
  const t = setTimeout(() => setMounted(false), 170);
7513
7653
  return () => clearTimeout(t);
7514
7654
  }, [open]);
7515
- React23__default.useEffect(() => {
7655
+ React24__default.useEffect(() => {
7516
7656
  if (!open) return void 0;
7517
7657
  const prev = document.body.style.overflow;
7518
7658
  document.body.style.overflow = "hidden";
@@ -7520,48 +7660,13 @@ function Drawer({
7520
7660
  document.body.style.overflow = prev;
7521
7661
  };
7522
7662
  }, [open]);
7523
- React23__default.useEffect(() => {
7524
- if (!open || !mounted) return void 0;
7525
- const node = panelRef.current;
7526
- const prevFocused = document.activeElement;
7527
- const first = node?.querySelector(
7528
- 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
7529
- );
7530
- (first || node)?.focus();
7531
- return () => {
7532
- if (prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
7533
- };
7534
- }, [open, mounted]);
7535
- React23__default.useEffect(() => {
7536
- if (!open) return;
7537
- const node = panelRef.current;
7538
- const focusables = () => node ? Array.from(
7539
- node.querySelectorAll(
7540
- 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
7541
- )
7542
- ).filter((el) => el.offsetParent !== null) : [];
7663
+ useFocusTrap(panelRef, open && mounted);
7664
+ React24__default.useEffect(() => {
7665
+ if (!open) return void 0;
7543
7666
  const onKey = (e) => {
7544
7667
  if (e.key === "Escape") {
7545
7668
  e.preventDefault();
7546
7669
  onClose?.();
7547
- return;
7548
- }
7549
- if (e.key !== "Tab") return;
7550
- const f = focusables();
7551
- if (!f.length) {
7552
- e.preventDefault();
7553
- node?.focus();
7554
- return;
7555
- }
7556
- const first = f[0], last = f[f.length - 1], ae = document.activeElement;
7557
- if (e.shiftKey) {
7558
- if (ae === first || ae === node || !node.contains(ae)) {
7559
- e.preventDefault();
7560
- last.focus();
7561
- }
7562
- } else if (ae === last || !node.contains(ae)) {
7563
- e.preventDefault();
7564
- first.focus();
7565
7670
  }
7566
7671
  };
7567
7672
  document.addEventListener("keydown", onKey);
@@ -7589,9 +7694,7 @@ function Drawer({
7589
7694
  footer ? /* @__PURE__ */ jsx("div", { className: "twc-drawer__footer", children: footer }) : null
7590
7695
  ] })
7591
7696
  ] });
7592
- if (typeof document === "undefined") return null;
7593
- const RD = typeof createPortal === "function" ? createPortal : null;
7594
- return RD ? RD(overlay, document.body) : overlay;
7697
+ return renderPortal(overlay);
7595
7698
  }
7596
7699
  var EMPTY_CSS = `
7597
7700
  .twc-empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-3);
@@ -7609,11 +7712,14 @@ function EmptyState({
7609
7712
  title,
7610
7713
  description,
7611
7714
  actions,
7612
- bordered = false,
7715
+ bordered,
7613
7716
  border,
7614
7717
  className = "",
7615
7718
  ...rest
7616
7719
  }) {
7720
+ if (process.env.NODE_ENV !== "production" && bordered !== void 0 && border === void 0) {
7721
+ warnOnce("EmptyState.bordered", "EmptyState: `bordered` is deprecated and will be removed in 2.0 \u2014 use `border`.");
7722
+ }
7617
7723
  const hasBorder = border ?? bordered;
7618
7724
  const __twcStyles = useScopedStyles("twc-empty-styles", EMPTY_CSS);
7619
7725
  return /* @__PURE__ */ jsxs("div", { className: `twc-empty ${className}`, "data-bordered": hasBorder || void 0, ...rest, children: [
@@ -7644,7 +7750,7 @@ function Field({
7644
7750
  ...rest
7645
7751
  }) {
7646
7752
  const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS5);
7647
- const autoId = React23__default.useId();
7753
+ const autoId = React24__default.useId();
7648
7754
  const fieldId = id || autoId;
7649
7755
  const descId = `${fieldId}-desc`;
7650
7756
  return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, "data-size": size, ...rest, children: [
@@ -7724,11 +7830,11 @@ function FileUpload({
7724
7830
  ...rest
7725
7831
  }) {
7726
7832
  const __twcStyles = useScopedStyles("twc-upload-styles", UPLOAD_CSS);
7727
- const [internal, setInternal] = React23__default.useState(defaultValue);
7833
+ const [internal, setInternal] = React24__default.useState(defaultValue);
7728
7834
  const files = value !== void 0 ? value : internal;
7729
- const [drag, setDrag] = React23__default.useState(false);
7730
- const inputRef = React23__default.useRef(null);
7731
- const autoId = React23__default.useId();
7835
+ const [drag, setDrag] = React24__default.useState(false);
7836
+ const inputRef = React24__default.useRef(null);
7837
+ const autoId = React24__default.useId();
7732
7838
  const fieldId = id || autoId;
7733
7839
  const descId = `${fieldId}-desc`;
7734
7840
  const invalid = Boolean(error);
@@ -7926,19 +8032,20 @@ function Kanban({
7926
8032
  defaultCards,
7927
8033
  onCardMove,
7928
8034
  renderCard,
8035
+ getCardLabel,
7929
8036
  className = "",
7930
8037
  ...rest
7931
8038
  }) {
7932
8039
  const __twcStyles = useScopedStyles("twc-kanban-styles", KANBAN_CSS);
7933
- const [internal, setInternal] = React23__default.useState(cards ?? defaultCards ?? []);
8040
+ const [internal, setInternal] = React24__default.useState(cards ?? defaultCards ?? []);
7934
8041
  const items = cards !== void 0 ? cards : internal;
7935
- const [drag, setDrag] = React23__default.useState(null);
7936
- const [overCol, setOverCol] = React23__default.useState(null);
7937
- const [grab, setGrab] = React23__default.useState(null);
7938
- const [announce, setAnnounce] = React23__default.useState("");
7939
- const rootRef = React23__default.useRef(null);
7940
- const focusIdRef = React23__default.useRef(null);
7941
- React23__default.useEffect(() => {
8042
+ const [drag, setDrag] = React24__default.useState(null);
8043
+ const [overCol, setOverCol] = React24__default.useState(null);
8044
+ const [grab, setGrab] = React24__default.useState(null);
8045
+ const [announce, setAnnounce] = React24__default.useState("");
8046
+ const rootRef = React24__default.useRef(null);
8047
+ const focusIdRef = React24__default.useRef(null);
8048
+ React24__default.useEffect(() => {
7942
8049
  if (focusIdRef.current == null) return void 0;
7943
8050
  const raf = requestAnimationFrame(() => {
7944
8051
  const id = focusIdRef.current;
@@ -7990,7 +8097,7 @@ function Kanban({
7990
8097
  }
7991
8098
  };
7992
8099
  const keyTargetCol = grab ? columns[grab.targetIdx]?.id : null;
7993
- return /* @__PURE__ */ jsxs("div", { className: `twc-kanban ${className}`, ref: rootRef, ...rest, children: [
8100
+ return /* @__PURE__ */ jsxs("div", { className: `twc-kanban ${className}`, ref: rootRef, role: "group", "aria-label": "Board", ...rest, children: [
7994
8101
  __twcStyles,
7995
8102
  /* @__PURE__ */ jsx("div", { className: "twc-kanban__sr", role: "status", "aria-live": "polite", children: announce }),
7996
8103
  columns.map((col, colIdx) => {
@@ -8000,7 +8107,7 @@ function Kanban({
8000
8107
  {
8001
8108
  className: "twc-kanban__col",
8002
8109
  role: "group",
8003
- "aria-label": typeof col.title === "string" ? col.title : void 0,
8110
+ "aria-label": col.ariaLabel ?? colTitle(col),
8004
8111
  "data-over": overCol === col.id || keyTargetCol === col.id || void 0,
8005
8112
  onDragOver: (e) => {
8006
8113
  e.preventDefault();
@@ -8031,6 +8138,8 @@ function Kanban({
8031
8138
  tabIndex: 0,
8032
8139
  "aria-roledescription": "draggable card",
8033
8140
  "data-card-id": card.id,
8141
+ "aria-label": getCardLabel?.(card) ?? (typeof card.ariaLabel === "string" ? card.ariaLabel : cardTitle(card)),
8142
+ "aria-pressed": grab && grab.id === card.id || void 0,
8034
8143
  "data-grabbed": grab && grab.id === card.id || void 0,
8035
8144
  onKeyDown: (e) => handleCardKey(e, card, colIdx),
8036
8145
  onBlur: () => {
@@ -8084,7 +8193,7 @@ var LIST_CSS = `
8084
8193
  `;
8085
8194
  function List({ items, plain = false, className = "", ...rest }) {
8086
8195
  const __twcStyles = useScopedStyles("twc-list-styles", LIST_CSS);
8087
- const safeHref11 = (url) => {
8196
+ const safeHref12 = (url) => {
8088
8197
  if (url == null) return void 0;
8089
8198
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
8090
8199
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -8092,7 +8201,7 @@ function List({ items, plain = false, className = "", ...rest }) {
8092
8201
  return /* @__PURE__ */ jsxs("ul", { className: `twc-list ${className}`, "data-plain": plain || void 0, ...rest, children: [
8093
8202
  __twcStyles,
8094
8203
  items.map((it, i) => {
8095
- const href = safeHref11(it.href);
8204
+ const href = safeHref12(it.href);
8096
8205
  const interactive = Boolean(it.onClick || href);
8097
8206
  const Tag2 = href ? "a" : interactive ? "button" : "div";
8098
8207
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -8146,7 +8255,7 @@ button.twc-navbar__brand, a.twc-navbar__brand { cursor: pointer; }
8146
8255
  .twc-navbar__menu-btn { display: inline-grid; }
8147
8256
  }
8148
8257
  `;
8149
- function safeHref3(url) {
8258
+ function safeHref4(url) {
8150
8259
  if (url == null) return void 0;
8151
8260
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
8152
8261
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -8159,16 +8268,19 @@ function Navbar({
8159
8268
  actions,
8160
8269
  sticky = true,
8161
8270
  onMenuClick,
8271
+ menuOpen,
8272
+ menuControls,
8273
+ navLabel = "Primary",
8162
8274
  className = "",
8163
8275
  ...rest
8164
8276
  }) {
8165
8277
  const __twcStyles = useScopedStyles("twc-navbar-styles", NAVBAR_CSS);
8166
8278
  return /* @__PURE__ */ jsxs("header", { className: `twc-navbar ${className}`, "data-sticky": sticky || void 0, ...rest, children: [
8167
8279
  __twcStyles,
8168
- onMenuClick ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-navbar__menu-btn", "aria-label": "Open menu", onClick: onMenuClick, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M4 12h16M4 18h16" }) }) }) : null,
8169
- brand ? brandHref ? /* @__PURE__ */ jsx("a", { className: "twc-navbar__brand", href: safeHref3(brandHref), children: brand }) : onBrandClick ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-navbar__brand", onClick: onBrandClick, children: brand }) : /* @__PURE__ */ jsx("span", { className: "twc-navbar__brand", children: brand }) : null,
8170
- /* @__PURE__ */ jsx("nav", { className: "twc-navbar__links", children: links.map((l, i) => {
8171
- const href = safeHref3(l.href);
8280
+ onMenuClick ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-navbar__menu-btn", "aria-expanded": menuOpen, "aria-controls": menuControls, "aria-label": menuOpen ? "Close menu" : "Open menu", onClick: onMenuClick, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M4 12h16M4 18h16" }) }) }) : null,
8281
+ brand ? brandHref ? /* @__PURE__ */ jsx("a", { className: "twc-navbar__brand", href: safeHref4(brandHref), children: brand }) : onBrandClick ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-navbar__brand", onClick: onBrandClick, children: brand }) : /* @__PURE__ */ jsx("span", { className: "twc-navbar__brand", children: brand }) : null,
8282
+ /* @__PURE__ */ jsx("nav", { className: "twc-navbar__links", "aria-label": navLabel, children: links.map((l, i) => {
8283
+ const href = safeHref4(l.href);
8172
8284
  const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
8173
8285
  l.icon,
8174
8286
  l.label
@@ -8236,21 +8348,21 @@ function Popover({
8236
8348
  ...rest
8237
8349
  }) {
8238
8350
  const __twcStyles = useScopedStyles("twc-popover-styles", POPOVER_CSS);
8239
- const [openState, setOpenState] = React23__default.useState(defaultOpen);
8240
- const [render, setRender] = React23__default.useState(false);
8241
- const [pos, setPos] = React23__default.useState(null);
8242
- const wrapRef = React23__default.useRef(null);
8243
- const popRef = React23__default.useRef(null);
8244
- const popId = React23__default.useId();
8351
+ const [openState, setOpenState] = React24__default.useState(defaultOpen);
8352
+ const [render, setRender] = React24__default.useState(false);
8353
+ const [pos, setPos] = React24__default.useState(null);
8354
+ const wrapRef = React24__default.useRef(null);
8355
+ const popRef = React24__default.useRef(null);
8356
+ const popId = React24__default.useId();
8245
8357
  const controlled = openProp !== void 0;
8246
8358
  const open = controlled ? !!openProp : openState;
8247
- const openRef = React23__default.useRef(open);
8359
+ const openRef = React24__default.useRef(open);
8248
8360
  openRef.current = open;
8249
- const controlledRef = React23__default.useRef(controlled);
8361
+ const controlledRef = React24__default.useRef(controlled);
8250
8362
  controlledRef.current = controlled;
8251
- const onOpenChangeRef = React23__default.useRef(onOpenChange);
8363
+ const onOpenChangeRef = React24__default.useRef(onOpenChange);
8252
8364
  onOpenChangeRef.current = onOpenChange;
8253
- const setOpen = React23__default.useCallback((next) => {
8365
+ const setOpen = React24__default.useCallback((next) => {
8254
8366
  const value = typeof next === "function" ? next(openRef.current) : next;
8255
8367
  if (value === openRef.current) return;
8256
8368
  if (!controlledRef.current) setOpenState(value);
@@ -8258,7 +8370,7 @@ function Popover({
8258
8370
  }, []);
8259
8371
  const toggle = () => setOpen((o) => !o);
8260
8372
  const RD = { createPortal: typeof createPortal === "function" ? createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
8261
- const place = React23__default.useCallback(() => {
8373
+ const place = React24__default.useCallback(() => {
8262
8374
  const t = wrapRef.current;
8263
8375
  if (!t) return;
8264
8376
  const r = t.getBoundingClientRect();
@@ -8289,7 +8401,7 @@ function Popover({
8289
8401
  arrow = { top: Math.min(Math.max(cy - top - 5.5, 8), ph - 18), [onRight ? "left" : "right"]: -6 };
8290
8402
  setPos({ top, left, width: w, flip: false, arrow });
8291
8403
  }, [placement, align, width]);
8292
- React23__default.useEffect(() => {
8404
+ React24__default.useEffect(() => {
8293
8405
  if (!open) return;
8294
8406
  place();
8295
8407
  const onMove = () => place();
@@ -8312,7 +8424,7 @@ function Popover({
8312
8424
  document.removeEventListener("keydown", onKey);
8313
8425
  };
8314
8426
  }, [open, place]);
8315
- React23__default.useEffect(() => {
8427
+ React24__default.useEffect(() => {
8316
8428
  if (open) {
8317
8429
  setRender(true);
8318
8430
  return;
@@ -8320,12 +8432,12 @@ function Popover({
8320
8432
  const t = setTimeout(() => setRender(false), 170);
8321
8433
  return () => clearTimeout(t);
8322
8434
  }, [open]);
8323
- React23__default.useEffect(() => {
8435
+ React24__default.useEffect(() => {
8324
8436
  if (render && open) place();
8325
8437
  }, [render, place]);
8326
- const restoreRef = React23__default.useRef(null);
8327
- const needFocusRef = React23__default.useRef(false);
8328
- React23__default.useEffect(() => {
8438
+ const restoreRef = React24__default.useRef(null);
8439
+ const needFocusRef = React24__default.useRef(false);
8440
+ React24__default.useEffect(() => {
8329
8441
  if (open) {
8330
8442
  restoreRef.current = document.activeElement;
8331
8443
  needFocusRef.current = true;
@@ -8336,7 +8448,7 @@ function Popover({
8336
8448
  needFocusRef.current = false;
8337
8449
  if (prev && typeof prev.focus === "function" && popRef.current?.contains(document.activeElement)) prev.focus();
8338
8450
  }, [open]);
8339
- React23__default.useEffect(() => {
8451
+ React24__default.useEffect(() => {
8340
8452
  if (open && render && pos && needFocusRef.current) {
8341
8453
  needFocusRef.current = false;
8342
8454
  popRef.current?.focus({ preventScroll: true });
@@ -8364,7 +8476,7 @@ function Popover({
8364
8476
  ]
8365
8477
  }
8366
8478
  ) : null;
8367
- const triggerEl = React23__default.isValidElement(trigger) ? React23__default.cloneElement(trigger, {
8479
+ const triggerEl = React24__default.isValidElement(trigger) ? React24__default.cloneElement(trigger, {
8368
8480
  onClick: (e) => {
8369
8481
  trigger.props.onClick?.(e);
8370
8482
  toggle();
@@ -8403,9 +8515,12 @@ function Progress({
8403
8515
  size = "md",
8404
8516
  indeterminate = false,
8405
8517
  showLabel = false,
8518
+ label,
8406
8519
  className = "",
8407
8520
  ...rest
8408
8521
  }) {
8522
+ const labelId = React24__default.useId();
8523
+ const { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...restProps } = rest;
8409
8524
  const __twcStyles = useScopedStyles("twc-progress-styles", `
8410
8525
  .twc-progress-wrap { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-sans); }
8411
8526
  .twc-progress {
@@ -8444,14 +8559,14 @@ function Progress({
8444
8559
  return (
8445
8560
  // Single-root contract: className and ...rest (style, id, handlers, …) share the outer
8446
8561
  // wrapper; role="progressbar" + aria-value* stay on the inner track.
8447
- /* @__PURE__ */ jsxs("div", { className: `twc-progress-wrap ${className}`, ...rest, children: [
8562
+ /* @__PURE__ */ jsxs("div", { className: `twc-progress-wrap ${className}`, ...restProps, children: [
8448
8563
  __twcStyles,
8449
- showLabel && !indeterminate ? /* @__PURE__ */ jsxs("div", { className: "twc-progress__meta", children: [
8450
- /* @__PURE__ */ jsx("span", { children: "Progress" }),
8451
- /* @__PURE__ */ jsxs("span", { children: [
8564
+ (showLabel || label != null) && !indeterminate ? /* @__PURE__ */ jsxs("div", { className: "twc-progress__meta", children: [
8565
+ /* @__PURE__ */ jsx("span", { id: labelId, children: label ?? "Progress" }),
8566
+ showLabel ? /* @__PURE__ */ jsxs("span", { children: [
8452
8567
  Math.round(pct),
8453
8568
  "%"
8454
- ] })
8569
+ ] }) : null
8455
8570
  ] }) : null,
8456
8571
  /* @__PURE__ */ jsx(
8457
8572
  "div",
@@ -8464,6 +8579,8 @@ function Progress({
8464
8579
  "aria-valuenow": indeterminate ? void 0 : Math.round(pct),
8465
8580
  "aria-valuemin": 0,
8466
8581
  "aria-valuemax": 100,
8582
+ "aria-label": ariaLabel,
8583
+ "aria-labelledby": ariaLabelledby ?? (label != null ? labelId : void 0),
8467
8584
  children: /* @__PURE__ */ jsx("div", { className: "twc-progress__bar", style: indeterminate ? void 0 : { width: `${pct}%` } })
8468
8585
  }
8469
8586
  )
@@ -8525,7 +8642,7 @@ function Radio({
8525
8642
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
8526
8643
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
8527
8644
  `);
8528
- const autoId = React23__default.useId();
8645
+ const autoId = React24__default.useId();
8529
8646
  const fieldId = id || autoId;
8530
8647
  const errId = `${fieldId}-error`;
8531
8648
  const invalid = Boolean(error);
@@ -8603,12 +8720,12 @@ function Rating({
8603
8720
  ...rest
8604
8721
  }) {
8605
8722
  const __twcStyles = useScopedStyles("twc-rating-styles", RATING_CSS);
8606
- const [internal, setInternal] = React23__default.useState(defaultValue);
8607
- const [hover, setHover] = React23__default.useState(0);
8723
+ const [internal, setInternal] = React24__default.useState(defaultValue);
8724
+ const [hover, setHover] = React24__default.useState(0);
8608
8725
  const val = value !== void 0 ? value : internal;
8609
8726
  const shown = hover || val;
8610
8727
  const interactive = !readOnly && !disabled;
8611
- const btnRefs = React23__default.useRef([]);
8728
+ const btnRefs = React24__default.useRef([]);
8612
8729
  const tabStar = Math.min(count, Math.max(1, Math.round(val) || 1));
8613
8730
  const set = (v) => {
8614
8731
  if (!interactive) return;
@@ -8702,12 +8819,12 @@ function Tooltip({
8702
8819
  ...rest
8703
8820
  }) {
8704
8821
  const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
8705
- const id = React23__default.useId();
8706
- const [show, setShow] = React23__default.useState(false);
8707
- const [coords, setCoords] = React23__default.useState(null);
8708
- const timer = React23__default.useRef(null);
8709
- const wrapRef = React23__default.useRef(null);
8710
- const tipRef = React23__default.useRef(null);
8822
+ const id = React24__default.useId();
8823
+ const [show, setShow] = React24__default.useState(false);
8824
+ const [coords, setCoords] = React24__default.useState(null);
8825
+ const timer = React24__default.useRef(null);
8826
+ const wrapRef = React24__default.useRef(null);
8827
+ const tipRef = React24__default.useRef(null);
8711
8828
  const open = () => {
8712
8829
  clearTimeout(timer.current);
8713
8830
  timer.current = setTimeout(() => setShow(true), delay);
@@ -8716,8 +8833,8 @@ function Tooltip({
8716
8833
  clearTimeout(timer.current);
8717
8834
  setShow(false);
8718
8835
  };
8719
- React23__default.useEffect(() => () => clearTimeout(timer.current), []);
8720
- const place = React23__default.useCallback(() => {
8836
+ React24__default.useEffect(() => () => clearTimeout(timer.current), []);
8837
+ const place = React24__default.useCallback(() => {
8721
8838
  const el = wrapRef.current;
8722
8839
  if (!el) return;
8723
8840
  const r = el.getBoundingClientRect();
@@ -8733,10 +8850,10 @@ function Tooltip({
8733
8850
  else if (placement === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
8734
8851
  else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
8735
8852
  }, [placement]);
8736
- React23__default.useEffect(() => {
8853
+ React24__default.useEffect(() => {
8737
8854
  place();
8738
8855
  }, [place]);
8739
- React23__default.useEffect(() => {
8856
+ React24__default.useEffect(() => {
8740
8857
  if (!show) return void 0;
8741
8858
  place();
8742
8859
  const onMove = () => place();
@@ -8747,7 +8864,7 @@ function Tooltip({
8747
8864
  window.removeEventListener("resize", onMove);
8748
8865
  };
8749
8866
  }, [show, place]);
8750
- React23__default.useEffect(() => {
8867
+ React24__default.useEffect(() => {
8751
8868
  if (!show) return;
8752
8869
  const onKeyDown = (e) => {
8753
8870
  if (e.key === "Escape") {
@@ -8759,7 +8876,7 @@ function Tooltip({
8759
8876
  return () => document.removeEventListener("keydown", onKeyDown);
8760
8877
  }, [show]);
8761
8878
  const describedBy = show ? id : void 0;
8762
- const trigger = React23__default.isValidElement(children) && children.type !== React23__default.Fragment ? React23__default.cloneElement(children, {
8879
+ const trigger = React24__default.isValidElement(children) && children.type !== React24__default.Fragment ? React24__default.cloneElement(children, {
8763
8880
  "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
8764
8881
  }) : /* @__PURE__ */ jsx("span", { "aria-describedby": describedBy, children });
8765
8882
  return /* @__PURE__ */ jsxs(
@@ -8815,6 +8932,7 @@ var SIDEBAR_CSS = `
8815
8932
  .twc-sidebar__brand { display: inline-flex; align-items: center; gap: var(--space-2-5); font-weight: var(--font-extrabold); font-size: var(--text-lg); letter-spacing: -0.02em; color: var(--color-text); white-space: nowrap; overflow: hidden; min-width: 0;
8816
8933
  transition: font-size var(--duration-base) var(--ease-standard), gap var(--duration-base) var(--ease-standard); }
8817
8934
  .twc-sidebar__nav { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: var(--space-3); display: flex; flex-direction: column; gap: 2px; }
8935
+ .twc-sidebar__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
8818
8936
  .twc-sidebar__section { font-size: 10px; font-weight: var(--font-bold); letter-spacing: var(--tracking-wider); text-transform: uppercase; color: var(--color-text-subtle); padding: var(--space-3) var(--space-3) var(--space-1); white-space: nowrap; overflow: hidden; max-height: 2.5rem; opacity: 1; visibility: visible;
8819
8937
  transition: max-height var(--duration-base) var(--ease-standard), padding var(--duration-base) var(--ease-standard), opacity var(--duration-fast) var(--ease-standard) var(--duration-fast), visibility 0s; }
8820
8938
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__section { max-height: 0; padding-top: 0; padding-bottom: 0; opacity: 0; visibility: hidden;
@@ -8856,6 +8974,23 @@ var SIDEBAR_CSS = `
8856
8974
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__foot { display: flex; flex-direction: column; align-items: center; padding: var(--space-2) 0; }
8857
8975
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__collapse { width: auto; padding: 11px; gap: 0; margin: 0; }
8858
8976
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__collapse span { display: none; }
8977
+
8978
+ /* Off-canvas overlay mode (mobile): the rail becomes a slide-over drawer behind a
8979
+ scrim, mirroring Drawer.jsx. Logical inset + a --_off var slide it in from the
8980
+ inline-start edge (mirrored under dir="rtl"). */
8981
+ .twc-sidebar__overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: var(--color-overlay); backdrop-filter: blur(2px); }
8982
+ .twc-sidebar__overlay[data-state="open"] { animation: twico-fade-in var(--duration-base) var(--ease-out); }
8983
+ .twc-sidebar__overlay[data-state="closed"] { animation: twc-sidebar-fade-out var(--duration-exit) var(--ease-in) forwards; pointer-events: none; }
8984
+ @keyframes twc-sidebar-fade-out { from { opacity: 1; } to { opacity: 0; } }
8985
+ .twc-sidebar--overlay { position: fixed; inset-block: 0; inset-inline-start: 0; height: 100%; max-width: 92vw; z-index: var(--z-modal); box-shadow: var(--shadow-xl); --_off: -100%; }
8986
+ [dir="rtl"] .twc-sidebar--overlay { inset-inline-start: auto; inset-inline-end: 0; --_off: 100%; }
8987
+ .twc-sidebar--overlay[data-state="open"] { animation: twc-sidebar-in var(--duration-base) var(--ease-out); }
8988
+ .twc-sidebar--overlay[data-state="closed"] { animation: twc-sidebar-out var(--duration-exit) var(--ease-in) forwards; }
8989
+ @keyframes twc-sidebar-in { from { transform: translateX(var(--_off)); } to { transform: translateX(0); } }
8990
+ @keyframes twc-sidebar-out { from { transform: translateX(0); } to { transform: translateX(var(--_off)); } }
8991
+ @media (prefers-reduced-motion: reduce) {
8992
+ .twc-sidebar__overlay[data-state], .twc-sidebar--overlay[data-state] { animation-duration: 1ms; }
8993
+ }
8859
8994
  `;
8860
8995
  function Sidebar({
8861
8996
  brand,
@@ -8865,63 +9000,149 @@ function Sidebar({
8865
9000
  defaultCollapsed = false,
8866
9001
  collapsible = true,
8867
9002
  onCollapsedChange,
9003
+ overlay = false,
9004
+ open: openProp,
9005
+ defaultOpen = false,
9006
+ onOpenChange,
9007
+ navLabel = "Main",
8868
9008
  className = "",
8869
9009
  ...rest
8870
9010
  }) {
8871
9011
  const __twcStyles = useScopedStyles("twc-sidebar-styles", SIDEBAR_CSS);
8872
- const [internal, setInternal] = React23__default.useState(defaultCollapsed);
9012
+ const navId = React24__default.useId();
9013
+ const panelRef = React24__default.useRef(null);
9014
+ const renderPortal = usePortal();
9015
+ const [internal, setInternal] = React24__default.useState(defaultCollapsed);
8873
9016
  const collapsed = collapsedProp !== void 0 ? collapsedProp : internal;
8874
9017
  const toggle = () => {
8875
9018
  const next = !collapsed;
8876
9019
  if (collapsedProp === void 0) setInternal(next);
8877
9020
  onCollapsedChange?.(next);
8878
9021
  };
8879
- const safeHref11 = (url) => {
9022
+ const [openInternal, setOpenInternal] = React24__default.useState(defaultOpen);
9023
+ const open = openProp !== void 0 ? openProp : openInternal;
9024
+ const setOpen = (next) => {
9025
+ if (openProp === void 0) setOpenInternal(next);
9026
+ onOpenChange?.(next);
9027
+ };
9028
+ const [mounted, setMounted] = React24__default.useState(open);
9029
+ React24__default.useEffect(() => {
9030
+ if (!overlay) return void 0;
9031
+ if (open) {
9032
+ setMounted(true);
9033
+ return void 0;
9034
+ }
9035
+ const t = setTimeout(() => setMounted(false), 170);
9036
+ return () => clearTimeout(t);
9037
+ }, [overlay, open]);
9038
+ React24__default.useEffect(() => {
9039
+ if (!overlay || !open) return void 0;
9040
+ const prev = document.body.style.overflow;
9041
+ document.body.style.overflow = "hidden";
9042
+ return () => {
9043
+ document.body.style.overflow = prev;
9044
+ };
9045
+ }, [overlay, open]);
9046
+ useFocusTrap(panelRef, overlay && open && mounted);
9047
+ React24__default.useEffect(() => {
9048
+ if (!overlay || !open) return void 0;
9049
+ const onKey = (e) => {
9050
+ if (e.key === "Escape") {
9051
+ e.preventDefault();
9052
+ if (openProp === void 0) setOpenInternal(false);
9053
+ onOpenChange?.(false);
9054
+ }
9055
+ };
9056
+ document.addEventListener("keydown", onKey);
9057
+ return () => document.removeEventListener("keydown", onKey);
9058
+ }, [overlay, open, openProp, onOpenChange]);
9059
+ const safeHref12 = (url) => {
8880
9060
  if (url == null) return void 0;
8881
9061
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
8882
9062
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
8883
9063
  };
8884
- return /* @__PURE__ */ jsxs("aside", { className: `twc-sidebar ${className}`, "data-collapsed": collapsed || void 0, ...rest, children: [
9064
+ const renderItem = (it, i) => {
9065
+ const href = safeHref12(it.href);
9066
+ const labelStr = typeof it.label === "string" ? it.label : void 0;
9067
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
9068
+ it.icon ? /* @__PURE__ */ jsx("span", { className: "twc-sidebar__ic", "aria-hidden": "true", children: it.icon }) : labelStr != null ? /* @__PURE__ */ jsx("span", { className: "twc-sidebar__ic twc-sidebar__ic--initial", "aria-hidden": "true", children: labelStr.charAt(0) }) : null,
9069
+ /* @__PURE__ */ jsx("span", { className: "twc-sidebar__label", children: it.label }),
9070
+ it.badge != null ? /* @__PURE__ */ jsx("span", { className: "twc-sidebar__badge", children: it.badge }) : null
9071
+ ] });
9072
+ const common = {
9073
+ className: "twc-sidebar__item",
9074
+ "data-active": it.active || void 0,
9075
+ "aria-current": it.active ? "page" : void 0,
9076
+ onClick: it.onClick,
9077
+ "aria-label": collapsed && labelStr != null ? labelStr : void 0
9078
+ };
9079
+ const node = href != null ? /* @__PURE__ */ jsx("a", { href, ...common, children: inner }) : /* @__PURE__ */ jsx("button", { type: "button", ...common, children: inner });
9080
+ return collapsed && labelStr != null ? /* @__PURE__ */ jsx(Tooltip, { label: labelStr, placement: "right", style: { display: "block" }, children: node }) : node;
9081
+ };
9082
+ const groups = [];
9083
+ let group = { sid: null, section: null, entries: [] };
9084
+ let secN = 0;
9085
+ for (let i = 0; i < items.length; i++) {
9086
+ const it = items[i];
9087
+ if (it.section) {
9088
+ if (group.entries.length || group.section != null) groups.push(group);
9089
+ secN += 1;
9090
+ group = { sid: `${navId}-sec-${secN}`, section: it.section, entries: [] };
9091
+ } else {
9092
+ group.entries.push({ it, i });
9093
+ }
9094
+ }
9095
+ if (group.entries.length || group.section != null) groups.push(group);
9096
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
8885
9097
  __twcStyles,
8886
9098
  brand ? /* @__PURE__ */ jsx("div", { className: "twc-sidebar__head", children: /* @__PURE__ */ jsx("span", { className: "twc-sidebar__brand", children: brand }) }) : null,
8887
- /* @__PURE__ */ jsx("nav", { className: "twc-sidebar__nav", children: items.map(
8888
- (it, i) => it.section ? /* @__PURE__ */ jsx("div", { className: "twc-sidebar__section", children: it.section }, i) : (() => {
8889
- const href = safeHref11(it.href);
8890
- const labelStr = typeof it.label === "string" ? it.label : void 0;
8891
- const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
8892
- it.icon ? /* @__PURE__ */ jsx("span", { className: "twc-sidebar__ic", "aria-hidden": "true", children: it.icon }) : labelStr != null ? /* @__PURE__ */ jsx("span", { className: "twc-sidebar__ic twc-sidebar__ic--initial", "aria-hidden": "true", children: labelStr.charAt(0) }) : null,
8893
- /* @__PURE__ */ jsx("span", { className: "twc-sidebar__label", children: it.label }),
8894
- it.badge != null ? /* @__PURE__ */ jsx("span", { className: "twc-sidebar__badge", children: it.badge }) : null
8895
- ] });
8896
- const common = {
8897
- className: "twc-sidebar__item",
8898
- "data-active": it.active || void 0,
8899
- "aria-current": it.active ? "page" : void 0,
8900
- onClick: it.onClick,
8901
- "aria-label": collapsed && labelStr != null ? labelStr : void 0
8902
- };
8903
- const node = href != null ? /* @__PURE__ */ jsx("a", { href, ...common, children: inner }, i) : /* @__PURE__ */ jsx("button", { type: "button", ...common, children: inner }, i);
8904
- return collapsed && labelStr != null ? /* @__PURE__ */ jsx(Tooltip, { label: labelStr, placement: "right", style: { display: "block" }, children: node }, i) : node;
8905
- })()
8906
- ) }),
9099
+ /* @__PURE__ */ jsx("nav", { id: navId, className: "twc-sidebar__nav", "aria-label": navLabel, children: groups.map((g, gi) => /* @__PURE__ */ jsxs(React24__default.Fragment, { children: [
9100
+ g.section != null ? /* @__PURE__ */ jsx("div", { className: "twc-sidebar__section", id: g.sid, children: g.section }) : null,
9101
+ /* @__PURE__ */ jsx("ul", { className: "twc-sidebar__list", ...g.section != null ? { "aria-labelledby": g.sid } : {}, children: g.entries.map(({ it, i }) => /* @__PURE__ */ jsx("li", { children: renderItem(it) }, i)) })
9102
+ ] }, gi)) }),
8907
9103
  footer || collapsible ? /* @__PURE__ */ jsxs("div", { className: "twc-sidebar__foot", children: [
8908
9104
  footer ? /* @__PURE__ */ jsx("div", { className: "twc-sidebar__foot-user", children: footer }) : null,
8909
- collapsible ? /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-sidebar__collapse", onClick: toggle, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", children: [
9105
+ collapsible ? /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-sidebar__collapse", onClick: toggle, "aria-expanded": !collapsed, "aria-controls": navId, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", children: [
8910
9106
  /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) }),
8911
9107
  /* @__PURE__ */ jsx("span", { children: "Collapse" })
8912
9108
  ] }) : null
8913
9109
  ] }) : null
8914
9110
  ] });
9111
+ if (!overlay) {
9112
+ return /* @__PURE__ */ jsx("aside", { className: `twc-sidebar ${className}`, "data-collapsed": collapsed || void 0, ...rest, children: body });
9113
+ }
9114
+ if (!mounted) return null;
9115
+ const state = open ? "open" : "closed";
9116
+ const drawer = /* @__PURE__ */ jsx("div", { className: "twc-sidebar__overlay", "data-state": state, onMouseDown: (e) => {
9117
+ if (e.target === e.currentTarget) setOpen(false);
9118
+ }, children: /* @__PURE__ */ jsx(
9119
+ "aside",
9120
+ {
9121
+ ref: panelRef,
9122
+ className: `twc-sidebar twc-sidebar--overlay ${className}`,
9123
+ "data-state": state,
9124
+ "data-collapsed": collapsed || void 0,
9125
+ role: "dialog",
9126
+ "aria-modal": "true",
9127
+ tabIndex: -1,
9128
+ "aria-label": navLabel || "Navigation",
9129
+ ...rest,
9130
+ children: body
9131
+ }
9132
+ ) });
9133
+ return renderPortal(drawer);
8915
9134
  }
8916
9135
  function Skeleton({
8917
9136
  variant = "text",
8918
9137
  width,
8919
9138
  height,
8920
9139
  lines = 1,
9140
+ label,
8921
9141
  className = "",
8922
9142
  style,
8923
9143
  ...rest
8924
9144
  }) {
9145
+ const a11y = label != null ? { role: "status", "aria-live": "polite", "aria-busy": true } : { "aria-hidden": true };
8925
9146
  const __twcStyles = useScopedStyles("twc-skeleton-styles", `
8926
9147
  .twc-skeleton {
8927
9148
  position: relative; overflow: hidden;
@@ -8937,25 +9158,31 @@ function Skeleton({
8937
9158
  .twc-skeleton[data-variant="rect"] { border-radius: var(--radius-md); }
8938
9159
  .twc-skeleton__group { display: flex; flex-direction: column; gap: 8px; }
8939
9160
  .twc-skeleton__group .twc-skeleton:last-child { width: 70%; }
9161
+ .twc-skeleton__sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
8940
9162
  /* The shimmer signals loading \u2014 keep it animating even under reduced motion. */
8941
9163
  @media (prefers-reduced-motion: reduce) {
8942
9164
  .twc-skeleton::after { animation-duration: 1.4s !important; animation-iteration-count: infinite !important; }
8943
9165
  }
8944
9166
  `);
8945
9167
  if (variant === "text" && lines > 1) {
8946
- return /* @__PURE__ */ jsxs("div", { className: `twc-skeleton__group ${className}`, style: { height, ...style }, ...rest, children: [
9168
+ return /* @__PURE__ */ jsxs("div", { className: `twc-skeleton__group ${className}`, style: { height, ...style }, ...a11y, ...rest, children: [
8947
9169
  __twcStyles,
9170
+ label != null ? /* @__PURE__ */ jsx("span", { className: "twc-skeleton__sr", children: label }) : null,
8948
9171
  Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ jsx("span", { className: "twc-skeleton", "data-variant": "text", style: { width: width || "100%" } }, i))
8949
9172
  ] });
8950
9173
  }
8951
- return /* @__PURE__ */ jsx(
9174
+ return /* @__PURE__ */ jsxs(
8952
9175
  "span",
8953
9176
  {
8954
9177
  className: `twc-skeleton ${className}`,
8955
9178
  "data-variant": variant,
8956
9179
  style: { width, height, ...style },
9180
+ ...a11y,
8957
9181
  ...rest,
8958
- children: __twcStyles
9182
+ children: [
9183
+ __twcStyles,
9184
+ label != null ? /* @__PURE__ */ jsx("span", { className: "twc-skeleton__sr", children: label }) : null
9185
+ ]
8959
9186
  }
8960
9187
  );
8961
9188
  }
@@ -9022,12 +9249,12 @@ function Slider({
9022
9249
  const max = Number.isFinite(maxProp) && maxProp > min ? maxProp : min + 1;
9023
9250
  const step = Number.isFinite(stepProp) && stepProp > 0 ? stepProp : 1;
9024
9251
  const __twcStyles = useScopedStyles("twc-slider-styles", SLIDER_CSS);
9025
- const autoId = React23__default.useId();
9252
+ const autoId = React24__default.useId();
9026
9253
  const fieldId = id || autoId;
9027
- const [internal, setInternal] = React23__default.useState(defaultValue);
9254
+ const [internal, setInternal] = React24__default.useState(defaultValue);
9028
9255
  const val = value !== void 0 ? value : internal;
9029
- const trackRef = React23__default.useRef(null);
9030
- const [dragging, setDragging] = React23__default.useState(false);
9256
+ const trackRef = React24__default.useRef(null);
9257
+ const [dragging, setDragging] = React24__default.useState(false);
9031
9258
  const pct = (val - min) / (max - min) * 100;
9032
9259
  const fmt = (v) => formatValue ? formatValue(v) : v;
9033
9260
  const clampSnap = (raw) => {
@@ -9045,8 +9272,8 @@ function Slider({
9045
9272
  const ratio = Math.min(1, Math.max(0, (clientX - r.left) / r.width));
9046
9273
  return clampSnap(min + ratio * (max - min));
9047
9274
  };
9048
- const dragCleanupRef = React23__default.useRef(null);
9049
- React23__default.useEffect(() => () => dragCleanupRef.current?.(), []);
9275
+ const dragCleanupRef = React24__default.useRef(null);
9276
+ React24__default.useEffect(() => () => dragCleanupRef.current?.(), []);
9050
9277
  function onPointerDown(e) {
9051
9278
  if (disabled) return;
9052
9279
  e.preventDefault();
@@ -9068,7 +9295,7 @@ function Slider({
9068
9295
  }
9069
9296
  function onKeyDown(e) {
9070
9297
  if (disabled) return;
9071
- let next = val;
9298
+ let next;
9072
9299
  if (e.key === "ArrowRight" || e.key === "ArrowUp") next = clampSnap(val + step);
9073
9300
  else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next = clampSnap(val - step);
9074
9301
  else if (e.key === "Home") next = min;
@@ -9121,12 +9348,15 @@ function Slider({
9121
9348
  function Spinner({
9122
9349
  size = "md",
9123
9350
  color,
9124
- tone = "current",
9351
+ tone,
9125
9352
  label = "Loading",
9126
9353
  className = "",
9127
9354
  ...rest
9128
9355
  }) {
9129
- const resolvedColor = color ?? tone;
9356
+ if (process.env.NODE_ENV !== "production" && tone !== void 0 && color === void 0) {
9357
+ warnOnce("Spinner.tone", "Spinner: `tone` is deprecated and will be removed in 2.0 \u2014 use `color`.");
9358
+ }
9359
+ const resolvedColor = color ?? tone ?? "current";
9130
9360
  const __twcStyles = useScopedStyles("twc-spinner-styles", `
9131
9361
  .twc-spinner {
9132
9362
  --_sz: 24px; --_bw: 2.5px;
@@ -9242,6 +9472,7 @@ var STEPPER_CSS = `
9242
9472
  .twc-stepper[data-orientation="vertical"] .twc-step__col { display: flex; flex-direction: column; align-items: center; }
9243
9473
  .twc-step[data-state="complete"] .twc-step__connector, .twc-step[data-state="active"] .twc-step__connector { background: var(--_accent); }
9244
9474
  .twc-stepper[data-orientation="vertical"] .twc-step__vbody { padding-bottom: var(--space-2); }
9475
+ .twc-step__sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
9245
9476
  `;
9246
9477
  var CheckIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
9247
9478
  var BangIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M12 8v5M12 17h.01" }) });
@@ -9257,7 +9488,7 @@ function Stepper({
9257
9488
  ...rest
9258
9489
  }) {
9259
9490
  const __twcStyles = useScopedStyles("twc-stepper-styles", STEPPER_CSS);
9260
- const [activeInternal, setActiveInternal] = React23__default.useState(defaultActive);
9491
+ const [activeInternal, setActiveInternal] = React24__default.useState(defaultActive);
9261
9492
  const active = activeProp !== void 0 ? activeProp : activeInternal;
9262
9493
  const handleStep = (i) => {
9263
9494
  if (activeProp === void 0) setActiveInternal(i);
@@ -9269,11 +9500,12 @@ function Stepper({
9269
9500
  if (i === active) return "active";
9270
9501
  return "upcoming";
9271
9502
  };
9272
- return /* @__PURE__ */ jsxs("div", { className: `twc-stepper ${className}`, "data-orientation": orientation, "data-tone": tone, ...rest, children: [
9503
+ return /* @__PURE__ */ jsxs("div", { className: `twc-stepper ${className}`, "data-orientation": orientation, "data-tone": tone, role: "group", "aria-label": "Progress", ...rest, children: [
9273
9504
  __twcStyles,
9274
9505
  steps.map((step, i) => {
9275
9506
  const state = stateOf(i, step);
9276
9507
  const last = i === steps.length - 1;
9508
+ const srText = `Step ${i + 1} of ${steps.length}${state === "complete" ? ", completed" : state === "error" ? ", error" : state === "active" ? ", current" : ", upcoming"}. `;
9277
9509
  const isClickable = clickable && i <= active;
9278
9510
  const interactive = isClickable ? {
9279
9511
  role: "button",
@@ -9295,8 +9527,10 @@ function Stepper({
9295
9527
  "data-state": state,
9296
9528
  "data-clickable": isClickable || void 0,
9297
9529
  "aria-current": state === "active" ? "step" : void 0,
9530
+ "aria-invalid": state === "error" ? "true" : void 0,
9298
9531
  ...interactive,
9299
9532
  children: [
9533
+ /* @__PURE__ */ jsx("span", { className: "twc-step__sr", children: srText }),
9300
9534
  /* @__PURE__ */ jsxs("div", { className: "twc-step__col", children: [
9301
9535
  indicator,
9302
9536
  !last ? /* @__PURE__ */ jsx("span", { className: "twc-step__connector" }) : null
@@ -9317,8 +9551,10 @@ function Stepper({
9317
9551
  "data-state": state,
9318
9552
  "data-clickable": isClickable || void 0,
9319
9553
  "aria-current": state === "active" ? "step" : void 0,
9554
+ "aria-invalid": state === "error" ? "true" : void 0,
9320
9555
  ...interactive,
9321
9556
  children: [
9557
+ /* @__PURE__ */ jsx("span", { className: "twc-step__sr", children: srText }),
9322
9558
  indicator,
9323
9559
  !last ? /* @__PURE__ */ jsx("span", { className: "twc-step__connector" }) : null,
9324
9560
  /* @__PURE__ */ jsxs("div", { className: "twc-step__body", children: [
@@ -9384,7 +9620,7 @@ function Switch({
9384
9620
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
9385
9621
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
9386
9622
  `);
9387
- const autoId = React23__default.useId();
9623
+ const autoId = React24__default.useId();
9388
9624
  const fieldId = id || autoId;
9389
9625
  const errId = `${fieldId}-error`;
9390
9626
  const invalid = Boolean(error);
@@ -9468,14 +9704,14 @@ function Table({
9468
9704
  ...rest
9469
9705
  }) {
9470
9706
  const __twcStyles = useScopedStyles("twc-table-styles", TABLE_CSS);
9471
- const cols = React23__default.useMemo(
9707
+ const cols = React24__default.useMemo(
9472
9708
  () => (columns || []).map((c) => ({ ...c, header: c.headerName, render: c.renderCell })),
9473
9709
  [columns]
9474
9710
  );
9475
9711
  const dataRows = rowsProp || [];
9476
- const [internalSort, setInternalSort] = React23__default.useState(defaultSort || { field: null, dir: "asc" });
9712
+ const [internalSort, setInternalSort] = React24__default.useState(defaultSort || { field: null, dir: "asc" });
9477
9713
  const sort = (sortProp !== void 0 ? sortProp : internalSort) || { field: null, dir: "asc" };
9478
- const rows = React23__default.useMemo(() => {
9714
+ const rows = React24__default.useMemo(() => {
9479
9715
  if (!sortable || !sort.field) return dataRows;
9480
9716
  const col = cols.find((c) => c.field === sort.field);
9481
9717
  if (!col) return dataRows;
@@ -9567,6 +9803,13 @@ var TABS_CSS = `
9567
9803
  .twc-tabs[data-variant="pill"] .twc-tabs__indicator {
9568
9804
  top: 4px; bottom: 4px; height: auto; background: var(--color-surface); box-shadow: var(--shadow-sm); border-radius: var(--radius-md);
9569
9805
  }
9806
+ .twc-tab[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; pointer-events: none; }
9807
+ /* Horizontal tablist scrolls when tabs overflow (vertical orientation untouched). Making
9808
+ overflow-x non-visible makes overflow-y compute to auto, which would clip the bottom:-1px
9809
+ indicator \u2014 so pin the horizontal indicator to bottom:0 (the list border-bottom is the baseline). */
9810
+ .twc-tabs:not([data-orientation="vertical"]) .twc-tabs__list { overflow-x: auto; scrollbar-width: none; }
9811
+ .twc-tabs:not([data-orientation="vertical"]) .twc-tabs__list::-webkit-scrollbar { display: none; }
9812
+ .twc-tabs:not([data-orientation="vertical"]) .twc-tabs__indicator { bottom: 0; }
9570
9813
  .twc-tabs__panel { padding-top: var(--space-4); }
9571
9814
 
9572
9815
  /* Vertical orientation */
@@ -9601,24 +9844,27 @@ function Tabs({
9601
9844
  }) {
9602
9845
  const vertical = orientation === "vertical";
9603
9846
  const __twcStyles = useScopedStyles("twc-tabs-styles", TABS_CSS);
9604
- const [internal, setInternal] = React23__default.useState(defaultValue ?? items[0]?.value);
9847
+ const [internal, setInternal] = React24__default.useState(defaultValue ?? items[0]?.value);
9605
9848
  const active = value ?? internal;
9606
- const listRef = React23__default.useRef(null);
9607
- const [ind, setInd] = React23__default.useState({ left: 0, width: 0, top: 0, height: 0 });
9608
- const baseId = React23__default.useId();
9849
+ const listRef = React24__default.useRef(null);
9850
+ const [ind, setInd] = React24__default.useState({ left: 0, width: 0, top: 0, height: 0 });
9851
+ const baseId = React24__default.useId();
9609
9852
  const tabIdAt = (i) => `${baseId}-tab-${i}`;
9610
9853
  const panelId = `${baseId}-panel`;
9611
9854
  const activeIndex = items.findIndex((it) => it.value === active);
9612
- const updateIndicator = React23__default.useCallback(() => {
9855
+ const updateIndicator = React24__default.useCallback(() => {
9613
9856
  const list = listRef.current;
9614
9857
  if (!list) return;
9615
9858
  const el = list.querySelector('[data-active="true"]');
9616
- if (el) setInd({ left: el.offsetLeft, width: el.offsetWidth, top: el.offsetTop, height: el.offsetHeight });
9617
- }, []);
9618
- React23__default.useEffect(() => {
9859
+ if (el) {
9860
+ setInd({ left: el.offsetLeft, width: el.offsetWidth, top: el.offsetTop, height: el.offsetHeight });
9861
+ if (!vertical) el.scrollIntoView?.({ inline: "nearest", block: "nearest" });
9862
+ }
9863
+ }, [vertical]);
9864
+ React24__default.useEffect(() => {
9619
9865
  updateIndicator();
9620
9866
  }, [active, updateIndicator, items, orientation]);
9621
- React23__default.useEffect(() => {
9867
+ React24__default.useEffect(() => {
9622
9868
  const r = () => updateIndicator();
9623
9869
  window.addEventListener("resize", r);
9624
9870
  if (typeof document !== "undefined" && document.fonts && document.fonts.ready) {
@@ -9639,20 +9885,32 @@ function Tabs({
9639
9885
  const keys = [prevKey, nextKey, "Home", "End"];
9640
9886
  if (!keys.includes(e.key)) return;
9641
9887
  const n = items.length;
9642
- if (!n) return;
9888
+ if (!n || items.every((it2) => it2.disabled)) return;
9643
9889
  e.preventDefault();
9644
9890
  let i = activeIndex < 0 ? 0 : activeIndex;
9645
- if (e.key === "Home") i = 0;
9646
- else if (e.key === "End") i = n - 1;
9647
- else {
9891
+ if (e.key === "Home") i = items.findIndex((it2) => !it2.disabled);
9892
+ else if (e.key === "End") {
9893
+ for (let k = n - 1; k >= 0; k--) {
9894
+ if (!items[k].disabled) {
9895
+ i = k;
9896
+ break;
9897
+ }
9898
+ }
9899
+ } else {
9648
9900
  const dir = e.key === nextKey ? 1 : -1;
9649
- i = (i + dir + n) % n;
9901
+ let guard = 0;
9902
+ do {
9903
+ i = (i + dir + n) % n;
9904
+ } while (items[i]?.disabled && ++guard <= n);
9650
9905
  }
9651
9906
  const it = items[i];
9652
- if (!it) return;
9907
+ if (!it || it.disabled) return;
9653
9908
  select(it.value);
9654
9909
  const btns = listRef.current?.querySelectorAll('[role="tab"]');
9655
- if (btns && btns[i]) btns[i].focus();
9910
+ if (btns && btns[i]) {
9911
+ btns[i].focus();
9912
+ btns[i].scrollIntoView?.({ inline: "nearest", block: "nearest" });
9913
+ }
9656
9914
  }
9657
9915
  return /* @__PURE__ */ jsxs("div", { className: `twc-tabs ${className}`, "data-variant": variant, "data-tone": tone, "data-orientation": orientation, ...rest, children: [
9658
9916
  __twcStyles,
@@ -9665,10 +9923,14 @@ function Tabs({
9665
9923
  className: "twc-tab",
9666
9924
  role: "tab",
9667
9925
  "aria-selected": it.value === active,
9926
+ "aria-disabled": it.disabled || void 0,
9927
+ disabled: it.disabled || void 0,
9668
9928
  "aria-controls": it.value === active && panelRendered ? panelId : void 0,
9669
- tabIndex: it.value === active ? 0 : -1,
9929
+ tabIndex: it.value === active && !it.disabled ? 0 : -1,
9670
9930
  "data-active": it.value === active || void 0,
9671
- onClick: () => select(it.value),
9931
+ onClick: () => {
9932
+ if (!it.disabled) select(it.value);
9933
+ },
9672
9934
  children: [
9673
9935
  it.icon,
9674
9936
  it.label,
@@ -9731,10 +9993,12 @@ function Tag({
9731
9993
  leftIcon,
9732
9994
  tone = "neutral",
9733
9995
  variant = "soft",
9996
+ removeLabel,
9734
9997
  className = "",
9735
9998
  ...rest
9736
9999
  }) {
9737
10000
  const __twcStyles = useScopedStyles("twc-tag-styles", TAG_CSS);
10001
+ const _removeLabel = removeLabel ?? (typeof children === "string" ? `Remove ${children}` : "Remove");
9738
10002
  return /* @__PURE__ */ jsxs("span", { className: `twc-tag ${className}`, "data-tone": tone, "data-variant": variant, "data-no-remove": !onRemove || void 0, ...rest, children: [
9739
10003
  __twcStyles,
9740
10004
  leftIcon,
@@ -9742,7 +10006,7 @@ function Tag({
9742
10006
  onRemove ? /* @__PURE__ */ jsx("button", { className: "twc-tag__remove", onClick: (e) => {
9743
10007
  e.stopPropagation();
9744
10008
  onRemove(e);
9745
- }, "aria-label": "Remove", type: "button", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
10009
+ }, "aria-label": _removeLabel, type: "button", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
9746
10010
  ] });
9747
10011
  }
9748
10012
  function Textarea({
@@ -9788,7 +10052,7 @@ function Textarea({
9788
10052
  .twc-textarea__el[aria-invalid="true"] { border-color: var(--color-danger); }
9789
10053
  .twc-textarea__el:disabled { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
9790
10054
  `);
9791
- const autoId = React23__default.useId();
10055
+ const autoId = React24__default.useId();
9792
10056
  const fieldId = id || autoId;
9793
10057
  const descId = `${fieldId}-desc`;
9794
10058
  const invalid = Boolean(error);
@@ -9926,19 +10190,19 @@ function Toast({
9926
10190
  }) {
9927
10191
  const resolvedTone = tone === "neutral" ? "default" : tone;
9928
10192
  const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
9929
- const onCloseRef = React23__default.useRef(onClose);
9930
- React23__default.useEffect(() => {
10193
+ const onCloseRef = React24__default.useRef(onClose);
10194
+ React24__default.useEffect(() => {
9931
10195
  onCloseRef.current = onClose;
9932
10196
  }, [onClose]);
9933
- const timer = React23__default.useRef();
9934
- const stop = React23__default.useCallback(() => clearTimeout(timer.current), []);
9935
- const start = React23__default.useCallback(() => {
10197
+ const timer = React24__default.useRef();
10198
+ const stop = React24__default.useCallback(() => clearTimeout(timer.current), []);
10199
+ const start = React24__default.useCallback(() => {
9936
10200
  stop();
9937
10201
  if (duration && duration !== Infinity && onCloseRef.current) {
9938
10202
  timer.current = setTimeout(() => onCloseRef.current && onCloseRef.current(), duration);
9939
10203
  }
9940
10204
  }, [duration, stop]);
9941
- React23__default.useEffect(() => {
10205
+ React24__default.useEffect(() => {
9942
10206
  start();
9943
10207
  return stop;
9944
10208
  }, [start, stop]);
@@ -9982,30 +10246,30 @@ function Toast({
9982
10246
  }
9983
10247
  function ToastViewport({ children, limit, className = "", ...rest }) {
9984
10248
  const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
9985
- const shown = limit && limit > 0 ? React23__default.Children.toArray(children).slice(-limit) : children;
10249
+ const shown = limit && limit > 0 ? React24__default.Children.toArray(children).slice(-limit) : children;
9986
10250
  return /* @__PURE__ */ jsxs("div", { className: `twc-toast-viewport ${className}`, ...rest, children: [
9987
10251
  __twcStyles,
9988
10252
  shown
9989
10253
  ] });
9990
10254
  }
9991
- var ToastContext = React23__default.createContext(null);
10255
+ var ToastContext = React24__default.createContext(null);
9992
10256
  function useToast() {
9993
- const ctx = React23__default.useContext(ToastContext);
10257
+ const ctx = React24__default.useContext(ToastContext);
9994
10258
  if (!ctx) throw new Error("useToast must be used within a <ToastProvider>.");
9995
10259
  return ctx;
9996
10260
  }
9997
10261
  function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps }) {
9998
- const [toasts, setToasts] = React23__default.useState([]);
9999
- const idRef = React23__default.useRef(0);
10000
- const limitRef = React23__default.useRef(limit);
10001
- React23__default.useEffect(() => {
10262
+ const [toasts, setToasts] = React24__default.useState([]);
10263
+ const idRef = React24__default.useRef(0);
10264
+ const limitRef = React24__default.useRef(limit);
10265
+ React24__default.useEffect(() => {
10002
10266
  limitRef.current = limit;
10003
10267
  }, [limit]);
10004
- const dismiss = React23__default.useCallback((id) => {
10268
+ const dismiss = React24__default.useCallback((id) => {
10005
10269
  setToasts((s) => s.filter((t) => t.id !== id));
10006
10270
  }, []);
10007
- const clear = React23__default.useCallback(() => setToasts([]), []);
10008
- const api = React23__default.useMemo(() => {
10271
+ const clear = React24__default.useCallback(() => setToasts([]), []);
10272
+ const api = React24__default.useMemo(() => {
10009
10273
  const push = (opts) => {
10010
10274
  const id = idRef.current += 1;
10011
10275
  const next = typeof opts === "string" ? { title: opts } : opts && typeof opts === "object" ? opts : {};
@@ -10026,7 +10290,7 @@ function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps
10026
10290
  toast.show = withTone("default");
10027
10291
  return { toast, dismiss, clear };
10028
10292
  }, [dismiss, clear]);
10029
- const value = React23__default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
10293
+ const value = React24__default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
10030
10294
  return /* @__PURE__ */ jsxs(ToastContext.Provider, { value, children: [
10031
10295
  children,
10032
10296
  /* @__PURE__ */ jsx(ToastViewport, { limit, ...viewportProps, children: toasts.map((t) => /* @__PURE__ */ jsx(
@@ -10066,7 +10330,7 @@ var TREE_CSS = `
10066
10330
  .twc-tree__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
10067
10331
  .twc-tree__badge { flex: none; font-size: 11px; color: var(--color-text-subtle); }
10068
10332
  `;
10069
- function Node({ node, depth, expanded, selectedId, tabbableId, rowRefs, onToggle, onSelect, onRowFocus }) {
10333
+ function Node({ node, depth, posInSet, setSize, expanded, selectedId, tabbableId, rowRefs, onToggle, onSelect, onRowFocus }) {
10070
10334
  const hasChildren = Array.isArray(node.children) && node.children.length > 0;
10071
10335
  const open = expanded.has(node.id);
10072
10336
  return /* @__PURE__ */ jsxs("li", { role: "none", children: [
@@ -10077,6 +10341,8 @@ function Node({ node, depth, expanded, selectedId, tabbableId, rowRefs, onToggle
10077
10341
  className: "twc-tree__row",
10078
10342
  role: "treeitem",
10079
10343
  "aria-level": depth + 1,
10344
+ "aria-posinset": posInSet,
10345
+ "aria-setsize": setSize,
10080
10346
  "aria-selected": selectedId === node.id,
10081
10347
  "data-selected": selectedId === node.id || void 0,
10082
10348
  "data-tree-id": node.id,
@@ -10100,11 +10366,13 @@ function Node({ node, depth, expanded, selectedId, tabbableId, rowRefs, onToggle
10100
10366
  ]
10101
10367
  }
10102
10368
  ),
10103
- hasChildren && open ? /* @__PURE__ */ jsx("ul", { className: "twc-tree__group twc-tree__group--child", role: "group", children: node.children.map((c) => /* @__PURE__ */ jsx(
10369
+ hasChildren && open ? /* @__PURE__ */ jsx("ul", { className: "twc-tree__group twc-tree__group--child", role: "group", children: node.children.map((c, i) => /* @__PURE__ */ jsx(
10104
10370
  Node,
10105
10371
  {
10106
10372
  node: c,
10107
10373
  depth: depth + 1,
10374
+ posInSet: i + 1,
10375
+ setSize: node.children.length,
10108
10376
  expanded,
10109
10377
  selectedId,
10110
10378
  tabbableId,
@@ -10130,12 +10398,13 @@ function TreeView({
10130
10398
  }) {
10131
10399
  const nodes = items;
10132
10400
  const __twcStyles = useScopedStyles("twc-tree-styles", TREE_CSS);
10133
- const [expInternal, setExpInternal] = React23__default.useState(() => new Set(defaultExpanded));
10401
+ const [expInternal, setExpInternal] = React24__default.useState(() => new Set(defaultExpanded));
10134
10402
  const expanded = expandedProp !== void 0 ? new Set(expandedProp) : expInternal;
10135
- const [selInternal, setSelInternal] = React23__default.useState(defaultSelectedId);
10403
+ const [selInternal, setSelInternal] = React24__default.useState(defaultSelectedId);
10136
10404
  const selectedId = selectedProp !== void 0 ? selectedProp : selInternal;
10137
- const [focusId, setFocusId] = React23__default.useState(null);
10138
- const rowRefs = React23__default.useRef(/* @__PURE__ */ new Map());
10405
+ const [focusId, setFocusId] = React24__default.useState(null);
10406
+ const rowRefs = React24__default.useRef(/* @__PURE__ */ new Map());
10407
+ const taRef = React24__default.useRef({ str: "", t: 0 });
10139
10408
  const toggle = (id) => {
10140
10409
  const n = new Set(expanded);
10141
10410
  n.has(id) ? n.delete(id) : n.add(id);
@@ -10149,10 +10418,12 @@ function TreeView({
10149
10418
  const visible = [];
10150
10419
  const parentOf = /* @__PURE__ */ new Map();
10151
10420
  const hasKids = /* @__PURE__ */ new Map();
10421
+ const labelText = /* @__PURE__ */ new Map();
10152
10422
  const walk = (nodes2, parentId) => {
10153
10423
  for (const n of nodes2) {
10154
10424
  visible.push(n.id);
10155
10425
  parentOf.set(n.id, parentId);
10426
+ if (typeof n.label === "string") labelText.set(n.id, n.label);
10156
10427
  const kids = Array.isArray(n.children) && n.children.length > 0;
10157
10428
  hasKids.set(n.id, kids);
10158
10429
  if (kids && expanded.has(n.id)) walk(n.children, n.id);
@@ -10190,17 +10461,36 @@ function TreeView({
10190
10461
  return;
10191
10462
  }
10192
10463
  next = parentOf.get(id);
10464
+ } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && /\S/.test(e.key)) {
10465
+ const now = Date.now();
10466
+ taRef.current.str = now - taRef.current.t > 500 ? e.key : taRef.current.str + e.key;
10467
+ taRef.current.t = now;
10468
+ const q = taRef.current.str.toLowerCase();
10469
+ const single = q.length > 1 && [...q].every((c) => c === q[0]);
10470
+ const needle = single ? q[0] : q;
10471
+ for (let k = 1; k <= visible.length; k++) {
10472
+ const cand = visible[(i + k) % visible.length];
10473
+ const lbl = labelText.get(cand);
10474
+ if (lbl && lbl.toLowerCase().startsWith(needle)) {
10475
+ e.preventDefault();
10476
+ focusRow(cand);
10477
+ break;
10478
+ }
10479
+ }
10480
+ return;
10193
10481
  } else return;
10194
10482
  e.preventDefault();
10195
10483
  if (next != null) focusRow(next);
10196
10484
  };
10197
10485
  return /* @__PURE__ */ jsxs("div", { className: `twc-tree ${className}`, role: "tree", onKeyDown, ...rest, children: [
10198
10486
  __twcStyles,
10199
- /* @__PURE__ */ jsx("ul", { className: "twc-tree__group", role: "none", children: nodes.map((n) => /* @__PURE__ */ jsx(
10487
+ /* @__PURE__ */ jsx("ul", { className: "twc-tree__group", role: "none", children: nodes.map((n, i) => /* @__PURE__ */ jsx(
10200
10488
  Node,
10201
10489
  {
10202
10490
  node: n,
10203
10491
  depth: 0,
10492
+ posInSet: i + 1,
10493
+ setSize: nodes.length,
10204
10494
  expanded,
10205
10495
  selectedId,
10206
10496
  tabbableId,
@@ -10214,12 +10504,22 @@ function TreeView({
10214
10504
  ] });
10215
10505
  }
10216
10506
  var SHELL_CSS = `
10217
- .twc-shell { display: flex; overflow: hidden; background: var(--color-bg); color: var(--color-text); font-family: var(--font-sans); }
10507
+ .twc-shell { position: relative; display: flex; overflow: hidden; background: var(--color-bg); color: var(--color-text); font-family: var(--font-sans); }
10508
+ .twc-shell__skip { position: absolute; inset-inline-start: var(--space-3); inset-block-start: var(--space-3); z-index: 100;
10509
+ padding: var(--space-2) var(--space-4); background: var(--color-surface); color: var(--color-text);
10510
+ border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md); font-family: var(--font-sans);
10511
+ transform: translateY(-200%); transition: transform var(--duration-fast) var(--ease-standard); }
10512
+ .twc-shell__skip:focus-visible { transform: translateY(0); outline: none; box-shadow: var(--ring); }
10218
10513
  .twc-shell__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; height: 100%; }
10219
10514
  .twc-shell__header { flex: none; display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
10220
10515
  min-height: 60px; padding-inline: var(--space-5); border-bottom: var(--border-thin) solid var(--color-border); background: var(--color-surface); }
10221
10516
  .twc-shell__content { flex: 1 1 auto; min-height: 0; overflow: auto; }
10222
10517
  .twc-shell__content[data-padded="true"] { padding: var(--space-6) var(--space-5); }
10518
+ /* Mobile: stack the shell so the sidebar (rendered as an off-canvas overlay) no
10519
+ longer reserves a column \u2014 the main content spans the full width. */
10520
+ @media (max-width: 720px) {
10521
+ .twc-shell { flex-direction: column; }
10522
+ }
10223
10523
  `;
10224
10524
  function AppShell({
10225
10525
  sidebar,
@@ -10227,17 +10527,27 @@ function AppShell({
10227
10527
  children,
10228
10528
  height = "100dvh",
10229
10529
  padded = true,
10530
+ mainId = "twc-main",
10531
+ skipLinkLabel = "Skip to content",
10532
+ sidebarOpen,
10533
+ onSidebarOpenChange,
10230
10534
  className = "",
10231
10535
  style,
10232
10536
  ...rest
10233
10537
  }) {
10234
10538
  const __twcStyles = useScopedStyles("twc-shell-styles", SHELL_CSS);
10539
+ const wiredSidebar = React24__default.isValidElement(sidebar) && (sidebarOpen !== void 0 || onSidebarOpenChange !== void 0) ? React24__default.cloneElement(sidebar, {
10540
+ overlay: sidebar.props.overlay !== void 0 ? sidebar.props.overlay : true,
10541
+ open: sidebar.props.open !== void 0 ? sidebar.props.open : sidebarOpen,
10542
+ onOpenChange: sidebar.props.onOpenChange !== void 0 ? sidebar.props.onOpenChange : onSidebarOpenChange
10543
+ }) : sidebar;
10235
10544
  return /* @__PURE__ */ jsxs("div", { className: `twc-shell ${className}`.trim(), style: { height, ...style }, ...rest, children: [
10236
10545
  __twcStyles,
10237
- sidebar,
10546
+ skipLinkLabel != null && skipLinkLabel !== false ? /* @__PURE__ */ jsx("a", { className: "twc-shell__skip", href: `#${mainId}`, children: skipLinkLabel }) : null,
10547
+ wiredSidebar,
10238
10548
  /* @__PURE__ */ jsxs("div", { className: "twc-shell__main", children: [
10239
10549
  header != null ? /* @__PURE__ */ jsx("header", { className: "twc-shell__header", children: header }) : null,
10240
- /* @__PURE__ */ jsx("main", { className: "twc-shell__content", "data-padded": padded ? "true" : void 0, children })
10550
+ /* @__PURE__ */ jsx("main", { className: "twc-shell__content", id: mainId, tabIndex: -1, "data-padded": padded ? "true" : void 0, children })
10241
10551
  ] })
10242
10552
  ] });
10243
10553
  }
@@ -10256,7 +10566,7 @@ function bgValue(bg) {
10256
10566
  if (BG[bg]) return `var(${BG[bg]})`;
10257
10567
  return String(bg).startsWith("--") ? `var(${bg})` : bg;
10258
10568
  }
10259
- function safeHref4(url) {
10569
+ function safeHref5(url) {
10260
10570
  if (url == null) return void 0;
10261
10571
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10262
10572
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10301,11 +10611,11 @@ function Box({
10301
10611
  boxShadow: shadow ? `var(--shadow-${shadow})` : void 0,
10302
10612
  ...style
10303
10613
  };
10304
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref4(rest.href);
10614
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref5(rest.href);
10305
10615
  return /* @__PURE__ */ jsx(Tag2, { className: `twc-box ${className}`.trim(), style: s, ...rest, children });
10306
10616
  }
10307
10617
  var SIZES = { sm: 640, md: 768, lg: 1024, xl: 1280, full: "100%" };
10308
- function safeHref5(url) {
10618
+ function safeHref6(url) {
10309
10619
  if (url == null) return void 0;
10310
10620
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10311
10621
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10320,7 +10630,7 @@ function Container({
10320
10630
  ...rest
10321
10631
  }) {
10322
10632
  const max = SIZES[size] ?? size;
10323
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref5(rest.href);
10633
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref6(rest.href);
10324
10634
  return /* @__PURE__ */ jsx(
10325
10635
  Tag2,
10326
10636
  {
@@ -10345,7 +10655,8 @@ function space(v) {
10345
10655
  function len(v) {
10346
10656
  return typeof v === "number" ? `${v}px` : v;
10347
10657
  }
10348
- function safeHref6(url) {
10658
+ var BP = { sm: 640, md: 768, lg: 1024, xl: 1280 };
10659
+ function safeHref7(url) {
10349
10660
  if (url == null) return void 0;
10350
10661
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10351
10662
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10355,29 +10666,54 @@ function Grid({
10355
10666
  columns,
10356
10667
  minChildWidth,
10357
10668
  gap = 4,
10669
+ rowGap,
10670
+ columnGap,
10358
10671
  align,
10359
10672
  justify,
10673
+ alignContent,
10674
+ justifyContent,
10360
10675
  className = "",
10361
10676
  style,
10362
10677
  children,
10363
10678
  ...rest
10364
10679
  }) {
10365
- const templateColumns = minChildWidth ? `repeat(auto-fill, minmax(min(${len(minChildWidth)}, 100%), 1fr))` : `repeat(${columns || 1}, minmax(0, 1fr))`;
10366
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref6(rest.href);
10367
- return /* @__PURE__ */ jsx(
10680
+ const responsive = columns != null && typeof columns === "object";
10681
+ const uid = React24__default.useId();
10682
+ const gridId = responsive ? `g${uid.replace(/[^a-zA-Z0-9]/g, "")}` : null;
10683
+ let css = "";
10684
+ if (responsive) {
10685
+ const base = columns.base ?? 1;
10686
+ const sel = `[data-twc-grid-id="${gridId}"]`;
10687
+ css = `${sel} { --twc-grid-cols: ${base}; }`;
10688
+ for (const bp of ["sm", "md", "lg", "xl"]) {
10689
+ if (columns[bp] != null) css += `
10690
+ @media (min-width: ${BP[bp]}px) { ${sel} { --twc-grid-cols: ${columns[bp]}; } }`;
10691
+ }
10692
+ }
10693
+ const __twcStyles = useScopedStyles(gridId ? `twc-grid-${gridId}` : "twc-grid", css);
10694
+ const templateColumns = minChildWidth ? `repeat(auto-fill, minmax(min(${len(minChildWidth)}, 100%), 1fr))` : responsive ? `repeat(var(--twc-grid-cols, ${columns.base ?? 1}), minmax(0, 1fr))` : `repeat(${columns || 1}, minmax(0, 1fr))`;
10695
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref7(rest.href);
10696
+ return /* @__PURE__ */ jsxs(
10368
10697
  Tag2,
10369
10698
  {
10370
10699
  className: `twc-grid ${className}`.trim(),
10700
+ "data-twc-grid-id": gridId || void 0,
10371
10701
  style: {
10372
10702
  display: "grid",
10373
10703
  gridTemplateColumns: templateColumns,
10374
- gap: space(gap),
10704
+ rowGap: space(rowGap ?? gap),
10705
+ columnGap: space(columnGap ?? gap),
10375
10706
  alignItems: align,
10376
10707
  justifyItems: justify,
10708
+ alignContent,
10709
+ justifyContent,
10377
10710
  ...style
10378
10711
  },
10379
10712
  ...rest,
10380
- children
10713
+ children: [
10714
+ responsive ? __twcStyles : null,
10715
+ children
10716
+ ]
10381
10717
  }
10382
10718
  );
10383
10719
  }
@@ -10386,7 +10722,7 @@ function space2(v) {
10386
10722
  if (typeof v === "number") return `var(--space-${String(v).replace(".", "-")})`;
10387
10723
  return v;
10388
10724
  }
10389
- function safeHref7(url) {
10725
+ function safeHref8(url) {
10390
10726
  if (url == null) return void 0;
10391
10727
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10392
10728
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10399,12 +10735,21 @@ function Stack({
10399
10735
  justify,
10400
10736
  wrap = false,
10401
10737
  inline = false,
10738
+ p,
10739
+ px,
10740
+ py,
10741
+ pt,
10742
+ pr,
10743
+ pb,
10744
+ pl,
10745
+ divider,
10402
10746
  className = "",
10403
10747
  style,
10404
10748
  children,
10405
10749
  ...rest
10406
10750
  }) {
10407
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref7(rest.href);
10751
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
10752
+ const kids = divider != null ? React24__default.Children.toArray(children).flatMap((child, i, arr) => i < arr.length - 1 ? [child, /* @__PURE__ */ jsx(React24__default.Fragment, { children: divider }, `twc-stack-div-${i}`)] : [child]) : children;
10408
10753
  return /* @__PURE__ */ jsx(
10409
10754
  Tag2,
10410
10755
  {
@@ -10416,11 +10761,15 @@ function Stack({
10416
10761
  alignItems: align,
10417
10762
  justifyContent: justify,
10418
10763
  flexWrap: wrap ? "wrap" : void 0,
10764
+ paddingTop: space2(pt ?? py ?? p),
10765
+ paddingRight: space2(pr ?? px ?? p),
10766
+ paddingBottom: space2(pb ?? py ?? p),
10767
+ paddingLeft: space2(pl ?? px ?? p),
10419
10768
  minWidth: 0,
10420
10769
  ...style
10421
10770
  },
10422
10771
  ...rest,
10423
- children
10772
+ children: kids
10424
10773
  }
10425
10774
  );
10426
10775
  }
@@ -10432,22 +10781,64 @@ var CODE_CSS = `
10432
10781
  border: var(--border-thin) solid var(--color-border);
10433
10782
  white-space: normal; overflow-wrap: anywhere; word-break: break-word;
10434
10783
  }
10784
+ .twc-code[data-block="true"] {
10785
+ display: block; position: relative; white-space: pre; overflow-x: auto;
10786
+ padding: 12px 14px; padding-inline-end: 40px; line-height: 1.6; font-size: 0.8125em;
10787
+ overflow-wrap: normal; word-break: normal;
10788
+ }
10789
+ .twc-code__copy {
10790
+ position: absolute; top: 6px; inset-inline-end: 6px; display: inline-grid; place-items: center;
10791
+ width: 26px; height: 26px; border: none; border-radius: var(--radius-sm);
10792
+ background: var(--color-surface); color: var(--color-text-subtle); cursor: pointer;
10793
+ transition: color var(--duration-fast), background-color var(--duration-fast);
10794
+ }
10795
+ .twc-code__copy:hover { color: var(--color-text); }
10796
+ .twc-code__copy:focus-visible { outline: none; box-shadow: var(--ring); }
10797
+ .twc-code__copy svg { width: 15px; height: 15px; display: block; }
10435
10798
  `;
10436
- function safeHref8(url) {
10799
+ function safeHref9(url) {
10437
10800
  if (url == null) return void 0;
10438
10801
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10439
10802
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
10440
10803
  }
10441
- function Code({ as: Tag2 = "code", className = "", children, ...rest }) {
10804
+ function Code({
10805
+ as,
10806
+ block = false,
10807
+ copyable = false,
10808
+ copyLabel = "Copy code",
10809
+ copiedLabel = "Copied",
10810
+ className = "",
10811
+ children,
10812
+ ...rest
10813
+ }) {
10442
10814
  const __twcStyles = useScopedStyles("twc-code-styles", CODE_CSS);
10443
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
10444
- return /* @__PURE__ */ jsxs(Tag2, { className: `twc-code ${className}`.trim(), ...rest, children: [
10815
+ const Tag2 = as ?? (block ? "pre" : "code");
10816
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref9(rest.href);
10817
+ const rootRef = React24__default.useRef(null);
10818
+ const [copied, setCopied] = React24__default.useState(false);
10819
+ const timerRef = React24__default.useRef(null);
10820
+ React24__default.useEffect(() => () => clearTimeout(timerRef.current), []);
10821
+ const doCopy = () => {
10822
+ if (typeof navigator === "undefined" || !navigator.clipboard) return;
10823
+ const text = typeof children === "string" ? children : rootRef.current?.textContent ?? "";
10824
+ navigator.clipboard.writeText(text).then(() => {
10825
+ setCopied(true);
10826
+ clearTimeout(timerRef.current);
10827
+ timerRef.current = setTimeout(() => setCopied(false), 2e3);
10828
+ }).catch(() => {
10829
+ });
10830
+ };
10831
+ return /* @__PURE__ */ jsxs(Tag2, { ref: rootRef, className: `twc-code ${className}`.trim(), "data-block": block || void 0, ...rest, children: [
10445
10832
  __twcStyles,
10833
+ copyable ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-code__copy", "aria-label": copied ? copiedLabel : copyLabel, onClick: doCopy, children: copied ? /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m20 6-11 11-5-5" }) }) : /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
10834
+ /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
10835
+ /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
10836
+ ] }) }) : null,
10446
10837
  children
10447
10838
  ] });
10448
10839
  }
10449
10840
  var LEVEL_SIZE = { 1: "4xl", 2: "2xl", 3: "xl", 4: "lg", 5: "base", 6: "sm" };
10450
- function safeHref9(url) {
10841
+ function safeHref10(url) {
10451
10842
  if (url == null) return void 0;
10452
10843
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10453
10844
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10456,15 +10847,18 @@ function Heading({
10456
10847
  as,
10457
10848
  level = 2,
10458
10849
  size,
10850
+ display = false,
10459
10851
  align,
10852
+ truncate,
10853
+ lineClamp,
10460
10854
  className = "",
10461
10855
  style,
10462
10856
  children,
10463
10857
  ...rest
10464
10858
  }) {
10465
10859
  const Tag2 = as || `h${level}`;
10466
- const sz = size || LEVEL_SIZE[level] || "2xl";
10467
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref9(rest.href);
10860
+ const sz = size || (display ? "display" : LEVEL_SIZE[level]) || "2xl";
10861
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref10(rest.href);
10468
10862
  return /* @__PURE__ */ jsx(
10469
10863
  Tag2,
10470
10864
  {
@@ -10478,6 +10872,7 @@ function Heading({
10478
10872
  letterSpacing: "-0.02em",
10479
10873
  fontSize: `var(--text-${sz})`,
10480
10874
  textAlign: align,
10875
+ ...lineClamp != null ? { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: lineClamp, overflow: "hidden" } : truncate ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 } : null,
10481
10876
  ...style
10482
10877
  },
10483
10878
  ...rest,
@@ -10496,9 +10891,11 @@ var TONE = {
10496
10891
  success: "--color-success",
10497
10892
  warning: "--color-warning-subtle-fg",
10498
10893
  info: "--color-info-subtle-fg",
10499
- neutral: "--color-text-muted"
10894
+ neutral: "--color-text-muted",
10895
+ // Adopt the surrounding color (e.g. inside a solid Button/Badge/Alert or a link).
10896
+ inherit: "inherit"
10500
10897
  };
10501
- function safeHref10(url) {
10898
+ function safeHref11(url) {
10502
10899
  if (url == null) return void 0;
10503
10900
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10504
10901
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10509,12 +10906,15 @@ function Text({
10509
10906
  tone = "default",
10510
10907
  weight,
10511
10908
  align,
10909
+ truncate,
10910
+ lineClamp,
10512
10911
  className = "",
10513
10912
  style,
10514
10913
  children,
10515
10914
  ...rest
10516
10915
  }) {
10517
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref10(rest.href);
10916
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref11(rest.href);
10917
+ const toneToken = TONE[tone] || TONE.default;
10518
10918
  return /* @__PURE__ */ jsx(
10519
10919
  Tag2,
10520
10920
  {
@@ -10524,9 +10924,10 @@ function Text({
10524
10924
  fontFamily: "var(--font-sans)",
10525
10925
  lineHeight: 1.6,
10526
10926
  fontSize: `var(--text-${size})`,
10527
- color: `var(${TONE[tone] || TONE.default})`,
10927
+ color: toneToken.startsWith("--") ? `var(${toneToken})` : toneToken,
10528
10928
  fontWeight: weight ? `var(--font-${weight})` : void 0,
10529
10929
  textAlign: align,
10930
+ ...lineClamp != null ? { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: lineClamp, overflow: "hidden" } : truncate ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 } : null,
10530
10931
  ...style
10531
10932
  },
10532
10933
  ...rest,
@@ -10534,58 +10935,68 @@ function Text({
10534
10935
  }
10535
10936
  );
10536
10937
  }
10537
- var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
10538
- var useIsomorphicLayoutEffect = canUseDOM ? React23__default.useLayoutEffect : React23__default.useEffect;
10938
+ var canUseDOM2 = typeof window !== "undefined" && typeof document !== "undefined";
10939
+ var useIsomorphicLayoutEffect = canUseDOM2 ? React24__default.useLayoutEffect : React24__default.useEffect;
10539
10940
  function useMounted() {
10540
- const [mounted, setMounted] = React23__default.useState(false);
10541
- React23__default.useEffect(() => {
10941
+ const [mounted, setMounted] = React24__default.useState(false);
10942
+ React24__default.useEffect(() => {
10542
10943
  setMounted(true);
10543
10944
  }, []);
10544
10945
  return mounted;
10545
10946
  }
10546
10947
  function usePrevious(value) {
10547
- const ref = React23__default.useRef(void 0);
10548
- React23__default.useEffect(() => {
10948
+ const ref = React24__default.useRef(void 0);
10949
+ React24__default.useEffect(() => {
10549
10950
  ref.current = value;
10550
10951
  }, [value]);
10551
10952
  return ref.current;
10552
10953
  }
10553
10954
  function useToggle(initial = false) {
10554
- const [on, setOn] = React23__default.useState(initial);
10555
- const toggle = React23__default.useCallback((next) => {
10955
+ const [on, setOn] = React24__default.useState(initial);
10956
+ const toggle = React24__default.useCallback((next) => {
10556
10957
  setOn((prev) => typeof next === "boolean" ? next : !prev);
10557
10958
  }, []);
10558
10959
  return [on, toggle, setOn];
10559
10960
  }
10560
10961
  function useDisclosure(initial = false) {
10561
- const [open, setOpen] = React23__default.useState(initial);
10562
- const onOpen = React23__default.useCallback(() => setOpen(true), []);
10563
- const onClose = React23__default.useCallback(() => setOpen(false), []);
10564
- const onToggle = React23__default.useCallback(() => setOpen((p) => !p), []);
10962
+ const [open, setOpen] = React24__default.useState(initial);
10963
+ const onOpen = React24__default.useCallback(() => setOpen(true), []);
10964
+ const onClose = React24__default.useCallback(() => setOpen(false), []);
10965
+ const onToggle = React24__default.useCallback(() => setOpen((p) => !p), []);
10565
10966
  return { open, onOpen, onClose, onToggle, setOpen };
10566
10967
  }
10567
10968
  function useControllableState({ value, defaultValue, onChange } = {}) {
10568
10969
  const isControlled = value !== void 0;
10569
- const [uncontrolled, setUncontrolled] = React23__default.useState(defaultValue);
10970
+ const [uncontrolled, setUncontrolled] = React24__default.useState(defaultValue);
10570
10971
  const current = isControlled ? value : uncontrolled;
10571
- const ref = React23__default.useRef({ current, isControlled, onChange });
10972
+ const ref = React24__default.useRef({ current, isControlled, onChange });
10572
10973
  useIsomorphicLayoutEffect(() => {
10573
10974
  ref.current = { current, isControlled, onChange };
10574
10975
  });
10575
- const setValue = React23__default.useCallback((next) => {
10976
+ const wasControlled = React24__default.useRef(isControlled);
10977
+ React24__default.useEffect(() => {
10978
+ if (wasControlled.current !== isControlled) {
10979
+ warnOnce(
10980
+ "useControllableState:switch",
10981
+ `useControllableState: a value is switching from ${wasControlled.current ? "controlled" : "uncontrolled"} to ${isControlled ? "controlled" : "uncontrolled"}. Decide between controlled (\`value\`) and uncontrolled (\`defaultValue\`) for the component's lifetime.`
10982
+ );
10983
+ wasControlled.current = isControlled;
10984
+ }
10985
+ });
10986
+ const setValue = React24__default.useCallback((next) => {
10576
10987
  const { current: cur, isControlled: ctrl, onChange: cb } = ref.current;
10577
10988
  const resolved = typeof next === "function" ? next(cur) : next;
10578
10989
  if (resolved === cur) return;
10579
10990
  if (!ctrl) setUncontrolled(resolved);
10580
10991
  if (cb) cb(resolved);
10581
10992
  }, []);
10582
- return [current, setValue];
10993
+ return [current, setValue, isControlled];
10583
10994
  }
10584
- function useMediaQuery(query) {
10585
- const get = () => canUseDOM ? window.matchMedia(query).matches : false;
10586
- const [matches3, setMatches] = React23__default.useState(get);
10587
- React23__default.useEffect(() => {
10588
- if (!canUseDOM) return void 0;
10995
+ function useMediaQuery(query, { defaultValue = false, initializeWithValue = false } = {}) {
10996
+ const get = () => canUseDOM2 ? window.matchMedia(query).matches : defaultValue;
10997
+ const [matches3, setMatches] = React24__default.useState(initializeWithValue ? get : defaultValue);
10998
+ useIsomorphicLayoutEffect(() => {
10999
+ if (!canUseDOM2) return void 0;
10589
11000
  const mql = window.matchMedia(query);
10590
11001
  const onChange = () => setMatches(mql.matches);
10591
11002
  onChange();
@@ -10598,10 +11009,10 @@ function usePrefersReducedMotion() {
10598
11009
  return useMediaQuery("(prefers-reduced-motion: reduce)");
10599
11010
  }
10600
11011
  function useColorScheme({ storageKey = "twico-theme", attribute = "class", element, disableTransitionsOnChange = true } = {}) {
10601
- const getTarget = () => element || (canUseDOM ? document.documentElement : null);
10602
- const firstApply = React23__default.useRef(true);
11012
+ const getTarget = () => element || (canUseDOM2 ? document.documentElement : null);
11013
+ const firstApply = React24__default.useRef(true);
10603
11014
  const read = () => {
10604
- if (!canUseDOM) return "light";
11015
+ if (!canUseDOM2) return "light";
10605
11016
  try {
10606
11017
  const stored = window.localStorage.getItem(storageKey);
10607
11018
  if (stored === "light" || stored === "dark") return stored;
@@ -10609,12 +11020,12 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
10609
11020
  }
10610
11021
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
10611
11022
  };
10612
- const [theme, setThemeState] = React23__default.useState(read);
10613
- const apply = React23__default.useCallback(
11023
+ const [theme, setThemeState] = React24__default.useState(read);
11024
+ const apply = React24__default.useCallback(
10614
11025
  (t) => {
10615
11026
  const target = getTarget();
10616
11027
  if (!target) return;
10617
- const skip = firstApply.current || !disableTransitionsOnChange || !canUseDOM;
11028
+ const skip = firstApply.current || !disableTransitionsOnChange || !canUseDOM2;
10618
11029
  firstApply.current = false;
10619
11030
  let css;
10620
11031
  if (!skip) {
@@ -10636,26 +11047,26 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
10636
11047
  useIsomorphicLayoutEffect(() => {
10637
11048
  apply(theme);
10638
11049
  }, [theme, apply]);
10639
- const themeRef = React23__default.useRef(theme);
11050
+ const themeRef = React24__default.useRef(theme);
10640
11051
  useIsomorphicLayoutEffect(() => {
10641
11052
  themeRef.current = theme;
10642
11053
  }, [theme]);
10643
- const setTheme = React23__default.useCallback(
11054
+ const setTheme = React24__default.useCallback(
10644
11055
  (t) => {
10645
11056
  setThemeState(t);
10646
11057
  try {
10647
- if (canUseDOM) window.localStorage.setItem(storageKey, t);
11058
+ if (canUseDOM2) window.localStorage.setItem(storageKey, t);
10648
11059
  } catch (e) {
10649
11060
  }
10650
- if (canUseDOM) window.dispatchEvent(new Event("twico:colorscheme"));
11061
+ if (canUseDOM2) window.dispatchEvent(new Event("twico:colorscheme"));
10651
11062
  },
10652
11063
  [storageKey]
10653
11064
  );
10654
- const toggle = React23__default.useCallback(() => {
11065
+ const toggle = React24__default.useCallback(() => {
10655
11066
  setTheme(themeRef.current === "dark" ? "light" : "dark");
10656
11067
  }, [setTheme]);
10657
- React23__default.useEffect(() => {
10658
- if (!canUseDOM) return void 0;
11068
+ React24__default.useEffect(() => {
11069
+ if (!canUseDOM2) return void 0;
10659
11070
  const sync = () => setThemeState(read());
10660
11071
  const onStorage = (e) => {
10661
11072
  if (e.key === storageKey) sync();
@@ -10670,15 +11081,15 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
10670
11081
  return { theme, setTheme, toggle, isDark: theme === "dark" };
10671
11082
  }
10672
11083
  function useEventListener(eventName, handler, element, options) {
10673
- const saved = React23__default.useRef(handler);
11084
+ const saved = React24__default.useRef(handler);
10674
11085
  useIsomorphicLayoutEffect(() => {
10675
11086
  saved.current = handler;
10676
11087
  }, [handler]);
10677
11088
  const capture = typeof options === "boolean" ? options : options && options.capture;
10678
11089
  const passive = typeof options === "object" && options ? options.passive : void 0;
10679
11090
  const once = typeof options === "object" && options ? options.once : void 0;
10680
- React23__default.useEffect(() => {
10681
- const target = element && element.current || element || (canUseDOM ? window : null);
11091
+ React24__default.useEffect(() => {
11092
+ const target = element && element.current || element || (canUseDOM2 ? window : null);
10682
11093
  if (!target || !target.addEventListener) return void 0;
10683
11094
  const opts = typeof options === "boolean" ? options : { capture, passive, once };
10684
11095
  const listener = (e) => saved.current(e);
@@ -10687,12 +11098,12 @@ function useEventListener(eventName, handler, element, options) {
10687
11098
  }, [eventName, element, capture, passive, once]);
10688
11099
  }
10689
11100
  function useClickOutside(ref, handler, events = ["mousedown", "touchstart"]) {
10690
- const saved = React23__default.useRef(handler);
11101
+ const saved = React24__default.useRef(handler);
10691
11102
  useIsomorphicLayoutEffect(() => {
10692
11103
  saved.current = handler;
10693
11104
  }, [handler]);
10694
- React23__default.useEffect(() => {
10695
- if (!canUseDOM) return void 0;
11105
+ React24__default.useEffect(() => {
11106
+ if (!canUseDOM2) return void 0;
10696
11107
  const listener = (e) => {
10697
11108
  const el = ref && ref.current;
10698
11109
  if (!el || el.contains(e.target)) return;
@@ -10718,7 +11129,7 @@ function useKeyPress(key, handler, options = {}) {
10718
11129
  }
10719
11130
  function useLocalStorage(key, initialValue) {
10720
11131
  const read = () => {
10721
- if (!canUseDOM) return initialValue;
11132
+ if (!canUseDOM2) return initialValue;
10722
11133
  try {
10723
11134
  const item = window.localStorage.getItem(key);
10724
11135
  return item ? JSON.parse(item) : initialValue;
@@ -10726,13 +11137,13 @@ function useLocalStorage(key, initialValue) {
10726
11137
  return initialValue;
10727
11138
  }
10728
11139
  };
10729
- const [stored, setStored] = React23__default.useState(read);
10730
- const setValue = React23__default.useCallback(
11140
+ const [stored, setStored] = React24__default.useState(read);
11141
+ const setValue = React24__default.useCallback(
10731
11142
  (value) => {
10732
11143
  setStored((prev) => {
10733
11144
  const next = typeof value === "function" ? value(prev) : value;
10734
11145
  try {
10735
- if (canUseDOM) window.localStorage.setItem(key, JSON.stringify(next));
11146
+ if (canUseDOM2) window.localStorage.setItem(key, JSON.stringify(next));
10736
11147
  } catch (e) {
10737
11148
  }
10738
11149
  return next;
@@ -10743,9 +11154,9 @@ function useLocalStorage(key, initialValue) {
10743
11154
  return [stored, setValue];
10744
11155
  }
10745
11156
  function useCopyToClipboard(timeout = 1500) {
10746
- const [copied, setCopied] = React23__default.useState(false);
10747
- const copy = React23__default.useCallback(async (text) => {
10748
- if (!canUseDOM || !navigator.clipboard) {
11157
+ const [copied, setCopied] = React24__default.useState(false);
11158
+ const copy = React24__default.useCallback(async (text) => {
11159
+ if (!canUseDOM2 || !navigator.clipboard) {
10749
11160
  setCopied(false);
10750
11161
  return false;
10751
11162
  }
@@ -10758,7 +11169,7 @@ function useCopyToClipboard(timeout = 1500) {
10758
11169
  return false;
10759
11170
  }
10760
11171
  }, []);
10761
- React23__default.useEffect(() => {
11172
+ React24__default.useEffect(() => {
10762
11173
  if (!copied) return void 0;
10763
11174
  const t = setTimeout(() => setCopied(false), timeout);
10764
11175
  return () => clearTimeout(t);
@@ -10766,23 +11177,23 @@ function useCopyToClipboard(timeout = 1500) {
10766
11177
  return { copied, copy };
10767
11178
  }
10768
11179
  function useDebouncedValue(value, delay = 200) {
10769
- const [debounced, setDebounced] = React23__default.useState(value);
10770
- React23__default.useEffect(() => {
11180
+ const [debounced, setDebounced] = React24__default.useState(value);
11181
+ React24__default.useEffect(() => {
10771
11182
  const t = setTimeout(() => setDebounced(value), delay);
10772
11183
  return () => clearTimeout(t);
10773
11184
  }, [value, delay]);
10774
11185
  return debounced;
10775
11186
  }
10776
11187
  function useDebouncedCallback(callback, delay = 200) {
10777
- const saved = React23__default.useRef(callback);
10778
- const timer = React23__default.useRef(null);
11188
+ const saved = React24__default.useRef(callback);
11189
+ const timer = React24__default.useRef(null);
10779
11190
  useIsomorphicLayoutEffect(() => {
10780
11191
  saved.current = callback;
10781
11192
  }, [callback]);
10782
- React23__default.useEffect(() => () => {
11193
+ React24__default.useEffect(() => () => {
10783
11194
  if (timer.current) clearTimeout(timer.current);
10784
11195
  }, []);
10785
- return React23__default.useCallback(
11196
+ return React24__default.useCallback(
10786
11197
  (...args) => {
10787
11198
  if (timer.current) clearTimeout(timer.current);
10788
11199
  timer.current = setTimeout(() => saved.current(...args), delay);
@@ -10791,34 +11202,34 @@ function useDebouncedCallback(callback, delay = 200) {
10791
11202
  );
10792
11203
  }
10793
11204
  function useInterval(callback, delay) {
10794
- const saved = React23__default.useRef(callback);
11205
+ const saved = React24__default.useRef(callback);
10795
11206
  useIsomorphicLayoutEffect(() => {
10796
11207
  saved.current = callback;
10797
11208
  }, [callback]);
10798
- React23__default.useEffect(() => {
11209
+ React24__default.useEffect(() => {
10799
11210
  if (delay == null) return void 0;
10800
11211
  const id = setInterval(() => saved.current(), delay);
10801
11212
  return () => clearInterval(id);
10802
11213
  }, [delay]);
10803
11214
  }
10804
11215
  function useTimeout(callback, delay) {
10805
- const saved = React23__default.useRef(callback);
11216
+ const saved = React24__default.useRef(callback);
10806
11217
  useIsomorphicLayoutEffect(() => {
10807
11218
  saved.current = callback;
10808
11219
  }, [callback]);
10809
- React23__default.useEffect(() => {
11220
+ React24__default.useEffect(() => {
10810
11221
  if (delay == null) return void 0;
10811
11222
  const id = setTimeout(() => saved.current(), delay);
10812
11223
  return () => clearTimeout(id);
10813
11224
  }, [delay]);
10814
11225
  }
10815
11226
  function useWindowSize() {
10816
- const [size, setSize] = React23__default.useState(() => ({
10817
- width: canUseDOM ? window.innerWidth : 0,
10818
- height: canUseDOM ? window.innerHeight : 0
11227
+ const [size, setSize] = React24__default.useState(() => ({
11228
+ width: canUseDOM2 ? window.innerWidth : 0,
11229
+ height: canUseDOM2 ? window.innerHeight : 0
10819
11230
  }));
10820
- React23__default.useEffect(() => {
10821
- if (!canUseDOM) return void 0;
11231
+ React24__default.useEffect(() => {
11232
+ if (!canUseDOM2) return void 0;
10822
11233
  const onResize = () => setSize({ width: window.innerWidth, height: window.innerHeight });
10823
11234
  onResize();
10824
11235
  window.addEventListener("resize", onResize);
@@ -10827,8 +11238,8 @@ function useWindowSize() {
10827
11238
  return size;
10828
11239
  }
10829
11240
  function useHover(ref) {
10830
- const [hovered, setHovered] = React23__default.useState(false);
10831
- React23__default.useEffect(() => {
11241
+ const [hovered, setHovered] = React24__default.useState(false);
11242
+ React24__default.useEffect(() => {
10832
11243
  const el = ref && ref.current;
10833
11244
  if (!el) return void 0;
10834
11245
  const on = () => setHovered(true);
@@ -10844,10 +11255,10 @@ function useHover(ref) {
10844
11255
  }
10845
11256
  function useIntersectionObserver(ref, options = {}) {
10846
11257
  const { root = null, rootMargin = "0px", threshold = 0 } = options;
10847
- const [entry, setEntry] = React23__default.useState(null);
10848
- React23__default.useEffect(() => {
11258
+ const [entry, setEntry] = React24__default.useState(null);
11259
+ React24__default.useEffect(() => {
10849
11260
  const el = ref && ref.current;
10850
- if (!canUseDOM || !el || typeof IntersectionObserver === "undefined") return void 0;
11261
+ if (!canUseDOM2 || !el || typeof IntersectionObserver === "undefined") return void 0;
10851
11262
  const obs = new IntersectionObserver(([e]) => setEntry(e), { root, rootMargin, threshold });
10852
11263
  obs.observe(el);
10853
11264
  return () => obs.disconnect();
@@ -10858,7 +11269,7 @@ var __scrollLockCount = 0;
10858
11269
  var __scrollLockSaved = "";
10859
11270
  function useScrollLock(locked = true) {
10860
11271
  useIsomorphicLayoutEffect(() => {
10861
- if (!canUseDOM || !locked) return void 0;
11272
+ if (!canUseDOM2 || !locked) return void 0;
10862
11273
  if (__scrollLockCount === 0) {
10863
11274
  __scrollLockSaved = document.body.style.overflow;
10864
11275
  document.body.style.overflow = "hidden";
@@ -10873,10 +11284,12 @@ function useScrollLock(locked = true) {
10873
11284
  }, [locked]);
10874
11285
  }
10875
11286
  function useId(prefix = "twc") {
10876
- const raw = React23__default.useId();
11287
+ const raw = React24__default.useId();
10877
11288
  return prefix ? `${prefix}-${raw.replace(/:/g, "")}` : raw;
10878
11289
  }
11290
+ var useFocusTrap2 = useFocusTrap;
11291
+ var usePortal2 = usePortal;
10879
11292
 
10880
- export { Accordion, Alert, AppShell, Avatar, AvatarMenu, Badge, Box, Breadcrumb, Button, Card, Carousel, Chart, Checkbox, Code, ColorPicker, Combobox, CommandPalette, Container, Currency, CurrencyField, Datatable, DatePicker, DateRangePicker, Dialog, Divider, Drawer, EmptyState, Field, FileUpload, Grid, Heading, IconButton, Input, Kanban, List, Menu, MultiSelect, Navbar, Pagination, Popover, Progress, Radio, Rating, Select, Sidebar, Skeleton, Slider, Spinner, Stack, Stat, Stepper, Switch, Table, Tabs, Tag, Text, Textarea, Timeline, Toast, ToastProvider, ToastViewport, Tooltip, TreeView, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
11293
+ export { Accordion, Alert, AppShell, Avatar, AvatarMenu, Badge, Box, Breadcrumb, Button, Card, Carousel, Chart, Checkbox, Code, ColorPicker, Combobox, CommandPalette, Container, Currency, CurrencyField, Datatable, DatePicker, DateRangePicker, Dialog, Divider, Drawer, EmptyState, Field, FileUpload, Grid, Heading, IconButton, Input, Kanban, List, Menu, MultiSelect, Navbar, Pagination, Popover, Progress, Radio, Rating, Select, Sidebar, Skeleton, Slider, Spinner, Stack, Stat, Stepper, Switch, Table, Tabs, Tag, Text, Textarea, Timeline, Toast, ToastProvider, ToastViewport, Tooltip, TreeView, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useFocusTrap2 as useFocusTrap, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePortal2 as usePortal, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
10881
11294
  //# sourceMappingURL=index.mjs.map
10882
11295
  //# sourceMappingURL=index.mjs.map