twico-ui 1.4.0 → 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.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React23 = require('react');
4
+ var React24 = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var reactDom = require('react-dom');
7
7
 
@@ -23,12 +23,12 @@ function _interopNamespace(e) {
23
23
  return Object.freeze(n);
24
24
  }
25
25
 
26
- var React23__namespace = /*#__PURE__*/_interopNamespace(React23);
26
+ var React24__namespace = /*#__PURE__*/_interopNamespace(React24);
27
27
 
28
28
  // components/navigation/Accordion.jsx
29
- var SUPPORTS_STYLE_HOIST = parseInt(String(React23__namespace.version), 10) >= 19;
29
+ var SUPPORTS_STYLE_HOIST = parseInt(String(React24__namespace.version), 10) >= 19;
30
30
  function useScopedStyles(id, css) {
31
- React23__namespace.useInsertionEffect(() => {
31
+ React24__namespace.useInsertionEffect(() => {
32
32
  if (SUPPORTS_STYLE_HOIST) return;
33
33
  if (typeof document === "undefined" || document.getElementById(id)) return;
34
34
  const el = document.createElement("style");
@@ -36,7 +36,7 @@ function useScopedStyles(id, css) {
36
36
  el.textContent = css;
37
37
  document.head.appendChild(el);
38
38
  }, [id, css]);
39
- return SUPPORTS_STYLE_HOIST ? React23__namespace.createElement("style", { href: id, precedence: "twc-ui" }, css) : null;
39
+ return SUPPORTS_STYLE_HOIST ? React24__namespace.createElement("style", { href: id, precedence: "twc-ui" }, css) : null;
40
40
  }
41
41
  var ACCORDION_CSS = `
42
42
  .twc-accordion { display: flex; flex-direction: column; font-family: var(--font-sans);
@@ -50,7 +50,9 @@ var ACCORDION_CSS = `
50
50
  color: var(--color-text); text-align: start;
51
51
  transition: background-color var(--duration-fast) var(--ease-standard);
52
52
  }
53
- .twc-accordion__trigger:hover { background: var(--color-surface-sunken); }
53
+ .twc-accordion__heading { margin: 0; font: inherit; }
54
+ .twc-accordion__trigger:hover:not(:disabled) { background: var(--color-surface-sunken); }
55
+ .twc-accordion__trigger:disabled { opacity: 0.45; cursor: not-allowed; }
54
56
  .twc-accordion__trigger:focus-visible { outline: none; box-shadow: var(--ring); }
55
57
  .twc-accordion__label { flex: 1; }
56
58
  .twc-accordion__chevron { flex: none; color: var(--color-text-subtle); transition: transform var(--duration-base) var(--ease-spring); }
@@ -69,14 +71,19 @@ function Accordion({
69
71
  defaultOpen = [],
70
72
  open: openProp,
71
73
  onOpenChange,
74
+ headingLevel = 3,
72
75
  className = "",
76
+ onKeyDown: onKeyDownProp,
73
77
  ...rest
74
78
  }) {
75
79
  const __twcStyles = useScopedStyles("twc-accordion-styles", ACCORDION_CSS);
76
- const [internal, setInternal] = React23__namespace.default.useState(() => new Set(defaultOpen));
80
+ const rootRef = React24__namespace.default.useRef(null);
81
+ const [internal, setInternal] = React24__namespace.default.useState(() => new Set(defaultOpen));
77
82
  const open = openProp !== void 0 ? new Set(openProp) : internal;
78
- const baseId = React23__namespace.default.useId();
83
+ const baseId = React24__namespace.default.useId();
79
84
  function toggle(val) {
85
+ const item = items.find((x) => x.value === val);
86
+ if (item?.disabled) return;
80
87
  const next = new Set(open);
81
88
  if (next.has(val)) next.delete(val);
82
89
  else {
@@ -86,18 +93,47 @@ function Accordion({
86
93
  if (openProp === void 0) setInternal(next);
87
94
  onOpenChange?.([...next]);
88
95
  }
89
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-accordion ${className}`, ...rest, children: [
96
+ function handleKeyDown(e) {
97
+ onKeyDownProp?.(e);
98
+ if (!(e.target instanceof HTMLElement) || !e.target.classList.contains("twc-accordion__trigger")) return;
99
+ const triggers = Array.from(rootRef.current.querySelectorAll(".twc-accordion__trigger")).filter((b) => !b.disabled);
100
+ const i = triggers.indexOf(e.target);
101
+ if (i < 0) return;
102
+ const len2 = triggers.length;
103
+ let next;
104
+ switch (e.key) {
105
+ case "ArrowDown":
106
+ next = (i + 1) % len2;
107
+ break;
108
+ case "ArrowUp":
109
+ next = (i - 1 + len2) % len2;
110
+ break;
111
+ case "Home":
112
+ next = 0;
113
+ break;
114
+ case "End":
115
+ next = len2 - 1;
116
+ break;
117
+ default:
118
+ return;
119
+ }
120
+ e.preventDefault();
121
+ triggers[next].focus();
122
+ }
123
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rootRef, className: `twc-accordion ${className}`, onKeyDown: handleKeyDown, ...rest, children: [
90
124
  __twcStyles,
91
125
  items.map((it, i) => {
92
126
  const isOpen = open.has(it.value);
93
127
  const triggerId = `${baseId}-trigger-${i}`;
94
128
  const panelId = `${baseId}-panel-${i}`;
129
+ const lvl = Math.min(6, Math.max(1, it.headingLevel ?? headingLevel));
130
+ const Heading2 = `h${lvl}`;
95
131
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-accordion__item", children: [
96
- /* @__PURE__ */ jsxRuntime.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: [
132
+ /* @__PURE__ */ jsxRuntime.jsx(Heading2, { className: "twc-accordion__heading", children: /* @__PURE__ */ jsxRuntime.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: [
97
133
  it.icon,
98
134
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-accordion__label", children: it.label }),
99
135
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-accordion__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" }) }) })
100
- ] }),
136
+ ] }) }),
101
137
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-accordion__panel", id: panelId, role: "region", "aria-labelledby": triggerId, "data-open": isOpen || void 0, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-accordion__panel-inner", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-accordion__content", children: it.content }) }) })
102
138
  ] }, it.value);
103
139
  })
@@ -153,11 +189,15 @@ function Alert({
153
189
  title,
154
190
  icon,
155
191
  onClose,
192
+ live,
193
+ closeLabel = "Dismiss",
156
194
  className = "",
157
195
  ...rest
158
196
  }) {
159
197
  const __twcStyles = useScopedStyles("twc-alert-styles", ALERT_CSS);
160
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-alert ${className}`, "data-tone": tone, "data-variant": variant, role: "alert", ...rest, children: [
198
+ const resolvedLive = live ?? (tone === "danger" || tone === "warning" ? "assertive" : tone === "success" || tone === "info" ? "polite" : "off");
199
+ const liveProps = resolvedLive === "assertive" ? { role: "alert" } : resolvedLive === "polite" ? { role: "status" } : {};
200
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-alert ${className}`, "data-tone": tone, "data-variant": variant, ...liveProps, ...rest, children: [
161
201
  __twcStyles,
162
202
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-alert__icon", "aria-hidden": "true", children: icon || /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
163
203
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
@@ -167,7 +207,7 @@ function Alert({
167
207
  title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-alert__title", children: title }) : null,
168
208
  children ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-alert__desc", children }) : null
169
209
  ] }),
170
- onClose ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-alert__close", onClick: onClose, "aria-label": "Dismiss", type: "button", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
210
+ onClose ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-alert__close", onClick: onClose, "aria-label": closeLabel, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
171
211
  ] });
172
212
  }
173
213
  var AVATAR_CSS = `
@@ -212,20 +252,25 @@ function safeSrc(url) {
212
252
  if (s.startsWith("data:") && !s.startsWith("data:image/")) return void 0;
213
253
  return url;
214
254
  }
255
+ var STATUS_LABELS = { online: "Online", busy: "Busy", away: "Away", offline: "Offline" };
215
256
  function Avatar({
216
257
  src,
217
258
  name,
218
259
  size = "md",
219
260
  square = false,
220
261
  status,
262
+ statusLabel,
263
+ statusLabels,
221
264
  ring = false,
222
265
  className = "",
223
266
  ...rest
224
267
  }) {
225
268
  const __twcStyles = useScopedStyles("twc-avatar-styles", AVATAR_CSS);
226
- const [errored, setErrored] = React23__namespace.default.useState(false);
269
+ const [errored, setErrored] = React24__namespace.default.useState(false);
227
270
  const cleanSrc = safeSrc(src);
228
271
  const showImg = cleanSrc && !errored;
272
+ const _statusLabel = status ? statusLabel ?? statusLabels?.[status] ?? STATUS_LABELS[status] : void 0;
273
+ const baseName = name || "avatar";
229
274
  return /* @__PURE__ */ jsxRuntime.jsxs(
230
275
  "span",
231
276
  {
@@ -233,12 +278,12 @@ function Avatar({
233
278
  "data-size": size,
234
279
  "data-square": square || void 0,
235
280
  role: "img",
236
- "aria-label": name || "avatar",
281
+ "aria-label": _statusLabel ? `${baseName}, ${_statusLabel}` : baseName,
237
282
  ...rest,
238
283
  children: [
239
284
  __twcStyles,
240
285
  showImg ? /* @__PURE__ */ jsxRuntime.jsx("img", { className: "twc-avatar__img", src: cleanSrc, alt: name || "", onError: () => setErrored(true) }, cleanSrc) : initials(name),
241
- status ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-avatar__status", "data-status": status }) : null
286
+ status ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-avatar__status", "data-status": status, title: _statusLabel }) : null
242
287
  ]
243
288
  }
244
289
  );
@@ -279,6 +324,11 @@ var MENU_CSS = `
279
324
  .twc-menu__item-label { flex: 1 1 auto; min-width: 0; }
280
325
  .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); }
281
326
  `;
327
+ var safeHref = (url) => {
328
+ if (url == null) return void 0;
329
+ const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
330
+ return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
331
+ };
282
332
  function Menu({
283
333
  trigger,
284
334
  items,
@@ -288,26 +338,29 @@ function Menu({
288
338
  open: openProp,
289
339
  defaultOpen = false,
290
340
  onOpenChange,
341
+ "aria-label": ariaLabel,
342
+ "aria-labelledby": ariaLabelledby,
291
343
  className = "",
292
344
  ...rest
293
345
  }) {
294
346
  const __twcStyles = useScopedStyles("twc-menu-styles", MENU_CSS);
295
- const [openState, setOpenState] = React23__namespace.default.useState(defaultOpen);
296
- const [render, setRender] = React23__namespace.default.useState(false);
297
- const [pos, setPos] = React23__namespace.default.useState(null);
298
- const [active, setActive] = React23__namespace.default.useState(-1);
299
- const wrapRef = React23__namespace.default.useRef(null);
300
- const menuRef = React23__namespace.default.useRef(null);
301
- const menuId = React23__namespace.default.useId();
347
+ const [openState, setOpenState] = React24__namespace.default.useState(defaultOpen);
348
+ const [render, setRender] = React24__namespace.default.useState(false);
349
+ const [pos, setPos] = React24__namespace.default.useState(null);
350
+ const [active, setActive] = React24__namespace.default.useState(-1);
351
+ const wrapRef = React24__namespace.default.useRef(null);
352
+ const menuRef = React24__namespace.default.useRef(null);
353
+ const menuId = React24__namespace.default.useId();
354
+ const headerId = `${menuId}-header`;
302
355
  const controlled = openProp !== void 0;
303
356
  const open = controlled ? !!openProp : openState;
304
- const openRef = React23__namespace.default.useRef(open);
357
+ const openRef = React24__namespace.default.useRef(open);
305
358
  openRef.current = open;
306
- const controlledRef = React23__namespace.default.useRef(controlled);
359
+ const controlledRef = React24__namespace.default.useRef(controlled);
307
360
  controlledRef.current = controlled;
308
- const onOpenChangeRef = React23__namespace.default.useRef(onOpenChange);
361
+ const onOpenChangeRef = React24__namespace.default.useRef(onOpenChange);
309
362
  onOpenChangeRef.current = onOpenChange;
310
- const setOpen = React23__namespace.default.useCallback((next) => {
363
+ const setOpen = React24__namespace.default.useCallback((next) => {
311
364
  const value = typeof next === "function" ? next(openRef.current) : next;
312
365
  if (value === openRef.current) return;
313
366
  if (!controlledRef.current) setOpenState(value);
@@ -315,7 +368,7 @@ function Menu({
315
368
  }, []);
316
369
  const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
317
370
  const interactiveIdx = items.map((it, i) => !it.separator && !it.heading ? i : -1).filter((i) => i >= 0);
318
- const place = React23__namespace.default.useCallback(() => {
371
+ const place = React24__namespace.default.useCallback(() => {
319
372
  const t = wrapRef.current;
320
373
  if (!t) return;
321
374
  const r = t.getBoundingClientRect();
@@ -330,7 +383,7 @@ function Menu({
330
383
  const avail = (flip ? r.top : vh - r.bottom) - gap - M;
331
384
  setPos({ top, bottom, left, width: w, flip, maxHeight: Math.max(120, avail) });
332
385
  }, [align, width]);
333
- React23__namespace.default.useEffect(() => {
386
+ React24__namespace.default.useEffect(() => {
334
387
  if (!open) return;
335
388
  place();
336
389
  const onMove = () => place();
@@ -348,7 +401,7 @@ function Menu({
348
401
  document.removeEventListener("mousedown", onDown);
349
402
  };
350
403
  }, [open, place]);
351
- React23__namespace.default.useEffect(() => {
404
+ React24__namespace.default.useEffect(() => {
352
405
  if (open) {
353
406
  setRender(true);
354
407
  return;
@@ -394,8 +447,12 @@ function Menu({
394
447
  e.preventDefault();
395
448
  const it = items[active];
396
449
  if (it && !it.disabled) {
397
- it.onClick?.();
398
- setOpen(false);
450
+ const el = typeof document !== "undefined" ? document.getElementById(`${menuId}-item-${active}`) : null;
451
+ if (el && el.tagName === "A") el.click();
452
+ else {
453
+ it.onClick?.();
454
+ setOpen(false);
455
+ }
399
456
  }
400
457
  }
401
458
  }
@@ -409,29 +466,32 @@ function Menu({
409
466
  "data-align": align,
410
467
  "data-flip": pos.flip || void 0,
411
468
  role: "menu",
469
+ "aria-label": ariaLabel,
470
+ "aria-labelledby": ariaLabelledby ?? (ariaLabel ? void 0 : header ? headerId : void 0),
412
471
  style: { top: pos.top, bottom: pos.bottom, left: pos.left, minWidth: pos.width, width: pos.width, maxHeight: pos.maxHeight },
413
472
  children: [
414
473
  __twcStyles,
415
- header ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__header", children: header }) : null,
474
+ header ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__header", id: headerId, children: header }) : null,
416
475
  items.map((it, i) => {
417
476
  if (it.separator) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__sep", role: "separator" }, `s${i}`);
418
477
  if (it.label && it.heading) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__label", children: it.label }, `h${i}`);
478
+ const href = !it.disabled ? safeHref(it.href) : void 0;
479
+ const Tag2 = href ? "a" : "button";
419
480
  return /* @__PURE__ */ jsxRuntime.jsxs(
420
- "button",
481
+ Tag2,
421
482
  {
422
- type: "button",
423
483
  id: `${menuId}-item-${i}`,
424
484
  className: "twc-menu__item",
425
485
  role: "menuitem",
426
486
  tabIndex: -1,
427
487
  "data-danger": it.danger || void 0,
428
488
  "data-active": active === i || void 0,
429
- disabled: it.disabled,
430
489
  onMouseEnter: () => setActive(i),
431
490
  onClick: () => {
432
491
  it.onClick?.();
433
492
  setOpen(false);
434
493
  },
494
+ ...Tag2 === "button" ? { type: "button", disabled: it.disabled } : { href, target: it.target, rel: it.rel },
435
495
  children: [
436
496
  it.icon,
437
497
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-menu__item-label", children: it.label }),
@@ -445,7 +505,7 @@ function Menu({
445
505
  }
446
506
  ) : null;
447
507
  const activeDescId = open && active >= 0 ? `${menuId}-item-${active}` : void 0;
448
- const triggerEl = React23__namespace.default.isValidElement(trigger) ? React23__namespace.default.cloneElement(trigger, {
508
+ const triggerEl = React24__namespace.default.isValidElement(trigger) ? React24__namespace.default.cloneElement(trigger, {
449
509
  onClick: (e) => {
450
510
  trigger.props.onClick?.(e);
451
511
  toggle();
@@ -528,7 +588,7 @@ function AvatarMenu({
528
588
  ]
529
589
  }
530
590
  );
531
- return /* @__PURE__ */ jsxRuntime.jsx(Menu, { className, trigger, items, header, align, width: 240, ...rest });
591
+ return /* @__PURE__ */ jsxRuntime.jsx(Menu, { className, trigger, items, header, align, width: 240, "aria-label": `${name || "Account"} menu`, ...rest });
532
592
  }
533
593
  var BADGE_CSS = `
534
594
  .twc-badge {
@@ -595,7 +655,7 @@ var BREADCRUMB_CSS = `
595
655
  .twc-breadcrumb__ellipsis { border: none; background: transparent; cursor: pointer; color: var(--color-text-subtle); padding: 3px 7px; border-radius: var(--radius-sm); font: inherit; }
596
656
  .twc-breadcrumb__ellipsis:hover { background: var(--color-surface-sunken); color: var(--color-text); }
597
657
  `;
598
- function safeHref(url) {
658
+ function safeHref2(url) {
599
659
  if (url == null) return void 0;
600
660
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
601
661
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -609,7 +669,7 @@ function Breadcrumb({
609
669
  ...rest
610
670
  }) {
611
671
  const __twcStyles = useScopedStyles("twc-breadcrumb-styles", BREADCRUMB_CSS);
612
- const [expanded, setExpanded] = React23__namespace.default.useState(false);
672
+ const [expanded, setExpanded] = React24__namespace.default.useState(false);
613
673
  const sep = separator || /* @__PURE__ */ jsxRuntime.jsx(ChevronSep, {});
614
674
  let display = items;
615
675
  if (maxItems > 0 && items.length > maxItems && !expanded) {
@@ -622,7 +682,7 @@ function Breadcrumb({
622
682
  __twcStyles,
623
683
  display.map((it, i) => {
624
684
  const last = i === display.length - 1;
625
- return /* @__PURE__ */ jsxRuntime.jsxs(React23__namespace.default.Fragment, { children: [
685
+ return /* @__PURE__ */ jsxRuntime.jsxs(React24__namespace.default.Fragment, { children: [
626
686
  it.ellipsis ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-breadcrumb__ellipsis", "aria-label": "Show more", onClick: () => setExpanded(true), children: "\u2026" }) : last ? /* @__PURE__ */ jsxRuntime.jsxs(
627
687
  "span",
628
688
  {
@@ -638,7 +698,7 @@ function Breadcrumb({
638
698
  "a",
639
699
  {
640
700
  className: "twc-breadcrumb__item",
641
- href: safeHref(it.href) || "#",
701
+ href: safeHref2(it.href) || "#",
642
702
  onClick: it.onClick,
643
703
  children: [
644
704
  it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
@@ -741,7 +801,7 @@ var CSS2 = `
741
801
  animation: twico-ripple var(--duration-slow) var(--ease-out) forwards;
742
802
  }
743
803
  `;
744
- function safeHref2(url) {
804
+ function safeHref3(url) {
745
805
  if (url == null) return void 0;
746
806
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
747
807
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -763,7 +823,7 @@ function Button({
763
823
  ...rest
764
824
  }) {
765
825
  const __twcStyles = useScopedStyles("twc-btn-styles", CSS2);
766
- const [ripples, setRipples] = React23__namespace.default.useState([]);
826
+ const [ripples, setRipples] = React24__namespace.default.useState([]);
767
827
  const Tag2 = as;
768
828
  const inert = Tag2 === "a" && (disabled || loading);
769
829
  function handleClick(e) {
@@ -792,7 +852,7 @@ function Button({
792
852
  "data-block": fullWidth || void 0,
793
853
  disabled: Tag2 === "button" ? disabled || loading : void 0,
794
854
  type: Tag2 === "button" ? "button" : void 0,
795
- href: inert ? void 0 : safeHref2(href),
855
+ href: inert ? void 0 : safeHref3(href),
796
856
  "aria-disabled": inert || void 0,
797
857
  tabIndex: inert ? -1 : void 0,
798
858
  "aria-busy": loading || void 0,
@@ -900,6 +960,15 @@ var CAROUSEL_CSS = `
900
960
  .twc-carousel__dot { width: 8px; height: 8px; border-radius: var(--radius-full); border: none; padding: 0; cursor: pointer;
901
961
  background: var(--color-border-strong); transition: width var(--duration-base) var(--ease-spring), background-color var(--duration-fast); }
902
962
  .twc-carousel__dot[data-active="true"] { width: 22px; background: var(--color-primary); }
963
+ .twc-carousel__pause { position: absolute; top: 12px; inset-inline-end: 12px; z-index: 2;
964
+ display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--radius-full);
965
+ background: color-mix(in srgb, var(--color-surface) 88%, transparent); color: var(--color-text);
966
+ border: var(--border-thin) solid var(--color-border); box-shadow: var(--shadow-sm); cursor: pointer;
967
+ backdrop-filter: blur(6px); transition: background-color var(--duration-fast) var(--ease-standard); }
968
+ .twc-carousel__pause:hover { background: var(--color-surface); }
969
+ .twc-carousel__pause svg { width: 15px; height: 15px; display: block; }
970
+ .twc-carousel__live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
971
+ overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
903
972
  `;
904
973
  function Carousel({
905
974
  children,
@@ -908,35 +977,76 @@ function Carousel({
908
977
  onIndexChange,
909
978
  showArrows = true,
910
979
  showDots = true,
980
+ showPauseButton = true,
911
981
  loop = true,
912
982
  autoPlay = false,
913
983
  interval = 4e3,
984
+ label,
985
+ pauseLabel = "Pause",
986
+ playLabel = "Play",
914
987
  className = "",
988
+ onKeyDown: onKeyDownProp,
989
+ "aria-label": ariaLabelProp,
990
+ "aria-labelledby": ariaLabelledbyProp,
915
991
  ...rest
916
992
  }) {
917
993
  const __twcStyles = useScopedStyles("twc-carousel-styles", CAROUSEL_CSS);
918
- const slides = React23__namespace.default.Children.toArray(children);
994
+ const slides = React24__namespace.default.Children.toArray(children);
919
995
  const count = slides.length;
920
- const [internal, setInternal] = React23__namespace.default.useState(defaultIndex);
996
+ const [internal, setInternal] = React24__namespace.default.useState(defaultIndex);
921
997
  const index = indexProp !== void 0 ? indexProp : internal;
922
- const [paused, setPaused] = React23__namespace.default.useState(false);
923
- const setIndex = React23__namespace.default.useCallback((i) => {
998
+ const [paused, setPaused] = React24__namespace.default.useState(false);
999
+ const [userPaused, setUserPaused] = React24__namespace.default.useState(false);
1000
+ const [prefersReduced, setPrefersReduced] = React24__namespace.default.useState(false);
1001
+ React24__namespace.default.useEffect(() => {
1002
+ if (typeof window === "undefined" || !window.matchMedia) return void 0;
1003
+ const mql = window.matchMedia("(prefers-reduced-motion: reduce)");
1004
+ const on = () => setPrefersReduced(mql.matches);
1005
+ on();
1006
+ mql.addEventListener("change", on);
1007
+ return () => mql.removeEventListener("change", on);
1008
+ }, []);
1009
+ const setIndex = React24__namespace.default.useCallback((i) => {
924
1010
  if (indexProp === void 0) setInternal(i);
925
1011
  onIndexChange?.(i);
926
1012
  }, [indexProp, onIndexChange]);
927
- const go = React23__namespace.default.useCallback((i) => {
1013
+ const go = React24__namespace.default.useCallback((i) => {
928
1014
  setIndex(loop ? (i + count) % count : Math.min(Math.max(i, 0), count - 1));
929
1015
  }, [count, loop, setIndex]);
930
- React23__namespace.default.useEffect(() => {
931
- if (!autoPlay || paused || count <= 1) return;
1016
+ const autoRotating = autoPlay && !paused && !userPaused && !prefersReduced && count > 1;
1017
+ React24__namespace.default.useEffect(() => {
1018
+ if (!autoRotating) return void 0;
932
1019
  const t = setInterval(() => {
933
1020
  const next = loop ? (index + 1) % count : index + 1 >= count ? index : index + 1;
934
1021
  if (next !== index) setIndex(next);
935
1022
  }, interval);
936
1023
  return () => clearInterval(t);
937
- }, [autoPlay, paused, count, interval, loop, index, setIndex]);
1024
+ }, [autoRotating, count, interval, loop, index, setIndex]);
938
1025
  const atStart = !loop && index === 0;
939
1026
  const atEnd = !loop && index === count - 1;
1027
+ const handleKeyDown = (e) => {
1028
+ onKeyDownProp?.(e);
1029
+ if (e.defaultPrevented) return;
1030
+ if (e.target.closest && e.target.closest('input, textarea, select, [contenteditable="true"]')) return;
1031
+ switch (e.key) {
1032
+ case "ArrowLeft":
1033
+ go(index - 1);
1034
+ break;
1035
+ case "ArrowRight":
1036
+ go(index + 1);
1037
+ break;
1038
+ case "Home":
1039
+ go(0);
1040
+ break;
1041
+ case "End":
1042
+ go(count - 1);
1043
+ break;
1044
+ default:
1045
+ return;
1046
+ }
1047
+ e.preventDefault();
1048
+ };
1049
+ const ariaLabel = ariaLabelledbyProp ? void 0 : ariaLabelProp ?? label ?? "Carousel";
940
1050
  return /* @__PURE__ */ jsxRuntime.jsxs(
941
1051
  "div",
942
1052
  {
@@ -945,12 +1055,17 @@ function Carousel({
945
1055
  onMouseLeave: () => setPaused(false),
946
1056
  onFocusCapture: () => setPaused(true),
947
1057
  onBlurCapture: () => setPaused(false),
1058
+ onKeyDown: handleKeyDown,
948
1059
  role: "region",
949
1060
  "aria-roledescription": "carousel",
1061
+ "aria-label": ariaLabel,
1062
+ "aria-labelledby": ariaLabelledbyProp,
950
1063
  ...rest,
951
1064
  children: [
952
1065
  __twcStyles,
953
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-carousel__viewport", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-carousel__track", style: { transform: `translateX(-${index * 100}%)` }, children: slides.map((s, i) => /* @__PURE__ */ jsxRuntime.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)) }) }),
1066
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-carousel__viewport", tabIndex: 0, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-carousel__track", style: { transform: `translateX(-${index * 100}%)` }, children: slides.map((s, i) => /* @__PURE__ */ jsxRuntime.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)) }) }),
1067
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-carousel__live", "aria-live": autoRotating ? "off" : "polite", "aria-atomic": "true", children: count > 1 ? `Slide ${index + 1} of ${count}` : null }),
1068
+ autoPlay && showPauseButton && count > 1 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-carousel__pause", "aria-label": userPaused ? playLabel : pauseLabel, onClick: () => setUserPaused((v) => !v), children: userPaused ? /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 5h4v14H6zM14 5h4v14h-4z" }) }) }) : null,
954
1069
  showArrows && count > 1 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
955
1070
  /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-carousel__arrow", "data-dir": "prev", "aria-label": "Previous", disabled: atStart, onClick: () => go(index - 1), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
956
1071
  /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-carousel__arrow", "data-dir": "next", "aria-label": "Next", disabled: atEnd, onClick: () => go(index + 1), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) }) })
@@ -973,6 +1088,7 @@ var CHART_CSS = `
973
1088
  .twc-chart__leg { display: inline-flex; align-items: center; gap: 6px; }
974
1089
  .twc-chart__leg-sw { width: 10px; height: 10px; border-radius: 3px; }
975
1090
  @keyframes twc-chart-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
1091
+ .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; }
976
1092
  `;
977
1093
  var SERIES_COLORS = ["var(--brand-500)", "var(--sky-500)", "var(--emerald-500)", "var(--amber-500)", "var(--rose-500)"];
978
1094
  function Chart({
@@ -987,10 +1103,14 @@ function Chart({
987
1103
  valueFormat,
988
1104
  ariaLabel,
989
1105
  "aria-label": ariaLabelProp,
1106
+ tableFallback = true,
1107
+ caption,
990
1108
  className = "",
991
1109
  ...rest
992
1110
  }) {
993
1111
  const __twcStyles = useScopedStyles("twc-chart-styles", CHART_CSS);
1112
+ const uid = React24__namespace.default.useId();
1113
+ const tableId = tableFallback ? `${uid}-table` : void 0;
994
1114
  const keys = series || ["value"];
995
1115
  const palette = colors && colors.length ? colors : SERIES_COLORS;
996
1116
  const W = 600, H = height, padL = showAxis ? 40 : 8, padR = 8, padT = 12, padB = showAxis ? 26 : 8;
@@ -1003,7 +1123,7 @@ function Chart({
1003
1123
  const svgAriaLabel = ariaLabelProp ?? ariaLabel ?? `${type} chart`;
1004
1124
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-chart ${className}`, ...rest, children: [
1005
1125
  __twcStyles,
1006
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": svgAriaLabel, preserveAspectRatio: "none", children: [
1126
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": svgAriaLabel, "aria-describedby": tableId, preserveAspectRatio: "none", children: [
1007
1127
  showGrid ? Array.from({ length: ticks + 1 }).map((_, i) => {
1008
1128
  const gy = padT + innerH / ticks * i;
1009
1129
  return /* @__PURE__ */ jsxRuntime.jsx("line", { className: "twc-chart__grid", x1: padL, y1: gy, x2: W - padR, y2: gy }, i);
@@ -1053,6 +1173,17 @@ function Chart({
1053
1173
  return /* @__PURE__ */ jsxRuntime.jsx("text", { className: "twc-chart__axis", x: cx, y: H - 8, textAnchor: "middle", children: d.label }, i);
1054
1174
  }) : null
1055
1175
  ] }),
1176
+ tableFallback ? /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "twc-chart__sr", id: tableId, children: [
1177
+ /* @__PURE__ */ jsxRuntime.jsx("caption", { children: caption ?? svgAriaLabel }),
1178
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1179
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col" }),
1180
+ keys.map((k) => /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: k }, k))
1181
+ ] }) }),
1182
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: data.map((d, i) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1183
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "row", children: d.label }),
1184
+ keys.map((k) => /* @__PURE__ */ jsxRuntime.jsx("td", { children: fmt(Number(d[k]) || 0) }, k))
1185
+ ] }, i)) })
1186
+ ] }) : null,
1056
1187
  showLegend && keys.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-chart__legend", children: keys.map((k, si) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-chart__leg", children: [
1057
1188
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-chart__leg-sw", style: { background: palette[si % palette.length] } }),
1058
1189
  k
@@ -1125,12 +1256,12 @@ function Checkbox({
1125
1256
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
1126
1257
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
1127
1258
  `);
1128
- const autoId = React23__namespace.default.useId();
1259
+ const autoId = React24__namespace.default.useId();
1129
1260
  const fieldId = id || autoId;
1130
1261
  const errId = `${fieldId}-error`;
1131
1262
  const invalid = Boolean(error);
1132
- const ref = React23__namespace.default.useRef(null);
1133
- React23__namespace.default.useEffect(() => {
1263
+ const ref = React24__namespace.default.useRef(null);
1264
+ React24__namespace.default.useEffect(() => {
1134
1265
  if (ref.current) ref.current.indeterminate = indeterminate;
1135
1266
  }, [indeterminate]);
1136
1267
  const describedBy = [rest["aria-describedby"], error ? errId : null].filter(Boolean).join(" ") || void 0;
@@ -1267,20 +1398,20 @@ function ColorPicker({
1267
1398
  }) {
1268
1399
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS);
1269
1400
  const __twcStyles1 = useScopedStyles("twc-colorpicker-styles", COLORPICKER_CSS);
1270
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
1401
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
1271
1402
  const hex = (value !== void 0 ? value : internal) || "#000000";
1272
- const lastValidRef = React23__namespace.default.useRef(hex);
1403
+ const lastValidRef = React24__namespace.default.useRef(hex);
1273
1404
  if (/^#[0-9a-f]{6}$/i.test(hex)) lastValidRef.current = hex;
1274
- const [open, setOpen] = React23__namespace.default.useState(false);
1275
- const [hsv, setHsv] = React23__namespace.default.useState(() => hexToHsv(hex) || { h: 239, s: 60, v: 94 });
1276
- const [coords, setCoords] = React23__namespace.default.useState(null);
1277
- const wrapRef = React23__namespace.default.useRef(null);
1278
- const triggerRef = React23__namespace.default.useRef(null);
1279
- const popRef = React23__namespace.default.useRef(null);
1280
- const areaRef = React23__namespace.default.useRef(null);
1281
- const hueRef = React23__namespace.default.useRef(null);
1405
+ const [open, setOpen] = React24__namespace.default.useState(false);
1406
+ const [hsv, setHsv] = React24__namespace.default.useState(() => hexToHsv(hex) || { h: 239, s: 60, v: 94 });
1407
+ const [coords, setCoords] = React24__namespace.default.useState(null);
1408
+ const wrapRef = React24__namespace.default.useRef(null);
1409
+ const triggerRef = React24__namespace.default.useRef(null);
1410
+ const popRef = React24__namespace.default.useRef(null);
1411
+ const areaRef = React24__namespace.default.useRef(null);
1412
+ const hueRef = React24__namespace.default.useRef(null);
1282
1413
  const POP_W = 240;
1283
- const place = React23__namespace.default.useCallback(() => {
1414
+ const place = React24__namespace.default.useCallback(() => {
1284
1415
  const el = triggerRef.current;
1285
1416
  if (!el) return;
1286
1417
  const r = el.getBoundingClientRect();
@@ -1291,7 +1422,7 @@ function ColorPicker({
1291
1422
  left = Math.max(8, left);
1292
1423
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
1293
1424
  }, []);
1294
- React23__namespace.default.useEffect(() => {
1425
+ React24__namespace.default.useEffect(() => {
1295
1426
  if (!open) return void 0;
1296
1427
  place();
1297
1428
  const onMove = () => place();
@@ -1302,17 +1433,17 @@ function ColorPicker({
1302
1433
  window.removeEventListener("resize", onMove);
1303
1434
  };
1304
1435
  }, [open, place]);
1305
- const labelId = React23__namespace.default.useId();
1436
+ const labelId = React24__namespace.default.useId();
1306
1437
  const descId = `${labelId}-desc`;
1307
1438
  const invalid = Boolean(error);
1308
- React23__namespace.default.useEffect(() => {
1439
+ React24__namespace.default.useEffect(() => {
1309
1440
  if (disabled) setOpen(false);
1310
1441
  }, [disabled]);
1311
- React23__namespace.default.useEffect(() => {
1442
+ React24__namespace.default.useEffect(() => {
1312
1443
  const v = hexToHsv(hex);
1313
1444
  if (v && hsvToHex(v.h, v.s, v.v).toLowerCase() !== hsvToHex(hsv.h, hsv.s, hsv.v).toLowerCase()) setHsv(v);
1314
1445
  }, [hex]);
1315
- React23__namespace.default.useEffect(() => {
1446
+ React24__namespace.default.useEffect(() => {
1316
1447
  if (!open) return;
1317
1448
  const onDown = (e) => {
1318
1449
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -1329,8 +1460,8 @@ function ColorPicker({
1329
1460
  document.removeEventListener("keydown", onKey);
1330
1461
  };
1331
1462
  }, [open]);
1332
- const prevOpen = React23__namespace.default.useRef(false);
1333
- React23__namespace.default.useEffect(() => {
1463
+ const prevOpen = React24__namespace.default.useRef(false);
1464
+ React24__namespace.default.useEffect(() => {
1334
1465
  let id;
1335
1466
  if (!prevOpen.current && open) {
1336
1467
  id = setTimeout(() => areaRef.current?.focus({ preventScroll: true }), 20);
@@ -1650,29 +1781,29 @@ function Combobox({
1650
1781
  ...rest
1651
1782
  }) {
1652
1783
  const __twcStyles = useScopedStyles("twc-combo-styles", COMBO_CSS);
1653
- const groups = React23__namespace.default.useMemo(() => normalizeGroups(options), [options]);
1654
- const flat = React23__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
1655
- const autoId = React23__namespace.default.useId();
1784
+ const groups = React24__namespace.default.useMemo(() => normalizeGroups(options), [options]);
1785
+ const flat = React24__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
1786
+ const autoId = React24__namespace.default.useId();
1656
1787
  const fieldId = id || autoId;
1657
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
1788
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
1658
1789
  const current = value !== void 0 ? value : internal;
1659
1790
  const selected = flat.find((o) => o.value === current);
1660
- const [open, setOpen] = React23__namespace.default.useState(false);
1661
- const [query, setQuery] = React23__namespace.default.useState("");
1662
- const [active, setActive] = React23__namespace.default.useState(0);
1663
- const [coords, setCoords] = React23__namespace.default.useState(null);
1664
- const wrapRef = React23__namespace.default.useRef(null);
1665
- const controlRef = React23__namespace.default.useRef(null);
1666
- const inputRef = React23__namespace.default.useRef(null);
1667
- const popRef = React23__namespace.default.useRef(null);
1668
- const listRef = React23__namespace.default.useRef(null);
1669
- const activeRef = React23__namespace.default.useRef(null);
1670
- const fGroups = React23__namespace.default.useMemo(
1791
+ const [open, setOpen] = React24__namespace.default.useState(false);
1792
+ const [query, setQuery] = React24__namespace.default.useState("");
1793
+ const [active, setActive] = React24__namespace.default.useState(0);
1794
+ const [coords, setCoords] = React24__namespace.default.useState(null);
1795
+ const wrapRef = React24__namespace.default.useRef(null);
1796
+ const controlRef = React24__namespace.default.useRef(null);
1797
+ const inputRef = React24__namespace.default.useRef(null);
1798
+ const popRef = React24__namespace.default.useRef(null);
1799
+ const listRef = React24__namespace.default.useRef(null);
1800
+ const activeRef = React24__namespace.default.useRef(null);
1801
+ const fGroups = React24__namespace.default.useMemo(
1671
1802
  () => groups.map((g) => ({ group: g.group, options: g.options.filter((o) => matches(o, query.trim())) })).filter((g) => g.options.length),
1672
1803
  [groups, query]
1673
1804
  );
1674
- const visible = React23__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
1675
- const place = React23__namespace.default.useCallback(() => {
1805
+ const visible = React24__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
1806
+ const place = React24__namespace.default.useCallback(() => {
1676
1807
  const el = controlRef.current;
1677
1808
  if (!el) return;
1678
1809
  const r = el.getBoundingClientRect();
@@ -1687,7 +1818,7 @@ function Combobox({
1687
1818
  flip
1688
1819
  });
1689
1820
  }, [placement, minWidth]);
1690
- React23__namespace.default.useEffect(() => {
1821
+ React24__namespace.default.useEffect(() => {
1691
1822
  if (!open || !portal) return;
1692
1823
  place();
1693
1824
  const onMove = () => place();
@@ -1698,7 +1829,7 @@ function Combobox({
1698
1829
  window.removeEventListener("resize", onMove);
1699
1830
  };
1700
1831
  }, [open, portal, place]);
1701
- React23__namespace.default.useEffect(() => {
1832
+ React24__namespace.default.useEffect(() => {
1702
1833
  if (!open) return;
1703
1834
  const onDown = (e) => {
1704
1835
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -1708,10 +1839,10 @@ function Combobox({
1708
1839
  document.addEventListener("mousedown", onDown);
1709
1840
  return () => document.removeEventListener("mousedown", onDown);
1710
1841
  }, [open]);
1711
- React23__namespace.default.useEffect(() => {
1842
+ React24__namespace.default.useEffect(() => {
1712
1843
  setActive(0);
1713
1844
  }, [query]);
1714
- React23__namespace.default.useEffect(() => {
1845
+ React24__namespace.default.useEffect(() => {
1715
1846
  if (open) ensureVisible(listRef.current, activeRef.current);
1716
1847
  }, [active, open]);
1717
1848
  function openMenu() {
@@ -1754,7 +1885,7 @@ function Combobox({
1754
1885
  const descId = `${fieldId}-desc`;
1755
1886
  const describedBy = error || hint ? descId : void 0;
1756
1887
  let counter = -1;
1757
- const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React23__namespace.default.Fragment, { children: [
1888
+ const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React24__namespace.default.Fragment, { children: [
1758
1889
  g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
1759
1890
  g.options.map((o) => {
1760
1891
  counter += 1;
@@ -1892,6 +2023,52 @@ function Combobox({
1892
2023
  error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
1893
2024
  ] });
1894
2025
  }
2026
+ var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
2027
+ 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"])';
2028
+ function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
2029
+ React24__namespace.default.useEffect(() => {
2030
+ if (!active || !canUseDOM) return void 0;
2031
+ const node = ref.current;
2032
+ if (!node) return void 0;
2033
+ const prevFocused = document.activeElement;
2034
+ const first = node.querySelector(FOCUSABLE);
2035
+ (first || node).focus();
2036
+ return () => {
2037
+ if (restoreFocus && prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
2038
+ };
2039
+ }, [active]);
2040
+ React24__namespace.default.useEffect(() => {
2041
+ if (!active || !canUseDOM) return void 0;
2042
+ const node = ref.current;
2043
+ const onKey = (e) => {
2044
+ if (e.key !== "Tab" || !node) return;
2045
+ const f = Array.from(node.querySelectorAll(FOCUSABLE)).filter((el) => el.offsetParent !== null);
2046
+ if (!f.length) {
2047
+ e.preventDefault();
2048
+ node.focus();
2049
+ return;
2050
+ }
2051
+ const first = f[0], last = f[f.length - 1], ae = document.activeElement;
2052
+ if (e.shiftKey) {
2053
+ if (ae === first || ae === node || !node.contains(ae)) {
2054
+ e.preventDefault();
2055
+ last.focus();
2056
+ }
2057
+ } else if (ae === last || !node.contains(ae)) {
2058
+ e.preventDefault();
2059
+ first.focus();
2060
+ }
2061
+ };
2062
+ document.addEventListener("keydown", onKey);
2063
+ return () => document.removeEventListener("keydown", onKey);
2064
+ }, [active]);
2065
+ }
2066
+ function usePortal() {
2067
+ return React24__namespace.default.useCallback((node) => {
2068
+ if (typeof document === "undefined") return null;
2069
+ return typeof reactDom.createPortal === "function" ? reactDom.createPortal(node, document.body) : node;
2070
+ }, []);
2071
+ }
1895
2072
  var COMMAND_CSS = `
1896
2073
  .twc-cmdk__overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: var(--color-overlay); backdrop-filter: blur(3px);
1897
2074
  display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
@@ -1937,14 +2114,15 @@ function CommandPalette({
1937
2114
  ...rest
1938
2115
  }) {
1939
2116
  const __twcStyles = useScopedStyles("twc-cmdk-styles", COMMAND_CSS);
1940
- const [query, setQuery] = React23__namespace.default.useState("");
1941
- const [active, setActive] = React23__namespace.default.useState(0);
1942
- const inputRef = React23__namespace.default.useRef(null);
1943
- const listRef = React23__namespace.default.useRef(null);
1944
- const paletteRef = React23__namespace.default.useRef(null);
1945
- const baseId = React23__namespace.default.useId();
1946
- const [mounted, setMounted] = React23__namespace.default.useState(open);
1947
- React23__namespace.default.useEffect(() => {
2117
+ const renderPortal = usePortal();
2118
+ const [query, setQuery] = React24__namespace.default.useState("");
2119
+ const [active, setActive] = React24__namespace.default.useState(0);
2120
+ const inputRef = React24__namespace.default.useRef(null);
2121
+ const listRef = React24__namespace.default.useRef(null);
2122
+ const paletteRef = React24__namespace.default.useRef(null);
2123
+ const baseId = React24__namespace.default.useId();
2124
+ const [mounted, setMounted] = React24__namespace.default.useState(open);
2125
+ React24__namespace.default.useEffect(() => {
1948
2126
  if (open) {
1949
2127
  setMounted(true);
1950
2128
  return;
@@ -1952,7 +2130,7 @@ function CommandPalette({
1952
2130
  const t = setTimeout(() => setMounted(false), 170);
1953
2131
  return () => clearTimeout(t);
1954
2132
  }, [open]);
1955
- React23__namespace.default.useEffect(() => {
2133
+ React24__namespace.default.useEffect(() => {
1956
2134
  if (!open) return void 0;
1957
2135
  const prev = document.body.style.overflow;
1958
2136
  document.body.style.overflow = "hidden";
@@ -1960,58 +2138,26 @@ function CommandPalette({
1960
2138
  document.body.style.overflow = prev;
1961
2139
  };
1962
2140
  }, [open]);
1963
- React23__namespace.default.useEffect(() => {
2141
+ React24__namespace.default.useEffect(() => {
1964
2142
  if (open) {
1965
2143
  setQuery("");
1966
2144
  setActive(0);
1967
- const t = setTimeout(() => inputRef.current?.focus(), 30);
1968
- return () => clearTimeout(t);
1969
2145
  }
1970
2146
  }, [open]);
1971
- React23__namespace.default.useEffect(() => {
1972
- if (!open) return;
1973
- const prevFocused = document.activeElement;
1974
- return () => {
1975
- if (prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
1976
- };
1977
- }, [open]);
1978
- React23__namespace.default.useEffect(() => {
1979
- if (!open) return;
1980
- const focusables = (node) => node ? Array.from(
1981
- node.querySelectorAll(
1982
- '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"])'
1983
- )
1984
- ).filter((el) => el.offsetParent !== null) : [];
2147
+ useFocusTrap(paletteRef, open && mounted);
2148
+ React24__namespace.default.useEffect(() => {
2149
+ if (!open) return void 0;
1985
2150
  const onKey = (e) => {
1986
2151
  if (e.key === "Escape") {
1987
2152
  e.preventDefault();
1988
2153
  onClose?.();
1989
- return;
1990
- }
1991
- if (e.key !== "Tab") return;
1992
- const node = paletteRef.current;
1993
- const f = focusables(node);
1994
- if (!f.length) {
1995
- e.preventDefault();
1996
- node?.focus();
1997
- return;
1998
- }
1999
- const first = f[0], last = f[f.length - 1], ae = document.activeElement;
2000
- if (e.shiftKey) {
2001
- if (ae === first || ae === node || !node.contains(ae)) {
2002
- e.preventDefault();
2003
- last.focus();
2004
- }
2005
- } else if (ae === last || !node.contains(ae)) {
2006
- e.preventDefault();
2007
- first.focus();
2008
2154
  }
2009
2155
  };
2010
2156
  document.addEventListener("keydown", onKey);
2011
2157
  return () => document.removeEventListener("keydown", onKey);
2012
2158
  }, [open, onClose]);
2013
2159
  const q = query.trim().toLowerCase();
2014
- const filtered = React23__namespace.default.useMemo(() => commands.filter(
2160
+ const filtered = React24__namespace.default.useMemo(() => commands.filter(
2015
2161
  (c) => !q || c.label.toLowerCase().includes(q) || (c.keywords || "").toLowerCase().includes(q) || (c.group || "").toLowerCase().includes(q)
2016
2162
  ), [commands, q]);
2017
2163
  const groups = [];
@@ -2026,7 +2172,7 @@ function CommandPalette({
2026
2172
  g.items.push(c);
2027
2173
  flat.push(c);
2028
2174
  });
2029
- React23__namespace.default.useEffect(() => {
2175
+ React24__namespace.default.useEffect(() => {
2030
2176
  setActive(0);
2031
2177
  }, [query]);
2032
2178
  const run = (cmd) => {
@@ -2046,11 +2192,11 @@ function CommandPalette({
2046
2192
  if (cmd) run(cmd);
2047
2193
  }
2048
2194
  }
2049
- React23__namespace.default.useEffect(() => {
2195
+ React24__namespace.default.useEffect(() => {
2050
2196
  const node = listRef.current?.querySelector('[data-active="true"]');
2051
2197
  if (node) node.scrollIntoView({ block: "nearest" });
2052
2198
  }, [active]);
2053
- if (!mounted || typeof document === "undefined") return null;
2199
+ if (!mounted) return null;
2054
2200
  const state = open ? "open" : "closed";
2055
2201
  const listId = `${baseId}-list`;
2056
2202
  const optionId = (i) => `${baseId}-opt-${i}`;
@@ -2116,8 +2262,7 @@ function CommandPalette({
2116
2262
  ] }, g.key || "_")) })
2117
2263
  ] })
2118
2264
  ] });
2119
- const RD = typeof reactDom.createPortal === "function" ? reactDom.createPortal : null;
2120
- return RD ? RD(overlay, document.body) : overlay;
2265
+ return renderPortal(overlay);
2121
2266
  }
2122
2267
  var CURRENCIES = {
2123
2268
  USD: { code: "USD", symbol: "$", precision: 2, label: "US Dollar" },
@@ -2220,11 +2365,11 @@ function Currency({
2220
2365
  const prec = precision != null ? precision : meta.precision;
2221
2366
  const sym = symbol != null ? symbol : meta.symbol;
2222
2367
  const cur = code != null ? code : meta.code;
2223
- const autoId = React23__namespace.default.useId();
2368
+ const autoId = React24__namespace.default.useId();
2224
2369
  const fieldId = id || autoId;
2225
2370
  const invalid = Boolean(error);
2226
2371
  const controlled = value !== void 0;
2227
- const [internal, setInternal] = React23__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2372
+ const [internal, setInternal] = React24__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2228
2373
  const shown = controlled ? clampPrecision(String(value ?? ""), prec) : internal;
2229
2374
  const describedBy = [error ? `${fieldId}-error` : hint ? `${fieldId}-hint` : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
2230
2375
  function handleChange(e) {
@@ -2398,32 +2543,32 @@ function Select({
2398
2543
  ...rest
2399
2544
  }) {
2400
2545
  const __twcStyles = useScopedStyles("twc-select-styles", SELECT_CSS);
2401
- const groups = React23__namespace.default.useMemo(() => normalizeGroups2(options), [options]);
2402
- const flat = React23__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
2403
- const autoId = React23__namespace.default.useId();
2546
+ const groups = React24__namespace.default.useMemo(() => normalizeGroups2(options), [options]);
2547
+ const flat = React24__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
2548
+ const autoId = React24__namespace.default.useId();
2404
2549
  const fieldId = id || autoId;
2405
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
2550
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
2406
2551
  const current = value !== void 0 ? value : internal;
2407
- const [open, setOpen] = React23__namespace.default.useState(false);
2408
- const [render, setRender] = React23__namespace.default.useState(false);
2409
- const [active, setActive] = React23__namespace.default.useState(0);
2410
- const [coords, setCoords] = React23__namespace.default.useState(null);
2411
- const [query, setQuery] = React23__namespace.default.useState("");
2412
- const wrapRef = React23__namespace.default.useRef(null);
2413
- const triggerRef = React23__namespace.default.useRef(null);
2414
- const popRef = React23__namespace.default.useRef(null);
2415
- const listRef = React23__namespace.default.useRef(null);
2416
- const activeRef = React23__namespace.default.useRef(null);
2417
- const searchRef = React23__namespace.default.useRef(null);
2552
+ const [open, setOpen] = React24__namespace.default.useState(false);
2553
+ const [render, setRender] = React24__namespace.default.useState(false);
2554
+ const [active, setActive] = React24__namespace.default.useState(0);
2555
+ const [coords, setCoords] = React24__namespace.default.useState(null);
2556
+ const [query, setQuery] = React24__namespace.default.useState("");
2557
+ const wrapRef = React24__namespace.default.useRef(null);
2558
+ const triggerRef = React24__namespace.default.useRef(null);
2559
+ const popRef = React24__namespace.default.useRef(null);
2560
+ const listRef = React24__namespace.default.useRef(null);
2561
+ const activeRef = React24__namespace.default.useRef(null);
2562
+ const searchRef = React24__namespace.default.useRef(null);
2418
2563
  const showSearch = searchable === void 0 ? flat.length > 5 : searchable;
2419
- const fGroups = React23__namespace.default.useMemo(() => {
2564
+ const fGroups = React24__namespace.default.useMemo(() => {
2420
2565
  const q = query.trim().toLowerCase();
2421
2566
  if (!q) return groups;
2422
2567
  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);
2423
2568
  }, [groups, query]);
2424
- const visible = React23__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
2569
+ const visible = React24__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
2425
2570
  const selected = flat.find((o) => o.value === current);
2426
- const place = React23__namespace.default.useCallback(() => {
2571
+ const place = React24__namespace.default.useCallback(() => {
2427
2572
  const el = triggerRef.current;
2428
2573
  if (!el) return;
2429
2574
  const r = el.getBoundingClientRect();
@@ -2438,7 +2583,7 @@ function Select({
2438
2583
  flip
2439
2584
  });
2440
2585
  }, [placement, minWidth]);
2441
- React23__namespace.default.useEffect(() => {
2586
+ React24__namespace.default.useEffect(() => {
2442
2587
  if (!open || !portal) return;
2443
2588
  place();
2444
2589
  const onMove = () => place();
@@ -2449,7 +2594,7 @@ function Select({
2449
2594
  window.removeEventListener("resize", onMove);
2450
2595
  };
2451
2596
  }, [open, portal, place]);
2452
- React23__namespace.default.useEffect(() => {
2597
+ React24__namespace.default.useEffect(() => {
2453
2598
  if (!open) return;
2454
2599
  const idx = flat.findIndex((o) => o.value === current);
2455
2600
  setActive(idx >= 0 ? idx : 0);
@@ -2465,13 +2610,13 @@ function Select({
2465
2610
  document.addEventListener("mousedown", onDown);
2466
2611
  return () => document.removeEventListener("mousedown", onDown);
2467
2612
  }, [open]);
2468
- React23__namespace.default.useEffect(() => {
2613
+ React24__namespace.default.useEffect(() => {
2469
2614
  setActive(0);
2470
2615
  }, [query]);
2471
- React23__namespace.default.useEffect(() => {
2616
+ React24__namespace.default.useEffect(() => {
2472
2617
  if (open) ensureVisible2(listRef.current, activeRef.current);
2473
2618
  }, [active, open]);
2474
- React23__namespace.default.useEffect(() => {
2619
+ React24__namespace.default.useEffect(() => {
2475
2620
  if (open) {
2476
2621
  setRender(true);
2477
2622
  return;
@@ -2479,8 +2624,8 @@ function Select({
2479
2624
  const t = setTimeout(() => setRender(false), 170);
2480
2625
  return () => clearTimeout(t);
2481
2626
  }, [open]);
2482
- const prevOpen = React23__namespace.default.useRef(false);
2483
- React23__namespace.default.useEffect(() => {
2627
+ const prevOpen = React24__namespace.default.useRef(false);
2628
+ React24__namespace.default.useEffect(() => {
2484
2629
  if (prevOpen.current && !open) {
2485
2630
  const ae = typeof document !== "undefined" ? document.activeElement : null;
2486
2631
  if (popRef.current && ae && popRef.current.contains(ae)) triggerRef.current?.focus();
@@ -2553,7 +2698,7 @@ function Select({
2553
2698
  }
2554
2699
  )
2555
2700
  ] }) : null,
2556
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React23__namespace.default.Fragment, { children: [
2701
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React24__namespace.default.Fragment, { children: [
2557
2702
  g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
2558
2703
  g.options.map((o) => {
2559
2704
  counter += 1;
@@ -2727,19 +2872,19 @@ function CurrencyField({
2727
2872
  ...rest
2728
2873
  }) {
2729
2874
  const __twcStyles = useScopedStyles("twc-curf-styles", CURF_CSS);
2730
- const autoId = React23__namespace.default.useId();
2875
+ const autoId = React24__namespace.default.useId();
2731
2876
  const fieldId = id || autoId;
2732
2877
  const invalid = Boolean(error);
2733
2878
  const curControlled = currency !== void 0;
2734
- const [curInternal, setCurInternal] = React23__namespace.default.useState(defaultCurrency);
2879
+ const [curInternal, setCurInternal] = React24__namespace.default.useState(defaultCurrency);
2735
2880
  const cur = curControlled ? currency : curInternal;
2736
2881
  const meta = CURRENCIES[cur] || CURRENCIES.USD;
2737
2882
  const prec = meta.precision;
2738
2883
  const valControlled = value !== void 0;
2739
- const [valInternal, setValInternal] = React23__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2884
+ const [valInternal, setValInternal] = React24__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
2740
2885
  const shown = valControlled ? clampPrecision(String(value ?? ""), prec) : valInternal;
2741
2886
  const describedBy = [error ? `${fieldId}-error` : hint ? `${fieldId}-hint` : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
2742
- const options = React23__namespace.default.useMemo(() => {
2887
+ const options = React24__namespace.default.useMemo(() => {
2743
2888
  if (!currencies) return CURRENCY_OPTIONS;
2744
2889
  return currencies.map((c) => typeof c === "string" ? { value: c, label: `${c} \u2014 ${(CURRENCIES[c] || {}).label || c}` } : c);
2745
2890
  }, [currencies]);
@@ -2874,12 +3019,12 @@ function Input({
2874
3019
  ...rest
2875
3020
  }) {
2876
3021
  const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS2);
2877
- const autoId = React23__namespace.default.useId();
3022
+ const autoId = React24__namespace.default.useId();
2878
3023
  const fieldId = id || autoId;
2879
3024
  const descId = `${fieldId}-desc`;
2880
3025
  const invalid = Boolean(error);
2881
3026
  const isPassword = type === "password";
2882
- const [revealed, setRevealed] = React23__namespace.default.useState(false);
3027
+ const [revealed, setRevealed] = React24__namespace.default.useState(false);
2883
3028
  const effectiveType = isPassword && revealed ? "text" : type;
2884
3029
  const suffix = rightIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-input__affix", children: rightIcon }) : isPassword ? /* @__PURE__ */ jsxRuntime.jsx(
2885
3030
  "button",
@@ -3060,28 +3205,28 @@ function MultiSelect({
3060
3205
  ...rest
3061
3206
  }) {
3062
3207
  const __twcStyles = useScopedStyles("twc-ms-styles", MULTI_CSS);
3063
- const groups = React23__namespace.default.useMemo(() => normalizeGroups3(options), [options]);
3064
- const flat = React23__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
3065
- const autoId = React23__namespace.default.useId();
3208
+ const groups = React24__namespace.default.useMemo(() => normalizeGroups3(options), [options]);
3209
+ const flat = React24__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
3210
+ const autoId = React24__namespace.default.useId();
3066
3211
  const fieldId = id || autoId;
3067
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
3212
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
3068
3213
  const selected = value !== void 0 ? value : internal;
3069
- const [open, setOpen] = React23__namespace.default.useState(false);
3070
- const [query, setQuery] = React23__namespace.default.useState("");
3071
- const [active, setActive] = React23__namespace.default.useState(0);
3072
- const [coords, setCoords] = React23__namespace.default.useState(null);
3073
- const wrapRef = React23__namespace.default.useRef(null);
3074
- const controlRef = React23__namespace.default.useRef(null);
3075
- const inputRef = React23__namespace.default.useRef(null);
3076
- const popRef = React23__namespace.default.useRef(null);
3077
- const listRef = React23__namespace.default.useRef(null);
3078
- const activeRef = React23__namespace.default.useRef(null);
3079
- const fGroups = React23__namespace.default.useMemo(
3214
+ const [open, setOpen] = React24__namespace.default.useState(false);
3215
+ const [query, setQuery] = React24__namespace.default.useState("");
3216
+ const [active, setActive] = React24__namespace.default.useState(0);
3217
+ const [coords, setCoords] = React24__namespace.default.useState(null);
3218
+ const wrapRef = React24__namespace.default.useRef(null);
3219
+ const controlRef = React24__namespace.default.useRef(null);
3220
+ const inputRef = React24__namespace.default.useRef(null);
3221
+ const popRef = React24__namespace.default.useRef(null);
3222
+ const listRef = React24__namespace.default.useRef(null);
3223
+ const activeRef = React24__namespace.default.useRef(null);
3224
+ const fGroups = React24__namespace.default.useMemo(
3080
3225
  () => groups.map((g) => ({ group: g.group, options: g.options.filter((o) => matches2(o, query.trim())) })).filter((g) => g.options.length),
3081
3226
  [groups, query]
3082
3227
  );
3083
- const visible = React23__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
3084
- const place = React23__namespace.default.useCallback(() => {
3228
+ const visible = React24__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
3229
+ const place = React24__namespace.default.useCallback(() => {
3085
3230
  const el = controlRef.current;
3086
3231
  if (!el) return;
3087
3232
  const r = el.getBoundingClientRect();
@@ -3096,7 +3241,7 @@ function MultiSelect({
3096
3241
  flip
3097
3242
  });
3098
3243
  }, [placement, minWidth]);
3099
- React23__namespace.default.useEffect(() => {
3244
+ React24__namespace.default.useEffect(() => {
3100
3245
  if (!open || !portal) return;
3101
3246
  place();
3102
3247
  const onMove = () => place();
@@ -3107,7 +3252,7 @@ function MultiSelect({
3107
3252
  window.removeEventListener("resize", onMove);
3108
3253
  };
3109
3254
  }, [open, portal, place]);
3110
- React23__namespace.default.useEffect(() => {
3255
+ React24__namespace.default.useEffect(() => {
3111
3256
  if (!open) return;
3112
3257
  const onDown = (e) => {
3113
3258
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -3118,10 +3263,10 @@ function MultiSelect({
3118
3263
  document.addEventListener("mousedown", onDown);
3119
3264
  return () => document.removeEventListener("mousedown", onDown);
3120
3265
  }, [open]);
3121
- React23__namespace.default.useEffect(() => {
3266
+ React24__namespace.default.useEffect(() => {
3122
3267
  setActive(0);
3123
3268
  }, [query]);
3124
- React23__namespace.default.useEffect(() => {
3269
+ React24__namespace.default.useEffect(() => {
3125
3270
  if (open) ensureVisible3(listRef.current, activeRef.current);
3126
3271
  }, [active, open]);
3127
3272
  function commit(next) {
@@ -3158,7 +3303,7 @@ function MultiSelect({
3158
3303
  const descId = `${fieldId}-desc`;
3159
3304
  const describedBy = error || hint ? descId : void 0;
3160
3305
  let counter = -1;
3161
- const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React23__namespace.default.Fragment, { children: [
3306
+ const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: "No results found" }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React24__namespace.default.Fragment, { children: [
3162
3307
  g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
3163
3308
  g.options.map((o) => {
3164
3309
  counter += 1;
@@ -3302,6 +3447,15 @@ function MultiSelect({
3302
3447
  error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
3303
3448
  ] });
3304
3449
  }
3450
+
3451
+ // components/_warn.js
3452
+ var seen = /* @__PURE__ */ new Set();
3453
+ function warnOnce(key, message) {
3454
+ if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production") return;
3455
+ if (seen.has(key)) return;
3456
+ seen.add(key);
3457
+ if (typeof console !== "undefined" && console.warn) console.warn(message);
3458
+ }
3305
3459
  var PAGINATION_CSS = `
3306
3460
  .twc-pagination { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-sans); }
3307
3461
  .twc-page {
@@ -3364,15 +3518,18 @@ function Pagination({
3364
3518
  siblings = 1,
3365
3519
  boundaries = 1,
3366
3520
  size = "md",
3367
- showJumper = false,
3521
+ showJumper,
3368
3522
  showPageJumper,
3369
3523
  jumperLabel = "Go to",
3370
3524
  className = "",
3371
3525
  ...rest
3372
3526
  }) {
3527
+ if (process.env.NODE_ENV !== "production" && showJumper !== void 0 && showPageJumper === void 0) {
3528
+ warnOnce("Pagination.showJumper", "Pagination: `showJumper` is deprecated and will be removed in 2.0 \u2014 use `showPageJumper`.");
3529
+ }
3373
3530
  const jumperEnabled = showPageJumper ?? showJumper;
3374
3531
  const __twcStyles = useScopedStyles("twc-pagination-styles", PAGINATION_CSS);
3375
- const [internal, setInternal] = React23__namespace.default.useState(defaultPage);
3532
+ const [internal, setInternal] = React24__namespace.default.useState(defaultPage);
3376
3533
  const page = pageProp !== void 0 ? pageProp : internal;
3377
3534
  const pages = buildPages(page, total, siblings, boundaries);
3378
3535
  const go = (p) => {
@@ -3380,7 +3537,7 @@ function Pagination({
3380
3537
  if (pageProp === void 0) setInternal(p);
3381
3538
  onChange?.(p);
3382
3539
  };
3383
- const [jump, setJump] = React23__namespace.default.useState("");
3540
+ const [jump, setJump] = React24__namespace.default.useState("");
3384
3541
  const submitJump = () => {
3385
3542
  const n = parseInt(jump, 10);
3386
3543
  if (!Number.isNaN(n)) go(Math.min(Math.max(n, 1), total));
@@ -3991,9 +4148,9 @@ function runDatatableQuery(rows, query, options = {}) {
3991
4148
  return { rows: page, total, filtered: out };
3992
4149
  }
3993
4150
  function useFloating() {
3994
- const [pos, setPos] = React23__namespace.default.useState(null);
3995
- const cfg = React23__namespace.default.useRef(null);
3996
- const place = React23__namespace.default.useCallback(() => {
4151
+ const [pos, setPos] = React24__namespace.default.useState(null);
4152
+ const cfg = React24__namespace.default.useRef(null);
4153
+ const place = React24__namespace.default.useCallback(() => {
3997
4154
  const c = cfg.current;
3998
4155
  if (!c || !c.el || !c.el.isConnected) return null;
3999
4156
  const r = c.el.getBoundingClientRect();
@@ -4004,17 +4161,17 @@ function useFloating() {
4004
4161
  const top = r.bottom + 6;
4005
4162
  return { top, left, width: c.width, anchorX: r.left + r.width / 2, maxHeight: Math.max(180, vh - top - M) };
4006
4163
  }, []);
4007
- const open = React23__namespace.default.useCallback((el, align = "left", width = 220) => {
4164
+ const open = React24__namespace.default.useCallback((el, align = "left", width = 220) => {
4008
4165
  cfg.current = { el, align, width };
4009
4166
  const p = place();
4010
4167
  if (p) setPos(p);
4011
4168
  }, [place]);
4012
- const close = React23__namespace.default.useCallback(() => {
4169
+ const close = React24__namespace.default.useCallback(() => {
4013
4170
  cfg.current = null;
4014
4171
  setPos(null);
4015
4172
  }, []);
4016
4173
  const isOpen = pos != null;
4017
- React23__namespace.default.useEffect(() => {
4174
+ React24__namespace.default.useEffect(() => {
4018
4175
  if (!isOpen) return void 0;
4019
4176
  const update = () => {
4020
4177
  const p = place();
@@ -4038,9 +4195,9 @@ function Caret({ pos }) {
4038
4195
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__caret", style: { left } });
4039
4196
  }
4040
4197
  function EditCell({ col, value, options, onChange, onCommit, onCommitValue, onCancel, onKeyDown }) {
4041
- const ref = React23__namespace.default.useRef(null);
4198
+ const ref = React24__namespace.default.useRef(null);
4042
4199
  const isSelect = col.editType === "select" || options && col.editType !== "text";
4043
- React23__namespace.default.useEffect(() => {
4200
+ React24__namespace.default.useEffect(() => {
4044
4201
  if (isSelect) {
4045
4202
  const t = setTimeout(() => ref.current?.querySelector(".twc-sel__trigger")?.click(), 0);
4046
4203
  return () => clearTimeout(t);
@@ -4243,7 +4400,7 @@ function Datatable({
4243
4400
  ...rest
4244
4401
  }) {
4245
4402
  const __twcStyles = useScopedStyles("twc-dt-styles", DT_CSS);
4246
- const cols = React23__namespace.default.useMemo(() => {
4403
+ const cols = React24__namespace.default.useMemo(() => {
4247
4404
  const out = columns.map((c) => {
4248
4405
  const isActions = c.type === "actions";
4249
4406
  return {
@@ -4278,7 +4435,7 @@ function Datatable({
4278
4435
  }
4279
4436
  return out;
4280
4437
  }, [columns, rowPinning]);
4281
- const _autoKey = React23__namespace.default.useRef();
4438
+ const _autoKey = React24__namespace.default.useRef();
4282
4439
  if (!_autoKey.current) _autoKey.current = { map: /* @__PURE__ */ new WeakMap(), n: 0 };
4283
4440
  const keyOf = rowKey || ((r, i) => {
4284
4441
  if (r != null && r.id != null) return r.id;
@@ -4293,17 +4450,17 @@ function Datatable({
4293
4450
  }
4294
4451
  return i;
4295
4452
  });
4296
- const [sort, setSort] = React23__namespace.default.useState(null);
4297
- const [filters, setFilters] = React23__namespace.default.useState([]);
4298
- const [hidden, setHidden] = React23__namespace.default.useState(() => /* @__PURE__ */ new Set());
4299
- const [showRowNum, setShowRowNum] = React23__namespace.default.useState(rowNumbers);
4300
- const [wrapped, setWrapped] = React23__namespace.default.useState(() => new Set((columns || []).filter((c) => c.wrapText).map((c) => c.field)));
4453
+ const [sort, setSort] = React24__namespace.default.useState(null);
4454
+ const [filters, setFilters] = React24__namespace.default.useState([]);
4455
+ const [hidden, setHidden] = React24__namespace.default.useState(() => /* @__PURE__ */ new Set());
4456
+ const [showRowNum, setShowRowNum] = React24__namespace.default.useState(rowNumbers);
4457
+ const [wrapped, setWrapped] = React24__namespace.default.useState(() => new Set((columns || []).filter((c) => c.wrapText).map((c) => c.field)));
4301
4458
  const toggleWrap = (field) => setWrapped((w) => {
4302
4459
  const n = new Set(w);
4303
4460
  n.has(field) ? n.delete(field) : n.add(field);
4304
4461
  return n;
4305
4462
  });
4306
- const [pins, setPins] = React23__namespace.default.useState(() => {
4463
+ const [pins, setPins] = React24__namespace.default.useState(() => {
4307
4464
  const left = [], right = [];
4308
4465
  columns.forEach((c) => {
4309
4466
  if (c.pinned === "left") left.push(c.field);
@@ -4311,34 +4468,34 @@ function Datatable({
4311
4468
  });
4312
4469
  return { left, right };
4313
4470
  });
4314
- const [density, setDensity] = React23__namespace.default.useState(densityProp);
4315
- const [quick, setQuick] = React23__namespace.default.useState("");
4316
- const [selected, setSelected] = React23__namespace.default.useState(() => /* @__PURE__ */ new Set());
4317
- const [activeRow, setActiveRow] = React23__namespace.default.useState(null);
4318
- const [activeCell, setActiveCell] = React23__namespace.default.useState(null);
4319
- const [page, setPage] = React23__namespace.default.useState(0);
4320
- const [rowsPerPage, setRowsPerPage] = React23__namespace.default.useState(pageSize > 0 ? pageSize : 10);
4321
- const [colQuery, setColQuery] = React23__namespace.default.useState("");
4322
- const [widths, setWidths] = React23__namespace.default.useState({});
4323
- const [order, setOrder] = React23__namespace.default.useState(() => columns.map((c) => c.field));
4324
- const [drag, setDrag] = React23__namespace.default.useState({ from: null, over: null, after: false });
4325
- const [aggOn, setAggOn] = React23__namespace.default.useState(showAggregation);
4326
- const [focus, setFocus] = React23__namespace.default.useState({ r: 0, c: 0 });
4327
- const gridRef = React23__namespace.default.useRef(null);
4328
- const [groupBy, setGroupBy] = React23__namespace.default.useState(rowGrouping || []);
4329
- const [collapsed, setCollapsed] = React23__namespace.default.useState(() => /* @__PURE__ */ new Set());
4330
- const [pinnedRows, setPinnedRows] = React23__namespace.default.useState({ top: [], bottom: [] });
4331
- const [headH, setHeadH] = React23__namespace.default.useState(41);
4332
- const theadRef = React23__namespace.default.useRef(null);
4333
- const [rowOrder, setRowOrder] = React23__namespace.default.useState(null);
4334
- const [rowHeights, setRowHeights] = React23__namespace.default.useState({});
4335
- const [rowDrag, setRowDrag] = React23__namespace.default.useState({ from: null, over: null, after: false });
4336
- const [rowGrab, setRowGrab] = React23__namespace.default.useState(null);
4337
- const [reorderMsg, setReorderMsg] = React23__namespace.default.useState("");
4338
- const rowFocusRef = React23__namespace.default.useRef(null);
4339
- const rootRef = React23__namespace.default.useRef(null);
4340
- const [compact, setCompact] = React23__namespace.default.useState(false);
4341
- React23__namespace.default.useEffect(() => {
4471
+ const [density, setDensity] = React24__namespace.default.useState(densityProp);
4472
+ const [quick, setQuick] = React24__namespace.default.useState("");
4473
+ const [selected, setSelected] = React24__namespace.default.useState(() => /* @__PURE__ */ new Set());
4474
+ const [activeRow, setActiveRow] = React24__namespace.default.useState(null);
4475
+ const [activeCell, setActiveCell] = React24__namespace.default.useState(null);
4476
+ const [page, setPage] = React24__namespace.default.useState(0);
4477
+ const [rowsPerPage, setRowsPerPage] = React24__namespace.default.useState(pageSize > 0 ? pageSize : 10);
4478
+ const [colQuery, setColQuery] = React24__namespace.default.useState("");
4479
+ const [widths, setWidths] = React24__namespace.default.useState({});
4480
+ const [order, setOrder] = React24__namespace.default.useState(() => columns.map((c) => c.field));
4481
+ const [drag, setDrag] = React24__namespace.default.useState({ from: null, over: null, after: false });
4482
+ const [aggOn, setAggOn] = React24__namespace.default.useState(showAggregation);
4483
+ const [focus, setFocus] = React24__namespace.default.useState({ r: 0, c: 0 });
4484
+ const gridRef = React24__namespace.default.useRef(null);
4485
+ const [groupBy, setGroupBy] = React24__namespace.default.useState(rowGrouping || []);
4486
+ const [collapsed, setCollapsed] = React24__namespace.default.useState(() => /* @__PURE__ */ new Set());
4487
+ const [pinnedRows, setPinnedRows] = React24__namespace.default.useState({ top: [], bottom: [] });
4488
+ const [headH, setHeadH] = React24__namespace.default.useState(41);
4489
+ const theadRef = React24__namespace.default.useRef(null);
4490
+ const [rowOrder, setRowOrder] = React24__namespace.default.useState(null);
4491
+ const [rowHeights, setRowHeights] = React24__namespace.default.useState({});
4492
+ const [rowDrag, setRowDrag] = React24__namespace.default.useState({ from: null, over: null, after: false });
4493
+ const [rowGrab, setRowGrab] = React24__namespace.default.useState(null);
4494
+ const [reorderMsg, setReorderMsg] = React24__namespace.default.useState("");
4495
+ const rowFocusRef = React24__namespace.default.useRef(null);
4496
+ const rootRef = React24__namespace.default.useRef(null);
4497
+ const [compact, setCompact] = React24__namespace.default.useState(false);
4498
+ React24__namespace.default.useEffect(() => {
4342
4499
  const el = rootRef.current;
4343
4500
  if (!el) return void 0;
4344
4501
  const measure = () => setCompact((el.clientWidth || 0) < 720);
@@ -4351,11 +4508,11 @@ function Datatable({
4351
4508
  else if (typeof window !== "undefined") window.removeEventListener("resize", measure);
4352
4509
  };
4353
4510
  }, []);
4354
- const scrollRef = React23__namespace.default.useRef(null);
4355
- const [scrollTop, setScrollTop] = React23__namespace.default.useState(0);
4356
- const [viewportH, setViewportH] = React23__namespace.default.useState(0);
4357
- const [pivotOn, setPivotOn] = React23__namespace.default.useState(pivotMode);
4358
- const [aggConfig, setAggConfig] = React23__namespace.default.useState(() => {
4511
+ const scrollRef = React24__namespace.default.useRef(null);
4512
+ const [scrollTop, setScrollTop] = React24__namespace.default.useState(0);
4513
+ const [viewportH, setViewportH] = React24__namespace.default.useState(0);
4514
+ const [pivotOn, setPivotOn] = React24__namespace.default.useState(pivotMode);
4515
+ const [aggConfig, setAggConfig] = React24__namespace.default.useState(() => {
4359
4516
  const m = {};
4360
4517
  (columns || []).forEach((c) => {
4361
4518
  if (typeof c.aggregation === "string") m[c.field] = c.aggregation;
@@ -4363,13 +4520,13 @@ function Datatable({
4363
4520
  return m;
4364
4521
  });
4365
4522
  const aggOf = (c) => aggConfig[c.field] || (typeof c.aggregation === "function" ? c.aggregation : null);
4366
- const [pivotConfig, setPivotConfig] = React23__namespace.default.useState(() => ({
4523
+ const [pivotConfig, setPivotConfig] = React24__namespace.default.useState(() => ({
4367
4524
  rows: pivot && pivot.rows || [],
4368
4525
  columns: pivot && pivot.columns || [],
4369
4526
  values: pivot && pivot.values || []
4370
4527
  }));
4371
4528
  const pivotActive = pivotOn && pivotConfig.rows.length > 0 && pivotConfig.values.length > 0;
4372
- React23__namespace.default.useEffect(() => {
4529
+ React24__namespace.default.useEffect(() => {
4373
4530
  setOrder((prev) => {
4374
4531
  const fields = columns.map((c) => c.field);
4375
4532
  const kept = prev.filter((f) => fields.includes(f));
@@ -4377,32 +4534,32 @@ function Datatable({
4377
4534
  return [...kept, ...added];
4378
4535
  });
4379
4536
  }, [columns]);
4380
- React23__namespace.default.useEffect(() => {
4537
+ React24__namespace.default.useEffect(() => {
4381
4538
  setDensity(densityProp);
4382
4539
  }, [densityProp]);
4383
- React23__namespace.default.useEffect(() => {
4540
+ React24__namespace.default.useEffect(() => {
4384
4541
  setAggOn(showAggregation);
4385
4542
  }, [showAggregation]);
4386
4543
  const rowGroupingKey = (rowGrouping || []).join("\0");
4387
- const rowGroupingKeyRef = React23__namespace.default.useRef(rowGroupingKey);
4388
- React23__namespace.default.useEffect(() => {
4544
+ const rowGroupingKeyRef = React24__namespace.default.useRef(rowGroupingKey);
4545
+ React24__namespace.default.useEffect(() => {
4389
4546
  if (rowGroupingKeyRef.current === rowGroupingKey) return;
4390
4547
  rowGroupingKeyRef.current = rowGroupingKey;
4391
4548
  setGroupBy(rowGrouping || []);
4392
4549
  }, [rowGroupingKey]);
4393
4550
  const widthOf = (c) => widths[c.field] ?? c.width ?? 160;
4394
- const [colMenu, setColMenu] = React23__namespace.default.useState(null);
4551
+ const [colMenu, setColMenu] = React24__namespace.default.useState(null);
4395
4552
  const [menuPos, openMenu, closeMenu] = useFloating();
4396
- const [panel, setPanel] = React23__namespace.default.useState(null);
4553
+ const [panel, setPanel] = React24__namespace.default.useState(null);
4397
4554
  const [panelPos, openPanel, closePanel] = useFloating();
4398
- const [rowMenu, setRowMenu] = React23__namespace.default.useState(null);
4555
+ const [rowMenu, setRowMenu] = React24__namespace.default.useState(null);
4399
4556
  const [rowMenuPos, openRowMenu, closeRowMenu] = useFloating();
4400
- const [exportOpen, setExportOpen] = React23__namespace.default.useState(false);
4557
+ const [exportOpen, setExportOpen] = React24__namespace.default.useState(false);
4401
4558
  const [exportPos, openExport, closeExport] = useFloating();
4402
- const menuTriggerRef = React23__namespace.default.useRef(null);
4403
- const colMenuRef = React23__namespace.default.useRef(null);
4404
- const rowMenuRef = React23__namespace.default.useRef(null);
4405
- const exportMenuRef = React23__namespace.default.useRef(null);
4559
+ const menuTriggerRef = React24__namespace.default.useRef(null);
4560
+ const colMenuRef = React24__namespace.default.useRef(null);
4561
+ const rowMenuRef = React24__namespace.default.useRef(null);
4562
+ const exportMenuRef = React24__namespace.default.useRef(null);
4406
4563
  function focusFirstItem(container) {
4407
4564
  if (!container) return;
4408
4565
  const first = container.querySelector('[role="menuitem"]:not([disabled])');
@@ -4441,16 +4598,16 @@ function Datatable({
4441
4598
  restoreTriggerFocus();
4442
4599
  }
4443
4600
  }
4444
- React23__namespace.default.useEffect(() => {
4601
+ React24__namespace.default.useEffect(() => {
4445
4602
  if (colMenu) focusFirstItem(colMenuRef.current);
4446
4603
  }, [colMenu]);
4447
- React23__namespace.default.useEffect(() => {
4604
+ React24__namespace.default.useEffect(() => {
4448
4605
  if (rowMenu) focusFirstItem(rowMenuRef.current);
4449
4606
  }, [rowMenu]);
4450
- React23__namespace.default.useEffect(() => {
4607
+ React24__namespace.default.useEffect(() => {
4451
4608
  if (exportOpen) focusFirstItem(exportMenuRef.current);
4452
4609
  }, [exportOpen]);
4453
- React23__namespace.default.useEffect(() => {
4610
+ React24__namespace.default.useEffect(() => {
4454
4611
  if (!colMenu && !panel && !rowMenu) return;
4455
4612
  const closeAll = () => {
4456
4613
  setColMenu(null);
@@ -4473,7 +4630,7 @@ function Datatable({
4473
4630
  document.removeEventListener("keydown", onKey);
4474
4631
  };
4475
4632
  }, [colMenu, panel, rowMenu]);
4476
- React23__namespace.default.useEffect(() => {
4633
+ React24__namespace.default.useEffect(() => {
4477
4634
  if (!exportOpen) return;
4478
4635
  const close = () => {
4479
4636
  setExportOpen(false);
@@ -4492,9 +4649,9 @@ function Datatable({
4492
4649
  document.removeEventListener("keydown", onKey);
4493
4650
  };
4494
4651
  }, [exportOpen]);
4495
- const colByField = React23__namespace.default.useMemo(() => Object.fromEntries(cols.map((c) => [c.field, c])), [cols]);
4652
+ const colByField = React24__namespace.default.useMemo(() => Object.fromEntries(cols.map((c) => [c.field, c])), [cols]);
4496
4653
  const visibleCols = cols.filter((c) => !hidden.has(c.field));
4497
- const ordered = React23__namespace.default.useMemo(() => {
4654
+ const ordered = React24__namespace.default.useMemo(() => {
4498
4655
  const orderIdx = (f) => {
4499
4656
  const i = order.indexOf(f);
4500
4657
  return i === -1 ? 9999 : i;
@@ -4529,7 +4686,7 @@ function Datatable({
4529
4686
  }
4530
4687
  return {};
4531
4688
  };
4532
- const processed = React23__namespace.default.useMemo(() => {
4689
+ const processed = React24__namespace.default.useMemo(() => {
4533
4690
  if (serverMode) {
4534
4691
  if (rowOrder) {
4535
4692
  const idx = new Map(rowOrder.map((k, i) => [k, i]));
@@ -4568,10 +4725,10 @@ function Datatable({
4568
4725
  const totalRows = serverMode ? serverTotal : processed.length;
4569
4726
  const totalPages = paginated ? Math.max(1, Math.ceil(totalRows / rowsPerPage)) : 1;
4570
4727
  const paged = !paginated || serverMode ? processed : processed.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
4571
- React23__namespace.default.useEffect(() => {
4728
+ React24__namespace.default.useEffect(() => {
4572
4729
  if (page > totalPages - 1) setPage(0);
4573
4730
  }, [totalPages]);
4574
- const activeGroupBy = React23__namespace.default.useMemo(() => groupBy.filter((f) => colByField[f]), [groupBy, colByField]);
4731
+ const activeGroupBy = React24__namespace.default.useMemo(() => groupBy.filter((f) => colByField[f]), [groupBy, colByField]);
4575
4732
  function subtotalText(rowsIn) {
4576
4733
  const parts = [];
4577
4734
  for (const c of ordered) {
@@ -4598,7 +4755,7 @@ function Datatable({
4598
4755
  if (agg === "max") return Math.max(...nums);
4599
4756
  return null;
4600
4757
  }
4601
- const displayItems = React23__namespace.default.useMemo(() => {
4758
+ const displayItems = React24__namespace.default.useMemo(() => {
4602
4759
  if (!activeGroupBy.length) return null;
4603
4760
  const build = (rowsIn, depth, prefix) => {
4604
4761
  if (depth >= activeGroupBy.length) return rowsIn.map((row) => ({ kind: "leaf", row }));
@@ -4640,7 +4797,7 @@ function Datatable({
4640
4797
  return { top, bottom };
4641
4798
  });
4642
4799
  }
4643
- React23__namespace.default.useEffect(() => {
4800
+ React24__namespace.default.useEffect(() => {
4644
4801
  if (!rowPinning) return;
4645
4802
  const measure = () => {
4646
4803
  if (theadRef.current) setHeadH(theadRef.current.offsetHeight || 41);
@@ -4654,12 +4811,12 @@ function Datatable({
4654
4811
  const pinnedTopRows = canPinRows ? pinnedRows.top.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
4655
4812
  const pinnedBottomRows = canPinRows ? pinnedRows.bottom.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
4656
4813
  const middleRows = canPinRows ? leafRows.filter((r, i) => !pinSideOf(keyOf(r, i))) : leafRows;
4657
- const keyIndex = React23__namespace.default.useMemo(() => {
4814
+ const keyIndex = React24__namespace.default.useMemo(() => {
4658
4815
  const m = /* @__PURE__ */ new Map();
4659
4816
  leafRows.forEach((r, i) => m.set(keyOf(r, i), i));
4660
4817
  return m;
4661
4818
  }, [leafRows]);
4662
- const keyIndexMid = React23__namespace.default.useMemo(() => {
4819
+ const keyIndexMid = React24__namespace.default.useMemo(() => {
4663
4820
  const m = /* @__PURE__ */ new Map();
4664
4821
  middleRows.forEach((r, i) => m.set(keyOf(r, keyIndex.get(keyOf(r)) ?? i), i));
4665
4822
  return m;
@@ -4744,7 +4901,7 @@ function Datatable({
4744
4901
  setReorderMsg("Reorder cancelled.");
4745
4902
  }
4746
4903
  }
4747
- React23__namespace.default.useEffect(() => {
4904
+ React24__namespace.default.useEffect(() => {
4748
4905
  if (rowFocusRef.current == null) return;
4749
4906
  const key = rowFocusRef.current;
4750
4907
  rowFocusRef.current = null;
@@ -4756,7 +4913,7 @@ function Datatable({
4756
4913
  });
4757
4914
  const estRowH = rowHeight ?? (density === "compact" ? 36 : density === "comfortable" ? 56 : 44);
4758
4915
  const virtualizing = virtualized && !paginated && !activeGroupBy.length && !loading;
4759
- React23__namespace.default.useEffect(() => {
4916
+ React24__namespace.default.useEffect(() => {
4760
4917
  if (!virtualizing) return;
4761
4918
  const el = scrollRef.current;
4762
4919
  if (!el) return;
@@ -4766,13 +4923,13 @@ function Datatable({
4766
4923
  if (ro) ro.observe(el);
4767
4924
  return () => ro && ro.disconnect();
4768
4925
  }, [virtualizing, height]);
4769
- const onScrollVirtual = React23__namespace.default.useCallback((e) => {
4926
+ const onScrollVirtual = React24__namespace.default.useCallback((e) => {
4770
4927
  setScrollTop(e.currentTarget.scrollTop);
4771
4928
  }, []);
4772
4929
  const vh = viewportH || (typeof height === "number" ? height : 440);
4773
- const rowHRef = React23__namespace.default.useRef(/* @__PURE__ */ new Map());
4774
- const [measureTick, setMeasureTick] = React23__namespace.default.useState(0);
4775
- const offsets = React23__namespace.default.useMemo(() => {
4930
+ const rowHRef = React24__namespace.default.useRef(/* @__PURE__ */ new Map());
4931
+ const [measureTick, setMeasureTick] = React24__namespace.default.useState(0);
4932
+ const offsets = React24__namespace.default.useMemo(() => {
4776
4933
  if (!virtualizing) return null;
4777
4934
  const total = middleRows.length;
4778
4935
  const arr = new Float64Array(total + 1);
@@ -4782,7 +4939,7 @@ function Datatable({
4782
4939
  }
4783
4940
  return arr;
4784
4941
  }, [virtualizing, middleRows, estRowH, measureTick]);
4785
- const vWindow = React23__namespace.default.useMemo(() => {
4942
+ const vWindow = React24__namespace.default.useMemo(() => {
4786
4943
  if (!virtualizing || !offsets) return null;
4787
4944
  const total = middleRows.length;
4788
4945
  const totalH = offsets[total];
@@ -4811,7 +4968,7 @@ function Datatable({
4811
4968
  if (start > end) start = end;
4812
4969
  return { start, end, padTop: offsets[start], padBottom: Math.max(0, totalH - offsets[end]) };
4813
4970
  }, [virtualizing, offsets, middleRows.length, vh, scrollTop, overscan]);
4814
- React23__namespace.default.useLayoutEffect(() => {
4971
+ React24__namespace.default.useLayoutEffect(() => {
4815
4972
  if (!virtualizing) return;
4816
4973
  const el = scrollRef.current;
4817
4974
  if (!el) return;
@@ -4826,9 +4983,9 @@ function Datatable({
4826
4983
  }
4827
4984
  if (changed) setMeasureTick((t) => t + 1);
4828
4985
  });
4829
- const onServerChangeRef = React23__namespace.default.useRef(onServerChange);
4986
+ const onServerChangeRef = React24__namespace.default.useRef(onServerChange);
4830
4987
  onServerChangeRef.current = onServerChange;
4831
- React23__namespace.default.useEffect(() => {
4988
+ React24__namespace.default.useEffect(() => {
4832
4989
  if (!serverMode) return;
4833
4990
  const t = setTimeout(() => {
4834
4991
  onServerChangeRef.current?.({
@@ -4863,7 +5020,7 @@ function Datatable({
4863
5020
  return n;
4864
5021
  });
4865
5022
  }
4866
- const movableMidFields = React23__namespace.default.useMemo(
5023
+ const movableMidFields = React24__namespace.default.useMemo(
4867
5024
  () => ordered.filter((c) => !pins.left.includes(c.field) && !pins.right.includes(c.field)).map((c) => c.field),
4868
5025
  [ordered, pins]
4869
5026
  );
@@ -4894,7 +5051,7 @@ function Datatable({
4894
5051
  }
4895
5052
  return [...set].sort((a, b) => a.localeCompare(b)).map((v) => ({ value: v, label: v }));
4896
5053
  }
4897
- const [resizing, setResizing] = React23__namespace.default.useState(false);
5054
+ const [resizing, setResizing] = React24__namespace.default.useState(false);
4898
5055
  function startResize(e, field) {
4899
5056
  e.preventDefault();
4900
5057
  e.stopPropagation();
@@ -5001,7 +5158,7 @@ function Datatable({
5001
5158
  if (!agg) return null;
5002
5159
  if (aggregationValues && col.field in aggregationValues) {
5003
5160
  const pre = aggregationValues[col.field];
5004
- if (pre && typeof pre === "object" && !React23__namespace.default.isValidElement(pre)) {
5161
+ if (pre && typeof pre === "object" && !React24__namespace.default.isValidElement(pre)) {
5005
5162
  if (typeof agg === "string" && agg in pre) return pre[agg];
5006
5163
  } else {
5007
5164
  return pre;
@@ -5119,14 +5276,14 @@ function Datatable({
5119
5276
  focusCell(r, c);
5120
5277
  }
5121
5278
  }
5122
- React23__namespace.default.useEffect(() => {
5279
+ React24__namespace.default.useEffect(() => {
5123
5280
  setFocus((f) => ({ r: Math.min(f.r, Math.max(0, leafRows.length - 1)), c: Math.min(f.c, Math.max(0, ordered.length - 1)) }));
5124
5281
  }, [leafRows.length, ordered.length, page]);
5125
- const selectedRows = React23__namespace.default.useMemo(() => rows.filter((r, i) => selected.has(keyOf(r, i))), [rows, selected]);
5282
+ const selectedRows = React24__namespace.default.useMemo(() => rows.filter((r, i) => selected.has(keyOf(r, i))), [rows, selected]);
5126
5283
  function clearSelection() {
5127
5284
  setSelected(/* @__PURE__ */ new Set());
5128
5285
  }
5129
- const [editing, setEditing] = React23__namespace.default.useState(null);
5286
+ const [editing, setEditing] = React24__namespace.default.useState(null);
5130
5287
  const isColEditable = (c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false));
5131
5288
  function beginEdit(rowK, col, row) {
5132
5289
  if (!isColEditable(col)) return;
@@ -5161,17 +5318,17 @@ function Datatable({
5161
5318
  cancelEdit();
5162
5319
  }
5163
5320
  }
5164
- const batchEditableCols = React23__namespace.default.useMemo(
5321
+ const batchEditableCols = React24__namespace.default.useMemo(
5165
5322
  () => cols.filter((c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false))),
5166
5323
  [cols, editMode]
5167
5324
  );
5168
- const [batchEdit, setBatchEdit] = React23__namespace.default.useState(null);
5325
+ const [batchEdit, setBatchEdit] = React24__namespace.default.useState(null);
5169
5326
  const [batchEditPos, openBatchEdit, closeBatchEdit] = useFloating();
5170
5327
  function openBatchEditor(el) {
5171
5328
  setBatchEdit({ fields: {}, values: {} });
5172
5329
  openBatchEdit(el, "left", 320);
5173
5330
  }
5174
- React23__namespace.default.useEffect(() => {
5331
+ React24__namespace.default.useEffect(() => {
5175
5332
  if (!batchEdit) return;
5176
5333
  const close = () => {
5177
5334
  setBatchEdit(null);
@@ -5190,7 +5347,7 @@ function Datatable({
5190
5347
  document.removeEventListener("keydown", onKey);
5191
5348
  };
5192
5349
  }, [batchEdit]);
5193
- React23__namespace.default.useEffect(() => {
5350
+ React24__namespace.default.useEffect(() => {
5194
5351
  if (batchEdit && selected.size === 0) {
5195
5352
  setBatchEdit(null);
5196
5353
  closeBatchEdit();
@@ -5227,7 +5384,7 @@ function Datatable({
5227
5384
  setBatchEdit(null);
5228
5385
  closeBatchEdit();
5229
5386
  }
5230
- React23__namespace.default.useEffect(() => {
5387
+ React24__namespace.default.useEffect(() => {
5231
5388
  if (!editing) return;
5232
5389
  const onDown = (e) => {
5233
5390
  if (e.target.closest(".twc-dt__editor-wrap") || e.target.closest(".twc-pop")) return;
@@ -5499,12 +5656,12 @@ function Datatable({
5499
5656
  const vlabel = (v) => v.label || (colByField[v.field]?.headerName || v.field);
5500
5657
  const rowFieldLabel = rFields.map((f) => colByField[f]?.headerName || f).join(" / ");
5501
5658
  const leafPaths = [];
5502
- const seen = /* @__PURE__ */ new Set();
5659
+ const seen2 = /* @__PURE__ */ new Set();
5503
5660
  for (const r of rows) {
5504
5661
  const path = colPathOf(r);
5505
5662
  const key = path.join("\0");
5506
- if (!seen.has(key)) {
5507
- seen.add(key);
5663
+ if (!seen2.has(key)) {
5664
+ seen2.add(key);
5508
5665
  leafPaths.push(path);
5509
5666
  }
5510
5667
  }
@@ -6032,7 +6189,7 @@ function Datatable({
6032
6189
  } }) })
6033
6190
  ] }) : null
6034
6191
  ] }),
6035
- paginated ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__footer-row", "data-pager": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Pagination, { size: "sm", page: page + 1, total: totalPages, boundaries: 3, showJumper: showPageJumper && totalPages > 5, onChange: (p) => setPage(p - 1) }) }) : null
6192
+ paginated ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__footer-row", "data-pager": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Pagination, { size: "sm", page: page + 1, total: totalPages, boundaries: 3, showPageJumper: showPageJumper && totalPages > 5, onChange: (p) => setPage(p - 1) }) }) : null
6036
6193
  ] }) : null,
6037
6194
  exportOpen && exportPos ? /* @__PURE__ */ jsxRuntime.jsxs(
6038
6195
  "div",
@@ -6749,23 +6906,23 @@ function DatePicker({
6749
6906
  }) {
6750
6907
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS3);
6751
6908
  const __twcStyles1 = useScopedStyles("twc-datepicker-styles", DATEPICKER_CSS);
6752
- const autoId = React23__namespace.default.useId();
6909
+ const autoId = React24__namespace.default.useId();
6753
6910
  const fieldId = id || autoId;
6754
6911
  const descId = `${fieldId}-desc`;
6755
6912
  const invalid = Boolean(error);
6756
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
6913
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
6757
6914
  const selected = value !== void 0 ? value : internal;
6758
- const [open, setOpen] = React23__namespace.default.useState(false);
6759
- const [view, setView] = React23__namespace.default.useState(selected || /* @__PURE__ */ new Date());
6760
- const [mode, setMode] = React23__namespace.default.useState("days");
6761
- const [focusDate, setFocusDate] = React23__namespace.default.useState(null);
6762
- const [coords, setCoords] = React23__namespace.default.useState(null);
6763
- const wrapRef = React23__namespace.default.useRef(null);
6764
- const triggerRef = React23__namespace.default.useRef(null);
6765
- const popRef = React23__namespace.default.useRef(null);
6766
- const gridRef = React23__namespace.default.useRef(null);
6915
+ const [open, setOpen] = React24__namespace.default.useState(false);
6916
+ const [view, setView] = React24__namespace.default.useState(selected || /* @__PURE__ */ new Date());
6917
+ const [mode, setMode] = React24__namespace.default.useState("days");
6918
+ const [focusDate, setFocusDate] = React24__namespace.default.useState(null);
6919
+ const [coords, setCoords] = React24__namespace.default.useState(null);
6920
+ const wrapRef = React24__namespace.default.useRef(null);
6921
+ const triggerRef = React24__namespace.default.useRef(null);
6922
+ const popRef = React24__namespace.default.useRef(null);
6923
+ const gridRef = React24__namespace.default.useRef(null);
6767
6924
  const POP_W = 280;
6768
- const place = React23__namespace.default.useCallback(() => {
6925
+ const place = React24__namespace.default.useCallback(() => {
6769
6926
  const el = triggerRef.current;
6770
6927
  if (!el) return;
6771
6928
  const r = el.getBoundingClientRect();
@@ -6776,7 +6933,7 @@ function DatePicker({
6776
6933
  left = Math.max(8, left);
6777
6934
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
6778
6935
  }, []);
6779
- React23__namespace.default.useEffect(() => {
6936
+ React24__namespace.default.useEffect(() => {
6780
6937
  if (!open) return void 0;
6781
6938
  place();
6782
6939
  const onMove = () => place();
@@ -6787,7 +6944,7 @@ function DatePicker({
6787
6944
  window.removeEventListener("resize", onMove);
6788
6945
  };
6789
6946
  }, [open, place]);
6790
- React23__namespace.default.useEffect(() => {
6947
+ React24__namespace.default.useEffect(() => {
6791
6948
  if (!open) return;
6792
6949
  setView(selected || /* @__PURE__ */ new Date());
6793
6950
  setMode("days");
@@ -6807,8 +6964,8 @@ function DatePicker({
6807
6964
  document.removeEventListener("keydown", onKey);
6808
6965
  };
6809
6966
  }, [open]);
6810
- const prevOpen = React23__namespace.default.useRef(false);
6811
- React23__namespace.default.useEffect(() => {
6967
+ const prevOpen = React24__namespace.default.useRef(false);
6968
+ React24__namespace.default.useEffect(() => {
6812
6969
  let id2;
6813
6970
  if (!prevOpen.current && open) {
6814
6971
  id2 = setTimeout(() => gridRef.current?.querySelector('[tabindex="0"]')?.focus({ preventScroll: true }), 30);
@@ -6819,9 +6976,9 @@ function DatePicker({
6819
6976
  prevOpen.current = open;
6820
6977
  return () => clearTimeout(id2);
6821
6978
  }, [open]);
6822
- const months = React23__namespace.default.useMemo(() => locale === void 0 ? MONTHS : monthNames(locale), [locale]);
6823
- const monthsShort = React23__namespace.default.useMemo(() => locale === void 0 ? MONTHS.map((n) => n.slice(0, 3)) : monthShortNames(locale), [locale]);
6824
- const dows = React23__namespace.default.useMemo(
6979
+ const months = React24__namespace.default.useMemo(() => locale === void 0 ? MONTHS : monthNames(locale), [locale]);
6980
+ const monthsShort = React24__namespace.default.useMemo(() => locale === void 0 ? MONTHS.map((n) => n.slice(0, 3)) : monthShortNames(locale), [locale]);
6981
+ const dows = React24__namespace.default.useMemo(
6825
6982
  () => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW[(i + weekStartsOn) % 7]) : weekdayNames(locale, weekStartsOn),
6826
6983
  [locale, weekStartsOn]
6827
6984
  );
@@ -6849,7 +7006,7 @@ function DatePicker({
6849
7006
  };
6850
7007
  const cells = Array.from({ length: 42 }, (_, i) => new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i));
6851
7008
  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);
6852
- React23__namespace.default.useEffect(() => {
7009
+ React24__namespace.default.useEffect(() => {
6853
7010
  if (!open || mode !== "days" || !focusDate) return;
6854
7011
  gridRef.current?.querySelector(`[data-key="${keyOf(focusDate)}"]`)?.focus();
6855
7012
  }, [focusDate, open, mode]);
@@ -7072,23 +7229,23 @@ function DateRangePicker({
7072
7229
  }) {
7073
7230
  const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS4);
7074
7231
  const __twcStyles1 = useScopedStyles("twc-drp-styles", RANGE_CSS);
7075
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
7232
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
7076
7233
  const range = value !== void 0 ? value : internal;
7077
- const [open, setOpen] = React23__namespace.default.useState(false);
7078
- const [view, setView] = React23__namespace.default.useState(range.start || /* @__PURE__ */ new Date());
7079
- const [hover, setHover] = React23__namespace.default.useState(null);
7080
- const [coords, setCoords] = React23__namespace.default.useState(null);
7081
- const wrapRef = React23__namespace.default.useRef(null);
7082
- const triggerRef = React23__namespace.default.useRef(null);
7083
- const popRef = React23__namespace.default.useRef(null);
7084
- const labelId = React23__namespace.default.useId();
7234
+ const [open, setOpen] = React24__namespace.default.useState(false);
7235
+ const [view, setView] = React24__namespace.default.useState(range.start || /* @__PURE__ */ new Date());
7236
+ const [hover, setHover] = React24__namespace.default.useState(null);
7237
+ const [coords, setCoords] = React24__namespace.default.useState(null);
7238
+ const wrapRef = React24__namespace.default.useRef(null);
7239
+ const triggerRef = React24__namespace.default.useRef(null);
7240
+ const popRef = React24__namespace.default.useRef(null);
7241
+ const labelId = React24__namespace.default.useId();
7085
7242
  const descId = `${labelId}-desc`;
7086
7243
  const invalid = Boolean(error);
7087
- React23__namespace.default.useEffect(() => {
7244
+ React24__namespace.default.useEffect(() => {
7088
7245
  if (disabled) setOpen(false);
7089
7246
  }, [disabled]);
7090
7247
  const POP_W = 420;
7091
- const place = React23__namespace.default.useCallback(() => {
7248
+ const place = React24__namespace.default.useCallback(() => {
7092
7249
  const el = triggerRef.current;
7093
7250
  if (!el) return;
7094
7251
  const r = el.getBoundingClientRect();
@@ -7099,7 +7256,7 @@ function DateRangePicker({
7099
7256
  left = Math.max(8, left);
7100
7257
  setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
7101
7258
  }, []);
7102
- React23__namespace.default.useEffect(() => {
7259
+ React24__namespace.default.useEffect(() => {
7103
7260
  if (!open) return void 0;
7104
7261
  place();
7105
7262
  const onMove = () => place();
@@ -7110,7 +7267,7 @@ function DateRangePicker({
7110
7267
  window.removeEventListener("resize", onMove);
7111
7268
  };
7112
7269
  }, [open, place]);
7113
- React23__namespace.default.useEffect(() => {
7270
+ React24__namespace.default.useEffect(() => {
7114
7271
  if (!open) return;
7115
7272
  const onDown = (e) => {
7116
7273
  if (wrapRef.current && wrapRef.current.contains(e.target)) return;
@@ -7148,8 +7305,8 @@ function DateRangePicker({
7148
7305
  setView(start);
7149
7306
  setOpen(false);
7150
7307
  };
7151
- const months = React23__namespace.default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
7152
- const dows = React23__namespace.default.useMemo(
7308
+ const months = React24__namespace.default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
7309
+ const dows = React24__namespace.default.useMemo(
7153
7310
  () => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW2[(i + weekStartsOn) % 7]) : weekdayNames2(locale, weekStartsOn),
7154
7311
  [locale, weekStartsOn]
7155
7312
  );
@@ -7330,13 +7487,14 @@ function Dialog({
7330
7487
  className = "",
7331
7488
  ...rest
7332
7489
  }) {
7333
- const autoId = React23__namespace.default.useId();
7490
+ const autoId = React24__namespace.default.useId();
7334
7491
  const titleId = `${autoId}-title`;
7335
7492
  const descId = `${autoId}-desc`;
7336
- const dialogRef = React23__namespace.default.useRef(null);
7493
+ const dialogRef = React24__namespace.default.useRef(null);
7337
7494
  const __twcStyles = useScopedStyles("twc-dialog-styles", DIALOG_CSS);
7338
- const [mounted, setMounted] = React23__namespace.default.useState(open);
7339
- React23__namespace.default.useEffect(() => {
7495
+ const renderPortal = usePortal();
7496
+ const [mounted, setMounted] = React24__namespace.default.useState(open);
7497
+ React24__namespace.default.useEffect(() => {
7340
7498
  if (open) {
7341
7499
  setMounted(true);
7342
7500
  return;
@@ -7344,7 +7502,7 @@ function Dialog({
7344
7502
  const t = setTimeout(() => setMounted(false), 170);
7345
7503
  return () => clearTimeout(t);
7346
7504
  }, [open]);
7347
- React23__namespace.default.useEffect(() => {
7505
+ React24__namespace.default.useEffect(() => {
7348
7506
  if (!open) return void 0;
7349
7507
  const prev = document.body.style.overflow;
7350
7508
  document.body.style.overflow = "hidden";
@@ -7352,48 +7510,13 @@ function Dialog({
7352
7510
  document.body.style.overflow = prev;
7353
7511
  };
7354
7512
  }, [open]);
7355
- React23__namespace.default.useEffect(() => {
7356
- if (!open || !mounted) return void 0;
7357
- const node = dialogRef.current;
7358
- const prevFocused = document.activeElement;
7359
- const first = node?.querySelector(
7360
- 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
7361
- );
7362
- (first || node)?.focus();
7363
- return () => {
7364
- if (prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
7365
- };
7366
- }, [open, mounted]);
7367
- React23__namespace.default.useEffect(() => {
7368
- if (!open) return;
7369
- const node = dialogRef.current;
7370
- const focusables = () => node ? Array.from(
7371
- node.querySelectorAll(
7372
- 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
7373
- )
7374
- ).filter((el) => el.offsetParent !== null) : [];
7513
+ useFocusTrap(dialogRef, open && mounted);
7514
+ React24__namespace.default.useEffect(() => {
7515
+ if (!open) return void 0;
7375
7516
  const onKey = (e) => {
7376
7517
  if (e.key === "Escape") {
7377
7518
  e.preventDefault();
7378
7519
  onClose?.();
7379
- return;
7380
- }
7381
- if (e.key !== "Tab") return;
7382
- const f = focusables();
7383
- if (!f.length) {
7384
- e.preventDefault();
7385
- node?.focus();
7386
- return;
7387
- }
7388
- const first = f[0], last = f[f.length - 1], ae = document.activeElement;
7389
- if (e.shiftKey) {
7390
- if (ae === first || ae === node || !node.contains(ae)) {
7391
- e.preventDefault();
7392
- last.focus();
7393
- }
7394
- } else if (ae === last || !node.contains(ae)) {
7395
- e.preventDefault();
7396
- first.focus();
7397
7520
  }
7398
7521
  };
7399
7522
  document.addEventListener("keydown", onKey);
@@ -7417,9 +7540,7 @@ function Dialog({
7417
7540
  footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dialog__footer", children: footer }) : null
7418
7541
  ] })
7419
7542
  ] });
7420
- if (typeof document === "undefined") return null;
7421
- const RD = typeof reactDom.createPortal === "function" ? reactDom.createPortal : null;
7422
- return RD ? RD(overlay, document.body) : overlay;
7543
+ return renderPortal(overlay);
7423
7544
  }
7424
7545
  var DIVIDER_CSS = `
7425
7546
  .twc-divider { border: none; background: var(--color-divider); }
@@ -7434,6 +7555,10 @@ var DIVIDER_CSS = `
7434
7555
  so ::before/::after land on the correct inline edge under RTL \u2014 no physical override needed. */
7435
7556
  .twc-divider-label[data-align="start"]::before { flex: 0 0 var(--space-6); }
7436
7557
  .twc-divider-label[data-align="end"]::after { flex: 0 0 var(--space-6); }
7558
+ /* Vertical labeled divider: stack the two segments above/below the label. */
7559
+ .twc-divider-label[data-orientation="vertical"] { flex-direction: column; align-self: stretch; min-height: 1em; margin: 0 var(--space-3); }
7560
+ .twc-divider-label[data-orientation="vertical"]::before,
7561
+ .twc-divider-label[data-orientation="vertical"]::after { width: 1px; height: auto; flex: 1; }
7437
7562
  `;
7438
7563
  function Divider({
7439
7564
  orientation = "horizontal",
@@ -7446,7 +7571,7 @@ function Divider({
7446
7571
  const __twcStyles = useScopedStyles("twc-divider-styles", DIVIDER_CSS);
7447
7572
  const resolvedAlign = align === "left" ? "start" : align === "right" ? "end" : align;
7448
7573
  if (children) {
7449
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-divider-label ${className}`, "data-align": resolvedAlign, role: "separator", ...rest, children: [
7574
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-divider-label ${className}`, "data-align": resolvedAlign, "data-orientation": orientation, role: "separator", "aria-orientation": orientation, ...rest, children: [
7450
7575
  __twcStyles,
7451
7576
  children
7452
7577
  ] });
@@ -7533,13 +7658,14 @@ function Drawer({
7533
7658
  style,
7534
7659
  ...rest
7535
7660
  }) {
7536
- const autoId = React23__namespace.default.useId();
7661
+ const autoId = React24__namespace.default.useId();
7537
7662
  const titleId = `${autoId}-title`;
7538
7663
  const descId = `${autoId}-desc`;
7539
- const panelRef = React23__namespace.default.useRef(null);
7664
+ const panelRef = React24__namespace.default.useRef(null);
7540
7665
  const __twcStyles = useScopedStyles("twc-drawer-styles", DRAWER_CSS);
7541
- const [mounted, setMounted] = React23__namespace.default.useState(open);
7542
- React23__namespace.default.useEffect(() => {
7666
+ const renderPortal = usePortal();
7667
+ const [mounted, setMounted] = React24__namespace.default.useState(open);
7668
+ React24__namespace.default.useEffect(() => {
7543
7669
  if (open) {
7544
7670
  setMounted(true);
7545
7671
  return;
@@ -7547,7 +7673,7 @@ function Drawer({
7547
7673
  const t = setTimeout(() => setMounted(false), 170);
7548
7674
  return () => clearTimeout(t);
7549
7675
  }, [open]);
7550
- React23__namespace.default.useEffect(() => {
7676
+ React24__namespace.default.useEffect(() => {
7551
7677
  if (!open) return void 0;
7552
7678
  const prev = document.body.style.overflow;
7553
7679
  document.body.style.overflow = "hidden";
@@ -7555,48 +7681,13 @@ function Drawer({
7555
7681
  document.body.style.overflow = prev;
7556
7682
  };
7557
7683
  }, [open]);
7558
- React23__namespace.default.useEffect(() => {
7559
- if (!open || !mounted) return void 0;
7560
- const node = panelRef.current;
7561
- const prevFocused = document.activeElement;
7562
- const first = node?.querySelector(
7563
- 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
7564
- );
7565
- (first || node)?.focus();
7566
- return () => {
7567
- if (prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
7568
- };
7569
- }, [open, mounted]);
7570
- React23__namespace.default.useEffect(() => {
7571
- if (!open) return;
7572
- const node = panelRef.current;
7573
- const focusables = () => node ? Array.from(
7574
- node.querySelectorAll(
7575
- 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
7576
- )
7577
- ).filter((el) => el.offsetParent !== null) : [];
7684
+ useFocusTrap(panelRef, open && mounted);
7685
+ React24__namespace.default.useEffect(() => {
7686
+ if (!open) return void 0;
7578
7687
  const onKey = (e) => {
7579
7688
  if (e.key === "Escape") {
7580
7689
  e.preventDefault();
7581
7690
  onClose?.();
7582
- return;
7583
- }
7584
- if (e.key !== "Tab") return;
7585
- const f = focusables();
7586
- if (!f.length) {
7587
- e.preventDefault();
7588
- node?.focus();
7589
- return;
7590
- }
7591
- const first = f[0], last = f[f.length - 1], ae = document.activeElement;
7592
- if (e.shiftKey) {
7593
- if (ae === first || ae === node || !node.contains(ae)) {
7594
- e.preventDefault();
7595
- last.focus();
7596
- }
7597
- } else if (ae === last || !node.contains(ae)) {
7598
- e.preventDefault();
7599
- first.focus();
7600
7691
  }
7601
7692
  };
7602
7693
  document.addEventListener("keydown", onKey);
@@ -7624,9 +7715,7 @@ function Drawer({
7624
7715
  footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drawer__footer", children: footer }) : null
7625
7716
  ] })
7626
7717
  ] });
7627
- if (typeof document === "undefined") return null;
7628
- const RD = typeof reactDom.createPortal === "function" ? reactDom.createPortal : null;
7629
- return RD ? RD(overlay, document.body) : overlay;
7718
+ return renderPortal(overlay);
7630
7719
  }
7631
7720
  var EMPTY_CSS = `
7632
7721
  .twc-empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-3);
@@ -7644,11 +7733,14 @@ function EmptyState({
7644
7733
  title,
7645
7734
  description,
7646
7735
  actions,
7647
- bordered = false,
7736
+ bordered,
7648
7737
  border,
7649
7738
  className = "",
7650
7739
  ...rest
7651
7740
  }) {
7741
+ if (process.env.NODE_ENV !== "production" && bordered !== void 0 && border === void 0) {
7742
+ warnOnce("EmptyState.bordered", "EmptyState: `bordered` is deprecated and will be removed in 2.0 \u2014 use `border`.");
7743
+ }
7652
7744
  const hasBorder = border ?? bordered;
7653
7745
  const __twcStyles = useScopedStyles("twc-empty-styles", EMPTY_CSS);
7654
7746
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-empty ${className}`, "data-bordered": hasBorder || void 0, ...rest, children: [
@@ -7679,7 +7771,7 @@ function Field({
7679
7771
  ...rest
7680
7772
  }) {
7681
7773
  const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS5);
7682
- const autoId = React23__namespace.default.useId();
7774
+ const autoId = React24__namespace.default.useId();
7683
7775
  const fieldId = id || autoId;
7684
7776
  const descId = `${fieldId}-desc`;
7685
7777
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-field ${className}`, "data-size": size, ...rest, children: [
@@ -7759,11 +7851,11 @@ function FileUpload({
7759
7851
  ...rest
7760
7852
  }) {
7761
7853
  const __twcStyles = useScopedStyles("twc-upload-styles", UPLOAD_CSS);
7762
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
7854
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
7763
7855
  const files = value !== void 0 ? value : internal;
7764
- const [drag, setDrag] = React23__namespace.default.useState(false);
7765
- const inputRef = React23__namespace.default.useRef(null);
7766
- const autoId = React23__namespace.default.useId();
7856
+ const [drag, setDrag] = React24__namespace.default.useState(false);
7857
+ const inputRef = React24__namespace.default.useRef(null);
7858
+ const autoId = React24__namespace.default.useId();
7767
7859
  const fieldId = id || autoId;
7768
7860
  const descId = `${fieldId}-desc`;
7769
7861
  const invalid = Boolean(error);
@@ -7961,19 +8053,20 @@ function Kanban({
7961
8053
  defaultCards,
7962
8054
  onCardMove,
7963
8055
  renderCard,
8056
+ getCardLabel,
7964
8057
  className = "",
7965
8058
  ...rest
7966
8059
  }) {
7967
8060
  const __twcStyles = useScopedStyles("twc-kanban-styles", KANBAN_CSS);
7968
- const [internal, setInternal] = React23__namespace.default.useState(cards ?? defaultCards ?? []);
8061
+ const [internal, setInternal] = React24__namespace.default.useState(cards ?? defaultCards ?? []);
7969
8062
  const items = cards !== void 0 ? cards : internal;
7970
- const [drag, setDrag] = React23__namespace.default.useState(null);
7971
- const [overCol, setOverCol] = React23__namespace.default.useState(null);
7972
- const [grab, setGrab] = React23__namespace.default.useState(null);
7973
- const [announce, setAnnounce] = React23__namespace.default.useState("");
7974
- const rootRef = React23__namespace.default.useRef(null);
7975
- const focusIdRef = React23__namespace.default.useRef(null);
7976
- React23__namespace.default.useEffect(() => {
8063
+ const [drag, setDrag] = React24__namespace.default.useState(null);
8064
+ const [overCol, setOverCol] = React24__namespace.default.useState(null);
8065
+ const [grab, setGrab] = React24__namespace.default.useState(null);
8066
+ const [announce, setAnnounce] = React24__namespace.default.useState("");
8067
+ const rootRef = React24__namespace.default.useRef(null);
8068
+ const focusIdRef = React24__namespace.default.useRef(null);
8069
+ React24__namespace.default.useEffect(() => {
7977
8070
  if (focusIdRef.current == null) return void 0;
7978
8071
  const raf = requestAnimationFrame(() => {
7979
8072
  const id = focusIdRef.current;
@@ -8025,7 +8118,7 @@ function Kanban({
8025
8118
  }
8026
8119
  };
8027
8120
  const keyTargetCol = grab ? columns[grab.targetIdx]?.id : null;
8028
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-kanban ${className}`, ref: rootRef, ...rest, children: [
8121
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-kanban ${className}`, ref: rootRef, role: "group", "aria-label": "Board", ...rest, children: [
8029
8122
  __twcStyles,
8030
8123
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-kanban__sr", role: "status", "aria-live": "polite", children: announce }),
8031
8124
  columns.map((col, colIdx) => {
@@ -8035,7 +8128,7 @@ function Kanban({
8035
8128
  {
8036
8129
  className: "twc-kanban__col",
8037
8130
  role: "group",
8038
- "aria-label": typeof col.title === "string" ? col.title : void 0,
8131
+ "aria-label": col.ariaLabel ?? colTitle(col),
8039
8132
  "data-over": overCol === col.id || keyTargetCol === col.id || void 0,
8040
8133
  onDragOver: (e) => {
8041
8134
  e.preventDefault();
@@ -8066,6 +8159,8 @@ function Kanban({
8066
8159
  tabIndex: 0,
8067
8160
  "aria-roledescription": "draggable card",
8068
8161
  "data-card-id": card.id,
8162
+ "aria-label": getCardLabel?.(card) ?? (typeof card.ariaLabel === "string" ? card.ariaLabel : cardTitle(card)),
8163
+ "aria-pressed": grab && grab.id === card.id || void 0,
8069
8164
  "data-grabbed": grab && grab.id === card.id || void 0,
8070
8165
  onKeyDown: (e) => handleCardKey(e, card, colIdx),
8071
8166
  onBlur: () => {
@@ -8119,7 +8214,7 @@ var LIST_CSS = `
8119
8214
  `;
8120
8215
  function List({ items, plain = false, className = "", ...rest }) {
8121
8216
  const __twcStyles = useScopedStyles("twc-list-styles", LIST_CSS);
8122
- const safeHref11 = (url) => {
8217
+ const safeHref12 = (url) => {
8123
8218
  if (url == null) return void 0;
8124
8219
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
8125
8220
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -8127,7 +8222,7 @@ function List({ items, plain = false, className = "", ...rest }) {
8127
8222
  return /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: `twc-list ${className}`, "data-plain": plain || void 0, ...rest, children: [
8128
8223
  __twcStyles,
8129
8224
  items.map((it, i) => {
8130
- const href = safeHref11(it.href);
8225
+ const href = safeHref12(it.href);
8131
8226
  const interactive = Boolean(it.onClick || href);
8132
8227
  const Tag2 = href ? "a" : interactive ? "button" : "div";
8133
8228
  const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -8181,7 +8276,7 @@ button.twc-navbar__brand, a.twc-navbar__brand { cursor: pointer; }
8181
8276
  .twc-navbar__menu-btn { display: inline-grid; }
8182
8277
  }
8183
8278
  `;
8184
- function safeHref3(url) {
8279
+ function safeHref4(url) {
8185
8280
  if (url == null) return void 0;
8186
8281
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
8187
8282
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -8194,16 +8289,19 @@ function Navbar({
8194
8289
  actions,
8195
8290
  sticky = true,
8196
8291
  onMenuClick,
8292
+ menuOpen,
8293
+ menuControls,
8294
+ navLabel = "Primary",
8197
8295
  className = "",
8198
8296
  ...rest
8199
8297
  }) {
8200
8298
  const __twcStyles = useScopedStyles("twc-navbar-styles", NAVBAR_CSS);
8201
8299
  return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: `twc-navbar ${className}`, "data-sticky": sticky || void 0, ...rest, children: [
8202
8300
  __twcStyles,
8203
- onMenuClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-navbar__menu-btn", "aria-label": "Open menu", onClick: onMenuClick, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 6h16M4 12h16M4 18h16" }) }) }) : null,
8204
- brand ? brandHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "twc-navbar__brand", href: safeHref3(brandHref), children: brand }) : onBrandClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-navbar__brand", onClick: onBrandClick, children: brand }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-navbar__brand", children: brand }) : null,
8205
- /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "twc-navbar__links", children: links.map((l, i) => {
8206
- const href = safeHref3(l.href);
8301
+ onMenuClick ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 6h16M4 12h16M4 18h16" }) }) }) : null,
8302
+ brand ? brandHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "twc-navbar__brand", href: safeHref4(brandHref), children: brand }) : onBrandClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-navbar__brand", onClick: onBrandClick, children: brand }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-navbar__brand", children: brand }) : null,
8303
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "twc-navbar__links", "aria-label": navLabel, children: links.map((l, i) => {
8304
+ const href = safeHref4(l.href);
8207
8305
  const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8208
8306
  l.icon,
8209
8307
  l.label
@@ -8271,21 +8369,21 @@ function Popover({
8271
8369
  ...rest
8272
8370
  }) {
8273
8371
  const __twcStyles = useScopedStyles("twc-popover-styles", POPOVER_CSS);
8274
- const [openState, setOpenState] = React23__namespace.default.useState(defaultOpen);
8275
- const [render, setRender] = React23__namespace.default.useState(false);
8276
- const [pos, setPos] = React23__namespace.default.useState(null);
8277
- const wrapRef = React23__namespace.default.useRef(null);
8278
- const popRef = React23__namespace.default.useRef(null);
8279
- const popId = React23__namespace.default.useId();
8372
+ const [openState, setOpenState] = React24__namespace.default.useState(defaultOpen);
8373
+ const [render, setRender] = React24__namespace.default.useState(false);
8374
+ const [pos, setPos] = React24__namespace.default.useState(null);
8375
+ const wrapRef = React24__namespace.default.useRef(null);
8376
+ const popRef = React24__namespace.default.useRef(null);
8377
+ const popId = React24__namespace.default.useId();
8280
8378
  const controlled = openProp !== void 0;
8281
8379
  const open = controlled ? !!openProp : openState;
8282
- const openRef = React23__namespace.default.useRef(open);
8380
+ const openRef = React24__namespace.default.useRef(open);
8283
8381
  openRef.current = open;
8284
- const controlledRef = React23__namespace.default.useRef(controlled);
8382
+ const controlledRef = React24__namespace.default.useRef(controlled);
8285
8383
  controlledRef.current = controlled;
8286
- const onOpenChangeRef = React23__namespace.default.useRef(onOpenChange);
8384
+ const onOpenChangeRef = React24__namespace.default.useRef(onOpenChange);
8287
8385
  onOpenChangeRef.current = onOpenChange;
8288
- const setOpen = React23__namespace.default.useCallback((next) => {
8386
+ const setOpen = React24__namespace.default.useCallback((next) => {
8289
8387
  const value = typeof next === "function" ? next(openRef.current) : next;
8290
8388
  if (value === openRef.current) return;
8291
8389
  if (!controlledRef.current) setOpenState(value);
@@ -8293,7 +8391,7 @@ function Popover({
8293
8391
  }, []);
8294
8392
  const toggle = () => setOpen((o) => !o);
8295
8393
  const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
8296
- const place = React23__namespace.default.useCallback(() => {
8394
+ const place = React24__namespace.default.useCallback(() => {
8297
8395
  const t = wrapRef.current;
8298
8396
  if (!t) return;
8299
8397
  const r = t.getBoundingClientRect();
@@ -8324,7 +8422,7 @@ function Popover({
8324
8422
  arrow = { top: Math.min(Math.max(cy - top - 5.5, 8), ph - 18), [onRight ? "left" : "right"]: -6 };
8325
8423
  setPos({ top, left, width: w, flip: false, arrow });
8326
8424
  }, [placement, align, width]);
8327
- React23__namespace.default.useEffect(() => {
8425
+ React24__namespace.default.useEffect(() => {
8328
8426
  if (!open) return;
8329
8427
  place();
8330
8428
  const onMove = () => place();
@@ -8347,7 +8445,7 @@ function Popover({
8347
8445
  document.removeEventListener("keydown", onKey);
8348
8446
  };
8349
8447
  }, [open, place]);
8350
- React23__namespace.default.useEffect(() => {
8448
+ React24__namespace.default.useEffect(() => {
8351
8449
  if (open) {
8352
8450
  setRender(true);
8353
8451
  return;
@@ -8355,12 +8453,12 @@ function Popover({
8355
8453
  const t = setTimeout(() => setRender(false), 170);
8356
8454
  return () => clearTimeout(t);
8357
8455
  }, [open]);
8358
- React23__namespace.default.useEffect(() => {
8456
+ React24__namespace.default.useEffect(() => {
8359
8457
  if (render && open) place();
8360
8458
  }, [render, place]);
8361
- const restoreRef = React23__namespace.default.useRef(null);
8362
- const needFocusRef = React23__namespace.default.useRef(false);
8363
- React23__namespace.default.useEffect(() => {
8459
+ const restoreRef = React24__namespace.default.useRef(null);
8460
+ const needFocusRef = React24__namespace.default.useRef(false);
8461
+ React24__namespace.default.useEffect(() => {
8364
8462
  if (open) {
8365
8463
  restoreRef.current = document.activeElement;
8366
8464
  needFocusRef.current = true;
@@ -8371,7 +8469,7 @@ function Popover({
8371
8469
  needFocusRef.current = false;
8372
8470
  if (prev && typeof prev.focus === "function" && popRef.current?.contains(document.activeElement)) prev.focus();
8373
8471
  }, [open]);
8374
- React23__namespace.default.useEffect(() => {
8472
+ React24__namespace.default.useEffect(() => {
8375
8473
  if (open && render && pos && needFocusRef.current) {
8376
8474
  needFocusRef.current = false;
8377
8475
  popRef.current?.focus({ preventScroll: true });
@@ -8399,7 +8497,7 @@ function Popover({
8399
8497
  ]
8400
8498
  }
8401
8499
  ) : null;
8402
- const triggerEl = React23__namespace.default.isValidElement(trigger) ? React23__namespace.default.cloneElement(trigger, {
8500
+ const triggerEl = React24__namespace.default.isValidElement(trigger) ? React24__namespace.default.cloneElement(trigger, {
8403
8501
  onClick: (e) => {
8404
8502
  trigger.props.onClick?.(e);
8405
8503
  toggle();
@@ -8438,9 +8536,12 @@ function Progress({
8438
8536
  size = "md",
8439
8537
  indeterminate = false,
8440
8538
  showLabel = false,
8539
+ label,
8441
8540
  className = "",
8442
8541
  ...rest
8443
8542
  }) {
8543
+ const labelId = React24__namespace.default.useId();
8544
+ const { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...restProps } = rest;
8444
8545
  const __twcStyles = useScopedStyles("twc-progress-styles", `
8445
8546
  .twc-progress-wrap { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-sans); }
8446
8547
  .twc-progress {
@@ -8479,14 +8580,14 @@ function Progress({
8479
8580
  return (
8480
8581
  // Single-root contract: className and ...rest (style, id, handlers, …) share the outer
8481
8582
  // wrapper; role="progressbar" + aria-value* stay on the inner track.
8482
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-progress-wrap ${className}`, ...rest, children: [
8583
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-progress-wrap ${className}`, ...restProps, children: [
8483
8584
  __twcStyles,
8484
- showLabel && !indeterminate ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-progress__meta", children: [
8485
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Progress" }),
8486
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
8585
+ (showLabel || label != null) && !indeterminate ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-progress__meta", children: [
8586
+ /* @__PURE__ */ jsxRuntime.jsx("span", { id: labelId, children: label ?? "Progress" }),
8587
+ showLabel ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
8487
8588
  Math.round(pct),
8488
8589
  "%"
8489
- ] })
8590
+ ] }) : null
8490
8591
  ] }) : null,
8491
8592
  /* @__PURE__ */ jsxRuntime.jsx(
8492
8593
  "div",
@@ -8499,6 +8600,8 @@ function Progress({
8499
8600
  "aria-valuenow": indeterminate ? void 0 : Math.round(pct),
8500
8601
  "aria-valuemin": 0,
8501
8602
  "aria-valuemax": 100,
8603
+ "aria-label": ariaLabel,
8604
+ "aria-labelledby": ariaLabelledby ?? (label != null ? labelId : void 0),
8502
8605
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-progress__bar", style: indeterminate ? void 0 : { width: `${pct}%` } })
8503
8606
  }
8504
8607
  )
@@ -8560,7 +8663,7 @@ function Radio({
8560
8663
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
8561
8664
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
8562
8665
  `);
8563
- const autoId = React23__namespace.default.useId();
8666
+ const autoId = React24__namespace.default.useId();
8564
8667
  const fieldId = id || autoId;
8565
8668
  const errId = `${fieldId}-error`;
8566
8669
  const invalid = Boolean(error);
@@ -8638,12 +8741,12 @@ function Rating({
8638
8741
  ...rest
8639
8742
  }) {
8640
8743
  const __twcStyles = useScopedStyles("twc-rating-styles", RATING_CSS);
8641
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
8642
- const [hover, setHover] = React23__namespace.default.useState(0);
8744
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
8745
+ const [hover, setHover] = React24__namespace.default.useState(0);
8643
8746
  const val = value !== void 0 ? value : internal;
8644
8747
  const shown = hover || val;
8645
8748
  const interactive = !readOnly && !disabled;
8646
- const btnRefs = React23__namespace.default.useRef([]);
8749
+ const btnRefs = React24__namespace.default.useRef([]);
8647
8750
  const tabStar = Math.min(count, Math.max(1, Math.round(val) || 1));
8648
8751
  const set = (v) => {
8649
8752
  if (!interactive) return;
@@ -8737,12 +8840,12 @@ function Tooltip({
8737
8840
  ...rest
8738
8841
  }) {
8739
8842
  const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
8740
- const id = React23__namespace.default.useId();
8741
- const [show, setShow] = React23__namespace.default.useState(false);
8742
- const [coords, setCoords] = React23__namespace.default.useState(null);
8743
- const timer = React23__namespace.default.useRef(null);
8744
- const wrapRef = React23__namespace.default.useRef(null);
8745
- const tipRef = React23__namespace.default.useRef(null);
8843
+ const id = React24__namespace.default.useId();
8844
+ const [show, setShow] = React24__namespace.default.useState(false);
8845
+ const [coords, setCoords] = React24__namespace.default.useState(null);
8846
+ const timer = React24__namespace.default.useRef(null);
8847
+ const wrapRef = React24__namespace.default.useRef(null);
8848
+ const tipRef = React24__namespace.default.useRef(null);
8746
8849
  const open = () => {
8747
8850
  clearTimeout(timer.current);
8748
8851
  timer.current = setTimeout(() => setShow(true), delay);
@@ -8751,8 +8854,8 @@ function Tooltip({
8751
8854
  clearTimeout(timer.current);
8752
8855
  setShow(false);
8753
8856
  };
8754
- React23__namespace.default.useEffect(() => () => clearTimeout(timer.current), []);
8755
- const place = React23__namespace.default.useCallback(() => {
8857
+ React24__namespace.default.useEffect(() => () => clearTimeout(timer.current), []);
8858
+ const place = React24__namespace.default.useCallback(() => {
8756
8859
  const el = wrapRef.current;
8757
8860
  if (!el) return;
8758
8861
  const r = el.getBoundingClientRect();
@@ -8768,10 +8871,10 @@ function Tooltip({
8768
8871
  else if (placement === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
8769
8872
  else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
8770
8873
  }, [placement]);
8771
- React23__namespace.default.useEffect(() => {
8874
+ React24__namespace.default.useEffect(() => {
8772
8875
  place();
8773
8876
  }, [place]);
8774
- React23__namespace.default.useEffect(() => {
8877
+ React24__namespace.default.useEffect(() => {
8775
8878
  if (!show) return void 0;
8776
8879
  place();
8777
8880
  const onMove = () => place();
@@ -8782,7 +8885,7 @@ function Tooltip({
8782
8885
  window.removeEventListener("resize", onMove);
8783
8886
  };
8784
8887
  }, [show, place]);
8785
- React23__namespace.default.useEffect(() => {
8888
+ React24__namespace.default.useEffect(() => {
8786
8889
  if (!show) return;
8787
8890
  const onKeyDown = (e) => {
8788
8891
  if (e.key === "Escape") {
@@ -8794,7 +8897,7 @@ function Tooltip({
8794
8897
  return () => document.removeEventListener("keydown", onKeyDown);
8795
8898
  }, [show]);
8796
8899
  const describedBy = show ? id : void 0;
8797
- const trigger = React23__namespace.default.isValidElement(children) && children.type !== React23__namespace.default.Fragment ? React23__namespace.default.cloneElement(children, {
8900
+ const trigger = React24__namespace.default.isValidElement(children) && children.type !== React24__namespace.default.Fragment ? React24__namespace.default.cloneElement(children, {
8798
8901
  "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
8799
8902
  }) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-describedby": describedBy, children });
8800
8903
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -8850,6 +8953,7 @@ var SIDEBAR_CSS = `
8850
8953
  .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;
8851
8954
  transition: font-size var(--duration-base) var(--ease-standard), gap var(--duration-base) var(--ease-standard); }
8852
8955
  .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; }
8956
+ .twc-sidebar__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
8853
8957
  .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;
8854
8958
  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; }
8855
8959
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__section { max-height: 0; padding-top: 0; padding-bottom: 0; opacity: 0; visibility: hidden;
@@ -8891,6 +8995,23 @@ var SIDEBAR_CSS = `
8891
8995
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__foot { display: flex; flex-direction: column; align-items: center; padding: var(--space-2) 0; }
8892
8996
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__collapse { width: auto; padding: 11px; gap: 0; margin: 0; }
8893
8997
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__collapse span { display: none; }
8998
+
8999
+ /* Off-canvas overlay mode (mobile): the rail becomes a slide-over drawer behind a
9000
+ scrim, mirroring Drawer.jsx. Logical inset + a --_off var slide it in from the
9001
+ inline-start edge (mirrored under dir="rtl"). */
9002
+ .twc-sidebar__overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: var(--color-overlay); backdrop-filter: blur(2px); }
9003
+ .twc-sidebar__overlay[data-state="open"] { animation: twico-fade-in var(--duration-base) var(--ease-out); }
9004
+ .twc-sidebar__overlay[data-state="closed"] { animation: twc-sidebar-fade-out var(--duration-exit) var(--ease-in) forwards; pointer-events: none; }
9005
+ @keyframes twc-sidebar-fade-out { from { opacity: 1; } to { opacity: 0; } }
9006
+ .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%; }
9007
+ [dir="rtl"] .twc-sidebar--overlay { inset-inline-start: auto; inset-inline-end: 0; --_off: 100%; }
9008
+ .twc-sidebar--overlay[data-state="open"] { animation: twc-sidebar-in var(--duration-base) var(--ease-out); }
9009
+ .twc-sidebar--overlay[data-state="closed"] { animation: twc-sidebar-out var(--duration-exit) var(--ease-in) forwards; }
9010
+ @keyframes twc-sidebar-in { from { transform: translateX(var(--_off)); } to { transform: translateX(0); } }
9011
+ @keyframes twc-sidebar-out { from { transform: translateX(0); } to { transform: translateX(var(--_off)); } }
9012
+ @media (prefers-reduced-motion: reduce) {
9013
+ .twc-sidebar__overlay[data-state], .twc-sidebar--overlay[data-state] { animation-duration: 1ms; }
9014
+ }
8894
9015
  `;
8895
9016
  function Sidebar({
8896
9017
  brand,
@@ -8900,63 +9021,149 @@ function Sidebar({
8900
9021
  defaultCollapsed = false,
8901
9022
  collapsible = true,
8902
9023
  onCollapsedChange,
9024
+ overlay = false,
9025
+ open: openProp,
9026
+ defaultOpen = false,
9027
+ onOpenChange,
9028
+ navLabel = "Main",
8903
9029
  className = "",
8904
9030
  ...rest
8905
9031
  }) {
8906
9032
  const __twcStyles = useScopedStyles("twc-sidebar-styles", SIDEBAR_CSS);
8907
- const [internal, setInternal] = React23__namespace.default.useState(defaultCollapsed);
9033
+ const navId = React24__namespace.default.useId();
9034
+ const panelRef = React24__namespace.default.useRef(null);
9035
+ const renderPortal = usePortal();
9036
+ const [internal, setInternal] = React24__namespace.default.useState(defaultCollapsed);
8908
9037
  const collapsed = collapsedProp !== void 0 ? collapsedProp : internal;
8909
9038
  const toggle = () => {
8910
9039
  const next = !collapsed;
8911
9040
  if (collapsedProp === void 0) setInternal(next);
8912
9041
  onCollapsedChange?.(next);
8913
9042
  };
8914
- const safeHref11 = (url) => {
9043
+ const [openInternal, setOpenInternal] = React24__namespace.default.useState(defaultOpen);
9044
+ const open = openProp !== void 0 ? openProp : openInternal;
9045
+ const setOpen = (next) => {
9046
+ if (openProp === void 0) setOpenInternal(next);
9047
+ onOpenChange?.(next);
9048
+ };
9049
+ const [mounted, setMounted] = React24__namespace.default.useState(open);
9050
+ React24__namespace.default.useEffect(() => {
9051
+ if (!overlay) return void 0;
9052
+ if (open) {
9053
+ setMounted(true);
9054
+ return void 0;
9055
+ }
9056
+ const t = setTimeout(() => setMounted(false), 170);
9057
+ return () => clearTimeout(t);
9058
+ }, [overlay, open]);
9059
+ React24__namespace.default.useEffect(() => {
9060
+ if (!overlay || !open) return void 0;
9061
+ const prev = document.body.style.overflow;
9062
+ document.body.style.overflow = "hidden";
9063
+ return () => {
9064
+ document.body.style.overflow = prev;
9065
+ };
9066
+ }, [overlay, open]);
9067
+ useFocusTrap(panelRef, overlay && open && mounted);
9068
+ React24__namespace.default.useEffect(() => {
9069
+ if (!overlay || !open) return void 0;
9070
+ const onKey = (e) => {
9071
+ if (e.key === "Escape") {
9072
+ e.preventDefault();
9073
+ if (openProp === void 0) setOpenInternal(false);
9074
+ onOpenChange?.(false);
9075
+ }
9076
+ };
9077
+ document.addEventListener("keydown", onKey);
9078
+ return () => document.removeEventListener("keydown", onKey);
9079
+ }, [overlay, open, openProp, onOpenChange]);
9080
+ const safeHref12 = (url) => {
8915
9081
  if (url == null) return void 0;
8916
9082
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
8917
9083
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
8918
9084
  };
8919
- return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: `twc-sidebar ${className}`, "data-collapsed": collapsed || void 0, ...rest, children: [
9085
+ const renderItem = (it, i) => {
9086
+ const href = safeHref12(it.href);
9087
+ const labelStr = typeof it.label === "string" ? it.label : void 0;
9088
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9089
+ it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__ic", "aria-hidden": "true", children: it.icon }) : labelStr != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__ic twc-sidebar__ic--initial", "aria-hidden": "true", children: labelStr.charAt(0) }) : null,
9090
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__label", children: it.label }),
9091
+ it.badge != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__badge", children: it.badge }) : null
9092
+ ] });
9093
+ const common = {
9094
+ className: "twc-sidebar__item",
9095
+ "data-active": it.active || void 0,
9096
+ "aria-current": it.active ? "page" : void 0,
9097
+ onClick: it.onClick,
9098
+ "aria-label": collapsed && labelStr != null ? labelStr : void 0
9099
+ };
9100
+ const node = href != null ? /* @__PURE__ */ jsxRuntime.jsx("a", { href, ...common, children: inner }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", ...common, children: inner });
9101
+ return collapsed && labelStr != null ? /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: labelStr, placement: "right", style: { display: "block" }, children: node }) : node;
9102
+ };
9103
+ const groups = [];
9104
+ let group = { sid: null, section: null, entries: [] };
9105
+ let secN = 0;
9106
+ for (let i = 0; i < items.length; i++) {
9107
+ const it = items[i];
9108
+ if (it.section) {
9109
+ if (group.entries.length || group.section != null) groups.push(group);
9110
+ secN += 1;
9111
+ group = { sid: `${navId}-sec-${secN}`, section: it.section, entries: [] };
9112
+ } else {
9113
+ group.entries.push({ it, i });
9114
+ }
9115
+ }
9116
+ if (group.entries.length || group.section != null) groups.push(group);
9117
+ const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8920
9118
  __twcStyles,
8921
9119
  brand ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__head", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__brand", children: brand }) }) : null,
8922
- /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "twc-sidebar__nav", children: items.map(
8923
- (it, i) => it.section ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__section", children: it.section }, i) : (() => {
8924
- const href = safeHref11(it.href);
8925
- const labelStr = typeof it.label === "string" ? it.label : void 0;
8926
- const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8927
- it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__ic", "aria-hidden": "true", children: it.icon }) : labelStr != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__ic twc-sidebar__ic--initial", "aria-hidden": "true", children: labelStr.charAt(0) }) : null,
8928
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__label", children: it.label }),
8929
- it.badge != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__badge", children: it.badge }) : null
8930
- ] });
8931
- const common = {
8932
- className: "twc-sidebar__item",
8933
- "data-active": it.active || void 0,
8934
- "aria-current": it.active ? "page" : void 0,
8935
- onClick: it.onClick,
8936
- "aria-label": collapsed && labelStr != null ? labelStr : void 0
8937
- };
8938
- const node = href != null ? /* @__PURE__ */ jsxRuntime.jsx("a", { href, ...common, children: inner }, i) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", ...common, children: inner }, i);
8939
- return collapsed && labelStr != null ? /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: labelStr, placement: "right", style: { display: "block" }, children: node }, i) : node;
8940
- })()
8941
- ) }),
9120
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { id: navId, className: "twc-sidebar__nav", "aria-label": navLabel, children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React24__namespace.default.Fragment, { children: [
9121
+ g.section != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__section", id: g.sid, children: g.section }) : null,
9122
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "twc-sidebar__list", ...g.section != null ? { "aria-labelledby": g.sid } : {}, children: g.entries.map(({ it, i }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: renderItem(it) }, i)) })
9123
+ ] }, gi)) }),
8942
9124
  footer || collapsible ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-sidebar__foot", children: [
8943
9125
  footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__foot-user", children: footer }) : null,
8944
- collapsible ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-sidebar__collapse", onClick: toggle, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", children: [
9126
+ collapsible ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-sidebar__collapse", onClick: toggle, "aria-expanded": !collapsed, "aria-controls": navId, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", children: [
8945
9127
  /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }),
8946
9128
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Collapse" })
8947
9129
  ] }) : null
8948
9130
  ] }) : null
8949
9131
  ] });
9132
+ if (!overlay) {
9133
+ return /* @__PURE__ */ jsxRuntime.jsx("aside", { className: `twc-sidebar ${className}`, "data-collapsed": collapsed || void 0, ...rest, children: body });
9134
+ }
9135
+ if (!mounted) return null;
9136
+ const state = open ? "open" : "closed";
9137
+ const drawer = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__overlay", "data-state": state, onMouseDown: (e) => {
9138
+ if (e.target === e.currentTarget) setOpen(false);
9139
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(
9140
+ "aside",
9141
+ {
9142
+ ref: panelRef,
9143
+ className: `twc-sidebar twc-sidebar--overlay ${className}`,
9144
+ "data-state": state,
9145
+ "data-collapsed": collapsed || void 0,
9146
+ role: "dialog",
9147
+ "aria-modal": "true",
9148
+ tabIndex: -1,
9149
+ "aria-label": navLabel || "Navigation",
9150
+ ...rest,
9151
+ children: body
9152
+ }
9153
+ ) });
9154
+ return renderPortal(drawer);
8950
9155
  }
8951
9156
  function Skeleton({
8952
9157
  variant = "text",
8953
9158
  width,
8954
9159
  height,
8955
9160
  lines = 1,
9161
+ label,
8956
9162
  className = "",
8957
9163
  style,
8958
9164
  ...rest
8959
9165
  }) {
9166
+ const a11y = label != null ? { role: "status", "aria-live": "polite", "aria-busy": true } : { "aria-hidden": true };
8960
9167
  const __twcStyles = useScopedStyles("twc-skeleton-styles", `
8961
9168
  .twc-skeleton {
8962
9169
  position: relative; overflow: hidden;
@@ -8972,25 +9179,31 @@ function Skeleton({
8972
9179
  .twc-skeleton[data-variant="rect"] { border-radius: var(--radius-md); }
8973
9180
  .twc-skeleton__group { display: flex; flex-direction: column; gap: 8px; }
8974
9181
  .twc-skeleton__group .twc-skeleton:last-child { width: 70%; }
9182
+ .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; }
8975
9183
  /* The shimmer signals loading \u2014 keep it animating even under reduced motion. */
8976
9184
  @media (prefers-reduced-motion: reduce) {
8977
9185
  .twc-skeleton::after { animation-duration: 1.4s !important; animation-iteration-count: infinite !important; }
8978
9186
  }
8979
9187
  `);
8980
9188
  if (variant === "text" && lines > 1) {
8981
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-skeleton__group ${className}`, style: { height, ...style }, ...rest, children: [
9189
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-skeleton__group ${className}`, style: { height, ...style }, ...a11y, ...rest, children: [
8982
9190
  __twcStyles,
9191
+ label != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-skeleton__sr", children: label }) : null,
8983
9192
  Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-skeleton", "data-variant": "text", style: { width: width || "100%" } }, i))
8984
9193
  ] });
8985
9194
  }
8986
- return /* @__PURE__ */ jsxRuntime.jsx(
9195
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8987
9196
  "span",
8988
9197
  {
8989
9198
  className: `twc-skeleton ${className}`,
8990
9199
  "data-variant": variant,
8991
9200
  style: { width, height, ...style },
9201
+ ...a11y,
8992
9202
  ...rest,
8993
- children: __twcStyles
9203
+ children: [
9204
+ __twcStyles,
9205
+ label != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-skeleton__sr", children: label }) : null
9206
+ ]
8994
9207
  }
8995
9208
  );
8996
9209
  }
@@ -9057,12 +9270,12 @@ function Slider({
9057
9270
  const max = Number.isFinite(maxProp) && maxProp > min ? maxProp : min + 1;
9058
9271
  const step = Number.isFinite(stepProp) && stepProp > 0 ? stepProp : 1;
9059
9272
  const __twcStyles = useScopedStyles("twc-slider-styles", SLIDER_CSS);
9060
- const autoId = React23__namespace.default.useId();
9273
+ const autoId = React24__namespace.default.useId();
9061
9274
  const fieldId = id || autoId;
9062
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue);
9275
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue);
9063
9276
  const val = value !== void 0 ? value : internal;
9064
- const trackRef = React23__namespace.default.useRef(null);
9065
- const [dragging, setDragging] = React23__namespace.default.useState(false);
9277
+ const trackRef = React24__namespace.default.useRef(null);
9278
+ const [dragging, setDragging] = React24__namespace.default.useState(false);
9066
9279
  const pct = (val - min) / (max - min) * 100;
9067
9280
  const fmt = (v) => formatValue ? formatValue(v) : v;
9068
9281
  const clampSnap = (raw) => {
@@ -9080,8 +9293,8 @@ function Slider({
9080
9293
  const ratio = Math.min(1, Math.max(0, (clientX - r.left) / r.width));
9081
9294
  return clampSnap(min + ratio * (max - min));
9082
9295
  };
9083
- const dragCleanupRef = React23__namespace.default.useRef(null);
9084
- React23__namespace.default.useEffect(() => () => dragCleanupRef.current?.(), []);
9296
+ const dragCleanupRef = React24__namespace.default.useRef(null);
9297
+ React24__namespace.default.useEffect(() => () => dragCleanupRef.current?.(), []);
9085
9298
  function onPointerDown(e) {
9086
9299
  if (disabled) return;
9087
9300
  e.preventDefault();
@@ -9156,12 +9369,15 @@ function Slider({
9156
9369
  function Spinner({
9157
9370
  size = "md",
9158
9371
  color,
9159
- tone = "current",
9372
+ tone,
9160
9373
  label = "Loading",
9161
9374
  className = "",
9162
9375
  ...rest
9163
9376
  }) {
9164
- const resolvedColor = color ?? tone;
9377
+ if (process.env.NODE_ENV !== "production" && tone !== void 0 && color === void 0) {
9378
+ warnOnce("Spinner.tone", "Spinner: `tone` is deprecated and will be removed in 2.0 \u2014 use `color`.");
9379
+ }
9380
+ const resolvedColor = color ?? tone ?? "current";
9165
9381
  const __twcStyles = useScopedStyles("twc-spinner-styles", `
9166
9382
  .twc-spinner {
9167
9383
  --_sz: 24px; --_bw: 2.5px;
@@ -9277,6 +9493,7 @@ var STEPPER_CSS = `
9277
9493
  .twc-stepper[data-orientation="vertical"] .twc-step__col { display: flex; flex-direction: column; align-items: center; }
9278
9494
  .twc-step[data-state="complete"] .twc-step__connector, .twc-step[data-state="active"] .twc-step__connector { background: var(--_accent); }
9279
9495
  .twc-stepper[data-orientation="vertical"] .twc-step__vbody { padding-bottom: var(--space-2); }
9496
+ .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; }
9280
9497
  `;
9281
9498
  var CheckIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) });
9282
9499
  var BangIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 8v5M12 17h.01" }) });
@@ -9292,7 +9509,7 @@ function Stepper({
9292
9509
  ...rest
9293
9510
  }) {
9294
9511
  const __twcStyles = useScopedStyles("twc-stepper-styles", STEPPER_CSS);
9295
- const [activeInternal, setActiveInternal] = React23__namespace.default.useState(defaultActive);
9512
+ const [activeInternal, setActiveInternal] = React24__namespace.default.useState(defaultActive);
9296
9513
  const active = activeProp !== void 0 ? activeProp : activeInternal;
9297
9514
  const handleStep = (i) => {
9298
9515
  if (activeProp === void 0) setActiveInternal(i);
@@ -9304,11 +9521,12 @@ function Stepper({
9304
9521
  if (i === active) return "active";
9305
9522
  return "upcoming";
9306
9523
  };
9307
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-stepper ${className}`, "data-orientation": orientation, "data-tone": tone, ...rest, children: [
9524
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-stepper ${className}`, "data-orientation": orientation, "data-tone": tone, role: "group", "aria-label": "Progress", ...rest, children: [
9308
9525
  __twcStyles,
9309
9526
  steps.map((step, i) => {
9310
9527
  const state = stateOf(i, step);
9311
9528
  const last = i === steps.length - 1;
9529
+ const srText = `Step ${i + 1} of ${steps.length}${state === "complete" ? ", completed" : state === "error" ? ", error" : state === "active" ? ", current" : ", upcoming"}. `;
9312
9530
  const isClickable = clickable && i <= active;
9313
9531
  const interactive = isClickable ? {
9314
9532
  role: "button",
@@ -9330,8 +9548,10 @@ function Stepper({
9330
9548
  "data-state": state,
9331
9549
  "data-clickable": isClickable || void 0,
9332
9550
  "aria-current": state === "active" ? "step" : void 0,
9551
+ "aria-invalid": state === "error" ? "true" : void 0,
9333
9552
  ...interactive,
9334
9553
  children: [
9554
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-step__sr", children: srText }),
9335
9555
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-step__col", children: [
9336
9556
  indicator,
9337
9557
  !last ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-step__connector" }) : null
@@ -9352,8 +9572,10 @@ function Stepper({
9352
9572
  "data-state": state,
9353
9573
  "data-clickable": isClickable || void 0,
9354
9574
  "aria-current": state === "active" ? "step" : void 0,
9575
+ "aria-invalid": state === "error" ? "true" : void 0,
9355
9576
  ...interactive,
9356
9577
  children: [
9578
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-step__sr", children: srText }),
9357
9579
  indicator,
9358
9580
  !last ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-step__connector" }) : null,
9359
9581
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-step__body", children: [
@@ -9419,7 +9641,7 @@ function Switch({
9419
9641
  .twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
9420
9642
  .twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
9421
9643
  `);
9422
- const autoId = React23__namespace.default.useId();
9644
+ const autoId = React24__namespace.default.useId();
9423
9645
  const fieldId = id || autoId;
9424
9646
  const errId = `${fieldId}-error`;
9425
9647
  const invalid = Boolean(error);
@@ -9503,14 +9725,14 @@ function Table({
9503
9725
  ...rest
9504
9726
  }) {
9505
9727
  const __twcStyles = useScopedStyles("twc-table-styles", TABLE_CSS);
9506
- const cols = React23__namespace.default.useMemo(
9728
+ const cols = React24__namespace.default.useMemo(
9507
9729
  () => (columns || []).map((c) => ({ ...c, header: c.headerName, render: c.renderCell })),
9508
9730
  [columns]
9509
9731
  );
9510
9732
  const dataRows = rowsProp || [];
9511
- const [internalSort, setInternalSort] = React23__namespace.default.useState(defaultSort || { field: null, dir: "asc" });
9733
+ const [internalSort, setInternalSort] = React24__namespace.default.useState(defaultSort || { field: null, dir: "asc" });
9512
9734
  const sort = (sortProp !== void 0 ? sortProp : internalSort) || { field: null, dir: "asc" };
9513
- const rows = React23__namespace.default.useMemo(() => {
9735
+ const rows = React24__namespace.default.useMemo(() => {
9514
9736
  if (!sortable || !sort.field) return dataRows;
9515
9737
  const col = cols.find((c) => c.field === sort.field);
9516
9738
  if (!col) return dataRows;
@@ -9602,6 +9824,13 @@ var TABS_CSS = `
9602
9824
  .twc-tabs[data-variant="pill"] .twc-tabs__indicator {
9603
9825
  top: 4px; bottom: 4px; height: auto; background: var(--color-surface); box-shadow: var(--shadow-sm); border-radius: var(--radius-md);
9604
9826
  }
9827
+ .twc-tab[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; pointer-events: none; }
9828
+ /* Horizontal tablist scrolls when tabs overflow (vertical orientation untouched). Making
9829
+ overflow-x non-visible makes overflow-y compute to auto, which would clip the bottom:-1px
9830
+ indicator \u2014 so pin the horizontal indicator to bottom:0 (the list border-bottom is the baseline). */
9831
+ .twc-tabs:not([data-orientation="vertical"]) .twc-tabs__list { overflow-x: auto; scrollbar-width: none; }
9832
+ .twc-tabs:not([data-orientation="vertical"]) .twc-tabs__list::-webkit-scrollbar { display: none; }
9833
+ .twc-tabs:not([data-orientation="vertical"]) .twc-tabs__indicator { bottom: 0; }
9605
9834
  .twc-tabs__panel { padding-top: var(--space-4); }
9606
9835
 
9607
9836
  /* Vertical orientation */
@@ -9636,24 +9865,27 @@ function Tabs({
9636
9865
  }) {
9637
9866
  const vertical = orientation === "vertical";
9638
9867
  const __twcStyles = useScopedStyles("twc-tabs-styles", TABS_CSS);
9639
- const [internal, setInternal] = React23__namespace.default.useState(defaultValue ?? items[0]?.value);
9868
+ const [internal, setInternal] = React24__namespace.default.useState(defaultValue ?? items[0]?.value);
9640
9869
  const active = value ?? internal;
9641
- const listRef = React23__namespace.default.useRef(null);
9642
- const [ind, setInd] = React23__namespace.default.useState({ left: 0, width: 0, top: 0, height: 0 });
9643
- const baseId = React23__namespace.default.useId();
9870
+ const listRef = React24__namespace.default.useRef(null);
9871
+ const [ind, setInd] = React24__namespace.default.useState({ left: 0, width: 0, top: 0, height: 0 });
9872
+ const baseId = React24__namespace.default.useId();
9644
9873
  const tabIdAt = (i) => `${baseId}-tab-${i}`;
9645
9874
  const panelId = `${baseId}-panel`;
9646
9875
  const activeIndex = items.findIndex((it) => it.value === active);
9647
- const updateIndicator = React23__namespace.default.useCallback(() => {
9876
+ const updateIndicator = React24__namespace.default.useCallback(() => {
9648
9877
  const list = listRef.current;
9649
9878
  if (!list) return;
9650
9879
  const el = list.querySelector('[data-active="true"]');
9651
- if (el) setInd({ left: el.offsetLeft, width: el.offsetWidth, top: el.offsetTop, height: el.offsetHeight });
9652
- }, []);
9653
- React23__namespace.default.useEffect(() => {
9880
+ if (el) {
9881
+ setInd({ left: el.offsetLeft, width: el.offsetWidth, top: el.offsetTop, height: el.offsetHeight });
9882
+ if (!vertical) el.scrollIntoView?.({ inline: "nearest", block: "nearest" });
9883
+ }
9884
+ }, [vertical]);
9885
+ React24__namespace.default.useEffect(() => {
9654
9886
  updateIndicator();
9655
9887
  }, [active, updateIndicator, items, orientation]);
9656
- React23__namespace.default.useEffect(() => {
9888
+ React24__namespace.default.useEffect(() => {
9657
9889
  const r = () => updateIndicator();
9658
9890
  window.addEventListener("resize", r);
9659
9891
  if (typeof document !== "undefined" && document.fonts && document.fonts.ready) {
@@ -9674,20 +9906,32 @@ function Tabs({
9674
9906
  const keys = [prevKey, nextKey, "Home", "End"];
9675
9907
  if (!keys.includes(e.key)) return;
9676
9908
  const n = items.length;
9677
- if (!n) return;
9909
+ if (!n || items.every((it2) => it2.disabled)) return;
9678
9910
  e.preventDefault();
9679
9911
  let i = activeIndex < 0 ? 0 : activeIndex;
9680
- if (e.key === "Home") i = 0;
9681
- else if (e.key === "End") i = n - 1;
9682
- else {
9912
+ if (e.key === "Home") i = items.findIndex((it2) => !it2.disabled);
9913
+ else if (e.key === "End") {
9914
+ for (let k = n - 1; k >= 0; k--) {
9915
+ if (!items[k].disabled) {
9916
+ i = k;
9917
+ break;
9918
+ }
9919
+ }
9920
+ } else {
9683
9921
  const dir = e.key === nextKey ? 1 : -1;
9684
- i = (i + dir + n) % n;
9922
+ let guard = 0;
9923
+ do {
9924
+ i = (i + dir + n) % n;
9925
+ } while (items[i]?.disabled && ++guard <= n);
9685
9926
  }
9686
9927
  const it = items[i];
9687
- if (!it) return;
9928
+ if (!it || it.disabled) return;
9688
9929
  select(it.value);
9689
9930
  const btns = listRef.current?.querySelectorAll('[role="tab"]');
9690
- if (btns && btns[i]) btns[i].focus();
9931
+ if (btns && btns[i]) {
9932
+ btns[i].focus();
9933
+ btns[i].scrollIntoView?.({ inline: "nearest", block: "nearest" });
9934
+ }
9691
9935
  }
9692
9936
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-tabs ${className}`, "data-variant": variant, "data-tone": tone, "data-orientation": orientation, ...rest, children: [
9693
9937
  __twcStyles,
@@ -9700,10 +9944,14 @@ function Tabs({
9700
9944
  className: "twc-tab",
9701
9945
  role: "tab",
9702
9946
  "aria-selected": it.value === active,
9947
+ "aria-disabled": it.disabled || void 0,
9948
+ disabled: it.disabled || void 0,
9703
9949
  "aria-controls": it.value === active && panelRendered ? panelId : void 0,
9704
- tabIndex: it.value === active ? 0 : -1,
9950
+ tabIndex: it.value === active && !it.disabled ? 0 : -1,
9705
9951
  "data-active": it.value === active || void 0,
9706
- onClick: () => select(it.value),
9952
+ onClick: () => {
9953
+ if (!it.disabled) select(it.value);
9954
+ },
9707
9955
  children: [
9708
9956
  it.icon,
9709
9957
  it.label,
@@ -9766,10 +10014,12 @@ function Tag({
9766
10014
  leftIcon,
9767
10015
  tone = "neutral",
9768
10016
  variant = "soft",
10017
+ removeLabel,
9769
10018
  className = "",
9770
10019
  ...rest
9771
10020
  }) {
9772
10021
  const __twcStyles = useScopedStyles("twc-tag-styles", TAG_CSS);
10022
+ const _removeLabel = removeLabel ?? (typeof children === "string" ? `Remove ${children}` : "Remove");
9773
10023
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `twc-tag ${className}`, "data-tone": tone, "data-variant": variant, "data-no-remove": !onRemove || void 0, ...rest, children: [
9774
10024
  __twcStyles,
9775
10025
  leftIcon,
@@ -9777,7 +10027,7 @@ function Tag({
9777
10027
  onRemove ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-tag__remove", onClick: (e) => {
9778
10028
  e.stopPropagation();
9779
10029
  onRemove(e);
9780
- }, "aria-label": "Remove", type: "button", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
10030
+ }, "aria-label": _removeLabel, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
9781
10031
  ] });
9782
10032
  }
9783
10033
  function Textarea({
@@ -9823,7 +10073,7 @@ function Textarea({
9823
10073
  .twc-textarea__el[aria-invalid="true"] { border-color: var(--color-danger); }
9824
10074
  .twc-textarea__el:disabled { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
9825
10075
  `);
9826
- const autoId = React23__namespace.default.useId();
10076
+ const autoId = React24__namespace.default.useId();
9827
10077
  const fieldId = id || autoId;
9828
10078
  const descId = `${fieldId}-desc`;
9829
10079
  const invalid = Boolean(error);
@@ -9961,19 +10211,19 @@ function Toast({
9961
10211
  }) {
9962
10212
  const resolvedTone = tone === "neutral" ? "default" : tone;
9963
10213
  const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
9964
- const onCloseRef = React23__namespace.default.useRef(onClose);
9965
- React23__namespace.default.useEffect(() => {
10214
+ const onCloseRef = React24__namespace.default.useRef(onClose);
10215
+ React24__namespace.default.useEffect(() => {
9966
10216
  onCloseRef.current = onClose;
9967
10217
  }, [onClose]);
9968
- const timer = React23__namespace.default.useRef();
9969
- const stop = React23__namespace.default.useCallback(() => clearTimeout(timer.current), []);
9970
- const start = React23__namespace.default.useCallback(() => {
10218
+ const timer = React24__namespace.default.useRef();
10219
+ const stop = React24__namespace.default.useCallback(() => clearTimeout(timer.current), []);
10220
+ const start = React24__namespace.default.useCallback(() => {
9971
10221
  stop();
9972
10222
  if (duration && duration !== Infinity && onCloseRef.current) {
9973
10223
  timer.current = setTimeout(() => onCloseRef.current && onCloseRef.current(), duration);
9974
10224
  }
9975
10225
  }, [duration, stop]);
9976
- React23__namespace.default.useEffect(() => {
10226
+ React24__namespace.default.useEffect(() => {
9977
10227
  start();
9978
10228
  return stop;
9979
10229
  }, [start, stop]);
@@ -10017,30 +10267,30 @@ function Toast({
10017
10267
  }
10018
10268
  function ToastViewport({ children, limit, className = "", ...rest }) {
10019
10269
  const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
10020
- const shown = limit && limit > 0 ? React23__namespace.default.Children.toArray(children).slice(-limit) : children;
10270
+ const shown = limit && limit > 0 ? React24__namespace.default.Children.toArray(children).slice(-limit) : children;
10021
10271
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-toast-viewport ${className}`, ...rest, children: [
10022
10272
  __twcStyles,
10023
10273
  shown
10024
10274
  ] });
10025
10275
  }
10026
- var ToastContext = React23__namespace.default.createContext(null);
10276
+ var ToastContext = React24__namespace.default.createContext(null);
10027
10277
  function useToast() {
10028
- const ctx = React23__namespace.default.useContext(ToastContext);
10278
+ const ctx = React24__namespace.default.useContext(ToastContext);
10029
10279
  if (!ctx) throw new Error("useToast must be used within a <ToastProvider>.");
10030
10280
  return ctx;
10031
10281
  }
10032
10282
  function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps }) {
10033
- const [toasts, setToasts] = React23__namespace.default.useState([]);
10034
- const idRef = React23__namespace.default.useRef(0);
10035
- const limitRef = React23__namespace.default.useRef(limit);
10036
- React23__namespace.default.useEffect(() => {
10283
+ const [toasts, setToasts] = React24__namespace.default.useState([]);
10284
+ const idRef = React24__namespace.default.useRef(0);
10285
+ const limitRef = React24__namespace.default.useRef(limit);
10286
+ React24__namespace.default.useEffect(() => {
10037
10287
  limitRef.current = limit;
10038
10288
  }, [limit]);
10039
- const dismiss = React23__namespace.default.useCallback((id) => {
10289
+ const dismiss = React24__namespace.default.useCallback((id) => {
10040
10290
  setToasts((s) => s.filter((t) => t.id !== id));
10041
10291
  }, []);
10042
- const clear = React23__namespace.default.useCallback(() => setToasts([]), []);
10043
- const api = React23__namespace.default.useMemo(() => {
10292
+ const clear = React24__namespace.default.useCallback(() => setToasts([]), []);
10293
+ const api = React24__namespace.default.useMemo(() => {
10044
10294
  const push = (opts) => {
10045
10295
  const id = idRef.current += 1;
10046
10296
  const next = typeof opts === "string" ? { title: opts } : opts && typeof opts === "object" ? opts : {};
@@ -10061,7 +10311,7 @@ function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps
10061
10311
  toast.show = withTone("default");
10062
10312
  return { toast, dismiss, clear };
10063
10313
  }, [dismiss, clear]);
10064
- const value = React23__namespace.default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
10314
+ const value = React24__namespace.default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
10065
10315
  return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value, children: [
10066
10316
  children,
10067
10317
  /* @__PURE__ */ jsxRuntime.jsx(ToastViewport, { limit, ...viewportProps, children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -10101,7 +10351,7 @@ var TREE_CSS = `
10101
10351
  .twc-tree__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
10102
10352
  .twc-tree__badge { flex: none; font-size: 11px; color: var(--color-text-subtle); }
10103
10353
  `;
10104
- function Node({ node, depth, expanded, selectedId, tabbableId, rowRefs, onToggle, onSelect, onRowFocus }) {
10354
+ function Node({ node, depth, posInSet, setSize, expanded, selectedId, tabbableId, rowRefs, onToggle, onSelect, onRowFocus }) {
10105
10355
  const hasChildren = Array.isArray(node.children) && node.children.length > 0;
10106
10356
  const open = expanded.has(node.id);
10107
10357
  return /* @__PURE__ */ jsxRuntime.jsxs("li", { role: "none", children: [
@@ -10112,6 +10362,8 @@ function Node({ node, depth, expanded, selectedId, tabbableId, rowRefs, onToggle
10112
10362
  className: "twc-tree__row",
10113
10363
  role: "treeitem",
10114
10364
  "aria-level": depth + 1,
10365
+ "aria-posinset": posInSet,
10366
+ "aria-setsize": setSize,
10115
10367
  "aria-selected": selectedId === node.id,
10116
10368
  "data-selected": selectedId === node.id || void 0,
10117
10369
  "data-tree-id": node.id,
@@ -10135,11 +10387,13 @@ function Node({ node, depth, expanded, selectedId, tabbableId, rowRefs, onToggle
10135
10387
  ]
10136
10388
  }
10137
10389
  ),
10138
- hasChildren && open ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "twc-tree__group twc-tree__group--child", role: "group", children: node.children.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
10390
+ hasChildren && open ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "twc-tree__group twc-tree__group--child", role: "group", children: node.children.map((c, i) => /* @__PURE__ */ jsxRuntime.jsx(
10139
10391
  Node,
10140
10392
  {
10141
10393
  node: c,
10142
10394
  depth: depth + 1,
10395
+ posInSet: i + 1,
10396
+ setSize: node.children.length,
10143
10397
  expanded,
10144
10398
  selectedId,
10145
10399
  tabbableId,
@@ -10165,12 +10419,13 @@ function TreeView({
10165
10419
  }) {
10166
10420
  const nodes = items;
10167
10421
  const __twcStyles = useScopedStyles("twc-tree-styles", TREE_CSS);
10168
- const [expInternal, setExpInternal] = React23__namespace.default.useState(() => new Set(defaultExpanded));
10422
+ const [expInternal, setExpInternal] = React24__namespace.default.useState(() => new Set(defaultExpanded));
10169
10423
  const expanded = expandedProp !== void 0 ? new Set(expandedProp) : expInternal;
10170
- const [selInternal, setSelInternal] = React23__namespace.default.useState(defaultSelectedId);
10424
+ const [selInternal, setSelInternal] = React24__namespace.default.useState(defaultSelectedId);
10171
10425
  const selectedId = selectedProp !== void 0 ? selectedProp : selInternal;
10172
- const [focusId, setFocusId] = React23__namespace.default.useState(null);
10173
- const rowRefs = React23__namespace.default.useRef(/* @__PURE__ */ new Map());
10426
+ const [focusId, setFocusId] = React24__namespace.default.useState(null);
10427
+ const rowRefs = React24__namespace.default.useRef(/* @__PURE__ */ new Map());
10428
+ const taRef = React24__namespace.default.useRef({ str: "", t: 0 });
10174
10429
  const toggle = (id) => {
10175
10430
  const n = new Set(expanded);
10176
10431
  n.has(id) ? n.delete(id) : n.add(id);
@@ -10184,10 +10439,12 @@ function TreeView({
10184
10439
  const visible = [];
10185
10440
  const parentOf = /* @__PURE__ */ new Map();
10186
10441
  const hasKids = /* @__PURE__ */ new Map();
10442
+ const labelText = /* @__PURE__ */ new Map();
10187
10443
  const walk = (nodes2, parentId) => {
10188
10444
  for (const n of nodes2) {
10189
10445
  visible.push(n.id);
10190
10446
  parentOf.set(n.id, parentId);
10447
+ if (typeof n.label === "string") labelText.set(n.id, n.label);
10191
10448
  const kids = Array.isArray(n.children) && n.children.length > 0;
10192
10449
  hasKids.set(n.id, kids);
10193
10450
  if (kids && expanded.has(n.id)) walk(n.children, n.id);
@@ -10225,17 +10482,36 @@ function TreeView({
10225
10482
  return;
10226
10483
  }
10227
10484
  next = parentOf.get(id);
10485
+ } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && /\S/.test(e.key)) {
10486
+ const now = Date.now();
10487
+ taRef.current.str = now - taRef.current.t > 500 ? e.key : taRef.current.str + e.key;
10488
+ taRef.current.t = now;
10489
+ const q = taRef.current.str.toLowerCase();
10490
+ const single = q.length > 1 && [...q].every((c) => c === q[0]);
10491
+ const needle = single ? q[0] : q;
10492
+ for (let k = 1; k <= visible.length; k++) {
10493
+ const cand = visible[(i + k) % visible.length];
10494
+ const lbl = labelText.get(cand);
10495
+ if (lbl && lbl.toLowerCase().startsWith(needle)) {
10496
+ e.preventDefault();
10497
+ focusRow(cand);
10498
+ break;
10499
+ }
10500
+ }
10501
+ return;
10228
10502
  } else return;
10229
10503
  e.preventDefault();
10230
10504
  if (next != null) focusRow(next);
10231
10505
  };
10232
10506
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-tree ${className}`, role: "tree", onKeyDown, ...rest, children: [
10233
10507
  __twcStyles,
10234
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "twc-tree__group", role: "none", children: nodes.map((n) => /* @__PURE__ */ jsxRuntime.jsx(
10508
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "twc-tree__group", role: "none", children: nodes.map((n, i) => /* @__PURE__ */ jsxRuntime.jsx(
10235
10509
  Node,
10236
10510
  {
10237
10511
  node: n,
10238
10512
  depth: 0,
10513
+ posInSet: i + 1,
10514
+ setSize: nodes.length,
10239
10515
  expanded,
10240
10516
  selectedId,
10241
10517
  tabbableId,
@@ -10249,12 +10525,22 @@ function TreeView({
10249
10525
  ] });
10250
10526
  }
10251
10527
  var SHELL_CSS = `
10252
- .twc-shell { display: flex; overflow: hidden; background: var(--color-bg); color: var(--color-text); font-family: var(--font-sans); }
10528
+ .twc-shell { position: relative; display: flex; overflow: hidden; background: var(--color-bg); color: var(--color-text); font-family: var(--font-sans); }
10529
+ .twc-shell__skip { position: absolute; inset-inline-start: var(--space-3); inset-block-start: var(--space-3); z-index: 100;
10530
+ padding: var(--space-2) var(--space-4); background: var(--color-surface); color: var(--color-text);
10531
+ border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md); font-family: var(--font-sans);
10532
+ transform: translateY(-200%); transition: transform var(--duration-fast) var(--ease-standard); }
10533
+ .twc-shell__skip:focus-visible { transform: translateY(0); outline: none; box-shadow: var(--ring); }
10253
10534
  .twc-shell__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; height: 100%; }
10254
10535
  .twc-shell__header { flex: none; display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
10255
10536
  min-height: 60px; padding-inline: var(--space-5); border-bottom: var(--border-thin) solid var(--color-border); background: var(--color-surface); }
10256
10537
  .twc-shell__content { flex: 1 1 auto; min-height: 0; overflow: auto; }
10257
10538
  .twc-shell__content[data-padded="true"] { padding: var(--space-6) var(--space-5); }
10539
+ /* Mobile: stack the shell so the sidebar (rendered as an off-canvas overlay) no
10540
+ longer reserves a column \u2014 the main content spans the full width. */
10541
+ @media (max-width: 720px) {
10542
+ .twc-shell { flex-direction: column; }
10543
+ }
10258
10544
  `;
10259
10545
  function AppShell({
10260
10546
  sidebar,
@@ -10262,17 +10548,27 @@ function AppShell({
10262
10548
  children,
10263
10549
  height = "100dvh",
10264
10550
  padded = true,
10551
+ mainId = "twc-main",
10552
+ skipLinkLabel = "Skip to content",
10553
+ sidebarOpen,
10554
+ onSidebarOpenChange,
10265
10555
  className = "",
10266
10556
  style,
10267
10557
  ...rest
10268
10558
  }) {
10269
10559
  const __twcStyles = useScopedStyles("twc-shell-styles", SHELL_CSS);
10560
+ const wiredSidebar = React24__namespace.default.isValidElement(sidebar) && (sidebarOpen !== void 0 || onSidebarOpenChange !== void 0) ? React24__namespace.default.cloneElement(sidebar, {
10561
+ overlay: sidebar.props.overlay !== void 0 ? sidebar.props.overlay : true,
10562
+ open: sidebar.props.open !== void 0 ? sidebar.props.open : sidebarOpen,
10563
+ onOpenChange: sidebar.props.onOpenChange !== void 0 ? sidebar.props.onOpenChange : onSidebarOpenChange
10564
+ }) : sidebar;
10270
10565
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-shell ${className}`.trim(), style: { height, ...style }, ...rest, children: [
10271
10566
  __twcStyles,
10272
- sidebar,
10567
+ skipLinkLabel != null && skipLinkLabel !== false ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "twc-shell__skip", href: `#${mainId}`, children: skipLinkLabel }) : null,
10568
+ wiredSidebar,
10273
10569
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-shell__main", children: [
10274
10570
  header != null ? /* @__PURE__ */ jsxRuntime.jsx("header", { className: "twc-shell__header", children: header }) : null,
10275
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "twc-shell__content", "data-padded": padded ? "true" : void 0, children })
10571
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "twc-shell__content", id: mainId, tabIndex: -1, "data-padded": padded ? "true" : void 0, children })
10276
10572
  ] })
10277
10573
  ] });
10278
10574
  }
@@ -10291,7 +10587,7 @@ function bgValue(bg) {
10291
10587
  if (BG[bg]) return `var(${BG[bg]})`;
10292
10588
  return String(bg).startsWith("--") ? `var(${bg})` : bg;
10293
10589
  }
10294
- function safeHref4(url) {
10590
+ function safeHref5(url) {
10295
10591
  if (url == null) return void 0;
10296
10592
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10297
10593
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10336,11 +10632,11 @@ function Box({
10336
10632
  boxShadow: shadow ? `var(--shadow-${shadow})` : void 0,
10337
10633
  ...style
10338
10634
  };
10339
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref4(rest.href);
10635
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref5(rest.href);
10340
10636
  return /* @__PURE__ */ jsxRuntime.jsx(Tag2, { className: `twc-box ${className}`.trim(), style: s, ...rest, children });
10341
10637
  }
10342
10638
  var SIZES = { sm: 640, md: 768, lg: 1024, xl: 1280, full: "100%" };
10343
- function safeHref5(url) {
10639
+ function safeHref6(url) {
10344
10640
  if (url == null) return void 0;
10345
10641
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10346
10642
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10355,7 +10651,7 @@ function Container({
10355
10651
  ...rest
10356
10652
  }) {
10357
10653
  const max = SIZES[size] ?? size;
10358
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref5(rest.href);
10654
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref6(rest.href);
10359
10655
  return /* @__PURE__ */ jsxRuntime.jsx(
10360
10656
  Tag2,
10361
10657
  {
@@ -10380,7 +10676,8 @@ function space(v) {
10380
10676
  function len(v) {
10381
10677
  return typeof v === "number" ? `${v}px` : v;
10382
10678
  }
10383
- function safeHref6(url) {
10679
+ var BP = { sm: 640, md: 768, lg: 1024, xl: 1280 };
10680
+ function safeHref7(url) {
10384
10681
  if (url == null) return void 0;
10385
10682
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10386
10683
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10390,29 +10687,54 @@ function Grid({
10390
10687
  columns,
10391
10688
  minChildWidth,
10392
10689
  gap = 4,
10690
+ rowGap,
10691
+ columnGap,
10393
10692
  align,
10394
10693
  justify,
10694
+ alignContent,
10695
+ justifyContent,
10395
10696
  className = "",
10396
10697
  style,
10397
10698
  children,
10398
10699
  ...rest
10399
10700
  }) {
10400
- const templateColumns = minChildWidth ? `repeat(auto-fill, minmax(min(${len(minChildWidth)}, 100%), 1fr))` : `repeat(${columns || 1}, minmax(0, 1fr))`;
10401
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref6(rest.href);
10402
- return /* @__PURE__ */ jsxRuntime.jsx(
10701
+ const responsive = columns != null && typeof columns === "object";
10702
+ const uid = React24__namespace.default.useId();
10703
+ const gridId = responsive ? `g${uid.replace(/[^a-zA-Z0-9]/g, "")}` : null;
10704
+ let css = "";
10705
+ if (responsive) {
10706
+ const base = columns.base ?? 1;
10707
+ const sel = `[data-twc-grid-id="${gridId}"]`;
10708
+ css = `${sel} { --twc-grid-cols: ${base}; }`;
10709
+ for (const bp of ["sm", "md", "lg", "xl"]) {
10710
+ if (columns[bp] != null) css += `
10711
+ @media (min-width: ${BP[bp]}px) { ${sel} { --twc-grid-cols: ${columns[bp]}; } }`;
10712
+ }
10713
+ }
10714
+ const __twcStyles = useScopedStyles(gridId ? `twc-grid-${gridId}` : "twc-grid", css);
10715
+ 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))`;
10716
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref7(rest.href);
10717
+ return /* @__PURE__ */ jsxRuntime.jsxs(
10403
10718
  Tag2,
10404
10719
  {
10405
10720
  className: `twc-grid ${className}`.trim(),
10721
+ "data-twc-grid-id": gridId || void 0,
10406
10722
  style: {
10407
10723
  display: "grid",
10408
10724
  gridTemplateColumns: templateColumns,
10409
- gap: space(gap),
10725
+ rowGap: space(rowGap ?? gap),
10726
+ columnGap: space(columnGap ?? gap),
10410
10727
  alignItems: align,
10411
10728
  justifyItems: justify,
10729
+ alignContent,
10730
+ justifyContent,
10412
10731
  ...style
10413
10732
  },
10414
10733
  ...rest,
10415
- children
10734
+ children: [
10735
+ responsive ? __twcStyles : null,
10736
+ children
10737
+ ]
10416
10738
  }
10417
10739
  );
10418
10740
  }
@@ -10421,7 +10743,7 @@ function space2(v) {
10421
10743
  if (typeof v === "number") return `var(--space-${String(v).replace(".", "-")})`;
10422
10744
  return v;
10423
10745
  }
10424
- function safeHref7(url) {
10746
+ function safeHref8(url) {
10425
10747
  if (url == null) return void 0;
10426
10748
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10427
10749
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10434,12 +10756,21 @@ function Stack({
10434
10756
  justify,
10435
10757
  wrap = false,
10436
10758
  inline = false,
10759
+ p,
10760
+ px,
10761
+ py,
10762
+ pt,
10763
+ pr,
10764
+ pb,
10765
+ pl,
10766
+ divider,
10437
10767
  className = "",
10438
10768
  style,
10439
10769
  children,
10440
10770
  ...rest
10441
10771
  }) {
10442
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref7(rest.href);
10772
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
10773
+ const kids = divider != null ? React24__namespace.default.Children.toArray(children).flatMap((child, i, arr) => i < arr.length - 1 ? [child, /* @__PURE__ */ jsxRuntime.jsx(React24__namespace.default.Fragment, { children: divider }, `twc-stack-div-${i}`)] : [child]) : children;
10443
10774
  return /* @__PURE__ */ jsxRuntime.jsx(
10444
10775
  Tag2,
10445
10776
  {
@@ -10451,11 +10782,15 @@ function Stack({
10451
10782
  alignItems: align,
10452
10783
  justifyContent: justify,
10453
10784
  flexWrap: wrap ? "wrap" : void 0,
10785
+ paddingTop: space2(pt ?? py ?? p),
10786
+ paddingRight: space2(pr ?? px ?? p),
10787
+ paddingBottom: space2(pb ?? py ?? p),
10788
+ paddingLeft: space2(pl ?? px ?? p),
10454
10789
  minWidth: 0,
10455
10790
  ...style
10456
10791
  },
10457
10792
  ...rest,
10458
- children
10793
+ children: kids
10459
10794
  }
10460
10795
  );
10461
10796
  }
@@ -10467,22 +10802,64 @@ var CODE_CSS = `
10467
10802
  border: var(--border-thin) solid var(--color-border);
10468
10803
  white-space: normal; overflow-wrap: anywhere; word-break: break-word;
10469
10804
  }
10805
+ .twc-code[data-block="true"] {
10806
+ display: block; position: relative; white-space: pre; overflow-x: auto;
10807
+ padding: 12px 14px; padding-inline-end: 40px; line-height: 1.6; font-size: 0.8125em;
10808
+ overflow-wrap: normal; word-break: normal;
10809
+ }
10810
+ .twc-code__copy {
10811
+ position: absolute; top: 6px; inset-inline-end: 6px; display: inline-grid; place-items: center;
10812
+ width: 26px; height: 26px; border: none; border-radius: var(--radius-sm);
10813
+ background: var(--color-surface); color: var(--color-text-subtle); cursor: pointer;
10814
+ transition: color var(--duration-fast), background-color var(--duration-fast);
10815
+ }
10816
+ .twc-code__copy:hover { color: var(--color-text); }
10817
+ .twc-code__copy:focus-visible { outline: none; box-shadow: var(--ring); }
10818
+ .twc-code__copy svg { width: 15px; height: 15px; display: block; }
10470
10819
  `;
10471
- function safeHref8(url) {
10820
+ function safeHref9(url) {
10472
10821
  if (url == null) return void 0;
10473
10822
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10474
10823
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
10475
10824
  }
10476
- function Code({ as: Tag2 = "code", className = "", children, ...rest }) {
10825
+ function Code({
10826
+ as,
10827
+ block = false,
10828
+ copyable = false,
10829
+ copyLabel = "Copy code",
10830
+ copiedLabel = "Copied",
10831
+ className = "",
10832
+ children,
10833
+ ...rest
10834
+ }) {
10477
10835
  const __twcStyles = useScopedStyles("twc-code-styles", CODE_CSS);
10478
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
10479
- return /* @__PURE__ */ jsxRuntime.jsxs(Tag2, { className: `twc-code ${className}`.trim(), ...rest, children: [
10836
+ const Tag2 = as ?? (block ? "pre" : "code");
10837
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref9(rest.href);
10838
+ const rootRef = React24__namespace.default.useRef(null);
10839
+ const [copied, setCopied] = React24__namespace.default.useState(false);
10840
+ const timerRef = React24__namespace.default.useRef(null);
10841
+ React24__namespace.default.useEffect(() => () => clearTimeout(timerRef.current), []);
10842
+ const doCopy = () => {
10843
+ if (typeof navigator === "undefined" || !navigator.clipboard) return;
10844
+ const text = typeof children === "string" ? children : rootRef.current?.textContent ?? "";
10845
+ navigator.clipboard.writeText(text).then(() => {
10846
+ setCopied(true);
10847
+ clearTimeout(timerRef.current);
10848
+ timerRef.current = setTimeout(() => setCopied(false), 2e3);
10849
+ }).catch(() => {
10850
+ });
10851
+ };
10852
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tag2, { ref: rootRef, className: `twc-code ${className}`.trim(), "data-block": block || void 0, ...rest, children: [
10480
10853
  __twcStyles,
10854
+ copyable ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-code__copy", "aria-label": copied ? copiedLabel : copyLabel, onClick: doCopy, children: copied ? /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m20 6-11 11-5-5" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
10855
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
10856
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
10857
+ ] }) }) : null,
10481
10858
  children
10482
10859
  ] });
10483
10860
  }
10484
10861
  var LEVEL_SIZE = { 1: "4xl", 2: "2xl", 3: "xl", 4: "lg", 5: "base", 6: "sm" };
10485
- function safeHref9(url) {
10862
+ function safeHref10(url) {
10486
10863
  if (url == null) return void 0;
10487
10864
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10488
10865
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10491,15 +10868,18 @@ function Heading({
10491
10868
  as,
10492
10869
  level = 2,
10493
10870
  size,
10871
+ display = false,
10494
10872
  align,
10873
+ truncate,
10874
+ lineClamp,
10495
10875
  className = "",
10496
10876
  style,
10497
10877
  children,
10498
10878
  ...rest
10499
10879
  }) {
10500
10880
  const Tag2 = as || `h${level}`;
10501
- const sz = size || LEVEL_SIZE[level] || "2xl";
10502
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref9(rest.href);
10881
+ const sz = size || (display ? "display" : LEVEL_SIZE[level]) || "2xl";
10882
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref10(rest.href);
10503
10883
  return /* @__PURE__ */ jsxRuntime.jsx(
10504
10884
  Tag2,
10505
10885
  {
@@ -10513,6 +10893,7 @@ function Heading({
10513
10893
  letterSpacing: "-0.02em",
10514
10894
  fontSize: `var(--text-${sz})`,
10515
10895
  textAlign: align,
10896
+ ...lineClamp != null ? { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: lineClamp, overflow: "hidden" } : truncate ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 } : null,
10516
10897
  ...style
10517
10898
  },
10518
10899
  ...rest,
@@ -10531,9 +10912,11 @@ var TONE = {
10531
10912
  success: "--color-success",
10532
10913
  warning: "--color-warning-subtle-fg",
10533
10914
  info: "--color-info-subtle-fg",
10534
- neutral: "--color-text-muted"
10915
+ neutral: "--color-text-muted",
10916
+ // Adopt the surrounding color (e.g. inside a solid Button/Badge/Alert or a link).
10917
+ inherit: "inherit"
10535
10918
  };
10536
- function safeHref10(url) {
10919
+ function safeHref11(url) {
10537
10920
  if (url == null) return void 0;
10538
10921
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
10539
10922
  return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
@@ -10544,12 +10927,15 @@ function Text({
10544
10927
  tone = "default",
10545
10928
  weight,
10546
10929
  align,
10930
+ truncate,
10931
+ lineClamp,
10547
10932
  className = "",
10548
10933
  style,
10549
10934
  children,
10550
10935
  ...rest
10551
10936
  }) {
10552
- if (Tag2 === "a" && rest.href != null) rest.href = safeHref10(rest.href);
10937
+ if (Tag2 === "a" && rest.href != null) rest.href = safeHref11(rest.href);
10938
+ const toneToken = TONE[tone] || TONE.default;
10553
10939
  return /* @__PURE__ */ jsxRuntime.jsx(
10554
10940
  Tag2,
10555
10941
  {
@@ -10559,9 +10945,10 @@ function Text({
10559
10945
  fontFamily: "var(--font-sans)",
10560
10946
  lineHeight: 1.6,
10561
10947
  fontSize: `var(--text-${size})`,
10562
- color: `var(${TONE[tone] || TONE.default})`,
10948
+ color: toneToken.startsWith("--") ? `var(${toneToken})` : toneToken,
10563
10949
  fontWeight: weight ? `var(--font-${weight})` : void 0,
10564
10950
  textAlign: align,
10951
+ ...lineClamp != null ? { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: lineClamp, overflow: "hidden" } : truncate ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 } : null,
10565
10952
  ...style
10566
10953
  },
10567
10954
  ...rest,
@@ -10569,58 +10956,68 @@ function Text({
10569
10956
  }
10570
10957
  );
10571
10958
  }
10572
- var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
10573
- var useIsomorphicLayoutEffect = canUseDOM ? React23__namespace.default.useLayoutEffect : React23__namespace.default.useEffect;
10959
+ var canUseDOM2 = typeof window !== "undefined" && typeof document !== "undefined";
10960
+ var useIsomorphicLayoutEffect = canUseDOM2 ? React24__namespace.default.useLayoutEffect : React24__namespace.default.useEffect;
10574
10961
  function useMounted() {
10575
- const [mounted, setMounted] = React23__namespace.default.useState(false);
10576
- React23__namespace.default.useEffect(() => {
10962
+ const [mounted, setMounted] = React24__namespace.default.useState(false);
10963
+ React24__namespace.default.useEffect(() => {
10577
10964
  setMounted(true);
10578
10965
  }, []);
10579
10966
  return mounted;
10580
10967
  }
10581
10968
  function usePrevious(value) {
10582
- const ref = React23__namespace.default.useRef(void 0);
10583
- React23__namespace.default.useEffect(() => {
10969
+ const ref = React24__namespace.default.useRef(void 0);
10970
+ React24__namespace.default.useEffect(() => {
10584
10971
  ref.current = value;
10585
10972
  }, [value]);
10586
10973
  return ref.current;
10587
10974
  }
10588
10975
  function useToggle(initial = false) {
10589
- const [on, setOn] = React23__namespace.default.useState(initial);
10590
- const toggle = React23__namespace.default.useCallback((next) => {
10976
+ const [on, setOn] = React24__namespace.default.useState(initial);
10977
+ const toggle = React24__namespace.default.useCallback((next) => {
10591
10978
  setOn((prev) => typeof next === "boolean" ? next : !prev);
10592
10979
  }, []);
10593
10980
  return [on, toggle, setOn];
10594
10981
  }
10595
10982
  function useDisclosure(initial = false) {
10596
- const [open, setOpen] = React23__namespace.default.useState(initial);
10597
- const onOpen = React23__namespace.default.useCallback(() => setOpen(true), []);
10598
- const onClose = React23__namespace.default.useCallback(() => setOpen(false), []);
10599
- const onToggle = React23__namespace.default.useCallback(() => setOpen((p) => !p), []);
10983
+ const [open, setOpen] = React24__namespace.default.useState(initial);
10984
+ const onOpen = React24__namespace.default.useCallback(() => setOpen(true), []);
10985
+ const onClose = React24__namespace.default.useCallback(() => setOpen(false), []);
10986
+ const onToggle = React24__namespace.default.useCallback(() => setOpen((p) => !p), []);
10600
10987
  return { open, onOpen, onClose, onToggle, setOpen };
10601
10988
  }
10602
10989
  function useControllableState({ value, defaultValue, onChange } = {}) {
10603
10990
  const isControlled = value !== void 0;
10604
- const [uncontrolled, setUncontrolled] = React23__namespace.default.useState(defaultValue);
10991
+ const [uncontrolled, setUncontrolled] = React24__namespace.default.useState(defaultValue);
10605
10992
  const current = isControlled ? value : uncontrolled;
10606
- const ref = React23__namespace.default.useRef({ current, isControlled, onChange });
10993
+ const ref = React24__namespace.default.useRef({ current, isControlled, onChange });
10607
10994
  useIsomorphicLayoutEffect(() => {
10608
10995
  ref.current = { current, isControlled, onChange };
10609
10996
  });
10610
- const setValue = React23__namespace.default.useCallback((next) => {
10997
+ const wasControlled = React24__namespace.default.useRef(isControlled);
10998
+ React24__namespace.default.useEffect(() => {
10999
+ if (wasControlled.current !== isControlled) {
11000
+ warnOnce(
11001
+ "useControllableState:switch",
11002
+ `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.`
11003
+ );
11004
+ wasControlled.current = isControlled;
11005
+ }
11006
+ });
11007
+ const setValue = React24__namespace.default.useCallback((next) => {
10611
11008
  const { current: cur, isControlled: ctrl, onChange: cb } = ref.current;
10612
11009
  const resolved = typeof next === "function" ? next(cur) : next;
10613
11010
  if (resolved === cur) return;
10614
11011
  if (!ctrl) setUncontrolled(resolved);
10615
11012
  if (cb) cb(resolved);
10616
11013
  }, []);
10617
- return [current, setValue];
11014
+ return [current, setValue, isControlled];
10618
11015
  }
10619
- function useMediaQuery(query) {
10620
- const get = () => canUseDOM ? window.matchMedia(query).matches : false;
10621
- const [matches3, setMatches] = React23__namespace.default.useState(get);
10622
- React23__namespace.default.useEffect(() => {
10623
- if (!canUseDOM) return void 0;
11016
+ function useMediaQuery(query, { defaultValue = false, initializeWithValue = false } = {}) {
11017
+ const get = () => canUseDOM2 ? window.matchMedia(query).matches : defaultValue;
11018
+ const [matches3, setMatches] = React24__namespace.default.useState(initializeWithValue ? get : defaultValue);
11019
+ useIsomorphicLayoutEffect(() => {
11020
+ if (!canUseDOM2) return void 0;
10624
11021
  const mql = window.matchMedia(query);
10625
11022
  const onChange = () => setMatches(mql.matches);
10626
11023
  onChange();
@@ -10633,10 +11030,10 @@ function usePrefersReducedMotion() {
10633
11030
  return useMediaQuery("(prefers-reduced-motion: reduce)");
10634
11031
  }
10635
11032
  function useColorScheme({ storageKey = "twico-theme", attribute = "class", element, disableTransitionsOnChange = true } = {}) {
10636
- const getTarget = () => element || (canUseDOM ? document.documentElement : null);
10637
- const firstApply = React23__namespace.default.useRef(true);
11033
+ const getTarget = () => element || (canUseDOM2 ? document.documentElement : null);
11034
+ const firstApply = React24__namespace.default.useRef(true);
10638
11035
  const read = () => {
10639
- if (!canUseDOM) return "light";
11036
+ if (!canUseDOM2) return "light";
10640
11037
  try {
10641
11038
  const stored = window.localStorage.getItem(storageKey);
10642
11039
  if (stored === "light" || stored === "dark") return stored;
@@ -10644,12 +11041,12 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
10644
11041
  }
10645
11042
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
10646
11043
  };
10647
- const [theme, setThemeState] = React23__namespace.default.useState(read);
10648
- const apply = React23__namespace.default.useCallback(
11044
+ const [theme, setThemeState] = React24__namespace.default.useState(read);
11045
+ const apply = React24__namespace.default.useCallback(
10649
11046
  (t) => {
10650
11047
  const target = getTarget();
10651
11048
  if (!target) return;
10652
- const skip = firstApply.current || !disableTransitionsOnChange || !canUseDOM;
11049
+ const skip = firstApply.current || !disableTransitionsOnChange || !canUseDOM2;
10653
11050
  firstApply.current = false;
10654
11051
  let css;
10655
11052
  if (!skip) {
@@ -10671,26 +11068,26 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
10671
11068
  useIsomorphicLayoutEffect(() => {
10672
11069
  apply(theme);
10673
11070
  }, [theme, apply]);
10674
- const themeRef = React23__namespace.default.useRef(theme);
11071
+ const themeRef = React24__namespace.default.useRef(theme);
10675
11072
  useIsomorphicLayoutEffect(() => {
10676
11073
  themeRef.current = theme;
10677
11074
  }, [theme]);
10678
- const setTheme = React23__namespace.default.useCallback(
11075
+ const setTheme = React24__namespace.default.useCallback(
10679
11076
  (t) => {
10680
11077
  setThemeState(t);
10681
11078
  try {
10682
- if (canUseDOM) window.localStorage.setItem(storageKey, t);
11079
+ if (canUseDOM2) window.localStorage.setItem(storageKey, t);
10683
11080
  } catch (e) {
10684
11081
  }
10685
- if (canUseDOM) window.dispatchEvent(new Event("twico:colorscheme"));
11082
+ if (canUseDOM2) window.dispatchEvent(new Event("twico:colorscheme"));
10686
11083
  },
10687
11084
  [storageKey]
10688
11085
  );
10689
- const toggle = React23__namespace.default.useCallback(() => {
11086
+ const toggle = React24__namespace.default.useCallback(() => {
10690
11087
  setTheme(themeRef.current === "dark" ? "light" : "dark");
10691
11088
  }, [setTheme]);
10692
- React23__namespace.default.useEffect(() => {
10693
- if (!canUseDOM) return void 0;
11089
+ React24__namespace.default.useEffect(() => {
11090
+ if (!canUseDOM2) return void 0;
10694
11091
  const sync = () => setThemeState(read());
10695
11092
  const onStorage = (e) => {
10696
11093
  if (e.key === storageKey) sync();
@@ -10705,15 +11102,15 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
10705
11102
  return { theme, setTheme, toggle, isDark: theme === "dark" };
10706
11103
  }
10707
11104
  function useEventListener(eventName, handler, element, options) {
10708
- const saved = React23__namespace.default.useRef(handler);
11105
+ const saved = React24__namespace.default.useRef(handler);
10709
11106
  useIsomorphicLayoutEffect(() => {
10710
11107
  saved.current = handler;
10711
11108
  }, [handler]);
10712
11109
  const capture = typeof options === "boolean" ? options : options && options.capture;
10713
11110
  const passive = typeof options === "object" && options ? options.passive : void 0;
10714
11111
  const once = typeof options === "object" && options ? options.once : void 0;
10715
- React23__namespace.default.useEffect(() => {
10716
- const target = element && element.current || element || (canUseDOM ? window : null);
11112
+ React24__namespace.default.useEffect(() => {
11113
+ const target = element && element.current || element || (canUseDOM2 ? window : null);
10717
11114
  if (!target || !target.addEventListener) return void 0;
10718
11115
  const opts = typeof options === "boolean" ? options : { capture, passive, once };
10719
11116
  const listener = (e) => saved.current(e);
@@ -10722,12 +11119,12 @@ function useEventListener(eventName, handler, element, options) {
10722
11119
  }, [eventName, element, capture, passive, once]);
10723
11120
  }
10724
11121
  function useClickOutside(ref, handler, events = ["mousedown", "touchstart"]) {
10725
- const saved = React23__namespace.default.useRef(handler);
11122
+ const saved = React24__namespace.default.useRef(handler);
10726
11123
  useIsomorphicLayoutEffect(() => {
10727
11124
  saved.current = handler;
10728
11125
  }, [handler]);
10729
- React23__namespace.default.useEffect(() => {
10730
- if (!canUseDOM) return void 0;
11126
+ React24__namespace.default.useEffect(() => {
11127
+ if (!canUseDOM2) return void 0;
10731
11128
  const listener = (e) => {
10732
11129
  const el = ref && ref.current;
10733
11130
  if (!el || el.contains(e.target)) return;
@@ -10753,7 +11150,7 @@ function useKeyPress(key, handler, options = {}) {
10753
11150
  }
10754
11151
  function useLocalStorage(key, initialValue) {
10755
11152
  const read = () => {
10756
- if (!canUseDOM) return initialValue;
11153
+ if (!canUseDOM2) return initialValue;
10757
11154
  try {
10758
11155
  const item = window.localStorage.getItem(key);
10759
11156
  return item ? JSON.parse(item) : initialValue;
@@ -10761,13 +11158,13 @@ function useLocalStorage(key, initialValue) {
10761
11158
  return initialValue;
10762
11159
  }
10763
11160
  };
10764
- const [stored, setStored] = React23__namespace.default.useState(read);
10765
- const setValue = React23__namespace.default.useCallback(
11161
+ const [stored, setStored] = React24__namespace.default.useState(read);
11162
+ const setValue = React24__namespace.default.useCallback(
10766
11163
  (value) => {
10767
11164
  setStored((prev) => {
10768
11165
  const next = typeof value === "function" ? value(prev) : value;
10769
11166
  try {
10770
- if (canUseDOM) window.localStorage.setItem(key, JSON.stringify(next));
11167
+ if (canUseDOM2) window.localStorage.setItem(key, JSON.stringify(next));
10771
11168
  } catch (e) {
10772
11169
  }
10773
11170
  return next;
@@ -10778,9 +11175,9 @@ function useLocalStorage(key, initialValue) {
10778
11175
  return [stored, setValue];
10779
11176
  }
10780
11177
  function useCopyToClipboard(timeout = 1500) {
10781
- const [copied, setCopied] = React23__namespace.default.useState(false);
10782
- const copy = React23__namespace.default.useCallback(async (text) => {
10783
- if (!canUseDOM || !navigator.clipboard) {
11178
+ const [copied, setCopied] = React24__namespace.default.useState(false);
11179
+ const copy = React24__namespace.default.useCallback(async (text) => {
11180
+ if (!canUseDOM2 || !navigator.clipboard) {
10784
11181
  setCopied(false);
10785
11182
  return false;
10786
11183
  }
@@ -10793,7 +11190,7 @@ function useCopyToClipboard(timeout = 1500) {
10793
11190
  return false;
10794
11191
  }
10795
11192
  }, []);
10796
- React23__namespace.default.useEffect(() => {
11193
+ React24__namespace.default.useEffect(() => {
10797
11194
  if (!copied) return void 0;
10798
11195
  const t = setTimeout(() => setCopied(false), timeout);
10799
11196
  return () => clearTimeout(t);
@@ -10801,23 +11198,23 @@ function useCopyToClipboard(timeout = 1500) {
10801
11198
  return { copied, copy };
10802
11199
  }
10803
11200
  function useDebouncedValue(value, delay = 200) {
10804
- const [debounced, setDebounced] = React23__namespace.default.useState(value);
10805
- React23__namespace.default.useEffect(() => {
11201
+ const [debounced, setDebounced] = React24__namespace.default.useState(value);
11202
+ React24__namespace.default.useEffect(() => {
10806
11203
  const t = setTimeout(() => setDebounced(value), delay);
10807
11204
  return () => clearTimeout(t);
10808
11205
  }, [value, delay]);
10809
11206
  return debounced;
10810
11207
  }
10811
11208
  function useDebouncedCallback(callback, delay = 200) {
10812
- const saved = React23__namespace.default.useRef(callback);
10813
- const timer = React23__namespace.default.useRef(null);
11209
+ const saved = React24__namespace.default.useRef(callback);
11210
+ const timer = React24__namespace.default.useRef(null);
10814
11211
  useIsomorphicLayoutEffect(() => {
10815
11212
  saved.current = callback;
10816
11213
  }, [callback]);
10817
- React23__namespace.default.useEffect(() => () => {
11214
+ React24__namespace.default.useEffect(() => () => {
10818
11215
  if (timer.current) clearTimeout(timer.current);
10819
11216
  }, []);
10820
- return React23__namespace.default.useCallback(
11217
+ return React24__namespace.default.useCallback(
10821
11218
  (...args) => {
10822
11219
  if (timer.current) clearTimeout(timer.current);
10823
11220
  timer.current = setTimeout(() => saved.current(...args), delay);
@@ -10826,34 +11223,34 @@ function useDebouncedCallback(callback, delay = 200) {
10826
11223
  );
10827
11224
  }
10828
11225
  function useInterval(callback, delay) {
10829
- const saved = React23__namespace.default.useRef(callback);
11226
+ const saved = React24__namespace.default.useRef(callback);
10830
11227
  useIsomorphicLayoutEffect(() => {
10831
11228
  saved.current = callback;
10832
11229
  }, [callback]);
10833
- React23__namespace.default.useEffect(() => {
11230
+ React24__namespace.default.useEffect(() => {
10834
11231
  if (delay == null) return void 0;
10835
11232
  const id = setInterval(() => saved.current(), delay);
10836
11233
  return () => clearInterval(id);
10837
11234
  }, [delay]);
10838
11235
  }
10839
11236
  function useTimeout(callback, delay) {
10840
- const saved = React23__namespace.default.useRef(callback);
11237
+ const saved = React24__namespace.default.useRef(callback);
10841
11238
  useIsomorphicLayoutEffect(() => {
10842
11239
  saved.current = callback;
10843
11240
  }, [callback]);
10844
- React23__namespace.default.useEffect(() => {
11241
+ React24__namespace.default.useEffect(() => {
10845
11242
  if (delay == null) return void 0;
10846
11243
  const id = setTimeout(() => saved.current(), delay);
10847
11244
  return () => clearTimeout(id);
10848
11245
  }, [delay]);
10849
11246
  }
10850
11247
  function useWindowSize() {
10851
- const [size, setSize] = React23__namespace.default.useState(() => ({
10852
- width: canUseDOM ? window.innerWidth : 0,
10853
- height: canUseDOM ? window.innerHeight : 0
11248
+ const [size, setSize] = React24__namespace.default.useState(() => ({
11249
+ width: canUseDOM2 ? window.innerWidth : 0,
11250
+ height: canUseDOM2 ? window.innerHeight : 0
10854
11251
  }));
10855
- React23__namespace.default.useEffect(() => {
10856
- if (!canUseDOM) return void 0;
11252
+ React24__namespace.default.useEffect(() => {
11253
+ if (!canUseDOM2) return void 0;
10857
11254
  const onResize = () => setSize({ width: window.innerWidth, height: window.innerHeight });
10858
11255
  onResize();
10859
11256
  window.addEventListener("resize", onResize);
@@ -10862,8 +11259,8 @@ function useWindowSize() {
10862
11259
  return size;
10863
11260
  }
10864
11261
  function useHover(ref) {
10865
- const [hovered, setHovered] = React23__namespace.default.useState(false);
10866
- React23__namespace.default.useEffect(() => {
11262
+ const [hovered, setHovered] = React24__namespace.default.useState(false);
11263
+ React24__namespace.default.useEffect(() => {
10867
11264
  const el = ref && ref.current;
10868
11265
  if (!el) return void 0;
10869
11266
  const on = () => setHovered(true);
@@ -10879,10 +11276,10 @@ function useHover(ref) {
10879
11276
  }
10880
11277
  function useIntersectionObserver(ref, options = {}) {
10881
11278
  const { root = null, rootMargin = "0px", threshold = 0 } = options;
10882
- const [entry, setEntry] = React23__namespace.default.useState(null);
10883
- React23__namespace.default.useEffect(() => {
11279
+ const [entry, setEntry] = React24__namespace.default.useState(null);
11280
+ React24__namespace.default.useEffect(() => {
10884
11281
  const el = ref && ref.current;
10885
- if (!canUseDOM || !el || typeof IntersectionObserver === "undefined") return void 0;
11282
+ if (!canUseDOM2 || !el || typeof IntersectionObserver === "undefined") return void 0;
10886
11283
  const obs = new IntersectionObserver(([e]) => setEntry(e), { root, rootMargin, threshold });
10887
11284
  obs.observe(el);
10888
11285
  return () => obs.disconnect();
@@ -10893,7 +11290,7 @@ var __scrollLockCount = 0;
10893
11290
  var __scrollLockSaved = "";
10894
11291
  function useScrollLock(locked = true) {
10895
11292
  useIsomorphicLayoutEffect(() => {
10896
- if (!canUseDOM || !locked) return void 0;
11293
+ if (!canUseDOM2 || !locked) return void 0;
10897
11294
  if (__scrollLockCount === 0) {
10898
11295
  __scrollLockSaved = document.body.style.overflow;
10899
11296
  document.body.style.overflow = "hidden";
@@ -10908,9 +11305,11 @@ function useScrollLock(locked = true) {
10908
11305
  }, [locked]);
10909
11306
  }
10910
11307
  function useId(prefix = "twc") {
10911
- const raw = React23__namespace.default.useId();
11308
+ const raw = React24__namespace.default.useId();
10912
11309
  return prefix ? `${prefix}-${raw.replace(/:/g, "")}` : raw;
10913
11310
  }
11311
+ var useFocusTrap2 = useFocusTrap;
11312
+ var usePortal2 = usePortal;
10914
11313
 
10915
11314
  exports.Accordion = Accordion;
10916
11315
  exports.Alert = Alert;
@@ -10984,6 +11383,7 @@ exports.useDebouncedCallback = useDebouncedCallback;
10984
11383
  exports.useDebouncedValue = useDebouncedValue;
10985
11384
  exports.useDisclosure = useDisclosure;
10986
11385
  exports.useEventListener = useEventListener;
11386
+ exports.useFocusTrap = useFocusTrap2;
10987
11387
  exports.useHover = useHover;
10988
11388
  exports.useId = useId;
10989
11389
  exports.useIntersectionObserver = useIntersectionObserver;
@@ -10993,6 +11393,7 @@ exports.useKeyPress = useKeyPress;
10993
11393
  exports.useLocalStorage = useLocalStorage;
10994
11394
  exports.useMediaQuery = useMediaQuery;
10995
11395
  exports.useMounted = useMounted;
11396
+ exports.usePortal = usePortal2;
10996
11397
  exports.usePrefersReducedMotion = usePrefersReducedMotion;
10997
11398
  exports.usePrevious = usePrevious;
10998
11399
  exports.useScrollLock = useScrollLock;