twico-ui 1.5.0 → 1.6.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 +1467 -852
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +180 -23
- package/dist/index.d.ts +180 -23
- package/dist/index.mjs +1466 -852
- package/dist/index.mjs.map +1 -1
- package/llms.txt +26 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var React25 = 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
|
|
26
|
+
var React25__namespace = /*#__PURE__*/_interopNamespace(React25);
|
|
27
27
|
|
|
28
28
|
// components/navigation/Accordion.jsx
|
|
29
|
-
var SUPPORTS_STYLE_HOIST = parseInt(String(
|
|
29
|
+
var SUPPORTS_STYLE_HOIST = parseInt(String(React25__namespace.version), 10) >= 19;
|
|
30
30
|
function useScopedStyles(id, css) {
|
|
31
|
-
|
|
31
|
+
React25__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 ?
|
|
39
|
+
return SUPPORTS_STYLE_HOIST ? React25__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);
|
|
@@ -77,10 +77,10 @@ function Accordion({
|
|
|
77
77
|
...rest
|
|
78
78
|
}) {
|
|
79
79
|
const __twcStyles = useScopedStyles("twc-accordion-styles", ACCORDION_CSS);
|
|
80
|
-
const rootRef =
|
|
81
|
-
const [internal, setInternal] =
|
|
80
|
+
const rootRef = React25__namespace.default.useRef(null);
|
|
81
|
+
const [internal, setInternal] = React25__namespace.default.useState(() => new Set(defaultOpen));
|
|
82
82
|
const open = openProp !== void 0 ? new Set(openProp) : internal;
|
|
83
|
-
const baseId =
|
|
83
|
+
const baseId = React25__namespace.default.useId();
|
|
84
84
|
function toggle(val) {
|
|
85
85
|
const item = items.find((x) => x.value === val);
|
|
86
86
|
if (item?.disabled) return;
|
|
@@ -266,7 +266,7 @@ function Avatar({
|
|
|
266
266
|
...rest
|
|
267
267
|
}) {
|
|
268
268
|
const __twcStyles = useScopedStyles("twc-avatar-styles", AVATAR_CSS);
|
|
269
|
-
const [errored, setErrored] =
|
|
269
|
+
const [errored, setErrored] = React25__namespace.default.useState(false);
|
|
270
270
|
const cleanSrc = safeSrc(src);
|
|
271
271
|
const showImg = cleanSrc && !errored;
|
|
272
272
|
const _statusLabel = status ? statusLabel ?? statusLabels?.[status] ?? STATUS_LABELS[status] : void 0;
|
|
@@ -291,7 +291,7 @@ function Avatar({
|
|
|
291
291
|
var MENU_CSS = `
|
|
292
292
|
.twc-menu-wrap { position: relative; display: inline-flex; }
|
|
293
293
|
.twc-menu {
|
|
294
|
-
position: fixed; z-index: var(--z-
|
|
294
|
+
position: fixed; z-index: var(--z-popover); min-width: 200px;
|
|
295
295
|
padding: var(--space-1-5); background: var(--color-surface-raised);
|
|
296
296
|
border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg);
|
|
297
297
|
box-shadow: var(--shadow-lg); font-family: var(--font-sans);
|
|
@@ -344,23 +344,25 @@ function Menu({
|
|
|
344
344
|
...rest
|
|
345
345
|
}) {
|
|
346
346
|
const __twcStyles = useScopedStyles("twc-menu-styles", MENU_CSS);
|
|
347
|
-
const [openState, setOpenState] =
|
|
348
|
-
const [render, setRender] =
|
|
349
|
-
const [pos, setPos] =
|
|
350
|
-
const [active, setActive] =
|
|
351
|
-
const wrapRef =
|
|
352
|
-
const menuRef =
|
|
353
|
-
const
|
|
347
|
+
const [openState, setOpenState] = React25__namespace.default.useState(defaultOpen);
|
|
348
|
+
const [render, setRender] = React25__namespace.default.useState(false);
|
|
349
|
+
const [pos, setPos] = React25__namespace.default.useState(null);
|
|
350
|
+
const [active, setActive] = React25__namespace.default.useState(-1);
|
|
351
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
352
|
+
const menuRef = React25__namespace.default.useRef(null);
|
|
353
|
+
const typeBufRef = React25__namespace.default.useRef("");
|
|
354
|
+
const typeTimerRef = React25__namespace.default.useRef(null);
|
|
355
|
+
const menuId = React25__namespace.default.useId();
|
|
354
356
|
const headerId = `${menuId}-header`;
|
|
355
357
|
const controlled = openProp !== void 0;
|
|
356
358
|
const open = controlled ? !!openProp : openState;
|
|
357
|
-
const openRef =
|
|
359
|
+
const openRef = React25__namespace.default.useRef(open);
|
|
358
360
|
openRef.current = open;
|
|
359
|
-
const controlledRef =
|
|
361
|
+
const controlledRef = React25__namespace.default.useRef(controlled);
|
|
360
362
|
controlledRef.current = controlled;
|
|
361
|
-
const onOpenChangeRef =
|
|
363
|
+
const onOpenChangeRef = React25__namespace.default.useRef(onOpenChange);
|
|
362
364
|
onOpenChangeRef.current = onOpenChange;
|
|
363
|
-
const setOpen =
|
|
365
|
+
const setOpen = React25__namespace.default.useCallback((next) => {
|
|
364
366
|
const value = typeof next === "function" ? next(openRef.current) : next;
|
|
365
367
|
if (value === openRef.current) return;
|
|
366
368
|
if (!controlledRef.current) setOpenState(value);
|
|
@@ -368,7 +370,7 @@ function Menu({
|
|
|
368
370
|
}, []);
|
|
369
371
|
const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
|
|
370
372
|
const interactiveIdx = items.map((it, i) => !it.separator && !it.heading ? i : -1).filter((i) => i >= 0);
|
|
371
|
-
const place =
|
|
373
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
372
374
|
const t = wrapRef.current;
|
|
373
375
|
if (!t) return;
|
|
374
376
|
const r = t.getBoundingClientRect();
|
|
@@ -383,7 +385,7 @@ function Menu({
|
|
|
383
385
|
const avail = (flip ? r.top : vh - r.bottom) - gap - M;
|
|
384
386
|
setPos({ top, bottom, left, width: w, flip, maxHeight: Math.max(120, avail) });
|
|
385
387
|
}, [align, width]);
|
|
386
|
-
|
|
388
|
+
React25__namespace.default.useEffect(() => {
|
|
387
389
|
if (!open) return;
|
|
388
390
|
place();
|
|
389
391
|
const onMove = () => place();
|
|
@@ -401,7 +403,7 @@ function Menu({
|
|
|
401
403
|
document.removeEventListener("mousedown", onDown);
|
|
402
404
|
};
|
|
403
405
|
}, [open, place]);
|
|
404
|
-
|
|
406
|
+
React25__namespace.default.useEffect(() => {
|
|
405
407
|
if (open) {
|
|
406
408
|
setRender(true);
|
|
407
409
|
return;
|
|
@@ -418,7 +420,7 @@ function Menu({
|
|
|
418
420
|
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
419
421
|
e.preventDefault();
|
|
420
422
|
setOpen(true);
|
|
421
|
-
setActive(-1);
|
|
423
|
+
setActive(interactiveIdx[0] ?? -1);
|
|
422
424
|
}
|
|
423
425
|
return;
|
|
424
426
|
}
|
|
@@ -439,6 +441,24 @@ function Menu({
|
|
|
439
441
|
if (next < 0) next = list.length - 1;
|
|
440
442
|
if (next >= list.length) next = 0;
|
|
441
443
|
setActive(list[next]);
|
|
444
|
+
} else if (e.key === "PageDown" || e.key === "PageUp") {
|
|
445
|
+
e.preventDefault();
|
|
446
|
+
const list = interactiveIdx;
|
|
447
|
+
if (list.length) {
|
|
448
|
+
const curPos = Math.max(0, list.indexOf(active));
|
|
449
|
+
const next = Math.min(list.length - 1, Math.max(0, curPos + (e.key === "PageDown" ? 5 : -5)));
|
|
450
|
+
setActive(list[next]);
|
|
451
|
+
}
|
|
452
|
+
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
453
|
+
typeBufRef.current += e.key.toLowerCase();
|
|
454
|
+
clearTimeout(typeTimerRef.current);
|
|
455
|
+
typeTimerRef.current = setTimeout(() => {
|
|
456
|
+
typeBufRef.current = "";
|
|
457
|
+
}, 500);
|
|
458
|
+
const b = typeBufRef.current;
|
|
459
|
+
const labelOf = (i) => String(items[i]?.label ?? "").toLowerCase();
|
|
460
|
+
const hit = interactiveIdx.find((i) => labelOf(i).startsWith(b));
|
|
461
|
+
if (hit != null) setActive(hit);
|
|
442
462
|
} else if (e.key === "Home" || e.key === "End") {
|
|
443
463
|
e.preventDefault();
|
|
444
464
|
const list = interactiveIdx;
|
|
@@ -466,12 +486,13 @@ function Menu({
|
|
|
466
486
|
"data-align": align,
|
|
467
487
|
"data-flip": pos.flip || void 0,
|
|
468
488
|
role: "menu",
|
|
489
|
+
"aria-orientation": "vertical",
|
|
469
490
|
"aria-label": ariaLabel,
|
|
470
491
|
"aria-labelledby": ariaLabelledby ?? (ariaLabel ? void 0 : header ? headerId : void 0),
|
|
471
492
|
style: { top: pos.top, bottom: pos.bottom, left: pos.left, minWidth: pos.width, width: pos.width, maxHeight: pos.maxHeight },
|
|
472
493
|
children: [
|
|
473
494
|
__twcStyles,
|
|
474
|
-
header ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__header", id: headerId, children: header }) : null,
|
|
495
|
+
header ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__header", id: headerId, role: "presentation", children: header }) : null,
|
|
475
496
|
items.map((it, i) => {
|
|
476
497
|
if (it.separator) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__sep", role: "separator" }, `s${i}`);
|
|
477
498
|
if (it.label && it.heading) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-menu__label", children: it.label }, `h${i}`);
|
|
@@ -505,7 +526,7 @@ function Menu({
|
|
|
505
526
|
}
|
|
506
527
|
) : null;
|
|
507
528
|
const activeDescId = open && active >= 0 ? `${menuId}-item-${active}` : void 0;
|
|
508
|
-
const triggerEl =
|
|
529
|
+
const triggerEl = React25__namespace.default.isValidElement(trigger) ? React25__namespace.default.cloneElement(trigger, {
|
|
509
530
|
onClick: (e) => {
|
|
510
531
|
trigger.props.onClick?.(e);
|
|
511
532
|
toggle();
|
|
@@ -645,8 +666,9 @@ function Badge({
|
|
|
645
666
|
}
|
|
646
667
|
var BREADCRUMB_CSS = `
|
|
647
668
|
.twc-breadcrumb { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; font-family: var(--font-sans); font-size: var(--text-sm); }
|
|
648
|
-
.twc-breadcrumb__item { display: inline-flex; align-items: center; gap: 6px; color: var(--color-text-muted); text-decoration: none; padding: 3px 7px; border-radius: var(--radius-sm); transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
|
|
649
|
-
.twc-breadcrumb__item
|
|
669
|
+
.twc-breadcrumb__item { display: inline-flex; align-items: center; gap: 6px; color: var(--color-text-muted); text-decoration: none; padding: 3px 7px; border: 0; background: transparent; font: inherit; border-radius: var(--radius-sm); transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
|
|
670
|
+
a.twc-breadcrumb__item, button.twc-breadcrumb__item { cursor: pointer; }
|
|
671
|
+
a.twc-breadcrumb__item:hover, button.twc-breadcrumb__item:hover { color: var(--color-text); background: var(--color-surface-sunken); }
|
|
650
672
|
.twc-breadcrumb__item[aria-current="page"] { color: var(--color-text); font-weight: var(--font-semibold); cursor: default; }
|
|
651
673
|
.twc-breadcrumb__item svg { width: 15px; height: 15px; flex: none; }
|
|
652
674
|
.twc-breadcrumb__sep { display: inline-flex; align-items: center; color: var(--color-text-subtle); pointer-events: none; }
|
|
@@ -669,7 +691,7 @@ function Breadcrumb({
|
|
|
669
691
|
...rest
|
|
670
692
|
}) {
|
|
671
693
|
const __twcStyles = useScopedStyles("twc-breadcrumb-styles", BREADCRUMB_CSS);
|
|
672
|
-
const [expanded, setExpanded] =
|
|
694
|
+
const [expanded, setExpanded] = React25__namespace.default.useState(false);
|
|
673
695
|
const sep = separator || /* @__PURE__ */ jsxRuntime.jsx(ChevronSep, {});
|
|
674
696
|
let display = items;
|
|
675
697
|
if (maxItems > 0 && items.length > maxItems && !expanded) {
|
|
@@ -682,7 +704,7 @@ function Breadcrumb({
|
|
|
682
704
|
__twcStyles,
|
|
683
705
|
display.map((it, i) => {
|
|
684
706
|
const last = i === display.length - 1;
|
|
685
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
707
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
|
|
686
708
|
it.ellipsis ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-breadcrumb__ellipsis", "aria-label": "Show more", onClick: () => setExpanded(true), children: "\u2026" }) : last ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
687
709
|
"span",
|
|
688
710
|
{
|
|
@@ -694,17 +716,18 @@ function Breadcrumb({
|
|
|
694
716
|
it.label
|
|
695
717
|
]
|
|
696
718
|
}
|
|
697
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
698
|
-
"
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
719
|
+
) : safeHref2(it.href) ? /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "twc-breadcrumb__item", href: safeHref2(it.href), onClick: it.onClick, children: [
|
|
720
|
+
it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
|
|
721
|
+
it.label
|
|
722
|
+
] }) : it.onClick ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-breadcrumb__item", onClick: it.onClick, children: [
|
|
723
|
+
it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
|
|
724
|
+
it.label
|
|
725
|
+
] }) : (
|
|
726
|
+
// #46: no href and no onClick → inert plain-text crumb (not a fake <a href="#">).
|
|
727
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-breadcrumb__item", children: [
|
|
728
|
+
it.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
|
|
729
|
+
it.label
|
|
730
|
+
] })
|
|
708
731
|
),
|
|
709
732
|
!last ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-breadcrumb__sep", "aria-hidden": "true", children: sep }) : null
|
|
710
733
|
] }, i);
|
|
@@ -823,7 +846,7 @@ function Button({
|
|
|
823
846
|
...rest
|
|
824
847
|
}) {
|
|
825
848
|
const __twcStyles = useScopedStyles("twc-btn-styles", CSS2);
|
|
826
|
-
const [ripples, setRipples] =
|
|
849
|
+
const [ripples, setRipples] = React25__namespace.default.useState([]);
|
|
827
850
|
const Tag2 = as;
|
|
828
851
|
const inert = Tag2 === "a" && (disabled || loading);
|
|
829
852
|
function handleClick(e) {
|
|
@@ -899,7 +922,9 @@ var CARD_CSS = `
|
|
|
899
922
|
.twc-card[data-pad="md"] { padding: var(--space-5); }
|
|
900
923
|
.twc-card[data-pad="lg"] { padding: var(--space-6); }
|
|
901
924
|
.twc-card[data-pad="none"] { padding: 0; }
|
|
902
|
-
.twc-card__header { display: flex; flex-
|
|
925
|
+
.twc-card__header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
|
|
926
|
+
.twc-card__heading { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
927
|
+
.twc-card__actions { flex: none; display: flex; align-items: center; gap: var(--space-2); }
|
|
903
928
|
.twc-card__title { font-size: var(--text-lg); font-weight: var(--font-bold); letter-spacing: -0.01em; }
|
|
904
929
|
.twc-card__subtitle { font-size: var(--text-sm); color: var(--color-text-muted); }
|
|
905
930
|
.twc-card__body { font-size: var(--text-sm); color: var(--color-text-muted); line-height: var(--leading-normal); }
|
|
@@ -909,6 +934,7 @@ function Card({
|
|
|
909
934
|
children,
|
|
910
935
|
title,
|
|
911
936
|
subtitle,
|
|
937
|
+
actions,
|
|
912
938
|
footer,
|
|
913
939
|
variant = "elevated",
|
|
914
940
|
padding = "md",
|
|
@@ -929,9 +955,12 @@ function Card({
|
|
|
929
955
|
...rest,
|
|
930
956
|
children: [
|
|
931
957
|
__twcStyles,
|
|
932
|
-
title || subtitle ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-card__header", children: [
|
|
933
|
-
|
|
934
|
-
|
|
958
|
+
title || subtitle || actions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-card__header", children: [
|
|
959
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-card__heading", children: [
|
|
960
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-card__title", children: title }) : null,
|
|
961
|
+
subtitle ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-card__subtitle", children: subtitle }) : null
|
|
962
|
+
] }),
|
|
963
|
+
actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-card__actions", children: actions }) : null
|
|
935
964
|
] }) : null,
|
|
936
965
|
children ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-card__body", children }) : null,
|
|
937
966
|
footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-card__footer", children: footer }) : null
|
|
@@ -991,14 +1020,14 @@ function Carousel({
|
|
|
991
1020
|
...rest
|
|
992
1021
|
}) {
|
|
993
1022
|
const __twcStyles = useScopedStyles("twc-carousel-styles", CAROUSEL_CSS);
|
|
994
|
-
const slides =
|
|
1023
|
+
const slides = React25__namespace.default.Children.toArray(children);
|
|
995
1024
|
const count = slides.length;
|
|
996
|
-
const [internal, setInternal] =
|
|
1025
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultIndex);
|
|
997
1026
|
const index = indexProp !== void 0 ? indexProp : internal;
|
|
998
|
-
const [paused, setPaused] =
|
|
999
|
-
const [userPaused, setUserPaused] =
|
|
1000
|
-
const [prefersReduced, setPrefersReduced] =
|
|
1001
|
-
|
|
1027
|
+
const [paused, setPaused] = React25__namespace.default.useState(false);
|
|
1028
|
+
const [userPaused, setUserPaused] = React25__namespace.default.useState(false);
|
|
1029
|
+
const [prefersReduced, setPrefersReduced] = React25__namespace.default.useState(false);
|
|
1030
|
+
React25__namespace.default.useEffect(() => {
|
|
1002
1031
|
if (typeof window === "undefined" || !window.matchMedia) return void 0;
|
|
1003
1032
|
const mql = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
1004
1033
|
const on = () => setPrefersReduced(mql.matches);
|
|
@@ -1006,15 +1035,15 @@ function Carousel({
|
|
|
1006
1035
|
mql.addEventListener("change", on);
|
|
1007
1036
|
return () => mql.removeEventListener("change", on);
|
|
1008
1037
|
}, []);
|
|
1009
|
-
const setIndex =
|
|
1038
|
+
const setIndex = React25__namespace.default.useCallback((i) => {
|
|
1010
1039
|
if (indexProp === void 0) setInternal(i);
|
|
1011
1040
|
onIndexChange?.(i);
|
|
1012
1041
|
}, [indexProp, onIndexChange]);
|
|
1013
|
-
const go =
|
|
1042
|
+
const go = React25__namespace.default.useCallback((i) => {
|
|
1014
1043
|
setIndex(loop ? (i + count) % count : Math.min(Math.max(i, 0), count - 1));
|
|
1015
1044
|
}, [count, loop, setIndex]);
|
|
1016
1045
|
const autoRotating = autoPlay && !paused && !userPaused && !prefersReduced && count > 1;
|
|
1017
|
-
|
|
1046
|
+
React25__namespace.default.useEffect(() => {
|
|
1018
1047
|
if (!autoRotating) return void 0;
|
|
1019
1048
|
const t = setInterval(() => {
|
|
1020
1049
|
const next = loop ? (index + 1) % count : index + 1 >= count ? index : index + 1;
|
|
@@ -1109,7 +1138,7 @@ function Chart({
|
|
|
1109
1138
|
...rest
|
|
1110
1139
|
}) {
|
|
1111
1140
|
const __twcStyles = useScopedStyles("twc-chart-styles", CHART_CSS);
|
|
1112
|
-
const uid =
|
|
1141
|
+
const uid = React25__namespace.default.useId();
|
|
1113
1142
|
const tableId = tableFallback ? `${uid}-table` : void 0;
|
|
1114
1143
|
const keys = series || ["value"];
|
|
1115
1144
|
const palette = colors && colors.length ? colors : SERIES_COLORS;
|
|
@@ -1201,6 +1230,15 @@ function shortNum(v) {
|
|
|
1201
1230
|
if (v >= 1e3) return (v / 1e3).toFixed(v % 1e3 ? 1 : 0) + "k";
|
|
1202
1231
|
return String(Math.round(v));
|
|
1203
1232
|
}
|
|
1233
|
+
|
|
1234
|
+
// components/_warn.js
|
|
1235
|
+
var seen = /* @__PURE__ */ new Set();
|
|
1236
|
+
function warnOnce(key, message) {
|
|
1237
|
+
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production") return;
|
|
1238
|
+
if (seen.has(key)) return;
|
|
1239
|
+
seen.add(key);
|
|
1240
|
+
if (typeof console !== "undefined" && console.warn) console.warn(message);
|
|
1241
|
+
}
|
|
1204
1242
|
function Checkbox({
|
|
1205
1243
|
label,
|
|
1206
1244
|
description,
|
|
@@ -1256,14 +1294,18 @@ function Checkbox({
|
|
|
1256
1294
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
1257
1295
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
1258
1296
|
`);
|
|
1259
|
-
const autoId =
|
|
1297
|
+
const autoId = React25__namespace.default.useId();
|
|
1260
1298
|
const fieldId = id || autoId;
|
|
1261
1299
|
const errId = `${fieldId}-error`;
|
|
1262
1300
|
const invalid = Boolean(error);
|
|
1263
|
-
const ref =
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1301
|
+
const ref = React25__namespace.default.useRef(null);
|
|
1302
|
+
const mixed = indeterminate && !checked;
|
|
1303
|
+
React25__namespace.default.useEffect(() => {
|
|
1304
|
+
if (ref.current) ref.current.indeterminate = mixed;
|
|
1305
|
+
}, [mixed]);
|
|
1306
|
+
if (process.env.NODE_ENV !== "production" && !label && !description && !rest["aria-label"] && !rest["aria-labelledby"]) {
|
|
1307
|
+
warnOnce("Checkbox.no-name", "Checkbox: no accessible name \u2014 pass `label`, or `aria-label`/`aria-labelledby` for a label-less control (WCAG 4.1.2).");
|
|
1308
|
+
}
|
|
1267
1309
|
const describedBy = [rest["aria-describedby"], error ? errId : null].filter(Boolean).join(" ") || void 0;
|
|
1268
1310
|
const control = /* @__PURE__ */ jsxRuntime.jsxs("label", { className: `twc-check ${className}`, "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, htmlFor: fieldId, children: [
|
|
1269
1311
|
__twcStyles,
|
|
@@ -1279,12 +1321,14 @@ function Checkbox({
|
|
|
1279
1321
|
disabled,
|
|
1280
1322
|
onChange,
|
|
1281
1323
|
...rest,
|
|
1324
|
+
required: required || void 0,
|
|
1282
1325
|
"aria-required": required || void 0,
|
|
1326
|
+
"aria-checked": mixed ? "mixed" : void 0,
|
|
1283
1327
|
"aria-invalid": invalid || void 0,
|
|
1284
1328
|
"aria-describedby": describedBy
|
|
1285
1329
|
}
|
|
1286
1330
|
),
|
|
1287
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-check__box", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "twc-check__svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3.5", strokeLinecap: "round", strokeLinejoin: "round", children:
|
|
1331
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-check__box", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "twc-check__svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3.5", strokeLinecap: "round", strokeLinejoin: "round", children: mixed ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }),
|
|
1288
1332
|
label || description ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-check__text", children: [
|
|
1289
1333
|
label ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-check__label", children: label }) : null,
|
|
1290
1334
|
description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-check__desc", children: description }) : null
|
|
@@ -1340,6 +1384,7 @@ var COLORPICKER_CSS = `
|
|
|
1340
1384
|
.twc-cp__hex[data-tone="info"] { --_accent: var(--color-info); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-info) 32%, transparent); }
|
|
1341
1385
|
.twc-cp__hex[data-tone="neutral"] { --_accent: var(--color-border-strong); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-text) 14%, transparent); }
|
|
1342
1386
|
.twc-cp__hex:focus { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
1387
|
+
.twc-cp__hex[data-invalid="true"] { border-color: var(--color-danger); }
|
|
1343
1388
|
.twc-cp__presets { display: flex; flex-wrap: wrap; gap: 5px; margin-top: var(--space-3); }
|
|
1344
1389
|
.twc-cp__preset { width: 22px; height: 22px; border-radius: var(--radius-sm); border: none; cursor: pointer; box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.12); padding: 0;
|
|
1345
1390
|
transition: transform var(--duration-fast) var(--ease-spring); }
|
|
@@ -1398,20 +1443,20 @@ function ColorPicker({
|
|
|
1398
1443
|
}) {
|
|
1399
1444
|
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS);
|
|
1400
1445
|
const __twcStyles1 = useScopedStyles("twc-colorpicker-styles", COLORPICKER_CSS);
|
|
1401
|
-
const [internal, setInternal] =
|
|
1446
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
1402
1447
|
const hex = (value !== void 0 ? value : internal) || "#000000";
|
|
1403
|
-
const lastValidRef =
|
|
1448
|
+
const lastValidRef = React25__namespace.default.useRef(hex);
|
|
1404
1449
|
if (/^#[0-9a-f]{6}$/i.test(hex)) lastValidRef.current = hex;
|
|
1405
|
-
const [open, setOpen] =
|
|
1406
|
-
const [hsv, setHsv] =
|
|
1407
|
-
const [coords, setCoords] =
|
|
1408
|
-
const wrapRef =
|
|
1409
|
-
const triggerRef =
|
|
1410
|
-
const popRef =
|
|
1411
|
-
const areaRef =
|
|
1412
|
-
const hueRef =
|
|
1450
|
+
const [open, setOpen] = React25__namespace.default.useState(false);
|
|
1451
|
+
const [hsv, setHsv] = React25__namespace.default.useState(() => hexToHsv(hex) || { h: 239, s: 60, v: 94 });
|
|
1452
|
+
const [coords, setCoords] = React25__namespace.default.useState(null);
|
|
1453
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
1454
|
+
const triggerRef = React25__namespace.default.useRef(null);
|
|
1455
|
+
const popRef = React25__namespace.default.useRef(null);
|
|
1456
|
+
const areaRef = React25__namespace.default.useRef(null);
|
|
1457
|
+
const hueRef = React25__namespace.default.useRef(null);
|
|
1413
1458
|
const POP_W = 240;
|
|
1414
|
-
const place =
|
|
1459
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
1415
1460
|
const el = triggerRef.current;
|
|
1416
1461
|
if (!el) return;
|
|
1417
1462
|
const r = el.getBoundingClientRect();
|
|
@@ -1422,7 +1467,7 @@ function ColorPicker({
|
|
|
1422
1467
|
left = Math.max(8, left);
|
|
1423
1468
|
setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
|
|
1424
1469
|
}, []);
|
|
1425
|
-
|
|
1470
|
+
React25__namespace.default.useEffect(() => {
|
|
1426
1471
|
if (!open) return void 0;
|
|
1427
1472
|
place();
|
|
1428
1473
|
const onMove = () => place();
|
|
@@ -1433,17 +1478,17 @@ function ColorPicker({
|
|
|
1433
1478
|
window.removeEventListener("resize", onMove);
|
|
1434
1479
|
};
|
|
1435
1480
|
}, [open, place]);
|
|
1436
|
-
const labelId =
|
|
1481
|
+
const labelId = React25__namespace.default.useId();
|
|
1437
1482
|
const descId = `${labelId}-desc`;
|
|
1438
1483
|
const invalid = Boolean(error);
|
|
1439
|
-
|
|
1484
|
+
React25__namespace.default.useEffect(() => {
|
|
1440
1485
|
if (disabled) setOpen(false);
|
|
1441
1486
|
}, [disabled]);
|
|
1442
|
-
|
|
1487
|
+
React25__namespace.default.useEffect(() => {
|
|
1443
1488
|
const v = hexToHsv(hex);
|
|
1444
1489
|
if (v && hsvToHex(v.h, v.s, v.v).toLowerCase() !== hsvToHex(hsv.h, hsv.s, hsv.v).toLowerCase()) setHsv(v);
|
|
1445
1490
|
}, [hex]);
|
|
1446
|
-
|
|
1491
|
+
React25__namespace.default.useEffect(() => {
|
|
1447
1492
|
if (!open) return;
|
|
1448
1493
|
const onDown = (e) => {
|
|
1449
1494
|
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
@@ -1460,8 +1505,8 @@ function ColorPicker({
|
|
|
1460
1505
|
document.removeEventListener("keydown", onKey);
|
|
1461
1506
|
};
|
|
1462
1507
|
}, [open]);
|
|
1463
|
-
const prevOpen =
|
|
1464
|
-
|
|
1508
|
+
const prevOpen = React25__namespace.default.useRef(false);
|
|
1509
|
+
React25__namespace.default.useEffect(() => {
|
|
1465
1510
|
let id;
|
|
1466
1511
|
if (!prevOpen.current && open) {
|
|
1467
1512
|
id = setTimeout(() => areaRef.current?.focus({ preventScroll: true }), 20);
|
|
@@ -1615,6 +1660,8 @@ function ColorPicker({
|
|
|
1615
1660
|
value: hex,
|
|
1616
1661
|
maxLength: 7,
|
|
1617
1662
|
"aria-label": "Hex color",
|
|
1663
|
+
"aria-invalid": !/^#[0-9a-f]{6}$/i.test(hex) || void 0,
|
|
1664
|
+
"data-invalid": !/^#[0-9a-f]{6}$/i.test(hex) || void 0,
|
|
1618
1665
|
onChange: (e) => {
|
|
1619
1666
|
let v = e.target.value;
|
|
1620
1667
|
if (!v.startsWith("#")) v = "#" + v;
|
|
@@ -1725,6 +1772,9 @@ var COMBO_CSS = `
|
|
|
1725
1772
|
.twc-opt__check { flex: none; color: var(--color-primary); display: inline-flex; }
|
|
1726
1773
|
.twc-opt__check svg { width: 16px; height: 16px; }
|
|
1727
1774
|
.twc-pop__empty { padding: 14px 12px; text-align: center; font-size: var(--text-sm); color: var(--color-text-subtle); }
|
|
1775
|
+
.twc-opt[data-disabled="true"] { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
|
|
1776
|
+
.twc-pop__loading { display: flex; align-items: center; justify-content: center; gap: var(--space-2); padding: 14px 12px; font-size: var(--text-sm); color: var(--color-text-muted); }
|
|
1777
|
+
.twc-pop__spinner { width: 15px; height: 15px; border-radius: var(--radius-full); border: 2px solid var(--color-border); border-top-color: var(--color-primary); animation: twico-spin 0.7s linear infinite; }
|
|
1728
1778
|
`;
|
|
1729
1779
|
function toOpt(o) {
|
|
1730
1780
|
return typeof o === "string" ? { value: o, label: o } : o;
|
|
@@ -1774,6 +1824,11 @@ function Combobox({
|
|
|
1774
1824
|
placement = "bottom",
|
|
1775
1825
|
portal = true,
|
|
1776
1826
|
minWidth = 0,
|
|
1827
|
+
onInputChange,
|
|
1828
|
+
filter,
|
|
1829
|
+
loading = false,
|
|
1830
|
+
emptyText = "No results found",
|
|
1831
|
+
name,
|
|
1777
1832
|
id,
|
|
1778
1833
|
className = "",
|
|
1779
1834
|
onFocus,
|
|
@@ -1781,29 +1836,38 @@ function Combobox({
|
|
|
1781
1836
|
...rest
|
|
1782
1837
|
}) {
|
|
1783
1838
|
const __twcStyles = useScopedStyles("twc-combo-styles", COMBO_CSS);
|
|
1784
|
-
const groups =
|
|
1785
|
-
const flat =
|
|
1786
|
-
const autoId =
|
|
1839
|
+
const groups = React25__namespace.default.useMemo(() => normalizeGroups(options), [options]);
|
|
1840
|
+
const flat = React25__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
|
|
1841
|
+
const autoId = React25__namespace.default.useId();
|
|
1787
1842
|
const fieldId = id || autoId;
|
|
1788
|
-
const [internal, setInternal] =
|
|
1843
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
1789
1844
|
const current = value !== void 0 ? value : internal;
|
|
1790
1845
|
const selected = flat.find((o) => o.value === current);
|
|
1791
|
-
const [open, setOpen] =
|
|
1792
|
-
const [query, setQuery] =
|
|
1793
|
-
const [active, setActive] =
|
|
1794
|
-
const [coords, setCoords] =
|
|
1795
|
-
const wrapRef =
|
|
1796
|
-
const controlRef =
|
|
1797
|
-
const inputRef =
|
|
1798
|
-
const popRef =
|
|
1799
|
-
const listRef =
|
|
1800
|
-
const activeRef =
|
|
1801
|
-
const fGroups =
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
const
|
|
1846
|
+
const [open, setOpen] = React25__namespace.default.useState(false);
|
|
1847
|
+
const [query, setQuery] = React25__namespace.default.useState("");
|
|
1848
|
+
const [active, setActive] = React25__namespace.default.useState(0);
|
|
1849
|
+
const [coords, setCoords] = React25__namespace.default.useState(null);
|
|
1850
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
1851
|
+
const controlRef = React25__namespace.default.useRef(null);
|
|
1852
|
+
const inputRef = React25__namespace.default.useRef(null);
|
|
1853
|
+
const popRef = React25__namespace.default.useRef(null);
|
|
1854
|
+
const listRef = React25__namespace.default.useRef(null);
|
|
1855
|
+
const activeRef = React25__namespace.default.useRef(null);
|
|
1856
|
+
const fGroups = React25__namespace.default.useMemo(() => {
|
|
1857
|
+
const q = query.trim();
|
|
1858
|
+
const fn = filter === false ? null : typeof filter === "function" ? filter : matches;
|
|
1859
|
+
return groups.map((g) => ({ group: g.group, options: fn ? g.options.filter((o) => fn(o, q)) : g.options })).filter((g) => g.options.length);
|
|
1860
|
+
}, [groups, query, filter]);
|
|
1861
|
+
const visible = React25__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
|
|
1862
|
+
const nextEnabled = (from, dir) => {
|
|
1863
|
+
let i = from + dir;
|
|
1864
|
+
while (i >= 0 && i < visible.length) {
|
|
1865
|
+
if (!visible[i]?.disabled) return i;
|
|
1866
|
+
i += dir;
|
|
1867
|
+
}
|
|
1868
|
+
return from;
|
|
1869
|
+
};
|
|
1870
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
1807
1871
|
const el = controlRef.current;
|
|
1808
1872
|
if (!el) return;
|
|
1809
1873
|
const r = el.getBoundingClientRect();
|
|
@@ -1818,7 +1882,7 @@ function Combobox({
|
|
|
1818
1882
|
flip
|
|
1819
1883
|
});
|
|
1820
1884
|
}, [placement, minWidth]);
|
|
1821
|
-
|
|
1885
|
+
React25__namespace.default.useEffect(() => {
|
|
1822
1886
|
if (!open || !portal) return;
|
|
1823
1887
|
place();
|
|
1824
1888
|
const onMove = () => place();
|
|
@@ -1829,7 +1893,7 @@ function Combobox({
|
|
|
1829
1893
|
window.removeEventListener("resize", onMove);
|
|
1830
1894
|
};
|
|
1831
1895
|
}, [open, portal, place]);
|
|
1832
|
-
|
|
1896
|
+
React25__namespace.default.useEffect(() => {
|
|
1833
1897
|
if (!open) return;
|
|
1834
1898
|
const onDown = (e) => {
|
|
1835
1899
|
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
@@ -1839,10 +1903,15 @@ function Combobox({
|
|
|
1839
1903
|
document.addEventListener("mousedown", onDown);
|
|
1840
1904
|
return () => document.removeEventListener("mousedown", onDown);
|
|
1841
1905
|
}, [open]);
|
|
1842
|
-
|
|
1906
|
+
React25__namespace.default.useEffect(() => {
|
|
1843
1907
|
setActive(0);
|
|
1844
1908
|
}, [query]);
|
|
1845
|
-
|
|
1909
|
+
React25__namespace.default.useEffect(() => {
|
|
1910
|
+
if (!open) return;
|
|
1911
|
+
const idx = flat.findIndex((o) => o.value === current);
|
|
1912
|
+
setActive(idx >= 0 ? idx : 0);
|
|
1913
|
+
}, [open]);
|
|
1914
|
+
React25__namespace.default.useEffect(() => {
|
|
1846
1915
|
if (open) ensureVisible(listRef.current, activeRef.current);
|
|
1847
1916
|
}, [active, open]);
|
|
1848
1917
|
function openMenu() {
|
|
@@ -1855,6 +1924,8 @@ function Combobox({
|
|
|
1855
1924
|
setQuery("");
|
|
1856
1925
|
}
|
|
1857
1926
|
function commit(v) {
|
|
1927
|
+
const o = flat.find((x) => x.value === v);
|
|
1928
|
+
if (o && o.disabled) return;
|
|
1858
1929
|
if (value === void 0) setInternal(v);
|
|
1859
1930
|
onChange?.(v);
|
|
1860
1931
|
close();
|
|
@@ -1866,17 +1937,20 @@ function Combobox({
|
|
|
1866
1937
|
openMenu();
|
|
1867
1938
|
return;
|
|
1868
1939
|
}
|
|
1869
|
-
setActive((a) =>
|
|
1940
|
+
setActive((a) => nextEnabled(a, 1));
|
|
1870
1941
|
} else if (e.key === "ArrowUp") {
|
|
1871
1942
|
e.preventDefault();
|
|
1872
|
-
setActive((a) =>
|
|
1943
|
+
setActive((a) => nextEnabled(a, -1));
|
|
1873
1944
|
} else if (e.key === "Enter") {
|
|
1874
1945
|
e.preventDefault();
|
|
1875
1946
|
if (open && visible[active]) commit(visible[active].value);
|
|
1876
1947
|
} else if (e.key === "Escape") {
|
|
1877
1948
|
close();
|
|
1878
1949
|
inputRef.current?.blur();
|
|
1879
|
-
} else if (e.key === "Backspace" && !query && selected)
|
|
1950
|
+
} else if (e.key === "Backspace" && !query && selected) {
|
|
1951
|
+
e.preventDefault();
|
|
1952
|
+
commit(null);
|
|
1953
|
+
}
|
|
1880
1954
|
}
|
|
1881
1955
|
const displayValue = open ? query : selected ? selected.label : "";
|
|
1882
1956
|
const listboxId = `${fieldId}-listbox`;
|
|
@@ -1885,7 +1959,10 @@ function Combobox({
|
|
|
1885
1959
|
const descId = `${fieldId}-desc`;
|
|
1886
1960
|
const describedBy = error || hint ? descId : void 0;
|
|
1887
1961
|
let counter = -1;
|
|
1888
|
-
const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children:
|
|
1962
|
+
const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
|
|
1963
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
|
|
1964
|
+
"Loading\u2026"
|
|
1965
|
+
] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
|
|
1889
1966
|
g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
1890
1967
|
g.options.map((o) => {
|
|
1891
1968
|
counter += 1;
|
|
@@ -1900,9 +1977,14 @@ function Combobox({
|
|
|
1900
1977
|
role: "option",
|
|
1901
1978
|
"aria-selected": isSel,
|
|
1902
1979
|
ref: idx === active ? activeRef : null,
|
|
1980
|
+
disabled: o.disabled || void 0,
|
|
1981
|
+
"aria-disabled": o.disabled || void 0,
|
|
1982
|
+
"data-disabled": o.disabled || void 0,
|
|
1903
1983
|
"data-selected": isSel || void 0,
|
|
1904
1984
|
"data-active": idx === active || void 0,
|
|
1905
|
-
onMouseEnter: () =>
|
|
1985
|
+
onMouseEnter: () => {
|
|
1986
|
+
if (!o.disabled) setActive(idx);
|
|
1987
|
+
},
|
|
1906
1988
|
onMouseDown: (e) => e.preventDefault(),
|
|
1907
1989
|
onClick: () => commit(o.value),
|
|
1908
1990
|
children: [
|
|
@@ -1930,7 +2012,7 @@ function Combobox({
|
|
|
1930
2012
|
id: listboxId,
|
|
1931
2013
|
role: "listbox",
|
|
1932
2014
|
ref: popRef,
|
|
1933
|
-
"data-placement": coords.flip ? "top" :
|
|
2015
|
+
"data-placement": coords.flip ? "top" : "bottom",
|
|
1934
2016
|
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-tooltip)" },
|
|
1935
2017
|
children: popInner
|
|
1936
2018
|
}
|
|
@@ -1943,6 +2025,7 @@ function Combobox({
|
|
|
1943
2025
|
}
|
|
1944
2026
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-field ${className}`, ref: wrapRef, children: [
|
|
1945
2027
|
__twcStyles,
|
|
2028
|
+
name ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: current ?? "" }) : null,
|
|
1946
2029
|
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
1947
2030
|
label,
|
|
1948
2031
|
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
@@ -1988,6 +2071,7 @@ function Combobox({
|
|
|
1988
2071
|
onChange: (e) => {
|
|
1989
2072
|
setQuery(e.target.value);
|
|
1990
2073
|
setOpen(true);
|
|
2074
|
+
onInputChange?.(e.target.value);
|
|
1991
2075
|
},
|
|
1992
2076
|
onKeyDown: (e) => {
|
|
1993
2077
|
onKeyDown?.(e);
|
|
@@ -2024,9 +2108,10 @@ function Combobox({
|
|
|
2024
2108
|
] });
|
|
2025
2109
|
}
|
|
2026
2110
|
var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
|
|
2111
|
+
var useIsoLayoutEffect = canUseDOM ? React25__namespace.default.useLayoutEffect : React25__namespace.default.useEffect;
|
|
2027
2112
|
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
2113
|
function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
|
|
2029
|
-
|
|
2114
|
+
React25__namespace.default.useEffect(() => {
|
|
2030
2115
|
if (!active || !canUseDOM) return void 0;
|
|
2031
2116
|
const node = ref.current;
|
|
2032
2117
|
if (!node) return void 0;
|
|
@@ -2037,7 +2122,7 @@ function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
|
|
|
2037
2122
|
if (restoreFocus && prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
|
|
2038
2123
|
};
|
|
2039
2124
|
}, [active]);
|
|
2040
|
-
|
|
2125
|
+
React25__namespace.default.useEffect(() => {
|
|
2041
2126
|
if (!active || !canUseDOM) return void 0;
|
|
2042
2127
|
const node = ref.current;
|
|
2043
2128
|
const onKey = (e) => {
|
|
@@ -2064,11 +2149,53 @@ function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
|
|
|
2064
2149
|
}, [active]);
|
|
2065
2150
|
}
|
|
2066
2151
|
function usePortal() {
|
|
2067
|
-
return
|
|
2152
|
+
return React25__namespace.default.useCallback((node) => {
|
|
2068
2153
|
if (typeof document === "undefined") return null;
|
|
2069
2154
|
return typeof reactDom.createPortal === "function" ? reactDom.createPortal(node, document.body) : node;
|
|
2070
2155
|
}, []);
|
|
2071
2156
|
}
|
|
2157
|
+
var __scrollLockCount = 0;
|
|
2158
|
+
var __scrollLockSaved = { overflow: "", paddingRight: "" };
|
|
2159
|
+
function useScrollLock(locked = true) {
|
|
2160
|
+
useIsoLayoutEffect(() => {
|
|
2161
|
+
if (!canUseDOM || !locked) return void 0;
|
|
2162
|
+
if (__scrollLockCount === 0) {
|
|
2163
|
+
const b = document.body;
|
|
2164
|
+
__scrollLockSaved = { overflow: b.style.overflow, paddingRight: b.style.paddingRight };
|
|
2165
|
+
const gutter = window.innerWidth - document.documentElement.clientWidth;
|
|
2166
|
+
b.style.overflow = "hidden";
|
|
2167
|
+
if (gutter > 0) b.style.paddingRight = `${(parseFloat(getComputedStyle(b).paddingRight) || 0) + gutter}px`;
|
|
2168
|
+
}
|
|
2169
|
+
__scrollLockCount += 1;
|
|
2170
|
+
return () => {
|
|
2171
|
+
__scrollLockCount -= 1;
|
|
2172
|
+
if (__scrollLockCount === 0) {
|
|
2173
|
+
document.body.style.overflow = __scrollLockSaved.overflow;
|
|
2174
|
+
document.body.style.paddingRight = __scrollLockSaved.paddingRight;
|
|
2175
|
+
}
|
|
2176
|
+
};
|
|
2177
|
+
}, [locked]);
|
|
2178
|
+
}
|
|
2179
|
+
function useInertBackground(ref, active) {
|
|
2180
|
+
React25__namespace.default.useEffect(() => {
|
|
2181
|
+
if (!active || !canUseDOM) return void 0;
|
|
2182
|
+
const node = ref.current;
|
|
2183
|
+
if (!node) return void 0;
|
|
2184
|
+
const changed = [];
|
|
2185
|
+
Array.from(document.body.children).forEach((el) => {
|
|
2186
|
+
if (el.contains(node) || el.hasAttribute("aria-hidden") || el.inert) return;
|
|
2187
|
+
el.inert = true;
|
|
2188
|
+
el.setAttribute("aria-hidden", "true");
|
|
2189
|
+
changed.push(el);
|
|
2190
|
+
});
|
|
2191
|
+
return () => {
|
|
2192
|
+
changed.forEach((el) => {
|
|
2193
|
+
el.inert = false;
|
|
2194
|
+
el.removeAttribute("aria-hidden");
|
|
2195
|
+
});
|
|
2196
|
+
};
|
|
2197
|
+
}, [active]);
|
|
2198
|
+
}
|
|
2072
2199
|
var COMMAND_CSS = `
|
|
2073
2200
|
.twc-cmdk__overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: var(--color-overlay); backdrop-filter: blur(3px);
|
|
2074
2201
|
display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
|
|
@@ -2110,19 +2237,20 @@ function CommandPalette({
|
|
|
2110
2237
|
commands,
|
|
2111
2238
|
placeholder = "Type a command or search\u2026",
|
|
2112
2239
|
emptyText = "No results found",
|
|
2240
|
+
searchLabel = "Command palette search",
|
|
2113
2241
|
className = "",
|
|
2114
2242
|
...rest
|
|
2115
2243
|
}) {
|
|
2116
2244
|
const __twcStyles = useScopedStyles("twc-cmdk-styles", COMMAND_CSS);
|
|
2117
2245
|
const renderPortal = usePortal();
|
|
2118
|
-
const [query, setQuery] =
|
|
2119
|
-
const [active, setActive] =
|
|
2120
|
-
const inputRef =
|
|
2121
|
-
const listRef =
|
|
2122
|
-
const paletteRef =
|
|
2123
|
-
const baseId =
|
|
2124
|
-
const [mounted, setMounted] =
|
|
2125
|
-
|
|
2246
|
+
const [query, setQuery] = React25__namespace.default.useState("");
|
|
2247
|
+
const [active, setActive] = React25__namespace.default.useState(0);
|
|
2248
|
+
const inputRef = React25__namespace.default.useRef(null);
|
|
2249
|
+
const listRef = React25__namespace.default.useRef(null);
|
|
2250
|
+
const paletteRef = React25__namespace.default.useRef(null);
|
|
2251
|
+
const baseId = React25__namespace.default.useId();
|
|
2252
|
+
const [mounted, setMounted] = React25__namespace.default.useState(open);
|
|
2253
|
+
React25__namespace.default.useEffect(() => {
|
|
2126
2254
|
if (open) {
|
|
2127
2255
|
setMounted(true);
|
|
2128
2256
|
return;
|
|
@@ -2130,22 +2258,15 @@ function CommandPalette({
|
|
|
2130
2258
|
const t = setTimeout(() => setMounted(false), 170);
|
|
2131
2259
|
return () => clearTimeout(t);
|
|
2132
2260
|
}, [open]);
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
const prev = document.body.style.overflow;
|
|
2136
|
-
document.body.style.overflow = "hidden";
|
|
2137
|
-
return () => {
|
|
2138
|
-
document.body.style.overflow = prev;
|
|
2139
|
-
};
|
|
2140
|
-
}, [open]);
|
|
2141
|
-
React24__namespace.default.useEffect(() => {
|
|
2261
|
+
useScrollLock(open);
|
|
2262
|
+
React25__namespace.default.useEffect(() => {
|
|
2142
2263
|
if (open) {
|
|
2143
2264
|
setQuery("");
|
|
2144
2265
|
setActive(0);
|
|
2145
2266
|
}
|
|
2146
2267
|
}, [open]);
|
|
2147
2268
|
useFocusTrap(paletteRef, open && mounted);
|
|
2148
|
-
|
|
2269
|
+
React25__namespace.default.useEffect(() => {
|
|
2149
2270
|
if (!open) return void 0;
|
|
2150
2271
|
const onKey = (e) => {
|
|
2151
2272
|
if (e.key === "Escape") {
|
|
@@ -2157,7 +2278,7 @@ function CommandPalette({
|
|
|
2157
2278
|
return () => document.removeEventListener("keydown", onKey);
|
|
2158
2279
|
}, [open, onClose]);
|
|
2159
2280
|
const q = query.trim().toLowerCase();
|
|
2160
|
-
const filtered =
|
|
2281
|
+
const filtered = React25__namespace.default.useMemo(() => commands.filter(
|
|
2161
2282
|
(c) => !q || c.label.toLowerCase().includes(q) || (c.keywords || "").toLowerCase().includes(q) || (c.group || "").toLowerCase().includes(q)
|
|
2162
2283
|
), [commands, q]);
|
|
2163
2284
|
const groups = [];
|
|
@@ -2172,7 +2293,7 @@ function CommandPalette({
|
|
|
2172
2293
|
g.items.push(c);
|
|
2173
2294
|
flat.push(c);
|
|
2174
2295
|
});
|
|
2175
|
-
|
|
2296
|
+
React25__namespace.default.useEffect(() => {
|
|
2176
2297
|
setActive(0);
|
|
2177
2298
|
}, [query]);
|
|
2178
2299
|
const run = (cmd) => {
|
|
@@ -2192,7 +2313,7 @@ function CommandPalette({
|
|
|
2192
2313
|
if (cmd) run(cmd);
|
|
2193
2314
|
}
|
|
2194
2315
|
}
|
|
2195
|
-
|
|
2316
|
+
React25__namespace.default.useEffect(() => {
|
|
2196
2317
|
const node = listRef.current?.querySelector('[data-active="true"]');
|
|
2197
2318
|
if (node) node.scrollIntoView({ block: "nearest" });
|
|
2198
2319
|
}, [active]);
|
|
@@ -2220,7 +2341,8 @@ function CommandPalette({
|
|
|
2220
2341
|
value: query,
|
|
2221
2342
|
placeholder,
|
|
2222
2343
|
role: "combobox",
|
|
2223
|
-
"aria-
|
|
2344
|
+
"aria-label": searchLabel,
|
|
2345
|
+
"aria-expanded": flat.length > 0 ? "true" : "false",
|
|
2224
2346
|
"aria-controls": listId,
|
|
2225
2347
|
"aria-activedescendant": activeId,
|
|
2226
2348
|
onChange: (e) => setQuery(e.target.value),
|
|
@@ -2322,7 +2444,9 @@ var CUR_CSS = `
|
|
|
2322
2444
|
.twc-cur:focus-within { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
2323
2445
|
.twc-cur[data-invalid="true"] { border-color: var(--color-danger); }
|
|
2324
2446
|
.twc-cur[data-invalid="true"]:focus-within { box-shadow: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 28%, transparent); }
|
|
2325
|
-
.twc-cur[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; }
|
|
2447
|
+
.twc-cur[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
2448
|
+
.twc-cur[data-readonly="true"] { background: var(--color-surface-sunken); }
|
|
2449
|
+
.twc-cur__el:disabled { cursor: not-allowed; }
|
|
2326
2450
|
.twc-cur__sym, .twc-cur__code {
|
|
2327
2451
|
display: inline-flex; align-items: center; padding: 0 var(--space-3);
|
|
2328
2452
|
background: var(--color-surface-sunken); color: var(--color-text-muted);
|
|
@@ -2365,18 +2489,29 @@ function Currency({
|
|
|
2365
2489
|
const prec = precision != null ? precision : meta.precision;
|
|
2366
2490
|
const sym = symbol != null ? symbol : meta.symbol;
|
|
2367
2491
|
const cur = code != null ? code : meta.code;
|
|
2368
|
-
const autoId =
|
|
2492
|
+
const autoId = React25__namespace.default.useId();
|
|
2369
2493
|
const fieldId = id || autoId;
|
|
2370
2494
|
const invalid = Boolean(error);
|
|
2371
2495
|
const controlled = value !== void 0;
|
|
2372
|
-
const [internal, setInternal] =
|
|
2496
|
+
const [internal, setInternal] = React25__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
|
|
2373
2497
|
const shown = controlled ? clampPrecision(String(value ?? ""), prec) : internal;
|
|
2374
|
-
|
|
2498
|
+
React25__namespace.default.useEffect(() => {
|
|
2499
|
+
if (!controlled) return;
|
|
2500
|
+
const raw = String(value ?? "");
|
|
2501
|
+
if (shown !== raw) {
|
|
2502
|
+
const n = Number(shown);
|
|
2503
|
+
onValueChange?.(shown === "" || Number.isNaN(n) ? null : n, shown);
|
|
2504
|
+
}
|
|
2505
|
+
}, [controlled, shown, value]);
|
|
2506
|
+
const descId = `${fieldId}-desc`;
|
|
2507
|
+
const describedBy = [error || hint ? descId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
2508
|
+
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
2375
2509
|
function handleChange(e) {
|
|
2376
2510
|
const next = clampPrecision(e.target.value, prec);
|
|
2377
2511
|
if (!controlled) setInternal(next);
|
|
2378
2512
|
onChange?.(e);
|
|
2379
|
-
|
|
2513
|
+
const n = Number(next);
|
|
2514
|
+
onValueChange?.(next === "" || Number.isNaN(n) ? null : n, next);
|
|
2380
2515
|
}
|
|
2381
2516
|
function handleBlur(e) {
|
|
2382
2517
|
rest.onBlur?.(e);
|
|
@@ -2393,7 +2528,7 @@ function Currency({
|
|
|
2393
2528
|
label,
|
|
2394
2529
|
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
2395
2530
|
] }) : null,
|
|
2396
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cur", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, children: [
|
|
2531
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cur", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, "data-readonly": rest.readOnly || void 0, children: [
|
|
2397
2532
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-cur__sym", "aria-hidden": "true", children: sym }),
|
|
2398
2533
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2399
2534
|
"input",
|
|
@@ -2406,16 +2541,16 @@ function Currency({
|
|
|
2406
2541
|
placeholder,
|
|
2407
2542
|
disabled,
|
|
2408
2543
|
required: required || void 0,
|
|
2409
|
-
"aria-invalid": invalid || void 0,
|
|
2410
2544
|
...rest,
|
|
2411
2545
|
onChange: handleChange,
|
|
2412
2546
|
onBlur: handleBlur,
|
|
2547
|
+
"aria-invalid": ariaInvalid,
|
|
2413
2548
|
"aria-describedby": describedBy
|
|
2414
2549
|
}
|
|
2415
2550
|
),
|
|
2416
2551
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-cur__code", children: cur })
|
|
2417
2552
|
] }),
|
|
2418
|
-
error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id:
|
|
2553
|
+
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
|
|
2419
2554
|
] });
|
|
2420
2555
|
}
|
|
2421
2556
|
var SELECT_CSS = `
|
|
@@ -2490,6 +2625,13 @@ var SELECT_CSS = `
|
|
|
2490
2625
|
.twc-opt__check { flex: none; color: var(--color-primary); display: inline-flex; }
|
|
2491
2626
|
.twc-opt__check svg { width: 16px; height: 16px; }
|
|
2492
2627
|
.twc-pop__empty { padding: 14px 12px; text-align: center; font-size: var(--text-sm); color: var(--color-text-subtle); }
|
|
2628
|
+
.twc-opt[data-disabled="true"] { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
|
|
2629
|
+
.twc-pop__loading { display: flex; align-items: center; justify-content: center; gap: var(--space-2); padding: 14px 12px; font-size: var(--text-sm); color: var(--color-text-muted); }
|
|
2630
|
+
.twc-pop__spinner { width: 15px; height: 15px; border-radius: var(--radius-full); border: 2px solid var(--color-border); border-top-color: var(--color-primary); animation: twico-spin 0.7s linear infinite; }
|
|
2631
|
+
.twc-pop__search-clear { flex: none; display: inline-grid; place-items: center; width: 18px; height: 18px; border: none; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-full); }
|
|
2632
|
+
.twc-pop__search-clear:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
2633
|
+
.twc-pop__search-clear svg { width: 13px; height: 13px; }
|
|
2634
|
+
.twc-sel__sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
2493
2635
|
`;
|
|
2494
2636
|
function toOpt2(o) {
|
|
2495
2637
|
return typeof o === "string" ? { value: o, label: o } : o;
|
|
@@ -2536,6 +2678,10 @@ function Select({
|
|
|
2536
2678
|
placement = "bottom",
|
|
2537
2679
|
portal = true,
|
|
2538
2680
|
minWidth = 0,
|
|
2681
|
+
matchTriggerWidth = true,
|
|
2682
|
+
loading = false,
|
|
2683
|
+
emptyText = "No results found",
|
|
2684
|
+
name,
|
|
2539
2685
|
id,
|
|
2540
2686
|
className = "",
|
|
2541
2687
|
onClick,
|
|
@@ -2543,47 +2689,58 @@ function Select({
|
|
|
2543
2689
|
...rest
|
|
2544
2690
|
}) {
|
|
2545
2691
|
const __twcStyles = useScopedStyles("twc-select-styles", SELECT_CSS);
|
|
2546
|
-
const
|
|
2547
|
-
const
|
|
2548
|
-
const
|
|
2692
|
+
const bufferRef = React25__namespace.default.useRef("");
|
|
2693
|
+
const bufferTimerRef = React25__namespace.default.useRef(null);
|
|
2694
|
+
const groups = React25__namespace.default.useMemo(() => normalizeGroups2(options), [options]);
|
|
2695
|
+
const flat = React25__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
|
|
2696
|
+
const autoId = React25__namespace.default.useId();
|
|
2549
2697
|
const fieldId = id || autoId;
|
|
2550
|
-
const [internal, setInternal] =
|
|
2698
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
2551
2699
|
const current = value !== void 0 ? value : internal;
|
|
2552
|
-
const [open, setOpen] =
|
|
2553
|
-
const [render, setRender] =
|
|
2554
|
-
const [active, setActive] =
|
|
2555
|
-
const [coords, setCoords] =
|
|
2556
|
-
const [query, setQuery] =
|
|
2557
|
-
const wrapRef =
|
|
2558
|
-
const triggerRef =
|
|
2559
|
-
const popRef =
|
|
2560
|
-
const listRef =
|
|
2561
|
-
const activeRef =
|
|
2562
|
-
const searchRef =
|
|
2700
|
+
const [open, setOpen] = React25__namespace.default.useState(false);
|
|
2701
|
+
const [render, setRender] = React25__namespace.default.useState(false);
|
|
2702
|
+
const [active, setActive] = React25__namespace.default.useState(0);
|
|
2703
|
+
const [coords, setCoords] = React25__namespace.default.useState(null);
|
|
2704
|
+
const [query, setQuery] = React25__namespace.default.useState("");
|
|
2705
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
2706
|
+
const triggerRef = React25__namespace.default.useRef(null);
|
|
2707
|
+
const popRef = React25__namespace.default.useRef(null);
|
|
2708
|
+
const listRef = React25__namespace.default.useRef(null);
|
|
2709
|
+
const activeRef = React25__namespace.default.useRef(null);
|
|
2710
|
+
const searchRef = React25__namespace.default.useRef(null);
|
|
2563
2711
|
const showSearch = searchable === void 0 ? flat.length > 5 : searchable;
|
|
2564
|
-
const fGroups =
|
|
2712
|
+
const fGroups = React25__namespace.default.useMemo(() => {
|
|
2565
2713
|
const q = query.trim().toLowerCase();
|
|
2566
2714
|
if (!q) return groups;
|
|
2567
2715
|
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);
|
|
2568
2716
|
}, [groups, query]);
|
|
2569
|
-
const visible =
|
|
2717
|
+
const visible = React25__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
|
|
2570
2718
|
const selected = flat.find((o) => o.value === current);
|
|
2571
|
-
const
|
|
2719
|
+
const nextEnabled = (from, dir) => {
|
|
2720
|
+
let i = from + dir;
|
|
2721
|
+
while (i >= 0 && i < visible.length) {
|
|
2722
|
+
if (!visible[i]?.disabled) return i;
|
|
2723
|
+
i += dir;
|
|
2724
|
+
}
|
|
2725
|
+
return from;
|
|
2726
|
+
};
|
|
2727
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
2572
2728
|
const el = triggerRef.current;
|
|
2573
2729
|
if (!el) return;
|
|
2574
2730
|
const r = el.getBoundingClientRect();
|
|
2575
2731
|
const vh = window.innerHeight;
|
|
2576
2732
|
const below = vh - r.bottom;
|
|
2577
2733
|
const flip = placement === "top" || below < 260 && r.top > below;
|
|
2734
|
+
const widthStyle = matchTriggerWidth ? { width: Math.max(r.width, minWidth) } : { width: "auto", minWidth: Math.max(r.width, minWidth), maxWidth: Math.max(160, window.innerWidth - r.left - 8) };
|
|
2578
2735
|
setCoords({
|
|
2579
2736
|
left: r.left,
|
|
2580
|
-
|
|
2737
|
+
...widthStyle,
|
|
2581
2738
|
top: flip ? void 0 : Math.round(r.bottom + 6),
|
|
2582
2739
|
bottom: flip ? Math.round(vh - r.top + 6) : void 0,
|
|
2583
2740
|
flip
|
|
2584
2741
|
});
|
|
2585
|
-
}, [placement, minWidth]);
|
|
2586
|
-
|
|
2742
|
+
}, [placement, minWidth, matchTriggerWidth]);
|
|
2743
|
+
React25__namespace.default.useEffect(() => {
|
|
2587
2744
|
if (!open || !portal) return;
|
|
2588
2745
|
place();
|
|
2589
2746
|
const onMove = () => place();
|
|
@@ -2594,7 +2751,7 @@ function Select({
|
|
|
2594
2751
|
window.removeEventListener("resize", onMove);
|
|
2595
2752
|
};
|
|
2596
2753
|
}, [open, portal, place]);
|
|
2597
|
-
|
|
2754
|
+
React25__namespace.default.useEffect(() => {
|
|
2598
2755
|
if (!open) return;
|
|
2599
2756
|
const idx = flat.findIndex((o) => o.value === current);
|
|
2600
2757
|
setActive(idx >= 0 ? idx : 0);
|
|
@@ -2610,13 +2767,13 @@ function Select({
|
|
|
2610
2767
|
document.addEventListener("mousedown", onDown);
|
|
2611
2768
|
return () => document.removeEventListener("mousedown", onDown);
|
|
2612
2769
|
}, [open]);
|
|
2613
|
-
|
|
2770
|
+
React25__namespace.default.useEffect(() => {
|
|
2614
2771
|
setActive(0);
|
|
2615
2772
|
}, [query]);
|
|
2616
|
-
|
|
2773
|
+
React25__namespace.default.useEffect(() => {
|
|
2617
2774
|
if (open) ensureVisible2(listRef.current, activeRef.current);
|
|
2618
2775
|
}, [active, open]);
|
|
2619
|
-
|
|
2776
|
+
React25__namespace.default.useEffect(() => {
|
|
2620
2777
|
if (open) {
|
|
2621
2778
|
setRender(true);
|
|
2622
2779
|
return;
|
|
@@ -2624,8 +2781,8 @@ function Select({
|
|
|
2624
2781
|
const t = setTimeout(() => setRender(false), 170);
|
|
2625
2782
|
return () => clearTimeout(t);
|
|
2626
2783
|
}, [open]);
|
|
2627
|
-
const prevOpen =
|
|
2628
|
-
|
|
2784
|
+
const prevOpen = React25__namespace.default.useRef(false);
|
|
2785
|
+
React25__namespace.default.useEffect(() => {
|
|
2629
2786
|
if (prevOpen.current && !open) {
|
|
2630
2787
|
const ae = typeof document !== "undefined" ? document.activeElement : null;
|
|
2631
2788
|
if (popRef.current && ae && popRef.current.contains(ae)) triggerRef.current?.focus();
|
|
@@ -2633,6 +2790,8 @@ function Select({
|
|
|
2633
2790
|
prevOpen.current = open;
|
|
2634
2791
|
}, [open]);
|
|
2635
2792
|
function commit(v) {
|
|
2793
|
+
const o = flat.find((x) => x.value === v);
|
|
2794
|
+
if (o && o.disabled) return;
|
|
2636
2795
|
if (value === void 0) setInternal(v);
|
|
2637
2796
|
onChange?.(v);
|
|
2638
2797
|
setOpen(false);
|
|
@@ -2653,6 +2812,18 @@ function Select({
|
|
|
2653
2812
|
setOpen(true);
|
|
2654
2813
|
return;
|
|
2655
2814
|
}
|
|
2815
|
+
if (!open && !showSearch && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
2816
|
+
e.preventDefault();
|
|
2817
|
+
bufferRef.current += e.key.toLowerCase();
|
|
2818
|
+
clearTimeout(bufferTimerRef.current);
|
|
2819
|
+
bufferTimerRef.current = setTimeout(() => {
|
|
2820
|
+
bufferRef.current = "";
|
|
2821
|
+
}, 500);
|
|
2822
|
+
const b = bufferRef.current;
|
|
2823
|
+
const match = flat.find((o) => !o.disabled && o.label.toLowerCase().startsWith(b)) || flat.find((o) => !o.disabled && o.label.toLowerCase().includes(b));
|
|
2824
|
+
if (match) commit(match.value);
|
|
2825
|
+
return;
|
|
2826
|
+
}
|
|
2656
2827
|
if (!open) return;
|
|
2657
2828
|
if (e.key === "Tab") {
|
|
2658
2829
|
setOpen(false);
|
|
@@ -2661,10 +2832,10 @@ function Select({
|
|
|
2661
2832
|
if (e.key === "Escape") setOpen(false);
|
|
2662
2833
|
else if (e.key === "ArrowDown") {
|
|
2663
2834
|
e.preventDefault();
|
|
2664
|
-
setActive((a) =>
|
|
2835
|
+
setActive((a) => nextEnabled(a, 1));
|
|
2665
2836
|
} else if (e.key === "ArrowUp") {
|
|
2666
2837
|
e.preventDefault();
|
|
2667
|
-
setActive((a) =>
|
|
2838
|
+
setActive((a) => nextEnabled(a, -1));
|
|
2668
2839
|
} else if (e.key === "Enter") {
|
|
2669
2840
|
e.preventDefault();
|
|
2670
2841
|
if (visible[active]) commit(visible[active].value);
|
|
@@ -2696,9 +2867,16 @@ function Select({
|
|
|
2696
2867
|
"aria-controls": listboxId,
|
|
2697
2868
|
"aria-activedescendant": activeId
|
|
2698
2869
|
}
|
|
2699
|
-
)
|
|
2870
|
+
),
|
|
2871
|
+
query ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-pop__search-clear", "aria-label": "Clear search", onClick: () => {
|
|
2872
|
+
setQuery("");
|
|
2873
|
+
searchRef.current?.focus();
|
|
2874
|
+
}, 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
|
|
2700
2875
|
] }) : null,
|
|
2701
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children:
|
|
2876
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", ref: listRef, children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
|
|
2877
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
|
|
2878
|
+
"Loading\u2026"
|
|
2879
|
+
] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
|
|
2702
2880
|
g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
2703
2881
|
g.options.map((o) => {
|
|
2704
2882
|
counter += 1;
|
|
@@ -2713,9 +2891,14 @@ function Select({
|
|
|
2713
2891
|
role: "option",
|
|
2714
2892
|
"aria-selected": isSel,
|
|
2715
2893
|
ref: idx === active ? activeRef : null,
|
|
2894
|
+
disabled: o.disabled || void 0,
|
|
2895
|
+
"aria-disabled": o.disabled || void 0,
|
|
2896
|
+
"data-disabled": o.disabled || void 0,
|
|
2716
2897
|
"data-selected": isSel || void 0,
|
|
2717
2898
|
"data-active": idx === active || void 0,
|
|
2718
|
-
onMouseEnter: () =>
|
|
2899
|
+
onMouseEnter: () => {
|
|
2900
|
+
if (!o.disabled) setActive(idx);
|
|
2901
|
+
},
|
|
2719
2902
|
onClick: () => commit(o.value),
|
|
2720
2903
|
children: [
|
|
2721
2904
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-opt__main", children: [
|
|
@@ -2728,7 +2911,8 @@ function Select({
|
|
|
2728
2911
|
o.value
|
|
2729
2912
|
);
|
|
2730
2913
|
})
|
|
2731
|
-
] }, gi)) })
|
|
2914
|
+
] }, gi)) }),
|
|
2915
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sel__sr", role: "status", "aria-live": "polite", children: loading ? "Loading\u2026" : visible.length === 0 ? emptyText : `${visible.length} result${visible.length === 1 ? "" : "s"}` })
|
|
2732
2916
|
] });
|
|
2733
2917
|
const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
|
|
2734
2918
|
const canPortal = portal && RD && RD.createPortal;
|
|
@@ -2745,19 +2929,20 @@ function Select({
|
|
|
2745
2929
|
role: "listbox",
|
|
2746
2930
|
ref: popRef,
|
|
2747
2931
|
"data-state": popState,
|
|
2748
|
-
"data-placement": coords.flip ? "top" :
|
|
2749
|
-
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-tooltip)" },
|
|
2932
|
+
"data-placement": coords.flip ? "top" : "bottom",
|
|
2933
|
+
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, minWidth: coords.minWidth, maxWidth: coords.maxWidth, right: "auto", zIndex: "var(--z-tooltip)" },
|
|
2750
2934
|
children: popInner
|
|
2751
2935
|
}
|
|
2752
2936
|
),
|
|
2753
2937
|
document.body
|
|
2754
2938
|
);
|
|
2755
2939
|
} else if (!portal) {
|
|
2756
|
-
popEl = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop", id: listboxId, role: "listbox", ref: popRef, "data-state": popState, "data-placement": placement === "top" ? "top" :
|
|
2940
|
+
popEl = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop", id: listboxId, role: "listbox", ref: popRef, "data-state": popState, "data-placement": placement === "top" ? "top" : "bottom", children: popInner });
|
|
2757
2941
|
}
|
|
2758
2942
|
}
|
|
2759
2943
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-field ${className}`, ref: wrapRef, children: [
|
|
2760
2944
|
__twcStyles,
|
|
2945
|
+
name ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: current ?? "" }) : null,
|
|
2761
2946
|
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
2762
2947
|
label,
|
|
2763
2948
|
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
@@ -2828,7 +3013,9 @@ var CURF_CSS = `
|
|
|
2828
3013
|
.twc-cur:focus-within { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
2829
3014
|
.twc-cur[data-invalid="true"] { border-color: var(--color-danger); }
|
|
2830
3015
|
.twc-cur[data-invalid="true"]:focus-within { box-shadow: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 28%, transparent); }
|
|
2831
|
-
.twc-cur[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; }
|
|
3016
|
+
.twc-cur[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
3017
|
+
.twc-cur[data-readonly="true"] { background: var(--color-surface-sunken); }
|
|
3018
|
+
.twc-cur__el:disabled { cursor: not-allowed; }
|
|
2832
3019
|
.twc-cur__sym, .twc-cur__code {
|
|
2833
3020
|
display: inline-flex; align-items: center; padding: 0 var(--space-3);
|
|
2834
3021
|
background: var(--color-surface-sunken); color: var(--color-text-muted);
|
|
@@ -2872,19 +3059,37 @@ function CurrencyField({
|
|
|
2872
3059
|
...rest
|
|
2873
3060
|
}) {
|
|
2874
3061
|
const __twcStyles = useScopedStyles("twc-curf-styles", CURF_CSS);
|
|
2875
|
-
const autoId =
|
|
3062
|
+
const autoId = React25__namespace.default.useId();
|
|
2876
3063
|
const fieldId = id || autoId;
|
|
2877
3064
|
const invalid = Boolean(error);
|
|
2878
3065
|
const curControlled = currency !== void 0;
|
|
2879
|
-
const [curInternal, setCurInternal] =
|
|
3066
|
+
const [curInternal, setCurInternal] = React25__namespace.default.useState(defaultCurrency);
|
|
2880
3067
|
const cur = curControlled ? currency : curInternal;
|
|
2881
3068
|
const meta = CURRENCIES[cur] || CURRENCIES.USD;
|
|
2882
3069
|
const prec = meta.precision;
|
|
2883
3070
|
const valControlled = value !== void 0;
|
|
2884
|
-
const [valInternal, setValInternal] =
|
|
3071
|
+
const [valInternal, setValInternal] = React25__namespace.default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
|
|
2885
3072
|
const shown = valControlled ? clampPrecision(String(value ?? ""), prec) : valInternal;
|
|
2886
|
-
const
|
|
2887
|
-
const
|
|
3073
|
+
const descId = `${fieldId}-desc`;
|
|
3074
|
+
const describedBy = [error || hint ? descId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
3075
|
+
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
3076
|
+
React25__namespace.default.useEffect(() => {
|
|
3077
|
+
if (!valControlled) {
|
|
3078
|
+
const clamped = clampPrecision(valInternal, prec);
|
|
3079
|
+
if (clamped !== valInternal) {
|
|
3080
|
+
setValInternal(clamped);
|
|
3081
|
+
const n = Number(clamped);
|
|
3082
|
+
onValueChange?.(clamped === "" || Number.isNaN(n) ? null : n, clamped, cur);
|
|
3083
|
+
}
|
|
3084
|
+
} else {
|
|
3085
|
+
const raw = String(value ?? "");
|
|
3086
|
+
if (shown !== raw) {
|
|
3087
|
+
const n = Number(shown);
|
|
3088
|
+
onValueChange?.(shown === "" || Number.isNaN(n) ? null : n, shown, cur);
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
}, [prec, cur, shown, value, valControlled, valInternal]);
|
|
3092
|
+
const options = React25__namespace.default.useMemo(() => {
|
|
2888
3093
|
if (!currencies) return CURRENCY_OPTIONS;
|
|
2889
3094
|
return currencies.map((c) => typeof c === "string" ? { value: c, label: `${c} \u2014 ${(CURRENCIES[c] || {}).label || c}` } : c);
|
|
2890
3095
|
}, [currencies]);
|
|
@@ -2893,13 +3098,15 @@ function CurrencyField({
|
|
|
2893
3098
|
onCurrencyChange?.(next);
|
|
2894
3099
|
const reclamped = clampPrecision(shown, (CURRENCIES[next] || CURRENCIES.USD).precision);
|
|
2895
3100
|
if (!valControlled) setValInternal(reclamped);
|
|
2896
|
-
|
|
3101
|
+
const rn = Number(reclamped);
|
|
3102
|
+
onValueChange?.(reclamped === "" || Number.isNaN(rn) ? null : rn, reclamped, next);
|
|
2897
3103
|
}
|
|
2898
3104
|
function handleChange(e) {
|
|
2899
3105
|
onChange?.(e);
|
|
2900
3106
|
const next = clampPrecision(e.target.value, prec);
|
|
2901
3107
|
if (!valControlled) setValInternal(next);
|
|
2902
|
-
|
|
3108
|
+
const n = Number(next);
|
|
3109
|
+
onValueChange?.(next === "" || Number.isNaN(n) ? null : n, next, cur);
|
|
2903
3110
|
}
|
|
2904
3111
|
function handleBlur(e) {
|
|
2905
3112
|
rest.onBlur?.(e);
|
|
@@ -2910,13 +3117,14 @@ function CurrencyField({
|
|
|
2910
3117
|
if (!valControlled) setValInternal(fixed);
|
|
2911
3118
|
onValueChange?.(Number(fixed), fixed, cur);
|
|
2912
3119
|
}
|
|
3120
|
+
const curLabel = typeof label === "string" && label ? `${label} currency` : "Currency";
|
|
2913
3121
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-field ${className}`, children: [
|
|
2914
3122
|
__twcStyles,
|
|
2915
3123
|
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
2916
3124
|
label,
|
|
2917
3125
|
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
2918
3126
|
] }) : null,
|
|
2919
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cur", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, children: [
|
|
3127
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cur", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, "data-readonly": rest.readOnly || void 0, children: [
|
|
2920
3128
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-curf__pick", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2921
3129
|
Select,
|
|
2922
3130
|
{
|
|
@@ -2927,7 +3135,7 @@ function CurrencyField({
|
|
|
2927
3135
|
searchable: true,
|
|
2928
3136
|
portal: true,
|
|
2929
3137
|
minWidth: 260,
|
|
2930
|
-
"aria-label":
|
|
3138
|
+
"aria-label": curLabel,
|
|
2931
3139
|
onChange: setCurrency
|
|
2932
3140
|
}
|
|
2933
3141
|
) }),
|
|
@@ -2943,16 +3151,16 @@ function CurrencyField({
|
|
|
2943
3151
|
placeholder,
|
|
2944
3152
|
disabled,
|
|
2945
3153
|
required: required || void 0,
|
|
2946
|
-
"aria-invalid": invalid || void 0,
|
|
2947
3154
|
...rest,
|
|
2948
3155
|
onChange: handleChange,
|
|
2949
3156
|
onBlur: handleBlur,
|
|
3157
|
+
"aria-invalid": ariaInvalid,
|
|
2950
3158
|
"aria-describedby": describedBy
|
|
2951
3159
|
}
|
|
2952
3160
|
),
|
|
2953
3161
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-cur__code", children: meta.code })
|
|
2954
3162
|
] }),
|
|
2955
|
-
error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id:
|
|
3163
|
+
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
|
|
2956
3164
|
] });
|
|
2957
3165
|
}
|
|
2958
3166
|
var FIELD_CSS2 = `
|
|
@@ -2988,6 +3196,7 @@ var FIELD_CSS2 = `
|
|
|
2988
3196
|
.twc-input[data-invalid="true"] { border-color: var(--color-danger); }
|
|
2989
3197
|
.twc-input[data-invalid="true"]:focus-within { box-shadow: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 28%, transparent); }
|
|
2990
3198
|
.twc-input[data-disabled] { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
3199
|
+
.twc-input[data-readonly] { background: var(--color-surface-sunken); }
|
|
2991
3200
|
.twc-input__el {
|
|
2992
3201
|
flex: 1; min-width: 0; border: none; outline: none; background: transparent;
|
|
2993
3202
|
font-family: inherit; font-size: var(--text-sm); color: var(--color-text); height: 100%;
|
|
@@ -3003,6 +3212,17 @@ var FIELD_CSS2 = `
|
|
|
3003
3212
|
.twc-input__reveal:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
3004
3213
|
.twc-input__reveal svg { width: 17px; height: 17px; }
|
|
3005
3214
|
`;
|
|
3215
|
+
var INPUT_EXTRA_CSS = `
|
|
3216
|
+
.twc-input { overflow: hidden; }
|
|
3217
|
+
.twc-input__addon { align-self: stretch; display: inline-flex; align-items: center; padding-inline: var(--space-3);
|
|
3218
|
+
background: var(--color-surface-sunken); color: var(--color-text-muted); font-size: var(--text-sm);
|
|
3219
|
+
font-weight: var(--font-semibold); white-space: nowrap; flex: none; }
|
|
3220
|
+
.twc-input__addon--start { border-inline-end: var(--border-thin) solid var(--color-border); margin-inline-start: calc(-1 * var(--space-3)); }
|
|
3221
|
+
.twc-input__addon--end { border-inline-start: var(--border-thin) solid var(--color-border); margin-inline-end: calc(-1 * var(--space-3)); }
|
|
3222
|
+
.twc-field__footer { display: flex; align-items: center; gap: var(--space-2); }
|
|
3223
|
+
.twc-field__count { margin-inline-start: auto; font-size: var(--text-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; flex: none; }
|
|
3224
|
+
.twc-field__count[data-danger="true"] { color: var(--color-danger-subtle-fg); }
|
|
3225
|
+
`;
|
|
3006
3226
|
function Input({
|
|
3007
3227
|
label,
|
|
3008
3228
|
hint,
|
|
@@ -3012,6 +3232,9 @@ function Input({
|
|
|
3012
3232
|
tone = "primary",
|
|
3013
3233
|
leftIcon,
|
|
3014
3234
|
rightIcon,
|
|
3235
|
+
leftAddon,
|
|
3236
|
+
rightAddon,
|
|
3237
|
+
showCount = false,
|
|
3015
3238
|
type = "text",
|
|
3016
3239
|
disabled = false,
|
|
3017
3240
|
id,
|
|
@@ -3019,12 +3242,26 @@ function Input({
|
|
|
3019
3242
|
...rest
|
|
3020
3243
|
}) {
|
|
3021
3244
|
const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS2);
|
|
3022
|
-
const
|
|
3245
|
+
const __twcExtra = useScopedStyles("twc-input-extra-styles", INPUT_EXTRA_CSS);
|
|
3246
|
+
const autoId = React25__namespace.default.useId();
|
|
3023
3247
|
const fieldId = id || autoId;
|
|
3024
3248
|
const descId = `${fieldId}-desc`;
|
|
3249
|
+
const countId = `${fieldId}-count`;
|
|
3025
3250
|
const invalid = Boolean(error);
|
|
3251
|
+
const countControlled = rest.value !== void 0;
|
|
3252
|
+
const [len2, setLen] = React25__namespace.default.useState(() => String(rest.defaultValue ?? "").length);
|
|
3253
|
+
const count = countControlled ? String(rest.value ?? "").length : len2;
|
|
3254
|
+
const max = rest.maxLength;
|
|
3255
|
+
const showCounter = showCount && max != null;
|
|
3256
|
+
const near = showCounter && count >= Math.floor(max * 0.9);
|
|
3257
|
+
const handleChange = (e) => {
|
|
3258
|
+
rest.onChange?.(e);
|
|
3259
|
+
if (showCount && !countControlled) setLen(e.target.value.length);
|
|
3260
|
+
};
|
|
3261
|
+
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
3262
|
+
const describedBy = [error || hint ? descId : null, showCounter ? countId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
3026
3263
|
const isPassword = type === "password";
|
|
3027
|
-
const [revealed, setRevealed] =
|
|
3264
|
+
const [revealed, setRevealed] = React25__namespace.default.useState(false);
|
|
3028
3265
|
const effectiveType = isPassword && revealed ? "text" : type;
|
|
3029
3266
|
const suffix = rightIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-input__affix", children: rightIcon }) : isPassword ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3030
3267
|
"button",
|
|
@@ -3049,11 +3286,13 @@ function Input({
|
|
|
3049
3286
|
) : null;
|
|
3050
3287
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-field ${className}`, children: [
|
|
3051
3288
|
__twcStyles,
|
|
3289
|
+
__twcExtra,
|
|
3052
3290
|
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
3053
3291
|
label,
|
|
3054
3292
|
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
3055
3293
|
] }) : null,
|
|
3056
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-input", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, children: [
|
|
3294
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-input", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, "data-readonly": rest.readOnly || void 0, children: [
|
|
3295
|
+
leftAddon != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-input__addon twc-input__addon--start", children: leftAddon }) : null,
|
|
3057
3296
|
leftIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-input__affix", children: leftIcon }) : null,
|
|
3058
3297
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3059
3298
|
"input",
|
|
@@ -3064,14 +3303,23 @@ function Input({
|
|
|
3064
3303
|
disabled,
|
|
3065
3304
|
required: required || void 0,
|
|
3066
3305
|
"aria-required": required || void 0,
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3306
|
+
...rest,
|
|
3307
|
+
onChange: handleChange,
|
|
3308
|
+
"aria-invalid": ariaInvalid,
|
|
3309
|
+
"aria-describedby": describedBy
|
|
3070
3310
|
}
|
|
3071
3311
|
),
|
|
3072
|
-
suffix
|
|
3312
|
+
suffix,
|
|
3313
|
+
rightAddon != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-input__addon twc-input__addon--end", children: rightAddon }) : null
|
|
3073
3314
|
] }),
|
|
3074
|
-
error
|
|
3315
|
+
error || hint || showCounter ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-field__footer", children: [
|
|
3316
|
+
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,
|
|
3317
|
+
showCounter ? /* @__PURE__ */ jsxRuntime.jsxs("span", { id: countId, className: "twc-field__count", "data-danger": near || void 0, "aria-live": "polite", children: [
|
|
3318
|
+
count,
|
|
3319
|
+
" / ",
|
|
3320
|
+
max
|
|
3321
|
+
] }) : null
|
|
3322
|
+
] }) : null
|
|
3075
3323
|
] });
|
|
3076
3324
|
}
|
|
3077
3325
|
var MULTI_CSS = `
|
|
@@ -3149,6 +3397,10 @@ var MULTI_CSS = `
|
|
|
3149
3397
|
.twc-opt__label { line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3150
3398
|
.twc-opt__desc { font-size: var(--text-xs); color: var(--color-text-muted); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3151
3399
|
.twc-pop__empty { padding: 14px 12px; text-align: center; font-size: var(--text-sm); color: var(--color-text-subtle); }
|
|
3400
|
+
.twc-opt[data-disabled="true"] { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
|
|
3401
|
+
.twc-pop__loading { display: flex; align-items: center; justify-content: center; gap: var(--space-2); padding: 14px 12px; font-size: var(--text-sm); color: var(--color-text-muted); }
|
|
3402
|
+
.twc-pop__spinner { width: 15px; height: 15px; border-radius: var(--radius-full); border: 2px solid var(--color-border); border-top-color: var(--color-primary); animation: twico-spin 0.7s linear infinite; }
|
|
3403
|
+
.twc-ms__more { flex: none; align-self: center; font-size: var(--text-xs); font-weight: var(--font-semibold); color: var(--color-text-muted); background: var(--color-surface-sunken); border-radius: var(--radius-sm); padding: 2px 7px; }
|
|
3152
3404
|
`;
|
|
3153
3405
|
function toOpt3(o) {
|
|
3154
3406
|
return typeof o === "string" ? { value: o, label: o } : o;
|
|
@@ -3198,6 +3450,11 @@ function MultiSelect({
|
|
|
3198
3450
|
placement = "bottom",
|
|
3199
3451
|
portal = true,
|
|
3200
3452
|
minWidth = 0,
|
|
3453
|
+
loading = false,
|
|
3454
|
+
emptyText = "No results found",
|
|
3455
|
+
name,
|
|
3456
|
+
max,
|
|
3457
|
+
maxTagCount,
|
|
3201
3458
|
id,
|
|
3202
3459
|
className = "",
|
|
3203
3460
|
onFocus,
|
|
@@ -3205,28 +3462,38 @@ function MultiSelect({
|
|
|
3205
3462
|
...rest
|
|
3206
3463
|
}) {
|
|
3207
3464
|
const __twcStyles = useScopedStyles("twc-ms-styles", MULTI_CSS);
|
|
3208
|
-
const groups =
|
|
3209
|
-
const flat =
|
|
3210
|
-
const autoId =
|
|
3465
|
+
const groups = React25__namespace.default.useMemo(() => normalizeGroups3(options), [options]);
|
|
3466
|
+
const flat = React25__namespace.default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
|
|
3467
|
+
const autoId = React25__namespace.default.useId();
|
|
3211
3468
|
const fieldId = id || autoId;
|
|
3212
|
-
const [internal, setInternal] =
|
|
3469
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
3213
3470
|
const selected = value !== void 0 ? value : internal;
|
|
3214
|
-
const [open, setOpen] =
|
|
3215
|
-
const [query, setQuery] =
|
|
3216
|
-
const [active, setActive] =
|
|
3217
|
-
const [coords, setCoords] =
|
|
3218
|
-
const wrapRef =
|
|
3219
|
-
const controlRef =
|
|
3220
|
-
const inputRef =
|
|
3221
|
-
const popRef =
|
|
3222
|
-
const listRef =
|
|
3223
|
-
const activeRef =
|
|
3224
|
-
const fGroups =
|
|
3471
|
+
const [open, setOpen] = React25__namespace.default.useState(false);
|
|
3472
|
+
const [query, setQuery] = React25__namespace.default.useState("");
|
|
3473
|
+
const [active, setActive] = React25__namespace.default.useState(0);
|
|
3474
|
+
const [coords, setCoords] = React25__namespace.default.useState(null);
|
|
3475
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
3476
|
+
const controlRef = React25__namespace.default.useRef(null);
|
|
3477
|
+
const inputRef = React25__namespace.default.useRef(null);
|
|
3478
|
+
const popRef = React25__namespace.default.useRef(null);
|
|
3479
|
+
const listRef = React25__namespace.default.useRef(null);
|
|
3480
|
+
const activeRef = React25__namespace.default.useRef(null);
|
|
3481
|
+
const fGroups = React25__namespace.default.useMemo(
|
|
3225
3482
|
() => groups.map((g) => ({ group: g.group, options: g.options.filter((o) => matches2(o, query.trim())) })).filter((g) => g.options.length),
|
|
3226
3483
|
[groups, query]
|
|
3227
3484
|
);
|
|
3228
|
-
const visible =
|
|
3229
|
-
const
|
|
3485
|
+
const visible = React25__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
|
|
3486
|
+
const capReached = max != null && (value !== void 0 ? value : internal).length >= max;
|
|
3487
|
+
const isOptDisabled = (o) => o.disabled || capReached && !(value !== void 0 ? value : internal).includes(o.value);
|
|
3488
|
+
const nextEnabled = (from, dir) => {
|
|
3489
|
+
let i = from + dir;
|
|
3490
|
+
while (i >= 0 && i < visible.length) {
|
|
3491
|
+
if (!isOptDisabled(visible[i])) return i;
|
|
3492
|
+
i += dir;
|
|
3493
|
+
}
|
|
3494
|
+
return from;
|
|
3495
|
+
};
|
|
3496
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
3230
3497
|
const el = controlRef.current;
|
|
3231
3498
|
if (!el) return;
|
|
3232
3499
|
const r = el.getBoundingClientRect();
|
|
@@ -3241,7 +3508,7 @@ function MultiSelect({
|
|
|
3241
3508
|
flip
|
|
3242
3509
|
});
|
|
3243
3510
|
}, [placement, minWidth]);
|
|
3244
|
-
|
|
3511
|
+
React25__namespace.default.useEffect(() => {
|
|
3245
3512
|
if (!open || !portal) return;
|
|
3246
3513
|
place();
|
|
3247
3514
|
const onMove = () => place();
|
|
@@ -3252,7 +3519,7 @@ function MultiSelect({
|
|
|
3252
3519
|
window.removeEventListener("resize", onMove);
|
|
3253
3520
|
};
|
|
3254
3521
|
}, [open, portal, place]);
|
|
3255
|
-
|
|
3522
|
+
React25__namespace.default.useEffect(() => {
|
|
3256
3523
|
if (!open) return;
|
|
3257
3524
|
const onDown = (e) => {
|
|
3258
3525
|
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
@@ -3263,10 +3530,10 @@ function MultiSelect({
|
|
|
3263
3530
|
document.addEventListener("mousedown", onDown);
|
|
3264
3531
|
return () => document.removeEventListener("mousedown", onDown);
|
|
3265
3532
|
}, [open]);
|
|
3266
|
-
|
|
3533
|
+
React25__namespace.default.useEffect(() => {
|
|
3267
3534
|
setActive(0);
|
|
3268
3535
|
}, [query]);
|
|
3269
|
-
|
|
3536
|
+
React25__namespace.default.useEffect(() => {
|
|
3270
3537
|
if (open) ensureVisible3(listRef.current, activeRef.current);
|
|
3271
3538
|
}, [active, open]);
|
|
3272
3539
|
function commit(next) {
|
|
@@ -3274,7 +3541,10 @@ function MultiSelect({
|
|
|
3274
3541
|
onChange?.(next);
|
|
3275
3542
|
}
|
|
3276
3543
|
function toggle(v) {
|
|
3277
|
-
|
|
3544
|
+
const o = flat.find((x) => x.value === v);
|
|
3545
|
+
const isSel = selected.includes(v);
|
|
3546
|
+
if (!isSel && o && isOptDisabled(o)) return;
|
|
3547
|
+
commit(isSel ? selected.filter((x) => x !== v) : [...selected, v]);
|
|
3278
3548
|
setQuery("");
|
|
3279
3549
|
inputRef.current?.focus();
|
|
3280
3550
|
}
|
|
@@ -3282,10 +3552,10 @@ function MultiSelect({
|
|
|
3282
3552
|
if (e.key === "ArrowDown") {
|
|
3283
3553
|
e.preventDefault();
|
|
3284
3554
|
if (!open) setOpen(true);
|
|
3285
|
-
else setActive((a) =>
|
|
3555
|
+
else setActive((a) => nextEnabled(a, 1));
|
|
3286
3556
|
} else if (e.key === "ArrowUp") {
|
|
3287
3557
|
e.preventDefault();
|
|
3288
|
-
setActive((a) =>
|
|
3558
|
+
setActive((a) => nextEnabled(a, -1));
|
|
3289
3559
|
} else if (e.key === "Enter") {
|
|
3290
3560
|
e.preventDefault();
|
|
3291
3561
|
if (open && visible[active]) toggle(visible[active].value);
|
|
@@ -3303,12 +3573,16 @@ function MultiSelect({
|
|
|
3303
3573
|
const descId = `${fieldId}-desc`;
|
|
3304
3574
|
const describedBy = error || hint ? descId : void 0;
|
|
3305
3575
|
let counter = -1;
|
|
3306
|
-
const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children:
|
|
3576
|
+
const popInner = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-pop__loading", role: "status", children: [
|
|
3577
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
|
|
3578
|
+
"Loading\u2026"
|
|
3579
|
+
] }) : visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
|
|
3307
3580
|
g.group ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
3308
3581
|
g.options.map((o) => {
|
|
3309
3582
|
counter += 1;
|
|
3310
3583
|
const idx = counter;
|
|
3311
3584
|
const isSel = selected.includes(o.value);
|
|
3585
|
+
const optDisabled = isOptDisabled(o);
|
|
3312
3586
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3313
3587
|
"button",
|
|
3314
3588
|
{
|
|
@@ -3318,9 +3592,14 @@ function MultiSelect({
|
|
|
3318
3592
|
role: "option",
|
|
3319
3593
|
"aria-selected": isSel,
|
|
3320
3594
|
ref: idx === active ? activeRef : null,
|
|
3595
|
+
disabled: optDisabled || void 0,
|
|
3596
|
+
"aria-disabled": optDisabled || void 0,
|
|
3597
|
+
"data-disabled": optDisabled || void 0,
|
|
3321
3598
|
"data-selected": isSel || void 0,
|
|
3322
3599
|
"data-active": idx === active || void 0,
|
|
3323
|
-
onMouseEnter: () =>
|
|
3600
|
+
onMouseEnter: () => {
|
|
3601
|
+
if (!optDisabled) setActive(idx);
|
|
3602
|
+
},
|
|
3324
3603
|
onMouseDown: (e) => e.preventDefault(),
|
|
3325
3604
|
onClick: () => toggle(o.value),
|
|
3326
3605
|
children: [
|
|
@@ -3346,7 +3625,7 @@ function MultiSelect({
|
|
|
3346
3625
|
{
|
|
3347
3626
|
className: "twc-pop twc-pop--portal",
|
|
3348
3627
|
ref: popRef,
|
|
3349
|
-
"data-placement": coords.flip ? "top" :
|
|
3628
|
+
"data-placement": coords.flip ? "top" : "bottom",
|
|
3350
3629
|
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-tooltip)" },
|
|
3351
3630
|
children: popInner
|
|
3352
3631
|
}
|
|
@@ -3359,6 +3638,7 @@ function MultiSelect({
|
|
|
3359
3638
|
}
|
|
3360
3639
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-field ${className}`, ref: wrapRef, children: [
|
|
3361
3640
|
__twcStyles,
|
|
3641
|
+
name ? selected.map((v, i) => /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: v }, i)) : null,
|
|
3362
3642
|
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
3363
3643
|
label,
|
|
3364
3644
|
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
@@ -3381,13 +3661,18 @@ function MultiSelect({
|
|
|
3381
3661
|
}
|
|
3382
3662
|
},
|
|
3383
3663
|
children: [
|
|
3384
|
-
selectedOpts.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-ms__chip", children: [
|
|
3664
|
+
(maxTagCount != null ? selectedOpts.slice(0, maxTagCount) : selectedOpts).map((o) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-ms__chip", children: [
|
|
3385
3665
|
o.label,
|
|
3386
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-ms__chip-x", "aria-label": `Remove ${o.label}`, onClick: (e) => {
|
|
3666
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", tabIndex: -1, className: "twc-ms__chip-x", "aria-label": `Remove ${o.label}`, onClick: (e) => {
|
|
3387
3667
|
e.stopPropagation();
|
|
3388
3668
|
toggle(o.value);
|
|
3389
3669
|
}, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) })
|
|
3390
3670
|
] }, o.value)),
|
|
3671
|
+
maxTagCount != null && selectedOpts.length > maxTagCount ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-ms__more", title: selectedOpts.slice(maxTagCount).map((o) => o.label).join(", "), children: [
|
|
3672
|
+
"+",
|
|
3673
|
+
selectedOpts.length - maxTagCount,
|
|
3674
|
+
" more"
|
|
3675
|
+
] }) : null,
|
|
3391
3676
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3392
3677
|
"input",
|
|
3393
3678
|
{
|
|
@@ -3419,7 +3704,7 @@ function MultiSelect({
|
|
|
3419
3704
|
...rest
|
|
3420
3705
|
}
|
|
3421
3706
|
),
|
|
3422
|
-
clearable && selected.length > 0 && !disabled ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-ms__clear", "aria-label": "Clear all", onClick: (e) => {
|
|
3707
|
+
clearable && selected.length > 0 && !disabled ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", tabIndex: -1, className: "twc-ms__clear", "aria-label": "Clear all", onClick: (e) => {
|
|
3423
3708
|
e.stopPropagation();
|
|
3424
3709
|
commit([]);
|
|
3425
3710
|
setQuery("");
|
|
@@ -3447,15 +3732,6 @@ function MultiSelect({
|
|
|
3447
3732
|
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
|
|
3448
3733
|
] });
|
|
3449
3734
|
}
|
|
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
|
-
}
|
|
3459
3735
|
var PAGINATION_CSS = `
|
|
3460
3736
|
.twc-pagination { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-sans); }
|
|
3461
3737
|
.twc-page {
|
|
@@ -3521,6 +3797,7 @@ function Pagination({
|
|
|
3521
3797
|
showJumper,
|
|
3522
3798
|
showPageJumper,
|
|
3523
3799
|
jumperLabel = "Go to",
|
|
3800
|
+
getPageLabel,
|
|
3524
3801
|
className = "",
|
|
3525
3802
|
...rest
|
|
3526
3803
|
}) {
|
|
@@ -3529,7 +3806,7 @@ function Pagination({
|
|
|
3529
3806
|
}
|
|
3530
3807
|
const jumperEnabled = showPageJumper ?? showJumper;
|
|
3531
3808
|
const __twcStyles = useScopedStyles("twc-pagination-styles", PAGINATION_CSS);
|
|
3532
|
-
const [internal, setInternal] =
|
|
3809
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultPage);
|
|
3533
3810
|
const page = pageProp !== void 0 ? pageProp : internal;
|
|
3534
3811
|
const pages = buildPages(page, total, siblings, boundaries);
|
|
3535
3812
|
const go = (p) => {
|
|
@@ -3537,7 +3814,7 @@ function Pagination({
|
|
|
3537
3814
|
if (pageProp === void 0) setInternal(p);
|
|
3538
3815
|
onChange?.(p);
|
|
3539
3816
|
};
|
|
3540
|
-
const [jump, setJump] =
|
|
3817
|
+
const [jump, setJump] = React25__namespace.default.useState("");
|
|
3541
3818
|
const submitJump = () => {
|
|
3542
3819
|
const n = parseInt(jump, 10);
|
|
3543
3820
|
if (!Number.isNaN(n)) go(Math.min(Math.max(n, 1), total));
|
|
@@ -3554,6 +3831,7 @@ function Pagination({
|
|
|
3554
3831
|
className: "twc-page",
|
|
3555
3832
|
"data-size": size,
|
|
3556
3833
|
"data-active": p === page || void 0,
|
|
3834
|
+
"aria-label": getPageLabel ? getPageLabel(p) : `Page ${p}`,
|
|
3557
3835
|
"aria-current": p === page ? "page" : void 0,
|
|
3558
3836
|
onClick: () => go(p),
|
|
3559
3837
|
children: p
|
|
@@ -3586,6 +3864,154 @@ function Pagination({
|
|
|
3586
3864
|
] }) : null
|
|
3587
3865
|
] });
|
|
3588
3866
|
}
|
|
3867
|
+
var TOOLTIP_CSS = `
|
|
3868
|
+
.twc-tooltip-wrap { display: inline-flex; }
|
|
3869
|
+
.twc-tooltip {
|
|
3870
|
+
position: fixed; z-index: var(--z-tooltip);
|
|
3871
|
+
padding: 6px 10px; border-radius: var(--radius-md);
|
|
3872
|
+
background: var(--color-text); color: var(--color-surface);
|
|
3873
|
+
font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--font-medium);
|
|
3874
|
+
line-height: 1.3; white-space: normal; max-width: var(--_tw-maxw, 260px); box-shadow: var(--shadow-md);
|
|
3875
|
+
opacity: 0; transform: scale(0.9); transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-spring);
|
|
3876
|
+
}
|
|
3877
|
+
.twc-tooltip[data-show="true"] { pointer-events: auto; }
|
|
3878
|
+
.twc-tooltip[data-show="true"] { opacity: 1; transform: scale(1); }
|
|
3879
|
+
.twc-tooltip[data-place="top"] { transform-origin: bottom center; translate: -50% 0; }
|
|
3880
|
+
.twc-tooltip[data-place="bottom"] { transform-origin: top center; translate: -50% 0; }
|
|
3881
|
+
.twc-tooltip[data-place="left"] { transform-origin: right center; translate: 0 -50%; }
|
|
3882
|
+
.twc-tooltip[data-place="right"] { transform-origin: left center; translate: 0 -50%; }
|
|
3883
|
+
.twc-tooltip[data-show="true"][data-place="top"], .twc-tooltip[data-show="true"][data-place="bottom"] { transform: scale(1); }
|
|
3884
|
+
.twc-tooltip__arrow { position: absolute; width: 7px; height: 7px; background: var(--color-text); transform: rotate(45deg); }
|
|
3885
|
+
.twc-tooltip[data-place="top"] .twc-tooltip__arrow { bottom: -3px; left: 50%; margin-left: -3.5px; }
|
|
3886
|
+
.twc-tooltip[data-place="bottom"] .twc-tooltip__arrow { top: -3px; left: 50%; margin-left: -3.5px; }
|
|
3887
|
+
.twc-tooltip[data-place="left"] .twc-tooltip__arrow { right: -3px; top: 50%; margin-top: -3.5px; }
|
|
3888
|
+
.twc-tooltip[data-place="right"] .twc-tooltip__arrow { left: -3px; top: 50%; margin-top: -3.5px; }
|
|
3889
|
+
@media (prefers-reduced-motion: reduce) { .twc-tooltip { transition: opacity var(--duration-fast) linear; transform: none; } }
|
|
3890
|
+
`;
|
|
3891
|
+
function Tooltip({
|
|
3892
|
+
children,
|
|
3893
|
+
label,
|
|
3894
|
+
placement = "top",
|
|
3895
|
+
delay = 120,
|
|
3896
|
+
className = "",
|
|
3897
|
+
...rest
|
|
3898
|
+
}) {
|
|
3899
|
+
const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
|
|
3900
|
+
const id = React25__namespace.default.useId();
|
|
3901
|
+
const [show, setShow] = React25__namespace.default.useState(false);
|
|
3902
|
+
const [coords, setCoords] = React25__namespace.default.useState(null);
|
|
3903
|
+
const timer = React25__namespace.default.useRef(null);
|
|
3904
|
+
const closeTimer = React25__namespace.default.useRef(null);
|
|
3905
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
3906
|
+
const tipRef = React25__namespace.default.useRef(null);
|
|
3907
|
+
const open = () => {
|
|
3908
|
+
clearTimeout(closeTimer.current);
|
|
3909
|
+
clearTimeout(timer.current);
|
|
3910
|
+
timer.current = setTimeout(() => setShow(true), delay);
|
|
3911
|
+
};
|
|
3912
|
+
const close = () => {
|
|
3913
|
+
clearTimeout(timer.current);
|
|
3914
|
+
clearTimeout(closeTimer.current);
|
|
3915
|
+
closeTimer.current = setTimeout(() => setShow(false), 120);
|
|
3916
|
+
};
|
|
3917
|
+
const cancelClose = () => {
|
|
3918
|
+
clearTimeout(closeTimer.current);
|
|
3919
|
+
};
|
|
3920
|
+
React25__namespace.default.useEffect(() => () => {
|
|
3921
|
+
clearTimeout(timer.current);
|
|
3922
|
+
clearTimeout(closeTimer.current);
|
|
3923
|
+
}, []);
|
|
3924
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
3925
|
+
const el = wrapRef.current;
|
|
3926
|
+
if (!el) return;
|
|
3927
|
+
const r = el.getBoundingClientRect();
|
|
3928
|
+
const cx = Math.round(r.left + r.width / 2), cy = Math.round(r.top + r.height / 2);
|
|
3929
|
+
const vw = window.innerWidth, vh = window.innerHeight, gap = 8, margin = 8;
|
|
3930
|
+
const tip = tipRef.current;
|
|
3931
|
+
const tw = tip ? tip.offsetWidth : 0, th = tip ? tip.offsetHeight : 0;
|
|
3932
|
+
const clampX = (c) => tw ? Math.round(Math.min(Math.max(c, margin + tw / 2), vw - margin - tw / 2)) : c;
|
|
3933
|
+
const clampY = (c) => th ? Math.round(Math.min(Math.max(c, margin + th / 2), vh - margin - th / 2)) : c;
|
|
3934
|
+
const spaceAbove = r.top - gap - margin, spaceBelow = vh - r.bottom - gap - margin;
|
|
3935
|
+
const spaceLeft = r.left - gap - margin, spaceRight = vw - r.right - gap - margin;
|
|
3936
|
+
let side = placement;
|
|
3937
|
+
if (placement === "top" && spaceAbove < th && spaceBelow > spaceAbove) side = "bottom";
|
|
3938
|
+
else if (placement === "bottom" && spaceBelow < th && spaceAbove > spaceBelow) side = "top";
|
|
3939
|
+
else if (placement === "left" && spaceLeft < tw && spaceRight > spaceLeft) side = "right";
|
|
3940
|
+
else if (placement === "right" && spaceRight < tw && spaceLeft > spaceRight) side = "left";
|
|
3941
|
+
const base = { left: "auto", right: "auto", top: "auto", bottom: "auto", place: side };
|
|
3942
|
+
if (side === "bottom") setCoords({ ...base, left: clampX(cx), top: Math.round(r.bottom + gap) });
|
|
3943
|
+
else if (side === "left") setCoords({ ...base, top: clampY(cy), right: Math.round(vw - r.left + gap) });
|
|
3944
|
+
else if (side === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
|
|
3945
|
+
else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
|
|
3946
|
+
}, [placement]);
|
|
3947
|
+
React25__namespace.default.useEffect(() => {
|
|
3948
|
+
place();
|
|
3949
|
+
}, [place]);
|
|
3950
|
+
React25__namespace.default.useEffect(() => {
|
|
3951
|
+
if (!show) return void 0;
|
|
3952
|
+
place();
|
|
3953
|
+
const onMove = () => place();
|
|
3954
|
+
window.addEventListener("scroll", onMove, true);
|
|
3955
|
+
window.addEventListener("resize", onMove);
|
|
3956
|
+
return () => {
|
|
3957
|
+
window.removeEventListener("scroll", onMove, true);
|
|
3958
|
+
window.removeEventListener("resize", onMove);
|
|
3959
|
+
};
|
|
3960
|
+
}, [show, place]);
|
|
3961
|
+
React25__namespace.default.useEffect(() => {
|
|
3962
|
+
if (!show) return;
|
|
3963
|
+
const onKeyDown = (e) => {
|
|
3964
|
+
if (e.key === "Escape") {
|
|
3965
|
+
clearTimeout(timer.current);
|
|
3966
|
+
setShow(false);
|
|
3967
|
+
}
|
|
3968
|
+
};
|
|
3969
|
+
document.addEventListener("keydown", onKeyDown);
|
|
3970
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
3971
|
+
}, [show]);
|
|
3972
|
+
const describedBy = show ? id : void 0;
|
|
3973
|
+
const trigger = React25__namespace.default.isValidElement(children) && children.type !== React25__namespace.default.Fragment ? React25__namespace.default.cloneElement(children, {
|
|
3974
|
+
"aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
|
|
3975
|
+
}) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-describedby": describedBy, children });
|
|
3976
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3977
|
+
"span",
|
|
3978
|
+
{
|
|
3979
|
+
ref: wrapRef,
|
|
3980
|
+
className: `twc-tooltip-wrap ${className}`,
|
|
3981
|
+
onMouseEnter: open,
|
|
3982
|
+
onMouseLeave: close,
|
|
3983
|
+
onFocus: open,
|
|
3984
|
+
onBlur: close,
|
|
3985
|
+
...rest,
|
|
3986
|
+
children: [
|
|
3987
|
+
__twcStyles,
|
|
3988
|
+
trigger,
|
|
3989
|
+
coords ? reactDom.createPortal(
|
|
3990
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3991
|
+
"span",
|
|
3992
|
+
{
|
|
3993
|
+
ref: tipRef,
|
|
3994
|
+
id,
|
|
3995
|
+
className: "twc-tooltip",
|
|
3996
|
+
"data-place": coords.place || placement,
|
|
3997
|
+
"data-show": show || void 0,
|
|
3998
|
+
role: "tooltip",
|
|
3999
|
+
"aria-hidden": show ? void 0 : "true",
|
|
4000
|
+
onMouseEnter: cancelClose,
|
|
4001
|
+
onMouseLeave: close,
|
|
4002
|
+
style: { position: "fixed", left: coords.left, right: coords.right, top: coords.top, bottom: coords.bottom },
|
|
4003
|
+
children: [
|
|
4004
|
+
label,
|
|
4005
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
|
|
4006
|
+
]
|
|
4007
|
+
}
|
|
4008
|
+
),
|
|
4009
|
+
document.body
|
|
4010
|
+
) : null
|
|
4011
|
+
]
|
|
4012
|
+
}
|
|
4013
|
+
);
|
|
4014
|
+
}
|
|
3589
4015
|
var DT_CSS = `
|
|
3590
4016
|
.twc-dt { display: flex; flex-direction: column; font-family: var(--font-sans); color: var(--color-text);
|
|
3591
4017
|
border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg);
|
|
@@ -4148,9 +4574,9 @@ function runDatatableQuery(rows, query, options = {}) {
|
|
|
4148
4574
|
return { rows: page, total, filtered: out };
|
|
4149
4575
|
}
|
|
4150
4576
|
function useFloating() {
|
|
4151
|
-
const [pos, setPos] =
|
|
4152
|
-
const cfg =
|
|
4153
|
-
const place =
|
|
4577
|
+
const [pos, setPos] = React25__namespace.default.useState(null);
|
|
4578
|
+
const cfg = React25__namespace.default.useRef(null);
|
|
4579
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
4154
4580
|
const c = cfg.current;
|
|
4155
4581
|
if (!c || !c.el || !c.el.isConnected) return null;
|
|
4156
4582
|
const r = c.el.getBoundingClientRect();
|
|
@@ -4161,17 +4587,17 @@ function useFloating() {
|
|
|
4161
4587
|
const top = r.bottom + 6;
|
|
4162
4588
|
return { top, left, width: c.width, anchorX: r.left + r.width / 2, maxHeight: Math.max(180, vh - top - M) };
|
|
4163
4589
|
}, []);
|
|
4164
|
-
const open =
|
|
4590
|
+
const open = React25__namespace.default.useCallback((el, align = "left", width = 220) => {
|
|
4165
4591
|
cfg.current = { el, align, width };
|
|
4166
4592
|
const p = place();
|
|
4167
4593
|
if (p) setPos(p);
|
|
4168
4594
|
}, [place]);
|
|
4169
|
-
const close =
|
|
4595
|
+
const close = React25__namespace.default.useCallback(() => {
|
|
4170
4596
|
cfg.current = null;
|
|
4171
4597
|
setPos(null);
|
|
4172
4598
|
}, []);
|
|
4173
4599
|
const isOpen = pos != null;
|
|
4174
|
-
|
|
4600
|
+
React25__namespace.default.useEffect(() => {
|
|
4175
4601
|
if (!isOpen) return void 0;
|
|
4176
4602
|
const update = () => {
|
|
4177
4603
|
const p = place();
|
|
@@ -4195,9 +4621,9 @@ function Caret({ pos }) {
|
|
|
4195
4621
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__caret", style: { left } });
|
|
4196
4622
|
}
|
|
4197
4623
|
function EditCell({ col, value, options, onChange, onCommit, onCommitValue, onCancel, onKeyDown }) {
|
|
4198
|
-
const ref =
|
|
4624
|
+
const ref = React25__namespace.default.useRef(null);
|
|
4199
4625
|
const isSelect = col.editType === "select" || options && col.editType !== "text";
|
|
4200
|
-
|
|
4626
|
+
React25__namespace.default.useEffect(() => {
|
|
4201
4627
|
if (isSelect) {
|
|
4202
4628
|
const t = setTimeout(() => ref.current?.querySelector(".twc-sel__trigger")?.click(), 0);
|
|
4203
4629
|
return () => clearTimeout(t);
|
|
@@ -4373,6 +4799,8 @@ function Datatable({
|
|
|
4373
4799
|
aggregationValues = null,
|
|
4374
4800
|
disableColumnReorder = false,
|
|
4375
4801
|
disableColumnResize = false,
|
|
4802
|
+
emptyMessage,
|
|
4803
|
+
renderEmpty,
|
|
4376
4804
|
editMode = false,
|
|
4377
4805
|
onRowUpdate,
|
|
4378
4806
|
onRowsChange,
|
|
@@ -4400,7 +4828,7 @@ function Datatable({
|
|
|
4400
4828
|
...rest
|
|
4401
4829
|
}) {
|
|
4402
4830
|
const __twcStyles = useScopedStyles("twc-dt-styles", DT_CSS);
|
|
4403
|
-
const cols =
|
|
4831
|
+
const cols = React25__namespace.default.useMemo(() => {
|
|
4404
4832
|
const out = columns.map((c) => {
|
|
4405
4833
|
const isActions = c.type === "actions";
|
|
4406
4834
|
return {
|
|
@@ -4435,7 +4863,7 @@ function Datatable({
|
|
|
4435
4863
|
}
|
|
4436
4864
|
return out;
|
|
4437
4865
|
}, [columns, rowPinning]);
|
|
4438
|
-
const _autoKey =
|
|
4866
|
+
const _autoKey = React25__namespace.default.useRef();
|
|
4439
4867
|
if (!_autoKey.current) _autoKey.current = { map: /* @__PURE__ */ new WeakMap(), n: 0 };
|
|
4440
4868
|
const keyOf = rowKey || ((r, i) => {
|
|
4441
4869
|
if (r != null && r.id != null) return r.id;
|
|
@@ -4450,17 +4878,17 @@ function Datatable({
|
|
|
4450
4878
|
}
|
|
4451
4879
|
return i;
|
|
4452
4880
|
});
|
|
4453
|
-
const [sort, setSort] =
|
|
4454
|
-
const [filters, setFilters] =
|
|
4455
|
-
const [hidden, setHidden] =
|
|
4456
|
-
const [showRowNum, setShowRowNum] =
|
|
4457
|
-
const [wrapped, setWrapped] =
|
|
4881
|
+
const [sort, setSort] = React25__namespace.default.useState(null);
|
|
4882
|
+
const [filters, setFilters] = React25__namespace.default.useState([]);
|
|
4883
|
+
const [hidden, setHidden] = React25__namespace.default.useState(() => /* @__PURE__ */ new Set());
|
|
4884
|
+
const [showRowNum, setShowRowNum] = React25__namespace.default.useState(rowNumbers);
|
|
4885
|
+
const [wrapped, setWrapped] = React25__namespace.default.useState(() => new Set((columns || []).filter((c) => c.wrapText).map((c) => c.field)));
|
|
4458
4886
|
const toggleWrap = (field) => setWrapped((w) => {
|
|
4459
4887
|
const n = new Set(w);
|
|
4460
4888
|
n.has(field) ? n.delete(field) : n.add(field);
|
|
4461
4889
|
return n;
|
|
4462
4890
|
});
|
|
4463
|
-
const [pins, setPins] =
|
|
4891
|
+
const [pins, setPins] = React25__namespace.default.useState(() => {
|
|
4464
4892
|
const left = [], right = [];
|
|
4465
4893
|
columns.forEach((c) => {
|
|
4466
4894
|
if (c.pinned === "left") left.push(c.field);
|
|
@@ -4468,34 +4896,34 @@ function Datatable({
|
|
|
4468
4896
|
});
|
|
4469
4897
|
return { left, right };
|
|
4470
4898
|
});
|
|
4471
|
-
const [density, setDensity] =
|
|
4472
|
-
const [quick, setQuick] =
|
|
4473
|
-
const [selected, setSelected] =
|
|
4474
|
-
const [activeRow, setActiveRow] =
|
|
4475
|
-
const [activeCell, setActiveCell] =
|
|
4476
|
-
const [page, setPage] =
|
|
4477
|
-
const [rowsPerPage, setRowsPerPage] =
|
|
4478
|
-
const [colQuery, setColQuery] =
|
|
4479
|
-
const [widths, setWidths] =
|
|
4480
|
-
const [order, setOrder] =
|
|
4481
|
-
const [drag, setDrag] =
|
|
4482
|
-
const [aggOn, setAggOn] =
|
|
4483
|
-
const [focus, setFocus] =
|
|
4484
|
-
const gridRef =
|
|
4485
|
-
const [groupBy, setGroupBy] =
|
|
4486
|
-
const [collapsed, setCollapsed] =
|
|
4487
|
-
const [pinnedRows, setPinnedRows] =
|
|
4488
|
-
const [headH, setHeadH] =
|
|
4489
|
-
const theadRef =
|
|
4490
|
-
const [rowOrder, setRowOrder] =
|
|
4491
|
-
const [rowHeights, setRowHeights] =
|
|
4492
|
-
const [rowDrag, setRowDrag] =
|
|
4493
|
-
const [rowGrab, setRowGrab] =
|
|
4494
|
-
const [reorderMsg, setReorderMsg] =
|
|
4495
|
-
const rowFocusRef =
|
|
4496
|
-
const rootRef =
|
|
4497
|
-
const [compact, setCompact] =
|
|
4498
|
-
|
|
4899
|
+
const [density, setDensity] = React25__namespace.default.useState(densityProp);
|
|
4900
|
+
const [quick, setQuick] = React25__namespace.default.useState("");
|
|
4901
|
+
const [selected, setSelected] = React25__namespace.default.useState(() => /* @__PURE__ */ new Set());
|
|
4902
|
+
const [activeRow, setActiveRow] = React25__namespace.default.useState(null);
|
|
4903
|
+
const [activeCell, setActiveCell] = React25__namespace.default.useState(null);
|
|
4904
|
+
const [page, setPage] = React25__namespace.default.useState(0);
|
|
4905
|
+
const [rowsPerPage, setRowsPerPage] = React25__namespace.default.useState(pageSize > 0 ? pageSize : 10);
|
|
4906
|
+
const [colQuery, setColQuery] = React25__namespace.default.useState("");
|
|
4907
|
+
const [widths, setWidths] = React25__namespace.default.useState({});
|
|
4908
|
+
const [order, setOrder] = React25__namespace.default.useState(() => columns.map((c) => c.field));
|
|
4909
|
+
const [drag, setDrag] = React25__namespace.default.useState({ from: null, over: null, after: false });
|
|
4910
|
+
const [aggOn, setAggOn] = React25__namespace.default.useState(showAggregation);
|
|
4911
|
+
const [focus, setFocus] = React25__namespace.default.useState({ r: 0, c: 0 });
|
|
4912
|
+
const gridRef = React25__namespace.default.useRef(null);
|
|
4913
|
+
const [groupBy, setGroupBy] = React25__namespace.default.useState(rowGrouping || []);
|
|
4914
|
+
const [collapsed, setCollapsed] = React25__namespace.default.useState(() => /* @__PURE__ */ new Set());
|
|
4915
|
+
const [pinnedRows, setPinnedRows] = React25__namespace.default.useState({ top: [], bottom: [] });
|
|
4916
|
+
const [headH, setHeadH] = React25__namespace.default.useState(41);
|
|
4917
|
+
const theadRef = React25__namespace.default.useRef(null);
|
|
4918
|
+
const [rowOrder, setRowOrder] = React25__namespace.default.useState(null);
|
|
4919
|
+
const [rowHeights, setRowHeights] = React25__namespace.default.useState({});
|
|
4920
|
+
const [rowDrag, setRowDrag] = React25__namespace.default.useState({ from: null, over: null, after: false });
|
|
4921
|
+
const [rowGrab, setRowGrab] = React25__namespace.default.useState(null);
|
|
4922
|
+
const [reorderMsg, setReorderMsg] = React25__namespace.default.useState("");
|
|
4923
|
+
const rowFocusRef = React25__namespace.default.useRef(null);
|
|
4924
|
+
const rootRef = React25__namespace.default.useRef(null);
|
|
4925
|
+
const [compact, setCompact] = React25__namespace.default.useState(false);
|
|
4926
|
+
React25__namespace.default.useEffect(() => {
|
|
4499
4927
|
const el = rootRef.current;
|
|
4500
4928
|
if (!el) return void 0;
|
|
4501
4929
|
const measure = () => setCompact((el.clientWidth || 0) < 720);
|
|
@@ -4508,11 +4936,11 @@ function Datatable({
|
|
|
4508
4936
|
else if (typeof window !== "undefined") window.removeEventListener("resize", measure);
|
|
4509
4937
|
};
|
|
4510
4938
|
}, []);
|
|
4511
|
-
const scrollRef =
|
|
4512
|
-
const [scrollTop, setScrollTop] =
|
|
4513
|
-
const [viewportH, setViewportH] =
|
|
4514
|
-
const [pivotOn, setPivotOn] =
|
|
4515
|
-
const [aggConfig, setAggConfig] =
|
|
4939
|
+
const scrollRef = React25__namespace.default.useRef(null);
|
|
4940
|
+
const [scrollTop, setScrollTop] = React25__namespace.default.useState(0);
|
|
4941
|
+
const [viewportH, setViewportH] = React25__namespace.default.useState(0);
|
|
4942
|
+
const [pivotOn, setPivotOn] = React25__namespace.default.useState(pivotMode);
|
|
4943
|
+
const [aggConfig, setAggConfig] = React25__namespace.default.useState(() => {
|
|
4516
4944
|
const m = {};
|
|
4517
4945
|
(columns || []).forEach((c) => {
|
|
4518
4946
|
if (typeof c.aggregation === "string") m[c.field] = c.aggregation;
|
|
@@ -4520,13 +4948,13 @@ function Datatable({
|
|
|
4520
4948
|
return m;
|
|
4521
4949
|
});
|
|
4522
4950
|
const aggOf = (c) => aggConfig[c.field] || (typeof c.aggregation === "function" ? c.aggregation : null);
|
|
4523
|
-
const [pivotConfig, setPivotConfig] =
|
|
4951
|
+
const [pivotConfig, setPivotConfig] = React25__namespace.default.useState(() => ({
|
|
4524
4952
|
rows: pivot && pivot.rows || [],
|
|
4525
4953
|
columns: pivot && pivot.columns || [],
|
|
4526
4954
|
values: pivot && pivot.values || []
|
|
4527
4955
|
}));
|
|
4528
4956
|
const pivotActive = pivotOn && pivotConfig.rows.length > 0 && pivotConfig.values.length > 0;
|
|
4529
|
-
|
|
4957
|
+
React25__namespace.default.useEffect(() => {
|
|
4530
4958
|
setOrder((prev) => {
|
|
4531
4959
|
const fields = columns.map((c) => c.field);
|
|
4532
4960
|
const kept = prev.filter((f) => fields.includes(f));
|
|
@@ -4534,32 +4962,32 @@ function Datatable({
|
|
|
4534
4962
|
return [...kept, ...added];
|
|
4535
4963
|
});
|
|
4536
4964
|
}, [columns]);
|
|
4537
|
-
|
|
4965
|
+
React25__namespace.default.useEffect(() => {
|
|
4538
4966
|
setDensity(densityProp);
|
|
4539
4967
|
}, [densityProp]);
|
|
4540
|
-
|
|
4968
|
+
React25__namespace.default.useEffect(() => {
|
|
4541
4969
|
setAggOn(showAggregation);
|
|
4542
4970
|
}, [showAggregation]);
|
|
4543
4971
|
const rowGroupingKey = (rowGrouping || []).join("\0");
|
|
4544
|
-
const rowGroupingKeyRef =
|
|
4545
|
-
|
|
4972
|
+
const rowGroupingKeyRef = React25__namespace.default.useRef(rowGroupingKey);
|
|
4973
|
+
React25__namespace.default.useEffect(() => {
|
|
4546
4974
|
if (rowGroupingKeyRef.current === rowGroupingKey) return;
|
|
4547
4975
|
rowGroupingKeyRef.current = rowGroupingKey;
|
|
4548
4976
|
setGroupBy(rowGrouping || []);
|
|
4549
4977
|
}, [rowGroupingKey]);
|
|
4550
4978
|
const widthOf = (c) => widths[c.field] ?? c.width ?? 160;
|
|
4551
|
-
const [colMenu, setColMenu] =
|
|
4979
|
+
const [colMenu, setColMenu] = React25__namespace.default.useState(null);
|
|
4552
4980
|
const [menuPos, openMenu, closeMenu] = useFloating();
|
|
4553
|
-
const [panel, setPanel] =
|
|
4981
|
+
const [panel, setPanel] = React25__namespace.default.useState(null);
|
|
4554
4982
|
const [panelPos, openPanel, closePanel] = useFloating();
|
|
4555
|
-
const [rowMenu, setRowMenu] =
|
|
4983
|
+
const [rowMenu, setRowMenu] = React25__namespace.default.useState(null);
|
|
4556
4984
|
const [rowMenuPos, openRowMenu, closeRowMenu] = useFloating();
|
|
4557
|
-
const [exportOpen, setExportOpen] =
|
|
4985
|
+
const [exportOpen, setExportOpen] = React25__namespace.default.useState(false);
|
|
4558
4986
|
const [exportPos, openExport, closeExport] = useFloating();
|
|
4559
|
-
const menuTriggerRef =
|
|
4560
|
-
const colMenuRef =
|
|
4561
|
-
const rowMenuRef =
|
|
4562
|
-
const exportMenuRef =
|
|
4987
|
+
const menuTriggerRef = React25__namespace.default.useRef(null);
|
|
4988
|
+
const colMenuRef = React25__namespace.default.useRef(null);
|
|
4989
|
+
const rowMenuRef = React25__namespace.default.useRef(null);
|
|
4990
|
+
const exportMenuRef = React25__namespace.default.useRef(null);
|
|
4563
4991
|
function focusFirstItem(container) {
|
|
4564
4992
|
if (!container) return;
|
|
4565
4993
|
const first = container.querySelector('[role="menuitem"]:not([disabled])');
|
|
@@ -4598,16 +5026,16 @@ function Datatable({
|
|
|
4598
5026
|
restoreTriggerFocus();
|
|
4599
5027
|
}
|
|
4600
5028
|
}
|
|
4601
|
-
|
|
5029
|
+
React25__namespace.default.useEffect(() => {
|
|
4602
5030
|
if (colMenu) focusFirstItem(colMenuRef.current);
|
|
4603
5031
|
}, [colMenu]);
|
|
4604
|
-
|
|
5032
|
+
React25__namespace.default.useEffect(() => {
|
|
4605
5033
|
if (rowMenu) focusFirstItem(rowMenuRef.current);
|
|
4606
5034
|
}, [rowMenu]);
|
|
4607
|
-
|
|
5035
|
+
React25__namespace.default.useEffect(() => {
|
|
4608
5036
|
if (exportOpen) focusFirstItem(exportMenuRef.current);
|
|
4609
5037
|
}, [exportOpen]);
|
|
4610
|
-
|
|
5038
|
+
React25__namespace.default.useEffect(() => {
|
|
4611
5039
|
if (!colMenu && !panel && !rowMenu) return;
|
|
4612
5040
|
const closeAll = () => {
|
|
4613
5041
|
setColMenu(null);
|
|
@@ -4630,7 +5058,7 @@ function Datatable({
|
|
|
4630
5058
|
document.removeEventListener("keydown", onKey);
|
|
4631
5059
|
};
|
|
4632
5060
|
}, [colMenu, panel, rowMenu]);
|
|
4633
|
-
|
|
5061
|
+
React25__namespace.default.useEffect(() => {
|
|
4634
5062
|
if (!exportOpen) return;
|
|
4635
5063
|
const close = () => {
|
|
4636
5064
|
setExportOpen(false);
|
|
@@ -4649,9 +5077,9 @@ function Datatable({
|
|
|
4649
5077
|
document.removeEventListener("keydown", onKey);
|
|
4650
5078
|
};
|
|
4651
5079
|
}, [exportOpen]);
|
|
4652
|
-
const colByField =
|
|
5080
|
+
const colByField = React25__namespace.default.useMemo(() => Object.fromEntries(cols.map((c) => [c.field, c])), [cols]);
|
|
4653
5081
|
const visibleCols = cols.filter((c) => !hidden.has(c.field));
|
|
4654
|
-
const ordered =
|
|
5082
|
+
const ordered = React25__namespace.default.useMemo(() => {
|
|
4655
5083
|
const orderIdx = (f) => {
|
|
4656
5084
|
const i = order.indexOf(f);
|
|
4657
5085
|
return i === -1 ? 9999 : i;
|
|
@@ -4686,7 +5114,7 @@ function Datatable({
|
|
|
4686
5114
|
}
|
|
4687
5115
|
return {};
|
|
4688
5116
|
};
|
|
4689
|
-
const processed =
|
|
5117
|
+
const processed = React25__namespace.default.useMemo(() => {
|
|
4690
5118
|
if (serverMode) {
|
|
4691
5119
|
if (rowOrder) {
|
|
4692
5120
|
const idx = new Map(rowOrder.map((k, i) => [k, i]));
|
|
@@ -4725,10 +5153,10 @@ function Datatable({
|
|
|
4725
5153
|
const totalRows = serverMode ? serverTotal : processed.length;
|
|
4726
5154
|
const totalPages = paginated ? Math.max(1, Math.ceil(totalRows / rowsPerPage)) : 1;
|
|
4727
5155
|
const paged = !paginated || serverMode ? processed : processed.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
|
|
4728
|
-
|
|
5156
|
+
React25__namespace.default.useEffect(() => {
|
|
4729
5157
|
if (page > totalPages - 1) setPage(0);
|
|
4730
5158
|
}, [totalPages]);
|
|
4731
|
-
const activeGroupBy =
|
|
5159
|
+
const activeGroupBy = React25__namespace.default.useMemo(() => groupBy.filter((f) => colByField[f]), [groupBy, colByField]);
|
|
4732
5160
|
function subtotalText(rowsIn) {
|
|
4733
5161
|
const parts = [];
|
|
4734
5162
|
for (const c of ordered) {
|
|
@@ -4755,7 +5183,7 @@ function Datatable({
|
|
|
4755
5183
|
if (agg === "max") return Math.max(...nums);
|
|
4756
5184
|
return null;
|
|
4757
5185
|
}
|
|
4758
|
-
const displayItems =
|
|
5186
|
+
const displayItems = React25__namespace.default.useMemo(() => {
|
|
4759
5187
|
if (!activeGroupBy.length) return null;
|
|
4760
5188
|
const build = (rowsIn, depth, prefix) => {
|
|
4761
5189
|
if (depth >= activeGroupBy.length) return rowsIn.map((row) => ({ kind: "leaf", row }));
|
|
@@ -4797,7 +5225,7 @@ function Datatable({
|
|
|
4797
5225
|
return { top, bottom };
|
|
4798
5226
|
});
|
|
4799
5227
|
}
|
|
4800
|
-
|
|
5228
|
+
React25__namespace.default.useEffect(() => {
|
|
4801
5229
|
if (!rowPinning) return;
|
|
4802
5230
|
const measure = () => {
|
|
4803
5231
|
if (theadRef.current) setHeadH(theadRef.current.offsetHeight || 41);
|
|
@@ -4811,12 +5239,12 @@ function Datatable({
|
|
|
4811
5239
|
const pinnedTopRows = canPinRows ? pinnedRows.top.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
|
|
4812
5240
|
const pinnedBottomRows = canPinRows ? pinnedRows.bottom.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
|
|
4813
5241
|
const middleRows = canPinRows ? leafRows.filter((r, i) => !pinSideOf(keyOf(r, i))) : leafRows;
|
|
4814
|
-
const keyIndex =
|
|
5242
|
+
const keyIndex = React25__namespace.default.useMemo(() => {
|
|
4815
5243
|
const m = /* @__PURE__ */ new Map();
|
|
4816
5244
|
leafRows.forEach((r, i) => m.set(keyOf(r, i), i));
|
|
4817
5245
|
return m;
|
|
4818
5246
|
}, [leafRows]);
|
|
4819
|
-
const keyIndexMid =
|
|
5247
|
+
const keyIndexMid = React25__namespace.default.useMemo(() => {
|
|
4820
5248
|
const m = /* @__PURE__ */ new Map();
|
|
4821
5249
|
middleRows.forEach((r, i) => m.set(keyOf(r, keyIndex.get(keyOf(r)) ?? i), i));
|
|
4822
5250
|
return m;
|
|
@@ -4901,7 +5329,7 @@ function Datatable({
|
|
|
4901
5329
|
setReorderMsg("Reorder cancelled.");
|
|
4902
5330
|
}
|
|
4903
5331
|
}
|
|
4904
|
-
|
|
5332
|
+
React25__namespace.default.useEffect(() => {
|
|
4905
5333
|
if (rowFocusRef.current == null) return;
|
|
4906
5334
|
const key = rowFocusRef.current;
|
|
4907
5335
|
rowFocusRef.current = null;
|
|
@@ -4913,7 +5341,7 @@ function Datatable({
|
|
|
4913
5341
|
});
|
|
4914
5342
|
const estRowH = rowHeight ?? (density === "compact" ? 36 : density === "comfortable" ? 56 : 44);
|
|
4915
5343
|
const virtualizing = virtualized && !paginated && !activeGroupBy.length && !loading;
|
|
4916
|
-
|
|
5344
|
+
React25__namespace.default.useEffect(() => {
|
|
4917
5345
|
if (!virtualizing) return;
|
|
4918
5346
|
const el = scrollRef.current;
|
|
4919
5347
|
if (!el) return;
|
|
@@ -4923,13 +5351,13 @@ function Datatable({
|
|
|
4923
5351
|
if (ro) ro.observe(el);
|
|
4924
5352
|
return () => ro && ro.disconnect();
|
|
4925
5353
|
}, [virtualizing, height]);
|
|
4926
|
-
const onScrollVirtual =
|
|
5354
|
+
const onScrollVirtual = React25__namespace.default.useCallback((e) => {
|
|
4927
5355
|
setScrollTop(e.currentTarget.scrollTop);
|
|
4928
5356
|
}, []);
|
|
4929
5357
|
const vh = viewportH || (typeof height === "number" ? height : 440);
|
|
4930
|
-
const rowHRef =
|
|
4931
|
-
const [measureTick, setMeasureTick] =
|
|
4932
|
-
const offsets =
|
|
5358
|
+
const rowHRef = React25__namespace.default.useRef(/* @__PURE__ */ new Map());
|
|
5359
|
+
const [measureTick, setMeasureTick] = React25__namespace.default.useState(0);
|
|
5360
|
+
const offsets = React25__namespace.default.useMemo(() => {
|
|
4933
5361
|
if (!virtualizing) return null;
|
|
4934
5362
|
const total = middleRows.length;
|
|
4935
5363
|
const arr = new Float64Array(total + 1);
|
|
@@ -4939,7 +5367,7 @@ function Datatable({
|
|
|
4939
5367
|
}
|
|
4940
5368
|
return arr;
|
|
4941
5369
|
}, [virtualizing, middleRows, estRowH, measureTick]);
|
|
4942
|
-
const vWindow =
|
|
5370
|
+
const vWindow = React25__namespace.default.useMemo(() => {
|
|
4943
5371
|
if (!virtualizing || !offsets) return null;
|
|
4944
5372
|
const total = middleRows.length;
|
|
4945
5373
|
const totalH = offsets[total];
|
|
@@ -4968,7 +5396,7 @@ function Datatable({
|
|
|
4968
5396
|
if (start > end) start = end;
|
|
4969
5397
|
return { start, end, padTop: offsets[start], padBottom: Math.max(0, totalH - offsets[end]) };
|
|
4970
5398
|
}, [virtualizing, offsets, middleRows.length, vh, scrollTop, overscan]);
|
|
4971
|
-
|
|
5399
|
+
React25__namespace.default.useLayoutEffect(() => {
|
|
4972
5400
|
if (!virtualizing) return;
|
|
4973
5401
|
const el = scrollRef.current;
|
|
4974
5402
|
if (!el) return;
|
|
@@ -4983,9 +5411,9 @@ function Datatable({
|
|
|
4983
5411
|
}
|
|
4984
5412
|
if (changed) setMeasureTick((t) => t + 1);
|
|
4985
5413
|
});
|
|
4986
|
-
const onServerChangeRef =
|
|
5414
|
+
const onServerChangeRef = React25__namespace.default.useRef(onServerChange);
|
|
4987
5415
|
onServerChangeRef.current = onServerChange;
|
|
4988
|
-
|
|
5416
|
+
React25__namespace.default.useEffect(() => {
|
|
4989
5417
|
if (!serverMode) return;
|
|
4990
5418
|
const t = setTimeout(() => {
|
|
4991
5419
|
onServerChangeRef.current?.({
|
|
@@ -5020,8 +5448,8 @@ function Datatable({
|
|
|
5020
5448
|
return n;
|
|
5021
5449
|
});
|
|
5022
5450
|
}
|
|
5023
|
-
const movableMidFields =
|
|
5024
|
-
() => ordered.filter((c) => !pins.left.includes(c.field) && !pins.right.includes(c.field)).map((c) => c.field),
|
|
5451
|
+
const movableMidFields = React25__namespace.default.useMemo(
|
|
5452
|
+
() => ordered.filter((c) => !pins.left.includes(c.field) && !pins.right.includes(c.field) && c.reorderable !== false).map((c) => c.field),
|
|
5025
5453
|
[ordered, pins]
|
|
5026
5454
|
);
|
|
5027
5455
|
function moveCol(field, dir) {
|
|
@@ -5051,7 +5479,7 @@ function Datatable({
|
|
|
5051
5479
|
}
|
|
5052
5480
|
return [...set].sort((a, b) => a.localeCompare(b)).map((v) => ({ value: v, label: v }));
|
|
5053
5481
|
}
|
|
5054
|
-
const [resizing, setResizing] =
|
|
5482
|
+
const [resizing, setResizing] = React25__namespace.default.useState(false);
|
|
5055
5483
|
function startResize(e, field) {
|
|
5056
5484
|
e.preventDefault();
|
|
5057
5485
|
e.stopPropagation();
|
|
@@ -5158,7 +5586,7 @@ function Datatable({
|
|
|
5158
5586
|
if (!agg) return null;
|
|
5159
5587
|
if (aggregationValues && col.field in aggregationValues) {
|
|
5160
5588
|
const pre = aggregationValues[col.field];
|
|
5161
|
-
if (pre && typeof pre === "object" && !
|
|
5589
|
+
if (pre && typeof pre === "object" && !React25__namespace.default.isValidElement(pre)) {
|
|
5162
5590
|
if (typeof agg === "string" && agg in pre) return pre[agg];
|
|
5163
5591
|
} else {
|
|
5164
5592
|
return pre;
|
|
@@ -5276,14 +5704,14 @@ function Datatable({
|
|
|
5276
5704
|
focusCell(r, c);
|
|
5277
5705
|
}
|
|
5278
5706
|
}
|
|
5279
|
-
|
|
5707
|
+
React25__namespace.default.useEffect(() => {
|
|
5280
5708
|
setFocus((f) => ({ r: Math.min(f.r, Math.max(0, leafRows.length - 1)), c: Math.min(f.c, Math.max(0, ordered.length - 1)) }));
|
|
5281
5709
|
}, [leafRows.length, ordered.length, page]);
|
|
5282
|
-
const selectedRows =
|
|
5710
|
+
const selectedRows = React25__namespace.default.useMemo(() => rows.filter((r, i) => selected.has(keyOf(r, i))), [rows, selected]);
|
|
5283
5711
|
function clearSelection() {
|
|
5284
5712
|
setSelected(/* @__PURE__ */ new Set());
|
|
5285
5713
|
}
|
|
5286
|
-
const [editing, setEditing] =
|
|
5714
|
+
const [editing, setEditing] = React25__namespace.default.useState(null);
|
|
5287
5715
|
const isColEditable = (c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false));
|
|
5288
5716
|
function beginEdit(rowK, col, row) {
|
|
5289
5717
|
if (!isColEditable(col)) return;
|
|
@@ -5318,17 +5746,17 @@ function Datatable({
|
|
|
5318
5746
|
cancelEdit();
|
|
5319
5747
|
}
|
|
5320
5748
|
}
|
|
5321
|
-
const batchEditableCols =
|
|
5749
|
+
const batchEditableCols = React25__namespace.default.useMemo(
|
|
5322
5750
|
() => cols.filter((c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false))),
|
|
5323
5751
|
[cols, editMode]
|
|
5324
5752
|
);
|
|
5325
|
-
const [batchEdit, setBatchEdit] =
|
|
5753
|
+
const [batchEdit, setBatchEdit] = React25__namespace.default.useState(null);
|
|
5326
5754
|
const [batchEditPos, openBatchEdit, closeBatchEdit] = useFloating();
|
|
5327
5755
|
function openBatchEditor(el) {
|
|
5328
5756
|
setBatchEdit({ fields: {}, values: {} });
|
|
5329
5757
|
openBatchEdit(el, "left", 320);
|
|
5330
5758
|
}
|
|
5331
|
-
|
|
5759
|
+
React25__namespace.default.useEffect(() => {
|
|
5332
5760
|
if (!batchEdit) return;
|
|
5333
5761
|
const close = () => {
|
|
5334
5762
|
setBatchEdit(null);
|
|
@@ -5347,7 +5775,7 @@ function Datatable({
|
|
|
5347
5775
|
document.removeEventListener("keydown", onKey);
|
|
5348
5776
|
};
|
|
5349
5777
|
}, [batchEdit]);
|
|
5350
|
-
|
|
5778
|
+
React25__namespace.default.useEffect(() => {
|
|
5351
5779
|
if (batchEdit && selected.size === 0) {
|
|
5352
5780
|
setBatchEdit(null);
|
|
5353
5781
|
closeBatchEdit();
|
|
@@ -5384,7 +5812,7 @@ function Datatable({
|
|
|
5384
5812
|
setBatchEdit(null);
|
|
5385
5813
|
closeBatchEdit();
|
|
5386
5814
|
}
|
|
5387
|
-
|
|
5815
|
+
React25__namespace.default.useEffect(() => {
|
|
5388
5816
|
if (!editing) return;
|
|
5389
5817
|
const onDown = (e) => {
|
|
5390
5818
|
if (e.target.closest(".twc-dt__editor-wrap") || e.target.closest(".twc-pop")) return;
|
|
@@ -5406,13 +5834,12 @@ function Datatable({
|
|
|
5406
5834
|
})() : [];
|
|
5407
5835
|
const menu = [...items.filter((a) => a.showInMenu), ...pinItems];
|
|
5408
5836
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__actions", style: { justifyContent: col.align === "right" ? "flex-end" : "flex-start" }, children: [
|
|
5409
|
-
inline.map((a, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5837
|
+
inline.map((a, i) => /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: a.label, placement: "top", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5410
5838
|
"button",
|
|
5411
5839
|
{
|
|
5412
5840
|
type: "button",
|
|
5413
5841
|
className: "twc-dt__act",
|
|
5414
5842
|
"data-danger": a.danger || void 0,
|
|
5415
|
-
title: a.label,
|
|
5416
5843
|
"aria-label": a.label,
|
|
5417
5844
|
disabled: a.disabled,
|
|
5418
5845
|
onClick: (e) => {
|
|
@@ -5420,16 +5847,14 @@ function Datatable({
|
|
|
5420
5847
|
a.onClick?.(row);
|
|
5421
5848
|
},
|
|
5422
5849
|
children: a.icon
|
|
5423
|
-
}
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
menu.length ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5850
|
+
}
|
|
5851
|
+
) }, i)),
|
|
5852
|
+
menu.length ? /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { label: "More actions", placement: "top", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5427
5853
|
"button",
|
|
5428
5854
|
{
|
|
5429
5855
|
type: "button",
|
|
5430
5856
|
className: "twc-dt__act",
|
|
5431
5857
|
"aria-label": "More actions",
|
|
5432
|
-
title: "More",
|
|
5433
5858
|
"aria-haspopup": "menu",
|
|
5434
5859
|
"aria-expanded": rowMenu && rowMenu.row === row || void 0,
|
|
5435
5860
|
onClick: (e) => {
|
|
@@ -5446,7 +5871,7 @@ function Datatable({
|
|
|
5446
5871
|
},
|
|
5447
5872
|
children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.more })
|
|
5448
5873
|
}
|
|
5449
|
-
) : null
|
|
5874
|
+
) }) : null
|
|
5450
5875
|
] });
|
|
5451
5876
|
}
|
|
5452
5877
|
const tableMinWidth = leadW + ordered.reduce((a, c) => a + widthOf(c), 0);
|
|
@@ -5990,7 +6415,7 @@ function Datatable({
|
|
|
5990
6415
|
const st = stickyOf(c.field);
|
|
5991
6416
|
const sorted = sort && sort.field === c.field ? sort.dir : void 0;
|
|
5992
6417
|
const w = widthOf(c);
|
|
5993
|
-
const reorderable = !disableColumnReorder && st.pin == null && c.type !== "actions";
|
|
6418
|
+
const reorderable = !disableColumnReorder && st.pin == null && c.type !== "actions" && c.reorderable !== false;
|
|
5994
6419
|
const resizable = !disableColumnResize && c.resizable !== false;
|
|
5995
6420
|
const hasMenu = !c.disableColumnMenu && (c.sortable || c.filterable || c.pinnable || c.hideable);
|
|
5996
6421
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6114,14 +6539,17 @@ function Datatable({
|
|
|
6114
6539
|
);
|
|
6115
6540
|
})
|
|
6116
6541
|
] }) }),
|
|
6117
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? Array.from({ length: paginated ? Math.min(rowsPerPage, 8) : 8 }).map((_, ri) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "twc-dt__row", children: [
|
|
6118
|
-
checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", "data-pin": "left", style: { insetInlineStart: 0, width: 44 }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", style: { "--_w": "18px", height: 18, borderRadius: 4 } }) }) : null,
|
|
6119
|
-
showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__rownum", "aria-hidden": "true", "data-pin": "left", style: { insetInlineStart: numLeft, width: NUM_W }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", style: { "--_w": "16px", height: 14, borderRadius: 4 } }) }) : null,
|
|
6542
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? Array.from({ length: paginated ? Math.min(rowsPerPage, 8) : 8 }).map((_, ri) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "twc-dt__row", role: "row", children: [
|
|
6543
|
+
checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", "data-pin": "left", style: { insetInlineStart: 0, width: 44 }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "18px", height: 18, borderRadius: 4 } }) }) : null,
|
|
6544
|
+
showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", style: { insetInlineStart: numLeft, width: NUM_W }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "16px", height: 14, borderRadius: 4 } }) }) : null,
|
|
6120
6545
|
ordered.map((c, ci) => {
|
|
6121
6546
|
const st = stickyOf(c.field);
|
|
6122
|
-
return /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", "data-num": c.type === "number" || void 0, "data-pin": st.pin, "data-pin-edge": st.edge, style: { width: widthOf(c), ...st.style }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", style: { "--_w": `${45 + (ri * 13 + ci * 29) % 45}%` } }) }, c.field);
|
|
6547
|
+
return /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", "data-num": c.type === "number" || void 0, "data-pin": st.pin, "data-pin-edge": st.edge, style: { width: widthOf(c), ...st.style }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": `${45 + (ri * 13 + ci * 29) % 45}%` } }) }, c.field);
|
|
6123
6548
|
})
|
|
6124
|
-
] }, ri)) : (displayItems ? displayItems.length === 0 : paged.length === 0) ?
|
|
6549
|
+
] }, ri)) : (displayItems ? displayItems.length === 0 : paged.length === 0) ? (
|
|
6550
|
+
// #121: customizable, filter-aware empty state. #122: grid roles on the empty row.
|
|
6551
|
+
/* @__PURE__ */ jsxRuntime.jsx("tr", { role: "row", "aria-rowindex": 2, children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", colSpan: totalCols, style: { maxWidth: "none" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__empty", children: renderEmpty ? renderEmpty() : emptyMessage ?? (filters.length > 0 || quick.trim() !== "" ? "No rows match your filters" : "No rows") }) }) })
|
|
6552
|
+
) : displayItems ? (() => {
|
|
6125
6553
|
let li = -1;
|
|
6126
6554
|
return displayItems.map((item) => item.kind === "group" ? renderGroupRow(item) : renderLeaf(item.row, ++li));
|
|
6127
6555
|
})() : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -6134,13 +6562,13 @@ function Datatable({
|
|
|
6134
6562
|
pinnedBottomRows.map((row) => renderLeaf(row, keyIndex.get(keyOf(row)), "bottom"))
|
|
6135
6563
|
] }) }),
|
|
6136
6564
|
hasAggregation && aggOn && !loading && paged.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("tfoot", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", children: [
|
|
6137
|
-
checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { "data-pin": "left", "data-pin-edge": pins.left.length || showRowNum ? void 0 : "left", style: { insetInlineStart: 0, width: 44 } }) : null,
|
|
6138
|
-
showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__rownum", "aria-hidden": "true", "data-pin": "left", "data-pin-edge": pins.left.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W } }) : null,
|
|
6565
|
+
checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { role: "gridcell", "data-pin": "left", "data-pin-edge": pins.left.length || showRowNum ? void 0 : "left", style: { insetInlineStart: 0, width: 44 } }) : null,
|
|
6566
|
+
showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", "data-pin-edge": pins.left.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W } }) : null,
|
|
6139
6567
|
ordered.map((c) => {
|
|
6140
6568
|
const st = stickyOf(c.field);
|
|
6141
6569
|
const v = aggregate(c);
|
|
6142
6570
|
const display = v == null ? null : c.aggregationFormatter ? c.aggregationFormatter(v) : c.valueFormatter ? c.valueFormatter(v, null) : typeof v === "number" ? v.toLocaleString() : v;
|
|
6143
|
-
return /* @__PURE__ */ jsxRuntime.jsx("td", { "data-num": c.type === "number" || void 0, "data-pin": st.pin, "data-pin-edge": st.edge, style: { width: widthOf(c), ...st.style }, children: v == null ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6571
|
+
return /* @__PURE__ */ jsxRuntime.jsx("td", { role: "gridcell", "data-num": c.type === "number" || void 0, "data-pin": st.pin, "data-pin-edge": st.edge, style: { width: widthOf(c), ...st.style }, children: v == null ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6144
6572
|
typeof aggOf(c) === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__agg-label", children: aggLabels[aggOf(c)] }) : null,
|
|
6145
6573
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__agg-val", children: display })
|
|
6146
6574
|
] }) }, c.field);
|
|
@@ -6183,7 +6611,7 @@ function Datatable({
|
|
|
6183
6611
|
})() }),
|
|
6184
6612
|
paginated ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__rpp", children: [
|
|
6185
6613
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__rpp-label", children: "Rows per page" }),
|
|
6186
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: 78 }, children: /* @__PURE__ */ jsxRuntime.jsx(Select, { size: "sm", portal: true, value: String(rowsPerPage), options: rppOptions, placement: "top", onChange: (v) => {
|
|
6614
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: 78 }, children: /* @__PURE__ */ jsxRuntime.jsx(Select, { size: "sm", portal: true, searchable: false, value: String(rowsPerPage), options: rppOptions, placement: "top", onChange: (v) => {
|
|
6187
6615
|
setRowsPerPage(Number(v));
|
|
6188
6616
|
setPage(0);
|
|
6189
6617
|
} }) })
|
|
@@ -6484,7 +6912,7 @@ function Datatable({
|
|
|
6484
6912
|
)
|
|
6485
6913
|
] }) : null,
|
|
6486
6914
|
shownColRows.length === 0 ? rowNumMatch ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__empty", style: { padding: "18px 12px" }, children: "No columns found" }) : shownColRows.map((c) => {
|
|
6487
|
-
const canDrag = !disableColumnReorder && !colQuery.trim();
|
|
6915
|
+
const canDrag = !disableColumnReorder && c.reorderable !== false && !colQuery.trim();
|
|
6488
6916
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6489
6917
|
"div",
|
|
6490
6918
|
{
|
|
@@ -6861,6 +7289,7 @@ var DATEPICKER_CSS = `
|
|
|
6861
7289
|
.twc-dp__day[data-today="true"] { font-weight: var(--font-bold); box-shadow: inset 0 0 0 1px var(--color-primary-border); }
|
|
6862
7290
|
.twc-dp__day[data-selected="true"] { background: var(--color-primary); color: var(--color-primary-fg); font-weight: var(--font-bold); }
|
|
6863
7291
|
.twc-dp__day:disabled { color: var(--color-text-subtle); opacity: 0.4; cursor: not-allowed; }
|
|
7292
|
+
.twc-dp__sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
6864
7293
|
.twc-dp__day:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
6865
7294
|
.twc-dp__months { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
|
|
6866
7295
|
.twc-dp__mo { padding: 10px 0; border: none; background: transparent; cursor: pointer; font-family: inherit; font-size: var(--text-sm); color: var(--color-text); border-radius: var(--radius-md); }
|
|
@@ -6906,23 +7335,23 @@ function DatePicker({
|
|
|
6906
7335
|
}) {
|
|
6907
7336
|
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS3);
|
|
6908
7337
|
const __twcStyles1 = useScopedStyles("twc-datepicker-styles", DATEPICKER_CSS);
|
|
6909
|
-
const autoId =
|
|
7338
|
+
const autoId = React25__namespace.default.useId();
|
|
6910
7339
|
const fieldId = id || autoId;
|
|
6911
7340
|
const descId = `${fieldId}-desc`;
|
|
6912
7341
|
const invalid = Boolean(error);
|
|
6913
|
-
const [internal, setInternal] =
|
|
7342
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
6914
7343
|
const selected = value !== void 0 ? value : internal;
|
|
6915
|
-
const [open, setOpen] =
|
|
6916
|
-
const [view, setView] =
|
|
6917
|
-
const [mode, setMode] =
|
|
6918
|
-
const [focusDate, setFocusDate] =
|
|
6919
|
-
const [coords, setCoords] =
|
|
6920
|
-
const wrapRef =
|
|
6921
|
-
const triggerRef =
|
|
6922
|
-
const popRef =
|
|
6923
|
-
const gridRef =
|
|
7344
|
+
const [open, setOpen] = React25__namespace.default.useState(false);
|
|
7345
|
+
const [view, setView] = React25__namespace.default.useState(selected || /* @__PURE__ */ new Date());
|
|
7346
|
+
const [mode, setMode] = React25__namespace.default.useState("days");
|
|
7347
|
+
const [focusDate, setFocusDate] = React25__namespace.default.useState(null);
|
|
7348
|
+
const [coords, setCoords] = React25__namespace.default.useState(null);
|
|
7349
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
7350
|
+
const triggerRef = React25__namespace.default.useRef(null);
|
|
7351
|
+
const popRef = React25__namespace.default.useRef(null);
|
|
7352
|
+
const gridRef = React25__namespace.default.useRef(null);
|
|
6924
7353
|
const POP_W = 280;
|
|
6925
|
-
const place =
|
|
7354
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
6926
7355
|
const el = triggerRef.current;
|
|
6927
7356
|
if (!el) return;
|
|
6928
7357
|
const r = el.getBoundingClientRect();
|
|
@@ -6933,7 +7362,7 @@ function DatePicker({
|
|
|
6933
7362
|
left = Math.max(8, left);
|
|
6934
7363
|
setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
|
|
6935
7364
|
}, []);
|
|
6936
|
-
|
|
7365
|
+
React25__namespace.default.useEffect(() => {
|
|
6937
7366
|
if (!open) return void 0;
|
|
6938
7367
|
place();
|
|
6939
7368
|
const onMove = () => place();
|
|
@@ -6944,7 +7373,7 @@ function DatePicker({
|
|
|
6944
7373
|
window.removeEventListener("resize", onMove);
|
|
6945
7374
|
};
|
|
6946
7375
|
}, [open, place]);
|
|
6947
|
-
|
|
7376
|
+
React25__namespace.default.useEffect(() => {
|
|
6948
7377
|
if (!open) return;
|
|
6949
7378
|
setView(selected || /* @__PURE__ */ new Date());
|
|
6950
7379
|
setMode("days");
|
|
@@ -6964,8 +7393,8 @@ function DatePicker({
|
|
|
6964
7393
|
document.removeEventListener("keydown", onKey);
|
|
6965
7394
|
};
|
|
6966
7395
|
}, [open]);
|
|
6967
|
-
const prevOpen =
|
|
6968
|
-
|
|
7396
|
+
const prevOpen = React25__namespace.default.useRef(false);
|
|
7397
|
+
React25__namespace.default.useEffect(() => {
|
|
6969
7398
|
let id2;
|
|
6970
7399
|
if (!prevOpen.current && open) {
|
|
6971
7400
|
id2 = setTimeout(() => gridRef.current?.querySelector('[tabindex="0"]')?.focus({ preventScroll: true }), 30);
|
|
@@ -6976,9 +7405,9 @@ function DatePicker({
|
|
|
6976
7405
|
prevOpen.current = open;
|
|
6977
7406
|
return () => clearTimeout(id2);
|
|
6978
7407
|
}, [open]);
|
|
6979
|
-
const months =
|
|
6980
|
-
const monthsShort =
|
|
6981
|
-
const dows =
|
|
7408
|
+
const months = React25__namespace.default.useMemo(() => locale === void 0 ? MONTHS : monthNames(locale), [locale]);
|
|
7409
|
+
const monthsShort = React25__namespace.default.useMemo(() => locale === void 0 ? MONTHS.map((n) => n.slice(0, 3)) : monthShortNames(locale), [locale]);
|
|
7410
|
+
const dows = React25__namespace.default.useMemo(
|
|
6982
7411
|
() => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW[(i + weekStartsOn) % 7]) : weekdayNames(locale, weekStartsOn),
|
|
6983
7412
|
[locale, weekStartsOn]
|
|
6984
7413
|
);
|
|
@@ -7006,7 +7435,7 @@ function DatePicker({
|
|
|
7006
7435
|
};
|
|
7007
7436
|
const cells = Array.from({ length: 42 }, (_, i) => new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i));
|
|
7008
7437
|
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);
|
|
7009
|
-
|
|
7438
|
+
React25__namespace.default.useEffect(() => {
|
|
7010
7439
|
if (!open || mode !== "days" || !focusDate) return;
|
|
7011
7440
|
gridRef.current?.querySelector(`[data-key="${keyOf(focusDate)}"]`)?.focus();
|
|
7012
7441
|
}, [focusDate, open, mode]);
|
|
@@ -7096,6 +7525,7 @@ function DatePicker({
|
|
|
7096
7525
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dp__head", children: [
|
|
7097
7526
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__nav", "aria-label": "Previous", onClick: () => setView(mode === "months" ? new Date(y - 1, m, 1) : new Date(y, m - 1, 1)), 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: "m15 18-6-6 6-6" }) }) }),
|
|
7098
7527
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__title", onClick: () => setMode(mode === "days" ? "months" : "days"), children: mode === "days" ? `${months[m]} ${y}` : y }),
|
|
7528
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dp__sr", "aria-live": "polite", children: mode === "days" ? `${months[m]} ${y}` : y }),
|
|
7099
7529
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__nav", "aria-label": "Next", onClick: () => setView(mode === "months" ? new Date(y + 1, m, 1) : new Date(y, m + 1, 1)), 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: "m9 18 6-6-6-6" }) }) })
|
|
7100
7530
|
] }),
|
|
7101
7531
|
mode === "days" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dp__grid", ref: gridRef, onKeyDown: onGridKeyDown, children: [
|
|
@@ -7196,6 +7626,7 @@ var RANGE_CSS = `
|
|
|
7196
7626
|
.twc-drp__day[data-edge="end"] { background: var(--color-primary); color: var(--color-primary-fg); border-radius: 0 var(--radius-md) var(--radius-md) 0; font-weight: var(--font-bold); }
|
|
7197
7627
|
.twc-drp__day[data-edge="both"] { background: var(--color-primary); color: var(--color-primary-fg); border-radius: var(--radius-md); font-weight: var(--font-bold); }
|
|
7198
7628
|
.twc-drp__day:disabled { opacity: 0.3; cursor: not-allowed; }
|
|
7629
|
+
.twc-drp__sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
7199
7630
|
[dir="rtl"] .twc-drp__nav svg { transform: scaleX(-1); }
|
|
7200
7631
|
`;
|
|
7201
7632
|
var MONTHS2 = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
@@ -7221,6 +7652,9 @@ function DateRangePicker({
|
|
|
7221
7652
|
presets = true,
|
|
7222
7653
|
locale,
|
|
7223
7654
|
weekStartsOn = 0,
|
|
7655
|
+
min,
|
|
7656
|
+
max,
|
|
7657
|
+
disabledDate,
|
|
7224
7658
|
disabled = false,
|
|
7225
7659
|
tone = "primary",
|
|
7226
7660
|
onChange,
|
|
@@ -7229,23 +7663,23 @@ function DateRangePicker({
|
|
|
7229
7663
|
}) {
|
|
7230
7664
|
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS4);
|
|
7231
7665
|
const __twcStyles1 = useScopedStyles("twc-drp-styles", RANGE_CSS);
|
|
7232
|
-
const [internal, setInternal] =
|
|
7666
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
7233
7667
|
const range = value !== void 0 ? value : internal;
|
|
7234
|
-
const [open, setOpen] =
|
|
7235
|
-
const [view, setView] =
|
|
7236
|
-
const [hover, setHover] =
|
|
7237
|
-
const [coords, setCoords] =
|
|
7238
|
-
const wrapRef =
|
|
7239
|
-
const triggerRef =
|
|
7240
|
-
const popRef =
|
|
7241
|
-
const labelId =
|
|
7668
|
+
const [open, setOpen] = React25__namespace.default.useState(false);
|
|
7669
|
+
const [view, setView] = React25__namespace.default.useState(range.start || /* @__PURE__ */ new Date());
|
|
7670
|
+
const [hover, setHover] = React25__namespace.default.useState(null);
|
|
7671
|
+
const [coords, setCoords] = React25__namespace.default.useState(null);
|
|
7672
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
7673
|
+
const triggerRef = React25__namespace.default.useRef(null);
|
|
7674
|
+
const popRef = React25__namespace.default.useRef(null);
|
|
7675
|
+
const labelId = React25__namespace.default.useId();
|
|
7242
7676
|
const descId = `${labelId}-desc`;
|
|
7243
7677
|
const invalid = Boolean(error);
|
|
7244
|
-
|
|
7678
|
+
React25__namespace.default.useEffect(() => {
|
|
7245
7679
|
if (disabled) setOpen(false);
|
|
7246
7680
|
}, [disabled]);
|
|
7247
7681
|
const POP_W = 420;
|
|
7248
|
-
const place =
|
|
7682
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
7249
7683
|
const el = triggerRef.current;
|
|
7250
7684
|
if (!el) return;
|
|
7251
7685
|
const r = el.getBoundingClientRect();
|
|
@@ -7256,7 +7690,7 @@ function DateRangePicker({
|
|
|
7256
7690
|
left = Math.max(8, left);
|
|
7257
7691
|
setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
|
|
7258
7692
|
}, []);
|
|
7259
|
-
|
|
7693
|
+
React25__namespace.default.useEffect(() => {
|
|
7260
7694
|
if (!open) return void 0;
|
|
7261
7695
|
place();
|
|
7262
7696
|
const onMove = () => place();
|
|
@@ -7267,7 +7701,7 @@ function DateRangePicker({
|
|
|
7267
7701
|
window.removeEventListener("resize", onMove);
|
|
7268
7702
|
};
|
|
7269
7703
|
}, [open, place]);
|
|
7270
|
-
|
|
7704
|
+
React25__namespace.default.useEffect(() => {
|
|
7271
7705
|
if (!open) return;
|
|
7272
7706
|
const onDown = (e) => {
|
|
7273
7707
|
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
@@ -7288,7 +7722,9 @@ function DateRangePicker({
|
|
|
7288
7722
|
if (value === void 0) setInternal(r);
|
|
7289
7723
|
onChange?.(r);
|
|
7290
7724
|
};
|
|
7725
|
+
const outOfRange = (d) => min && ymd(d) < ymd(min) || max && ymd(d) > ymd(max) || Boolean(disabledDate && disabledDate(d));
|
|
7291
7726
|
const clickDay = (d) => {
|
|
7727
|
+
if (outOfRange(d)) return;
|
|
7292
7728
|
if (!range.start || range.start && range.end) {
|
|
7293
7729
|
set({ start: d, end: null });
|
|
7294
7730
|
} else {
|
|
@@ -7305,8 +7741,8 @@ function DateRangePicker({
|
|
|
7305
7741
|
setView(start);
|
|
7306
7742
|
setOpen(false);
|
|
7307
7743
|
};
|
|
7308
|
-
const months =
|
|
7309
|
-
const dows =
|
|
7744
|
+
const months = React25__namespace.default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
|
|
7745
|
+
const dows = React25__namespace.default.useMemo(
|
|
7310
7746
|
() => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW2[(i + weekStartsOn) % 7]) : weekdayNames2(locale, weekStartsOn),
|
|
7311
7747
|
[locale, weekStartsOn]
|
|
7312
7748
|
);
|
|
@@ -7388,6 +7824,11 @@ function DateRangePicker({
|
|
|
7388
7824
|
" ",
|
|
7389
7825
|
y
|
|
7390
7826
|
] }),
|
|
7827
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-drp__sr", "aria-live": "polite", children: [
|
|
7828
|
+
months[m],
|
|
7829
|
+
" ",
|
|
7830
|
+
y
|
|
7831
|
+
] }),
|
|
7391
7832
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__nav", "aria-label": "Next month", onClick: () => setView(new Date(y, m + 1, 1)), 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: "m9 18 6-6-6-6" }) }) })
|
|
7392
7833
|
] }),
|
|
7393
7834
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__grid", children: [
|
|
@@ -7401,6 +7842,7 @@ function DateRangePicker({
|
|
|
7401
7842
|
type: "button",
|
|
7402
7843
|
className: "twc-drp__day",
|
|
7403
7844
|
"data-outside": outside || void 0,
|
|
7845
|
+
disabled: outOfRange(d) || void 0,
|
|
7404
7846
|
"data-in": inRange(t) || void 0,
|
|
7405
7847
|
"data-edge": edgeOf(t) || void 0,
|
|
7406
7848
|
"aria-pressed": !!edgeOf(t),
|
|
@@ -7487,14 +7929,14 @@ function Dialog({
|
|
|
7487
7929
|
className = "",
|
|
7488
7930
|
...rest
|
|
7489
7931
|
}) {
|
|
7490
|
-
const autoId =
|
|
7932
|
+
const autoId = React25__namespace.default.useId();
|
|
7491
7933
|
const titleId = `${autoId}-title`;
|
|
7492
7934
|
const descId = `${autoId}-desc`;
|
|
7493
|
-
const dialogRef =
|
|
7935
|
+
const dialogRef = React25__namespace.default.useRef(null);
|
|
7494
7936
|
const __twcStyles = useScopedStyles("twc-dialog-styles", DIALOG_CSS);
|
|
7495
7937
|
const renderPortal = usePortal();
|
|
7496
|
-
const [mounted, setMounted] =
|
|
7497
|
-
|
|
7938
|
+
const [mounted, setMounted] = React25__namespace.default.useState(open);
|
|
7939
|
+
React25__namespace.default.useEffect(() => {
|
|
7498
7940
|
if (open) {
|
|
7499
7941
|
setMounted(true);
|
|
7500
7942
|
return;
|
|
@@ -7502,16 +7944,10 @@ function Dialog({
|
|
|
7502
7944
|
const t = setTimeout(() => setMounted(false), 170);
|
|
7503
7945
|
return () => clearTimeout(t);
|
|
7504
7946
|
}, [open]);
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
const prev = document.body.style.overflow;
|
|
7508
|
-
document.body.style.overflow = "hidden";
|
|
7509
|
-
return () => {
|
|
7510
|
-
document.body.style.overflow = prev;
|
|
7511
|
-
};
|
|
7512
|
-
}, [open]);
|
|
7947
|
+
useScrollLock(open);
|
|
7948
|
+
useInertBackground(dialogRef, open && mounted);
|
|
7513
7949
|
useFocusTrap(dialogRef, open && mounted);
|
|
7514
|
-
|
|
7950
|
+
React25__namespace.default.useEffect(() => {
|
|
7515
7951
|
if (!open) return void 0;
|
|
7516
7952
|
const onKey = (e) => {
|
|
7517
7953
|
if (e.key === "Escape") {
|
|
@@ -7658,14 +8094,14 @@ function Drawer({
|
|
|
7658
8094
|
style,
|
|
7659
8095
|
...rest
|
|
7660
8096
|
}) {
|
|
7661
|
-
const autoId =
|
|
8097
|
+
const autoId = React25__namespace.default.useId();
|
|
7662
8098
|
const titleId = `${autoId}-title`;
|
|
7663
8099
|
const descId = `${autoId}-desc`;
|
|
7664
|
-
const panelRef =
|
|
8100
|
+
const panelRef = React25__namespace.default.useRef(null);
|
|
7665
8101
|
const __twcStyles = useScopedStyles("twc-drawer-styles", DRAWER_CSS);
|
|
7666
8102
|
const renderPortal = usePortal();
|
|
7667
|
-
const [mounted, setMounted] =
|
|
7668
|
-
|
|
8103
|
+
const [mounted, setMounted] = React25__namespace.default.useState(open);
|
|
8104
|
+
React25__namespace.default.useEffect(() => {
|
|
7669
8105
|
if (open) {
|
|
7670
8106
|
setMounted(true);
|
|
7671
8107
|
return;
|
|
@@ -7673,16 +8109,10 @@ function Drawer({
|
|
|
7673
8109
|
const t = setTimeout(() => setMounted(false), 170);
|
|
7674
8110
|
return () => clearTimeout(t);
|
|
7675
8111
|
}, [open]);
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
return () => {
|
|
7681
|
-
document.body.style.overflow = prev;
|
|
7682
|
-
};
|
|
7683
|
-
}, [open]);
|
|
7684
|
-
useFocusTrap(panelRef, open && mounted);
|
|
7685
|
-
React24__namespace.default.useEffect(() => {
|
|
8112
|
+
useScrollLock(open);
|
|
8113
|
+
useInertBackground(panelRef, open && mounted);
|
|
8114
|
+
useFocusTrap(panelRef, open && mounted);
|
|
8115
|
+
React25__namespace.default.useEffect(() => {
|
|
7686
8116
|
if (!open) return void 0;
|
|
7687
8117
|
const onKey = (e) => {
|
|
7688
8118
|
if (e.key === "Escape") {
|
|
@@ -7771,16 +8201,21 @@ function Field({
|
|
|
7771
8201
|
...rest
|
|
7772
8202
|
}) {
|
|
7773
8203
|
const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS5);
|
|
7774
|
-
const autoId =
|
|
8204
|
+
const autoId = React25__namespace.default.useId();
|
|
7775
8205
|
const fieldId = id || autoId;
|
|
7776
8206
|
const descId = `${fieldId}-desc`;
|
|
8207
|
+
const hasMsg = Boolean(error || hint);
|
|
8208
|
+
const control = React25__namespace.default.isValidElement(children) ? React25__namespace.default.cloneElement(children, {
|
|
8209
|
+
"aria-describedby": [children.props["aria-describedby"], hasMsg ? descId : null].filter(Boolean).join(" ") || void 0,
|
|
8210
|
+
"aria-invalid": children.props["aria-invalid"] !== void 0 ? children.props["aria-invalid"] : error ? true : void 0
|
|
8211
|
+
}) : children;
|
|
7777
8212
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-field ${className}`, "data-size": size, ...rest, children: [
|
|
7778
8213
|
__twcStyles,
|
|
7779
8214
|
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", htmlFor, children: [
|
|
7780
8215
|
label,
|
|
7781
8216
|
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
7782
8217
|
] }) : null,
|
|
7783
|
-
|
|
8218
|
+
control,
|
|
7784
8219
|
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
|
|
7785
8220
|
] });
|
|
7786
8221
|
}
|
|
@@ -7834,6 +8269,14 @@ function fmtSize(bytes) {
|
|
|
7834
8269
|
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
|
7835
8270
|
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
|
7836
8271
|
}
|
|
8272
|
+
function matchesAccept(file, accept) {
|
|
8273
|
+
if (!accept) return true;
|
|
8274
|
+
const toks = accept.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
|
|
8275
|
+
if (!toks.length) return true;
|
|
8276
|
+
const name = file.name.toLowerCase(), type = (file.type || "").toLowerCase();
|
|
8277
|
+
return toks.some((t) => t.startsWith(".") ? name.endsWith(t) : t.endsWith("/*") ? type.startsWith(t.slice(0, -1)) : type === t);
|
|
8278
|
+
}
|
|
8279
|
+
var fileKey = (f) => `${f.name}-${f.size}-${f.lastModified}`;
|
|
7837
8280
|
function FileUpload({
|
|
7838
8281
|
accept,
|
|
7839
8282
|
multiple = false,
|
|
@@ -7845,17 +8288,20 @@ function FileUpload({
|
|
|
7845
8288
|
required = false,
|
|
7846
8289
|
value,
|
|
7847
8290
|
defaultValue = [],
|
|
8291
|
+
maxSize,
|
|
8292
|
+
maxFiles,
|
|
8293
|
+
onReject,
|
|
7848
8294
|
onChange,
|
|
7849
8295
|
id,
|
|
7850
8296
|
className = "",
|
|
7851
8297
|
...rest
|
|
7852
8298
|
}) {
|
|
7853
8299
|
const __twcStyles = useScopedStyles("twc-upload-styles", UPLOAD_CSS);
|
|
7854
|
-
const [internal, setInternal] =
|
|
8300
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
7855
8301
|
const files = value !== void 0 ? value : internal;
|
|
7856
|
-
const [drag, setDrag] =
|
|
7857
|
-
const inputRef =
|
|
7858
|
-
const autoId =
|
|
8302
|
+
const [drag, setDrag] = React25__namespace.default.useState(false);
|
|
8303
|
+
const inputRef = React25__namespace.default.useRef(null);
|
|
8304
|
+
const autoId = React25__namespace.default.useId();
|
|
7859
8305
|
const fieldId = id || autoId;
|
|
7860
8306
|
const descId = `${fieldId}-desc`;
|
|
7861
8307
|
const invalid = Boolean(error);
|
|
@@ -7864,8 +8310,28 @@ function FileUpload({
|
|
|
7864
8310
|
onChange?.(next);
|
|
7865
8311
|
};
|
|
7866
8312
|
function addFiles(list) {
|
|
7867
|
-
const
|
|
7868
|
-
|
|
8313
|
+
const incoming = Array.from(list);
|
|
8314
|
+
const retained = multiple ? files.slice() : [];
|
|
8315
|
+
const seen2 = new Set(retained.map(fileKey));
|
|
8316
|
+
const accepted = [];
|
|
8317
|
+
const rejections = [];
|
|
8318
|
+
for (const f of incoming) {
|
|
8319
|
+
if (multiple && seen2.has(fileKey(f))) continue;
|
|
8320
|
+
let reason = null;
|
|
8321
|
+
if (accept && !matchesAccept(f, accept)) reason = "type";
|
|
8322
|
+
else if (maxSize && f.size > maxSize) reason = "size";
|
|
8323
|
+
else if (multiple && maxFiles && retained.length + accepted.length >= maxFiles) reason = "count";
|
|
8324
|
+
if (reason) {
|
|
8325
|
+
rejections.push({ file: f, reason });
|
|
8326
|
+
continue;
|
|
8327
|
+
}
|
|
8328
|
+
accepted.push(f);
|
|
8329
|
+
if (multiple) seen2.add(fileKey(f));
|
|
8330
|
+
}
|
|
8331
|
+
if (rejections.length) onReject?.(rejections);
|
|
8332
|
+
if (multiple) {
|
|
8333
|
+
if (accepted.length) set([...retained, ...accepted]);
|
|
8334
|
+
} else if (accepted.length) set(accepted.slice(0, 1));
|
|
7869
8335
|
}
|
|
7870
8336
|
function remove(i) {
|
|
7871
8337
|
set(files.filter((_, idx) => idx !== i));
|
|
@@ -7939,7 +8405,7 @@ function FileUpload({
|
|
|
7939
8405
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-upload__file-size", children: fmtSize(f.size) })
|
|
7940
8406
|
] }),
|
|
7941
8407
|
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-upload__file-x", "aria-label": `Remove ${f.name}`, onClick: () => remove(i), 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" }) }) })
|
|
7942
|
-
] },
|
|
8408
|
+
] }, fileKey(f))) }) : null,
|
|
7943
8409
|
error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__error", children: error }) : null
|
|
7944
8410
|
] });
|
|
7945
8411
|
}
|
|
@@ -8058,15 +8524,15 @@ function Kanban({
|
|
|
8058
8524
|
...rest
|
|
8059
8525
|
}) {
|
|
8060
8526
|
const __twcStyles = useScopedStyles("twc-kanban-styles", KANBAN_CSS);
|
|
8061
|
-
const [internal, setInternal] =
|
|
8527
|
+
const [internal, setInternal] = React25__namespace.default.useState(cards ?? defaultCards ?? []);
|
|
8062
8528
|
const items = cards !== void 0 ? cards : internal;
|
|
8063
|
-
const [drag, setDrag] =
|
|
8064
|
-
const [overCol, setOverCol] =
|
|
8065
|
-
const [grab, setGrab] =
|
|
8066
|
-
const [announce, setAnnounce] =
|
|
8067
|
-
const rootRef =
|
|
8068
|
-
const focusIdRef =
|
|
8069
|
-
|
|
8529
|
+
const [drag, setDrag] = React25__namespace.default.useState(null);
|
|
8530
|
+
const [overCol, setOverCol] = React25__namespace.default.useState(null);
|
|
8531
|
+
const [grab, setGrab] = React25__namespace.default.useState(null);
|
|
8532
|
+
const [announce, setAnnounce] = React25__namespace.default.useState("");
|
|
8533
|
+
const rootRef = React25__namespace.default.useRef(null);
|
|
8534
|
+
const focusIdRef = React25__namespace.default.useRef(null);
|
|
8535
|
+
React25__namespace.default.useEffect(() => {
|
|
8070
8536
|
if (focusIdRef.current == null) return void 0;
|
|
8071
8537
|
const raf = requestAnimationFrame(() => {
|
|
8072
8538
|
const id = focusIdRef.current;
|
|
@@ -8211,42 +8677,49 @@ var LIST_CSS = `
|
|
|
8211
8677
|
.twc-list__title { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
8212
8678
|
.twc-list__desc { font-size: var(--text-xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
8213
8679
|
.twc-list__trail { flex: none; display: inline-flex; align-items: center; gap: var(--space-2); color: var(--color-text-subtle); font-size: var(--text-sm); }
|
|
8680
|
+
.twc-list__empty { padding: 30px 12px; text-align: center; color: var(--color-text-subtle); font-size: var(--text-sm); }
|
|
8214
8681
|
`;
|
|
8215
|
-
function List({ items, plain = false, className = "", ...rest }) {
|
|
8682
|
+
function List({ items, plain = false, emptyMessage, className = "", ...rest }) {
|
|
8216
8683
|
const __twcStyles = useScopedStyles("twc-list-styles", LIST_CSS);
|
|
8217
8684
|
const safeHref12 = (url) => {
|
|
8218
8685
|
if (url == null) return void 0;
|
|
8219
8686
|
const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
|
|
8220
8687
|
return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
|
|
8221
8688
|
};
|
|
8222
|
-
return
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8689
|
+
return (
|
|
8690
|
+
// role="list" before {...rest} so a consumer can still override it (e.g. role="menu");
|
|
8691
|
+
// list-style:none + display:contents on the <li> drop the implicit list/listitem roles
|
|
8692
|
+
// in some engines, so we set them explicitly (#123).
|
|
8693
|
+
/* @__PURE__ */ jsxRuntime.jsxs("ul", { className: `twc-list ${className}`, role: "list", "data-plain": plain || void 0, ...rest, children: [
|
|
8694
|
+
__twcStyles,
|
|
8695
|
+
items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("li", { role: "presentation", style: { display: "contents" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-list__empty", children: emptyMessage ?? "Nothing here yet" }) }) : items.map((it, i) => {
|
|
8696
|
+
const href = safeHref12(it.href);
|
|
8697
|
+
const interactive = Boolean(it.onClick || href);
|
|
8698
|
+
const Tag2 = href ? "a" : interactive ? "button" : "div";
|
|
8699
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8700
|
+
it.leading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-list__lead", "aria-hidden": "true", children: it.leading }) : null,
|
|
8701
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-list__main", children: [
|
|
8702
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-list__title", children: it.title }),
|
|
8703
|
+
it.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-list__desc", children: it.description }) : null
|
|
8704
|
+
] }),
|
|
8705
|
+
it.trailing ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-list__trail", children: it.trailing }) : null
|
|
8706
|
+
] });
|
|
8707
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { role: "listitem", style: { display: "contents" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8708
|
+
Tag2,
|
|
8709
|
+
{
|
|
8710
|
+
className: "twc-list__item",
|
|
8711
|
+
"data-interactive": interactive || void 0,
|
|
8712
|
+
"data-active": it.active || void 0,
|
|
8713
|
+
"aria-current": it.active ? "page" : void 0,
|
|
8714
|
+
href,
|
|
8715
|
+
type: Tag2 === "button" ? "button" : void 0,
|
|
8716
|
+
onClick: it.onClick,
|
|
8717
|
+
children: content
|
|
8718
|
+
}
|
|
8719
|
+
) }, i);
|
|
8720
|
+
})
|
|
8721
|
+
] })
|
|
8722
|
+
);
|
|
8250
8723
|
}
|
|
8251
8724
|
var NAVBAR_CSS = `
|
|
8252
8725
|
.twc-navbar { display: flex; align-items: center; gap: var(--space-4); height: 60px; padding: 0 var(--space-5);
|
|
@@ -8369,21 +8842,21 @@ function Popover({
|
|
|
8369
8842
|
...rest
|
|
8370
8843
|
}) {
|
|
8371
8844
|
const __twcStyles = useScopedStyles("twc-popover-styles", POPOVER_CSS);
|
|
8372
|
-
const [openState, setOpenState] =
|
|
8373
|
-
const [render, setRender] =
|
|
8374
|
-
const [pos, setPos] =
|
|
8375
|
-
const wrapRef =
|
|
8376
|
-
const popRef =
|
|
8377
|
-
const popId =
|
|
8845
|
+
const [openState, setOpenState] = React25__namespace.default.useState(defaultOpen);
|
|
8846
|
+
const [render, setRender] = React25__namespace.default.useState(false);
|
|
8847
|
+
const [pos, setPos] = React25__namespace.default.useState(null);
|
|
8848
|
+
const wrapRef = React25__namespace.default.useRef(null);
|
|
8849
|
+
const popRef = React25__namespace.default.useRef(null);
|
|
8850
|
+
const popId = React25__namespace.default.useId();
|
|
8378
8851
|
const controlled = openProp !== void 0;
|
|
8379
8852
|
const open = controlled ? !!openProp : openState;
|
|
8380
|
-
const openRef =
|
|
8853
|
+
const openRef = React25__namespace.default.useRef(open);
|
|
8381
8854
|
openRef.current = open;
|
|
8382
|
-
const controlledRef =
|
|
8855
|
+
const controlledRef = React25__namespace.default.useRef(controlled);
|
|
8383
8856
|
controlledRef.current = controlled;
|
|
8384
|
-
const onOpenChangeRef =
|
|
8857
|
+
const onOpenChangeRef = React25__namespace.default.useRef(onOpenChange);
|
|
8385
8858
|
onOpenChangeRef.current = onOpenChange;
|
|
8386
|
-
const setOpen =
|
|
8859
|
+
const setOpen = React25__namespace.default.useCallback((next) => {
|
|
8387
8860
|
const value = typeof next === "function" ? next(openRef.current) : next;
|
|
8388
8861
|
if (value === openRef.current) return;
|
|
8389
8862
|
if (!controlledRef.current) setOpenState(value);
|
|
@@ -8391,7 +8864,7 @@ function Popover({
|
|
|
8391
8864
|
}, []);
|
|
8392
8865
|
const toggle = () => setOpen((o) => !o);
|
|
8393
8866
|
const RD = { createPortal: typeof reactDom.createPortal === "function" ? reactDom.createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
|
|
8394
|
-
const place =
|
|
8867
|
+
const place = React25__namespace.default.useCallback(() => {
|
|
8395
8868
|
const t = wrapRef.current;
|
|
8396
8869
|
if (!t) return;
|
|
8397
8870
|
const r = t.getBoundingClientRect();
|
|
@@ -8401,7 +8874,13 @@ function Popover({
|
|
|
8401
8874
|
let top, left, flip = false, arrow = {};
|
|
8402
8875
|
const vertical = placement === "top" || placement === "bottom";
|
|
8403
8876
|
if (vertical) {
|
|
8404
|
-
|
|
8877
|
+
const ph2 = popRef.current ? popRef.current.offsetHeight : 120;
|
|
8878
|
+
const spaceAbove = r.top - gap - M;
|
|
8879
|
+
const spaceBelow = vh - r.bottom - gap - M;
|
|
8880
|
+
let openUp = placement === "top";
|
|
8881
|
+
if (openUp && spaceAbove < ph2 && spaceBelow > spaceAbove) openUp = false;
|
|
8882
|
+
else if (!openUp && spaceBelow < ph2 && spaceAbove > spaceBelow) openUp = true;
|
|
8883
|
+
flip = openUp;
|
|
8405
8884
|
top = flip ? void 0 : r.bottom + gap;
|
|
8406
8885
|
const bottom = flip ? vh - r.top + gap : void 0;
|
|
8407
8886
|
let l = align === "start" ? r.left : align === "end" ? r.right - w : r.left + r.width / 2 - w / 2;
|
|
@@ -8422,7 +8901,7 @@ function Popover({
|
|
|
8422
8901
|
arrow = { top: Math.min(Math.max(cy - top - 5.5, 8), ph - 18), [onRight ? "left" : "right"]: -6 };
|
|
8423
8902
|
setPos({ top, left, width: w, flip: false, arrow });
|
|
8424
8903
|
}, [placement, align, width]);
|
|
8425
|
-
|
|
8904
|
+
React25__namespace.default.useEffect(() => {
|
|
8426
8905
|
if (!open) return;
|
|
8427
8906
|
place();
|
|
8428
8907
|
const onMove = () => place();
|
|
@@ -8445,7 +8924,7 @@ function Popover({
|
|
|
8445
8924
|
document.removeEventListener("keydown", onKey);
|
|
8446
8925
|
};
|
|
8447
8926
|
}, [open, place]);
|
|
8448
|
-
|
|
8927
|
+
React25__namespace.default.useEffect(() => {
|
|
8449
8928
|
if (open) {
|
|
8450
8929
|
setRender(true);
|
|
8451
8930
|
return;
|
|
@@ -8453,12 +8932,12 @@ function Popover({
|
|
|
8453
8932
|
const t = setTimeout(() => setRender(false), 170);
|
|
8454
8933
|
return () => clearTimeout(t);
|
|
8455
8934
|
}, [open]);
|
|
8456
|
-
|
|
8935
|
+
React25__namespace.default.useEffect(() => {
|
|
8457
8936
|
if (render && open) place();
|
|
8458
8937
|
}, [render, place]);
|
|
8459
|
-
const restoreRef =
|
|
8460
|
-
const needFocusRef =
|
|
8461
|
-
|
|
8938
|
+
const restoreRef = React25__namespace.default.useRef(null);
|
|
8939
|
+
const needFocusRef = React25__namespace.default.useRef(false);
|
|
8940
|
+
React25__namespace.default.useEffect(() => {
|
|
8462
8941
|
if (open) {
|
|
8463
8942
|
restoreRef.current = document.activeElement;
|
|
8464
8943
|
needFocusRef.current = true;
|
|
@@ -8469,12 +8948,7 @@ function Popover({
|
|
|
8469
8948
|
needFocusRef.current = false;
|
|
8470
8949
|
if (prev && typeof prev.focus === "function" && popRef.current?.contains(document.activeElement)) prev.focus();
|
|
8471
8950
|
}, [open]);
|
|
8472
|
-
|
|
8473
|
-
if (open && render && pos && needFocusRef.current) {
|
|
8474
|
-
needFocusRef.current = false;
|
|
8475
|
-
popRef.current?.focus({ preventScroll: true });
|
|
8476
|
-
}
|
|
8477
|
-
}, [open, render, pos]);
|
|
8951
|
+
useFocusTrap(popRef, open && render && !!pos, { restoreFocus: false });
|
|
8478
8952
|
const pop = render && pos ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8479
8953
|
"div",
|
|
8480
8954
|
{
|
|
@@ -8485,6 +8959,7 @@ function Popover({
|
|
|
8485
8959
|
"data-state": open ? "open" : "closed",
|
|
8486
8960
|
"data-flip": pos.flip || void 0,
|
|
8487
8961
|
role: "dialog",
|
|
8962
|
+
"aria-modal": "true",
|
|
8488
8963
|
"aria-labelledby": title ? `${popId}-title` : void 0,
|
|
8489
8964
|
style: { top: pos.top, bottom: pos.bottom, left: pos.left, width: pos.width },
|
|
8490
8965
|
children: [
|
|
@@ -8497,7 +8972,7 @@ function Popover({
|
|
|
8497
8972
|
]
|
|
8498
8973
|
}
|
|
8499
8974
|
) : null;
|
|
8500
|
-
const triggerEl =
|
|
8975
|
+
const triggerEl = React25__namespace.default.isValidElement(trigger) ? React25__namespace.default.cloneElement(trigger, {
|
|
8501
8976
|
onClick: (e) => {
|
|
8502
8977
|
trigger.props.onClick?.(e);
|
|
8503
8978
|
toggle();
|
|
@@ -8540,7 +9015,7 @@ function Progress({
|
|
|
8540
9015
|
className = "",
|
|
8541
9016
|
...rest
|
|
8542
9017
|
}) {
|
|
8543
|
-
const labelId =
|
|
9018
|
+
const labelId = React25__namespace.default.useId();
|
|
8544
9019
|
const { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...restProps } = rest;
|
|
8545
9020
|
const __twcStyles = useScopedStyles("twc-progress-styles", `
|
|
8546
9021
|
.twc-progress-wrap { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-sans); }
|
|
@@ -8663,10 +9138,13 @@ function Radio({
|
|
|
8663
9138
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
8664
9139
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
8665
9140
|
`);
|
|
8666
|
-
const autoId =
|
|
9141
|
+
const autoId = React25__namespace.default.useId();
|
|
8667
9142
|
const fieldId = id || autoId;
|
|
8668
9143
|
const errId = `${fieldId}-error`;
|
|
8669
9144
|
const invalid = Boolean(error);
|
|
9145
|
+
if (process.env.NODE_ENV !== "production" && !label && !description && !rest["aria-label"] && !rest["aria-labelledby"]) {
|
|
9146
|
+
warnOnce("Radio.no-name", "Radio: no accessible name \u2014 pass `label`, or `aria-label`/`aria-labelledby` for a label-less control (WCAG 4.1.2).");
|
|
9147
|
+
}
|
|
8670
9148
|
const describedBy = [rest["aria-describedby"], error ? errId : null].filter(Boolean).join(" ") || void 0;
|
|
8671
9149
|
const control = /* @__PURE__ */ jsxRuntime.jsxs("label", { className: `twc-radio ${className}`, "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, htmlFor: fieldId, children: [
|
|
8672
9150
|
__twcStyles,
|
|
@@ -8683,6 +9161,7 @@ function Radio({
|
|
|
8683
9161
|
disabled,
|
|
8684
9162
|
onChange,
|
|
8685
9163
|
...rest,
|
|
9164
|
+
required: required || void 0,
|
|
8686
9165
|
"aria-required": required || void 0,
|
|
8687
9166
|
"aria-invalid": invalid || void 0,
|
|
8688
9167
|
"aria-describedby": describedBy
|
|
@@ -8700,11 +9179,103 @@ function Radio({
|
|
|
8700
9179
|
/* @__PURE__ */ jsxRuntime.jsx("span", { id: errId, className: "twc-field__error", children: error })
|
|
8701
9180
|
] });
|
|
8702
9181
|
}
|
|
9182
|
+
var RADIO_GROUP_CSS = `
|
|
9183
|
+
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
9184
|
+
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
9185
|
+
.twc-field__req { color: var(--color-danger); }
|
|
9186
|
+
.twc-field__hint { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
9187
|
+
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
9188
|
+
.twc-radio-group__items { display: flex; flex-direction: column; gap: var(--space-2-5); }
|
|
9189
|
+
.twc-radio-group__items[data-orientation="horizontal"] { flex-direction: row; flex-wrap: wrap; gap: var(--space-4); }
|
|
9190
|
+
`;
|
|
9191
|
+
function RadioGroup({
|
|
9192
|
+
name,
|
|
9193
|
+
value,
|
|
9194
|
+
defaultValue,
|
|
9195
|
+
onChange,
|
|
9196
|
+
options,
|
|
9197
|
+
children,
|
|
9198
|
+
label,
|
|
9199
|
+
hint,
|
|
9200
|
+
error,
|
|
9201
|
+
orientation = "vertical",
|
|
9202
|
+
disabled = false,
|
|
9203
|
+
required = false,
|
|
9204
|
+
size = "md",
|
|
9205
|
+
tone = "primary",
|
|
9206
|
+
id,
|
|
9207
|
+
className = "",
|
|
9208
|
+
...rest
|
|
9209
|
+
}) {
|
|
9210
|
+
const __twcStyles = useScopedStyles("twc-radio-group-styles", RADIO_GROUP_CSS);
|
|
9211
|
+
const autoId = React25__namespace.default.useId();
|
|
9212
|
+
const fieldId = id || autoId;
|
|
9213
|
+
const labelId = `${fieldId}-label`;
|
|
9214
|
+
const descId = `${fieldId}-desc`;
|
|
9215
|
+
const groupName = name || `${fieldId}-name`;
|
|
9216
|
+
const invalid = Boolean(error);
|
|
9217
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
9218
|
+
const current = value !== void 0 ? value : internal;
|
|
9219
|
+
const select = (v) => {
|
|
9220
|
+
if (value === void 0) setInternal(v);
|
|
9221
|
+
onChange?.(v);
|
|
9222
|
+
};
|
|
9223
|
+
const radios = options ? options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9224
|
+
Radio,
|
|
9225
|
+
{
|
|
9226
|
+
name: groupName,
|
|
9227
|
+
value: o.value,
|
|
9228
|
+
label: o.label,
|
|
9229
|
+
description: o.description,
|
|
9230
|
+
checked: current === o.value,
|
|
9231
|
+
onChange: () => select(o.value),
|
|
9232
|
+
disabled: disabled || o.disabled,
|
|
9233
|
+
required,
|
|
9234
|
+
size,
|
|
9235
|
+
tone
|
|
9236
|
+
},
|
|
9237
|
+
o.value
|
|
9238
|
+
)) : React25__namespace.default.Children.map(children, (child) => {
|
|
9239
|
+
if (!React25__namespace.default.isValidElement(child)) return child;
|
|
9240
|
+
const v = child.props.value;
|
|
9241
|
+
return React25__namespace.default.cloneElement(child, {
|
|
9242
|
+
name: child.props.name ?? groupName,
|
|
9243
|
+
checked: child.props.checked ?? current === v,
|
|
9244
|
+
onChange: child.props.onChange ?? (() => select(v)),
|
|
9245
|
+
disabled: child.props.disabled ?? disabled,
|
|
9246
|
+
required: child.props.required ?? required,
|
|
9247
|
+
size: child.props.size ?? size,
|
|
9248
|
+
tone: child.props.tone ?? tone
|
|
9249
|
+
});
|
|
9250
|
+
});
|
|
9251
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9252
|
+
"div",
|
|
9253
|
+
{
|
|
9254
|
+
className: `twc-field ${className}`,
|
|
9255
|
+
role: "radiogroup",
|
|
9256
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
9257
|
+
"aria-describedby": error || hint ? descId : void 0,
|
|
9258
|
+
"aria-invalid": invalid || void 0,
|
|
9259
|
+
"aria-required": required || void 0,
|
|
9260
|
+
"data-orientation": orientation,
|
|
9261
|
+
...rest,
|
|
9262
|
+
children: [
|
|
9263
|
+
__twcStyles,
|
|
9264
|
+
label ? /* @__PURE__ */ jsxRuntime.jsxs("span", { id: labelId, className: "twc-field__label", children: [
|
|
9265
|
+
label,
|
|
9266
|
+
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
9267
|
+
] }) : null,
|
|
9268
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-radio-group__items", "data-orientation": orientation === "horizontal" ? "horizontal" : void 0, children: radios }),
|
|
9269
|
+
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
|
|
9270
|
+
]
|
|
9271
|
+
}
|
|
9272
|
+
);
|
|
9273
|
+
}
|
|
8703
9274
|
var RATING_CSS = `
|
|
8704
9275
|
.twc-rating { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-sans); }
|
|
8705
9276
|
.twc-rating__stars { display: inline-flex; gap: 2px; }
|
|
8706
|
-
.twc-rating__btn { border: none; background: transparent; padding: 1px; cursor: pointer;
|
|
8707
|
-
transition: transform var(--duration-fast) var(--ease-spring)
|
|
9277
|
+
.twc-rating__btn { border: none; background: transparent; padding: 1px; cursor: pointer; line-height: 0;
|
|
9278
|
+
transition: transform var(--duration-fast) var(--ease-spring); }
|
|
8708
9279
|
.twc-rating__btn:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius-sm); }
|
|
8709
9280
|
.twc-rating[data-readonly="true"] .twc-rating__btn { cursor: default; }
|
|
8710
9281
|
.twc-rating[data-disabled="true"] { opacity: 0.55; }
|
|
@@ -8718,8 +9289,11 @@ var RATING_CSS = `
|
|
|
8718
9289
|
.twc-rating[data-tone="danger"] { --_accent: var(--color-danger); }
|
|
8719
9290
|
.twc-rating[data-tone="info"] { --_accent: var(--color-info); }
|
|
8720
9291
|
.twc-rating[data-tone="neutral"] { --_accent: var(--color-text); }
|
|
8721
|
-
|
|
8722
|
-
.twc-
|
|
9292
|
+
/* Per-star partial fill: an accent-colored star clipped to var(--twc-fill) over an empty star. */
|
|
9293
|
+
.twc-rating__star { position: relative; display: inline-block; line-height: 0; }
|
|
9294
|
+
.twc-rating__bg { color: var(--color-border-strong); }
|
|
9295
|
+
.twc-rating__fg { position: absolute; inset-block: 0; inset-inline-start: 0; width: var(--twc-fill, 0%); overflow: hidden; color: var(--_c, var(--_accent)); }
|
|
9296
|
+
.twc-rating svg { width: var(--_sz, 24px); height: var(--_sz, 24px); display: block; }
|
|
8723
9297
|
.twc-rating[data-size="sm"] { --_sz: 18px; }
|
|
8724
9298
|
.twc-rating[data-size="lg"] { --_sz: 32px; }
|
|
8725
9299
|
.twc-rating__value { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
|
|
@@ -8735,19 +9309,26 @@ function Rating({
|
|
|
8735
9309
|
readOnly = false,
|
|
8736
9310
|
disabled = false,
|
|
8737
9311
|
showValue = false,
|
|
9312
|
+
clearable = true,
|
|
9313
|
+
format,
|
|
9314
|
+
name,
|
|
8738
9315
|
onChange,
|
|
8739
9316
|
className = "",
|
|
8740
9317
|
style,
|
|
8741
9318
|
...rest
|
|
8742
9319
|
}) {
|
|
8743
9320
|
const __twcStyles = useScopedStyles("twc-rating-styles", RATING_CSS);
|
|
8744
|
-
const [internal, setInternal] =
|
|
8745
|
-
const [hover, setHover] =
|
|
9321
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue);
|
|
9322
|
+
const [hover, setHover] = React25__namespace.default.useState(0);
|
|
8746
9323
|
const val = value !== void 0 ? value : internal;
|
|
8747
9324
|
const shown = hover || val;
|
|
8748
9325
|
const interactive = !readOnly && !disabled;
|
|
8749
|
-
const btnRefs =
|
|
9326
|
+
const btnRefs = React25__namespace.default.useRef([]);
|
|
8750
9327
|
const tabStar = Math.min(count, Math.max(1, Math.round(val) || 1));
|
|
9328
|
+
const fmt = (v) => format ? format(v) : Number.isInteger(v) ? String(v) : v.toFixed(1);
|
|
9329
|
+
if (process.env.NODE_ENV !== "production" && interactive && !Number.isInteger(val)) {
|
|
9330
|
+
warnOnce("Rating.fractional-interactive", "Rating: a fractional value only renders (partial-fill display) in readOnly mode \u2014 interactive selection is integer-only.");
|
|
9331
|
+
}
|
|
8751
9332
|
const set = (v) => {
|
|
8752
9333
|
if (!interactive) return;
|
|
8753
9334
|
if (value === void 0) setInternal(v);
|
|
@@ -8760,18 +9341,46 @@ function Rating({
|
|
|
8760
9341
|
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next = Math.max(1, val - 1);
|
|
8761
9342
|
else if (e.key === "Home") next = 1;
|
|
8762
9343
|
else if (e.key === "End") next = count;
|
|
9344
|
+
else if (clearable && (e.key === "Delete" || e.key === "Backspace")) next = 0;
|
|
8763
9345
|
else return;
|
|
8764
9346
|
e.preventDefault();
|
|
8765
9347
|
set(next);
|
|
8766
|
-
btnRefs.current[next - 1]?.focus();
|
|
9348
|
+
btnRefs.current[Math.max(0, next - 1)]?.focus();
|
|
9349
|
+
};
|
|
9350
|
+
const star = (n) => {
|
|
9351
|
+
const fill = Math.max(0, Math.min(1, shown - (n - 1)));
|
|
9352
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-rating__star", style: { "--twc-fill": `${fill * 100}%` }, children: [
|
|
9353
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "twc-rating__bg", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: StarPath }) }),
|
|
9354
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-rating__fg", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: StarPath }) }) })
|
|
9355
|
+
] });
|
|
8767
9356
|
};
|
|
9357
|
+
if (readOnly) {
|
|
9358
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9359
|
+
"div",
|
|
9360
|
+
{
|
|
9361
|
+
className: `twc-rating ${className}`,
|
|
9362
|
+
"data-size": size,
|
|
9363
|
+
"data-tone": tone,
|
|
9364
|
+
"data-readonly": "true",
|
|
9365
|
+
style: color ? { "--_c": color, ...style } : style,
|
|
9366
|
+
role: "img",
|
|
9367
|
+
"aria-label": `${fmt(val)} out of ${count} stars`,
|
|
9368
|
+
...rest,
|
|
9369
|
+
children: [
|
|
9370
|
+
__twcStyles,
|
|
9371
|
+
name ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: val, disabled: disabled || void 0 }) : null,
|
|
9372
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-rating__stars", children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-rating__btn", children: star(i + 1) }, i + 1)) }),
|
|
9373
|
+
showValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-rating__value", children: fmt(val) }) : null
|
|
9374
|
+
]
|
|
9375
|
+
}
|
|
9376
|
+
);
|
|
9377
|
+
}
|
|
8768
9378
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8769
9379
|
"div",
|
|
8770
9380
|
{
|
|
8771
9381
|
className: `twc-rating ${className}`,
|
|
8772
9382
|
"data-size": size,
|
|
8773
9383
|
"data-tone": tone,
|
|
8774
|
-
"data-readonly": readOnly || void 0,
|
|
8775
9384
|
"data-disabled": disabled || void 0,
|
|
8776
9385
|
style: color ? { "--_c": color, ...style } : style,
|
|
8777
9386
|
role: "radiogroup",
|
|
@@ -8780,6 +9389,7 @@ function Rating({
|
|
|
8780
9389
|
...rest,
|
|
8781
9390
|
children: [
|
|
8782
9391
|
__twcStyles,
|
|
9392
|
+
name ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: val, disabled: disabled || void 0 }) : null,
|
|
8783
9393
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-rating__stars", onMouseLeave: () => setHover(0), onKeyDown, children: Array.from({ length: count }).map((_, i) => {
|
|
8784
9394
|
const n = i + 1;
|
|
8785
9395
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -8790,149 +9400,19 @@ function Rating({
|
|
|
8790
9400
|
},
|
|
8791
9401
|
type: "button",
|
|
8792
9402
|
className: "twc-rating__btn",
|
|
8793
|
-
"data-on": n <= shown || void 0,
|
|
8794
9403
|
role: "radio",
|
|
8795
9404
|
"aria-label": `${n} star${n > 1 ? "s" : ""}`,
|
|
8796
9405
|
"aria-checked": n === val,
|
|
8797
|
-
disabled
|
|
9406
|
+
disabled,
|
|
8798
9407
|
tabIndex: interactive && n === tabStar ? 0 : -1,
|
|
8799
9408
|
onMouseEnter: () => interactive && setHover(n),
|
|
8800
|
-
onClick: () => set(n === val ? 0 : n),
|
|
8801
|
-
children:
|
|
9409
|
+
onClick: () => set(n === val && clearable ? 0 : n),
|
|
9410
|
+
children: star(n)
|
|
8802
9411
|
},
|
|
8803
9412
|
n
|
|
8804
9413
|
);
|
|
8805
9414
|
}) }),
|
|
8806
|
-
showValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-rating__value", children: val
|
|
8807
|
-
]
|
|
8808
|
-
}
|
|
8809
|
-
);
|
|
8810
|
-
}
|
|
8811
|
-
var TOOLTIP_CSS = `
|
|
8812
|
-
.twc-tooltip-wrap { display: inline-flex; }
|
|
8813
|
-
.twc-tooltip {
|
|
8814
|
-
position: fixed; z-index: var(--z-tooltip); pointer-events: none;
|
|
8815
|
-
padding: 6px 10px; border-radius: var(--radius-md);
|
|
8816
|
-
background: var(--color-text); color: var(--color-surface);
|
|
8817
|
-
font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--font-medium);
|
|
8818
|
-
line-height: 1.3; white-space: nowrap; box-shadow: var(--shadow-md);
|
|
8819
|
-
opacity: 0; transform: scale(0.9); transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-spring);
|
|
8820
|
-
}
|
|
8821
|
-
.twc-tooltip[data-show="true"] { opacity: 1; transform: scale(1); }
|
|
8822
|
-
.twc-tooltip[data-place="top"] { transform-origin: bottom center; translate: -50% 0; }
|
|
8823
|
-
.twc-tooltip[data-place="bottom"] { transform-origin: top center; translate: -50% 0; }
|
|
8824
|
-
.twc-tooltip[data-place="left"] { transform-origin: right center; translate: 0 -50%; }
|
|
8825
|
-
.twc-tooltip[data-place="right"] { transform-origin: left center; translate: 0 -50%; }
|
|
8826
|
-
.twc-tooltip[data-show="true"][data-place="top"], .twc-tooltip[data-show="true"][data-place="bottom"] { transform: scale(1); }
|
|
8827
|
-
.twc-tooltip__arrow { position: absolute; width: 7px; height: 7px; background: var(--color-text); transform: rotate(45deg); }
|
|
8828
|
-
.twc-tooltip[data-place="top"] .twc-tooltip__arrow { bottom: -3px; left: 50%; margin-left: -3.5px; }
|
|
8829
|
-
.twc-tooltip[data-place="bottom"] .twc-tooltip__arrow { top: -3px; left: 50%; margin-left: -3.5px; }
|
|
8830
|
-
.twc-tooltip[data-place="left"] .twc-tooltip__arrow { right: -3px; top: 50%; margin-top: -3.5px; }
|
|
8831
|
-
.twc-tooltip[data-place="right"] .twc-tooltip__arrow { left: -3px; top: 50%; margin-top: -3.5px; }
|
|
8832
|
-
@media (prefers-reduced-motion: reduce) { .twc-tooltip { transition: opacity var(--duration-fast) linear; transform: none; } }
|
|
8833
|
-
`;
|
|
8834
|
-
function Tooltip({
|
|
8835
|
-
children,
|
|
8836
|
-
label,
|
|
8837
|
-
placement = "top",
|
|
8838
|
-
delay = 120,
|
|
8839
|
-
className = "",
|
|
8840
|
-
...rest
|
|
8841
|
-
}) {
|
|
8842
|
-
const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
|
|
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);
|
|
8849
|
-
const open = () => {
|
|
8850
|
-
clearTimeout(timer.current);
|
|
8851
|
-
timer.current = setTimeout(() => setShow(true), delay);
|
|
8852
|
-
};
|
|
8853
|
-
const close = () => {
|
|
8854
|
-
clearTimeout(timer.current);
|
|
8855
|
-
setShow(false);
|
|
8856
|
-
};
|
|
8857
|
-
React24__namespace.default.useEffect(() => () => clearTimeout(timer.current), []);
|
|
8858
|
-
const place = React24__namespace.default.useCallback(() => {
|
|
8859
|
-
const el = wrapRef.current;
|
|
8860
|
-
if (!el) return;
|
|
8861
|
-
const r = el.getBoundingClientRect();
|
|
8862
|
-
const cx = Math.round(r.left + r.width / 2), cy = Math.round(r.top + r.height / 2);
|
|
8863
|
-
const vw = window.innerWidth, vh = window.innerHeight, gap = 8, margin = 8;
|
|
8864
|
-
const tip = tipRef.current;
|
|
8865
|
-
const tw = tip ? tip.offsetWidth : 0, th = tip ? tip.offsetHeight : 0;
|
|
8866
|
-
const clampX = (c) => tw ? Math.round(Math.min(Math.max(c, margin + tw / 2), vw - margin - tw / 2)) : c;
|
|
8867
|
-
const clampY = (c) => th ? Math.round(Math.min(Math.max(c, margin + th / 2), vh - margin - th / 2)) : c;
|
|
8868
|
-
const base = { left: "auto", right: "auto", top: "auto", bottom: "auto" };
|
|
8869
|
-
if (placement === "bottom") setCoords({ ...base, left: clampX(cx), top: Math.round(r.bottom + gap) });
|
|
8870
|
-
else if (placement === "left") setCoords({ ...base, top: clampY(cy), right: Math.round(vw - r.left + gap) });
|
|
8871
|
-
else if (placement === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
|
|
8872
|
-
else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
|
|
8873
|
-
}, [placement]);
|
|
8874
|
-
React24__namespace.default.useEffect(() => {
|
|
8875
|
-
place();
|
|
8876
|
-
}, [place]);
|
|
8877
|
-
React24__namespace.default.useEffect(() => {
|
|
8878
|
-
if (!show) return void 0;
|
|
8879
|
-
place();
|
|
8880
|
-
const onMove = () => place();
|
|
8881
|
-
window.addEventListener("scroll", onMove, true);
|
|
8882
|
-
window.addEventListener("resize", onMove);
|
|
8883
|
-
return () => {
|
|
8884
|
-
window.removeEventListener("scroll", onMove, true);
|
|
8885
|
-
window.removeEventListener("resize", onMove);
|
|
8886
|
-
};
|
|
8887
|
-
}, [show, place]);
|
|
8888
|
-
React24__namespace.default.useEffect(() => {
|
|
8889
|
-
if (!show) return;
|
|
8890
|
-
const onKeyDown = (e) => {
|
|
8891
|
-
if (e.key === "Escape") {
|
|
8892
|
-
clearTimeout(timer.current);
|
|
8893
|
-
setShow(false);
|
|
8894
|
-
}
|
|
8895
|
-
};
|
|
8896
|
-
document.addEventListener("keydown", onKeyDown);
|
|
8897
|
-
return () => document.removeEventListener("keydown", onKeyDown);
|
|
8898
|
-
}, [show]);
|
|
8899
|
-
const describedBy = show ? id : void 0;
|
|
8900
|
-
const trigger = React24__namespace.default.isValidElement(children) && children.type !== React24__namespace.default.Fragment ? React24__namespace.default.cloneElement(children, {
|
|
8901
|
-
"aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
|
|
8902
|
-
}) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-describedby": describedBy, children });
|
|
8903
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8904
|
-
"span",
|
|
8905
|
-
{
|
|
8906
|
-
ref: wrapRef,
|
|
8907
|
-
className: `twc-tooltip-wrap ${className}`,
|
|
8908
|
-
onMouseEnter: open,
|
|
8909
|
-
onMouseLeave: close,
|
|
8910
|
-
onFocus: open,
|
|
8911
|
-
onBlur: close,
|
|
8912
|
-
...rest,
|
|
8913
|
-
children: [
|
|
8914
|
-
__twcStyles,
|
|
8915
|
-
trigger,
|
|
8916
|
-
coords ? reactDom.createPortal(
|
|
8917
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8918
|
-
"span",
|
|
8919
|
-
{
|
|
8920
|
-
ref: tipRef,
|
|
8921
|
-
id,
|
|
8922
|
-
className: "twc-tooltip",
|
|
8923
|
-
"data-place": placement,
|
|
8924
|
-
"data-show": show || void 0,
|
|
8925
|
-
role: "tooltip",
|
|
8926
|
-
"aria-hidden": show ? void 0 : "true",
|
|
8927
|
-
style: { position: "fixed", left: coords.left, right: coords.right, top: coords.top, bottom: coords.bottom },
|
|
8928
|
-
children: [
|
|
8929
|
-
label,
|
|
8930
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
|
|
8931
|
-
]
|
|
8932
|
-
}
|
|
8933
|
-
),
|
|
8934
|
-
document.body
|
|
8935
|
-
) : null
|
|
9415
|
+
showValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-rating__value", children: fmt(val) }) : null
|
|
8936
9416
|
]
|
|
8937
9417
|
}
|
|
8938
9418
|
);
|
|
@@ -9030,24 +9510,24 @@ function Sidebar({
|
|
|
9030
9510
|
...rest
|
|
9031
9511
|
}) {
|
|
9032
9512
|
const __twcStyles = useScopedStyles("twc-sidebar-styles", SIDEBAR_CSS);
|
|
9033
|
-
const navId =
|
|
9034
|
-
const panelRef =
|
|
9513
|
+
const navId = React25__namespace.default.useId();
|
|
9514
|
+
const panelRef = React25__namespace.default.useRef(null);
|
|
9035
9515
|
const renderPortal = usePortal();
|
|
9036
|
-
const [internal, setInternal] =
|
|
9516
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultCollapsed);
|
|
9037
9517
|
const collapsed = collapsedProp !== void 0 ? collapsedProp : internal;
|
|
9038
9518
|
const toggle = () => {
|
|
9039
9519
|
const next = !collapsed;
|
|
9040
9520
|
if (collapsedProp === void 0) setInternal(next);
|
|
9041
9521
|
onCollapsedChange?.(next);
|
|
9042
9522
|
};
|
|
9043
|
-
const [openInternal, setOpenInternal] =
|
|
9523
|
+
const [openInternal, setOpenInternal] = React25__namespace.default.useState(defaultOpen);
|
|
9044
9524
|
const open = openProp !== void 0 ? openProp : openInternal;
|
|
9045
9525
|
const setOpen = (next) => {
|
|
9046
9526
|
if (openProp === void 0) setOpenInternal(next);
|
|
9047
9527
|
onOpenChange?.(next);
|
|
9048
9528
|
};
|
|
9049
|
-
const [mounted, setMounted] =
|
|
9050
|
-
|
|
9529
|
+
const [mounted, setMounted] = React25__namespace.default.useState(open);
|
|
9530
|
+
React25__namespace.default.useEffect(() => {
|
|
9051
9531
|
if (!overlay) return void 0;
|
|
9052
9532
|
if (open) {
|
|
9053
9533
|
setMounted(true);
|
|
@@ -9056,7 +9536,7 @@ function Sidebar({
|
|
|
9056
9536
|
const t = setTimeout(() => setMounted(false), 170);
|
|
9057
9537
|
return () => clearTimeout(t);
|
|
9058
9538
|
}, [overlay, open]);
|
|
9059
|
-
|
|
9539
|
+
React25__namespace.default.useEffect(() => {
|
|
9060
9540
|
if (!overlay || !open) return void 0;
|
|
9061
9541
|
const prev = document.body.style.overflow;
|
|
9062
9542
|
document.body.style.overflow = "hidden";
|
|
@@ -9065,7 +9545,7 @@ function Sidebar({
|
|
|
9065
9545
|
};
|
|
9066
9546
|
}, [overlay, open]);
|
|
9067
9547
|
useFocusTrap(panelRef, overlay && open && mounted);
|
|
9068
|
-
|
|
9548
|
+
React25__namespace.default.useEffect(() => {
|
|
9069
9549
|
if (!overlay || !open) return void 0;
|
|
9070
9550
|
const onKey = (e) => {
|
|
9071
9551
|
if (e.key === "Escape") {
|
|
@@ -9117,7 +9597,7 @@ function Sidebar({
|
|
|
9117
9597
|
const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9118
9598
|
__twcStyles,
|
|
9119
9599
|
brand ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__head", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-sidebar__brand", children: brand }) }) : null,
|
|
9120
|
-
/* @__PURE__ */ jsxRuntime.jsx("nav", { id: navId, className: "twc-sidebar__nav", "aria-label": navLabel, children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9600
|
+
/* @__PURE__ */ jsxRuntime.jsx("nav", { id: navId, className: "twc-sidebar__nav", "aria-label": navLabel, children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React25__namespace.default.Fragment, { children: [
|
|
9121
9601
|
g.section != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-sidebar__section", id: g.sid, children: g.section }) : null,
|
|
9122
9602
|
/* @__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
9603
|
] }, gi)) }),
|
|
@@ -9256,11 +9736,16 @@ function Slider({
|
|
|
9256
9736
|
min: minProp = 0,
|
|
9257
9737
|
max: maxProp = 100,
|
|
9258
9738
|
step: stepProp = 1,
|
|
9739
|
+
pageStep: pageStepProp,
|
|
9740
|
+
precision,
|
|
9259
9741
|
tone = "primary",
|
|
9260
9742
|
disabled = false,
|
|
9743
|
+
range = false,
|
|
9261
9744
|
showValue = true,
|
|
9262
9745
|
showTicks = false,
|
|
9263
9746
|
formatValue,
|
|
9747
|
+
getAriaValueText,
|
|
9748
|
+
name,
|
|
9264
9749
|
onChange,
|
|
9265
9750
|
id,
|
|
9266
9751
|
className = "",
|
|
@@ -9269,38 +9754,73 @@ function Slider({
|
|
|
9269
9754
|
const min = Number.isFinite(minProp) ? minProp : 0;
|
|
9270
9755
|
const max = Number.isFinite(maxProp) && maxProp > min ? maxProp : min + 1;
|
|
9271
9756
|
const step = Number.isFinite(stepProp) && stepProp > 0 ? stepProp : 1;
|
|
9272
|
-
const
|
|
9273
|
-
const
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
9277
|
-
|
|
9278
|
-
const
|
|
9279
|
-
const pct = (val - min) / (max - min) * 100;
|
|
9280
|
-
const fmt = (v) => formatValue ? formatValue(v) : v;
|
|
9757
|
+
const pageStep = Number.isFinite(pageStepProp) && pageStepProp > 0 ? pageStepProp : Math.max(step, (max - min) / 10);
|
|
9758
|
+
const stepDecimals = (() => {
|
|
9759
|
+
const s = String(step);
|
|
9760
|
+
const i = s.indexOf(".");
|
|
9761
|
+
return i === -1 ? 0 : s.length - i - 1;
|
|
9762
|
+
})();
|
|
9763
|
+
const decimals = Number.isInteger(precision) && precision >= 0 ? precision : stepDecimals;
|
|
9281
9764
|
const clampSnap = (raw) => {
|
|
9282
9765
|
const stepped = Math.round((raw - min) / step) * step + min;
|
|
9283
9766
|
return Math.min(max, Math.max(min, Math.round(stepped * 1e6) / 1e6));
|
|
9284
9767
|
};
|
|
9285
|
-
const
|
|
9286
|
-
|
|
9287
|
-
|
|
9768
|
+
const __twcStyles = useScopedStyles("twc-slider-styles", SLIDER_CSS);
|
|
9769
|
+
const autoId = React25__namespace.default.useId();
|
|
9770
|
+
const fieldId = id || autoId;
|
|
9771
|
+
const isRange = range || Array.isArray(value) || Array.isArray(defaultValue);
|
|
9772
|
+
const [internal, setInternal] = React25__namespace.default.useState(() => {
|
|
9773
|
+
if (isRange) {
|
|
9774
|
+
const dv = Array.isArray(defaultValue) ? defaultValue : [min, max];
|
|
9775
|
+
return [clampSnap(dv[0]), clampSnap(dv[1])];
|
|
9776
|
+
}
|
|
9777
|
+
return clampSnap(Number.isFinite(defaultValue) ? defaultValue : min);
|
|
9778
|
+
});
|
|
9779
|
+
const rawVal = value !== void 0 ? value : internal;
|
|
9780
|
+
const clampedVals = (isRange ? [Number(rawVal[0]), Number(rawVal[1])] : [Number(rawVal)]).map((v) => Math.min(max, Math.max(min, Number.isFinite(v) ? v : min)));
|
|
9781
|
+
const indices = isRange ? [0, 1] : [0];
|
|
9782
|
+
const trackRef = React25__namespace.default.useRef(null);
|
|
9783
|
+
const [dragging, setDragging] = React25__namespace.default.useState(false);
|
|
9784
|
+
const fmt = (v) => formatValue ? formatValue(v) : v.toFixed(decimals);
|
|
9785
|
+
const valueTextFor = (v) => {
|
|
9786
|
+
if (getAriaValueText) return getAriaValueText(v);
|
|
9787
|
+
if (formatValue) {
|
|
9788
|
+
const d = formatValue(v);
|
|
9789
|
+
return typeof d === "string" || typeof d === "number" ? String(d) : void 0;
|
|
9790
|
+
}
|
|
9791
|
+
return decimals > 0 ? v.toFixed(decimals) : void 0;
|
|
9792
|
+
};
|
|
9793
|
+
const commit = (nextVals) => {
|
|
9794
|
+
const out = isRange ? nextVals : nextVals[0];
|
|
9795
|
+
if (value === void 0) setInternal(out);
|
|
9796
|
+
onChange?.(out);
|
|
9797
|
+
};
|
|
9798
|
+
const setThumb = (i, raw) => {
|
|
9799
|
+
const next = clampedVals.slice();
|
|
9800
|
+
next[i] = clampSnap(raw);
|
|
9801
|
+
if (isRange) {
|
|
9802
|
+
if (i === 0) next[0] = Math.min(next[0], next[1]);
|
|
9803
|
+
else next[1] = Math.max(next[1], next[0]);
|
|
9804
|
+
}
|
|
9805
|
+
commit(next);
|
|
9288
9806
|
};
|
|
9289
9807
|
const fromClientX = (clientX) => {
|
|
9290
9808
|
const node = trackRef.current;
|
|
9291
|
-
if (!node) return
|
|
9809
|
+
if (!node) return clampedVals[0];
|
|
9292
9810
|
const r = node.getBoundingClientRect();
|
|
9293
9811
|
const ratio = Math.min(1, Math.max(0, (clientX - r.left) / r.width));
|
|
9294
9812
|
return clampSnap(min + ratio * (max - min));
|
|
9295
9813
|
};
|
|
9296
|
-
const dragCleanupRef =
|
|
9297
|
-
|
|
9814
|
+
const dragCleanupRef = React25__namespace.default.useRef(null);
|
|
9815
|
+
React25__namespace.default.useEffect(() => () => dragCleanupRef.current?.(), []);
|
|
9298
9816
|
function onPointerDown(e) {
|
|
9299
9817
|
if (disabled) return;
|
|
9300
9818
|
e.preventDefault();
|
|
9819
|
+
const posVal = fromClientX(e.clientX);
|
|
9820
|
+
const idx = isRange ? Math.abs(posVal - clampedVals[0]) <= Math.abs(posVal - clampedVals[1]) ? 0 : 1 : 0;
|
|
9301
9821
|
setDragging(true);
|
|
9302
|
-
|
|
9303
|
-
const move = (ev) =>
|
|
9822
|
+
setThumb(idx, posVal);
|
|
9823
|
+
const move = (ev) => setThumb(idx, fromClientX(ev.clientX));
|
|
9304
9824
|
const detach = () => {
|
|
9305
9825
|
window.removeEventListener("pointermove", move);
|
|
9306
9826
|
window.removeEventListener("pointerup", up);
|
|
@@ -9314,54 +9834,68 @@ function Slider({
|
|
|
9314
9834
|
window.addEventListener("pointermove", move);
|
|
9315
9835
|
window.addEventListener("pointerup", up);
|
|
9316
9836
|
}
|
|
9317
|
-
function
|
|
9837
|
+
function onThumbKeyDown(e, i) {
|
|
9318
9838
|
if (disabled) return;
|
|
9839
|
+
const cur = clampedVals[i];
|
|
9319
9840
|
let next;
|
|
9320
|
-
if (e.key === "ArrowRight" || e.key === "ArrowUp") next =
|
|
9321
|
-
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next =
|
|
9841
|
+
if (e.key === "ArrowRight" || e.key === "ArrowUp") next = cur + step;
|
|
9842
|
+
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next = cur - step;
|
|
9843
|
+
else if (e.key === "PageUp") next = cur + pageStep;
|
|
9844
|
+
else if (e.key === "PageDown") next = cur - pageStep;
|
|
9322
9845
|
else if (e.key === "Home") next = min;
|
|
9323
9846
|
else if (e.key === "End") next = max;
|
|
9324
9847
|
else return;
|
|
9325
9848
|
e.preventDefault();
|
|
9326
|
-
|
|
9849
|
+
setThumb(i, next);
|
|
9327
9850
|
}
|
|
9328
9851
|
const ticks = showTicks ? Math.floor((max - min) / step) + 1 : 0;
|
|
9329
9852
|
const labelId = label ? `${fieldId}-label` : void 0;
|
|
9330
9853
|
const descId = `${fieldId}-desc`;
|
|
9331
9854
|
const invalid = Boolean(error);
|
|
9332
|
-
const
|
|
9333
|
-
const
|
|
9855
|
+
const headValue = isRange ? `${fmt(clampedVals[0])} \u2013 ${fmt(clampedVals[1])}` : fmt(clampedVals[0]);
|
|
9856
|
+
const fillLo = (Math.min(...clampedVals) - min) / (max - min) * 100;
|
|
9857
|
+
const fillHi = (Math.max(...clampedVals) - min) / (max - min) * 100;
|
|
9858
|
+
const fillStyle = isRange ? { left: `${fillLo}%`, width: `${fillHi - fillLo}%` } : { width: `${fillHi}%` };
|
|
9334
9859
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-slider ${className}`, "data-tone": tone, "data-disabled": disabled || void 0, ...rest, children: [
|
|
9335
9860
|
__twcStyles,
|
|
9861
|
+
name ? clampedVals.map((v, i) => /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: v, disabled: disabled || void 0 }, i)) : null,
|
|
9336
9862
|
label || showValue ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-slider__head", children: [
|
|
9337
9863
|
label ? /* @__PURE__ */ jsxRuntime.jsx("label", { className: "twc-slider__label", id: labelId, children: label }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
|
|
9338
|
-
showValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-slider__value", children:
|
|
9864
|
+
showValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-slider__value", children: headValue }) : null
|
|
9339
9865
|
] }) : null,
|
|
9340
9866
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-slider__track", ref: trackRef, "data-show-bubble": dragging || void 0, onPointerDown, children: [
|
|
9341
9867
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-slider__rail" }),
|
|
9342
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-slider__fill", style:
|
|
9868
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-slider__fill", style: fillStyle }),
|
|
9343
9869
|
showTicks ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-slider__ticks", children: Array.from({ length: ticks }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-slider__tick", style: { left: `${ticks > 1 ? i / (ticks - 1) * 100 : 0}%` } }, i)) }) : null,
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9870
|
+
indices.map((i) => {
|
|
9871
|
+
const tv = clampedVals[i];
|
|
9872
|
+
const p = (tv - min) / (max - min) * 100;
|
|
9873
|
+
const tMin = isRange && i === 1 ? clampedVals[0] : min;
|
|
9874
|
+
const tMax = isRange && i === 0 ? clampedVals[1] : max;
|
|
9875
|
+
const thumbLabel = isRange ? i === 0 ? "Minimum" : "Maximum" : labelId ? void 0 : "Slider";
|
|
9876
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9877
|
+
"div",
|
|
9878
|
+
{
|
|
9879
|
+
id: i === 0 ? fieldId : void 0,
|
|
9880
|
+
className: "twc-slider__thumb",
|
|
9881
|
+
style: { left: `${p}%` },
|
|
9882
|
+
role: "slider",
|
|
9883
|
+
tabIndex: disabled ? -1 : 0,
|
|
9884
|
+
"aria-valuemin": tMin,
|
|
9885
|
+
"aria-valuemax": tMax,
|
|
9886
|
+
"aria-valuenow": tv,
|
|
9887
|
+
"aria-valuetext": valueTextFor(tv),
|
|
9888
|
+
"aria-labelledby": isRange ? void 0 : labelId,
|
|
9889
|
+
"aria-label": thumbLabel,
|
|
9890
|
+
"aria-describedby": error || hint ? descId : void 0,
|
|
9891
|
+
"aria-invalid": invalid || void 0,
|
|
9892
|
+
"aria-disabled": disabled || void 0,
|
|
9893
|
+
onKeyDown: (e) => onThumbKeyDown(e, i),
|
|
9894
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-slider__bubble", children: fmt(tv) })
|
|
9895
|
+
},
|
|
9896
|
+
i
|
|
9897
|
+
);
|
|
9898
|
+
})
|
|
9365
9899
|
] }),
|
|
9366
9900
|
error || hint ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-slider__msgs", children: error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__error", children: error }) : /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__hint", children: hint }) }) : null
|
|
9367
9901
|
] });
|
|
@@ -9509,7 +10043,7 @@ function Stepper({
|
|
|
9509
10043
|
...rest
|
|
9510
10044
|
}) {
|
|
9511
10045
|
const __twcStyles = useScopedStyles("twc-stepper-styles", STEPPER_CSS);
|
|
9512
|
-
const [activeInternal, setActiveInternal] =
|
|
10046
|
+
const [activeInternal, setActiveInternal] = React25__namespace.default.useState(defaultActive);
|
|
9513
10047
|
const active = activeProp !== void 0 ? activeProp : activeInternal;
|
|
9514
10048
|
const handleStep = (i) => {
|
|
9515
10049
|
if (activeProp === void 0) setActiveInternal(i);
|
|
@@ -9641,10 +10175,13 @@ function Switch({
|
|
|
9641
10175
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
9642
10176
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
9643
10177
|
`);
|
|
9644
|
-
const autoId =
|
|
10178
|
+
const autoId = React25__namespace.default.useId();
|
|
9645
10179
|
const fieldId = id || autoId;
|
|
9646
10180
|
const errId = `${fieldId}-error`;
|
|
9647
10181
|
const invalid = Boolean(error);
|
|
10182
|
+
if (process.env.NODE_ENV !== "production" && !label && !description && !rest["aria-label"] && !rest["aria-labelledby"]) {
|
|
10183
|
+
warnOnce("Switch.no-name", "Switch: no accessible name \u2014 pass `label`, or `aria-label`/`aria-labelledby` for a label-less control (WCAG 4.1.2).");
|
|
10184
|
+
}
|
|
9648
10185
|
const describedBy = [rest["aria-describedby"], error ? errId : null].filter(Boolean).join(" ") || void 0;
|
|
9649
10186
|
const control = /* @__PURE__ */ jsxRuntime.jsxs("label", { className: `twc-switch ${className}`, "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, htmlFor: fieldId, children: [
|
|
9650
10187
|
__twcStyles,
|
|
@@ -9660,6 +10197,7 @@ function Switch({
|
|
|
9660
10197
|
disabled,
|
|
9661
10198
|
onChange,
|
|
9662
10199
|
...rest,
|
|
10200
|
+
required: required || void 0,
|
|
9663
10201
|
"aria-required": required || void 0,
|
|
9664
10202
|
"aria-invalid": invalid || void 0,
|
|
9665
10203
|
"aria-describedby": describedBy
|
|
@@ -9706,6 +10244,13 @@ var TABLE_CSS = `
|
|
|
9706
10244
|
.twc-table[data-size="lg"] thead th { padding: var(--space-4) var(--space-5); }
|
|
9707
10245
|
.twc-table[data-size="lg"] tbody td { padding: var(--space-4) var(--space-5); font-size: var(--text-base); }
|
|
9708
10246
|
.twc-table[data-sticky="true"] thead th { position: sticky; top: 0; z-index: 2; background: var(--color-surface); box-shadow: inset 0 calc(-1 * var(--border-thin)) 0 0 var(--color-border); }
|
|
10247
|
+
.twc-table__caption { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
10248
|
+
.twc-table__empty { padding: 30px 12px; text-align: center; color: var(--color-text-subtle); font-size: var(--text-sm); }
|
|
10249
|
+
.twc-table__sk { display: inline-block; height: 12px; border-radius: var(--radius-sm); background: var(--color-surface-sunken);
|
|
10250
|
+
position: relative; overflow: hidden; width: var(--_w, 70%); }
|
|
10251
|
+
.twc-table__sk::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%);
|
|
10252
|
+
background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--color-text) 8%, transparent), transparent);
|
|
10253
|
+
animation: twico-shimmer 1.4s infinite; }
|
|
9709
10254
|
`;
|
|
9710
10255
|
function Table({
|
|
9711
10256
|
columns,
|
|
@@ -9721,18 +10266,26 @@ function Table({
|
|
|
9721
10266
|
selectedKeys,
|
|
9722
10267
|
stickyHeader = false,
|
|
9723
10268
|
maxHeight,
|
|
10269
|
+
loading = false,
|
|
10270
|
+
loadingRows = 8,
|
|
10271
|
+
emptyMessage = "No data",
|
|
10272
|
+
ariaLabel,
|
|
10273
|
+
caption,
|
|
10274
|
+
// Pulled out of `rest` so they land on the <table>, not the wrapper <div> (#128).
|
|
10275
|
+
"aria-label": ariaLabelRaw,
|
|
10276
|
+
"aria-labelledby": ariaLabelledby,
|
|
9724
10277
|
className = "",
|
|
9725
10278
|
...rest
|
|
9726
10279
|
}) {
|
|
9727
10280
|
const __twcStyles = useScopedStyles("twc-table-styles", TABLE_CSS);
|
|
9728
|
-
const cols =
|
|
10281
|
+
const cols = React25__namespace.default.useMemo(
|
|
9729
10282
|
() => (columns || []).map((c) => ({ ...c, header: c.headerName, render: c.renderCell })),
|
|
9730
10283
|
[columns]
|
|
9731
10284
|
);
|
|
9732
10285
|
const dataRows = rowsProp || [];
|
|
9733
|
-
const [internalSort, setInternalSort] =
|
|
10286
|
+
const [internalSort, setInternalSort] = React25__namespace.default.useState(defaultSort || { field: null, dir: "asc" });
|
|
9734
10287
|
const sort = (sortProp !== void 0 ? sortProp : internalSort) || { field: null, dir: "asc" };
|
|
9735
|
-
const rows =
|
|
10288
|
+
const rows = React25__namespace.default.useMemo(() => {
|
|
9736
10289
|
if (!sortable || !sort.field) return dataRows;
|
|
9737
10290
|
const col = cols.find((c) => c.field === sort.field);
|
|
9738
10291
|
if (!col) return dataRows;
|
|
@@ -9755,32 +10308,46 @@ function Table({
|
|
|
9755
10308
|
const wrapStyle = maxHeight !== void 0 ? { ...rest.style, maxHeight, overflowY: "auto" } : rest.style;
|
|
9756
10309
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-table-wrap ${className}`, ...rest, style: wrapStyle, children: [
|
|
9757
10310
|
__twcStyles,
|
|
9758
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
|
|
9783
|
-
|
|
10311
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10312
|
+
"table",
|
|
10313
|
+
{
|
|
10314
|
+
className: "twc-table",
|
|
10315
|
+
"data-hover": hover || void 0,
|
|
10316
|
+
"data-striped": striped || void 0,
|
|
10317
|
+
"data-size": size,
|
|
10318
|
+
"data-sticky": stickyHeader || void 0,
|
|
10319
|
+
"aria-label": ariaLabelRaw ?? ariaLabel,
|
|
10320
|
+
"aria-labelledby": ariaLabelledby,
|
|
10321
|
+
"aria-busy": loading || void 0,
|
|
10322
|
+
children: [
|
|
10323
|
+
caption != null ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "twc-table__caption", children: caption }) : null,
|
|
10324
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: cols.map((c) => {
|
|
10325
|
+
const active = sort.field === c.field;
|
|
10326
|
+
const canSort = sortable && c.sortable !== false;
|
|
10327
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10328
|
+
"th",
|
|
10329
|
+
{
|
|
10330
|
+
"data-align": c.align,
|
|
10331
|
+
"data-sortable": canSort || void 0,
|
|
10332
|
+
"data-active": active || void 0,
|
|
10333
|
+
"data-dir": active ? sort.dir : void 0,
|
|
10334
|
+
style: c.width ? { width: c.width } : void 0,
|
|
10335
|
+
"aria-sort": active ? sort.dir === "asc" ? "ascending" : "descending" : canSort ? "none" : void 0,
|
|
10336
|
+
children: canSort ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-table__sort", onClick: () => toggleSort(c.field), children: [
|
|
10337
|
+
c.header,
|
|
10338
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m18 15-6-6-6 6" }) })
|
|
10339
|
+
] }) : c.header
|
|
10340
|
+
},
|
|
10341
|
+
c.field
|
|
10342
|
+
);
|
|
10343
|
+
}) }) }),
|
|
10344
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? Array.from({ length: loadingRows }).map((_, ri) => /* @__PURE__ */ jsxRuntime.jsx("tr", { children: cols.map((c) => /* @__PURE__ */ jsxRuntime.jsx("td", { "data-align": c.align, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-table__sk" }) }, c.field)) }, `sk${ri}`)) : rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: cols.length || 1, className: "twc-table__empty", children: emptyMessage }) }) : rows.map((row, i) => {
|
|
10345
|
+
const k = keyFn(row, i);
|
|
10346
|
+
return /* @__PURE__ */ jsxRuntime.jsx("tr", { "data-selected": selected.has(k) || void 0, children: cols.map((c) => /* @__PURE__ */ jsxRuntime.jsx("td", { "data-align": c.align, children: c.render ? c.render(row[c.field], row, i) : row[c.field] }, c.field)) }, k);
|
|
10347
|
+
}) })
|
|
10348
|
+
]
|
|
10349
|
+
}
|
|
10350
|
+
)
|
|
9784
10351
|
] });
|
|
9785
10352
|
}
|
|
9786
10353
|
var TABS_CSS = `
|
|
@@ -9865,15 +10432,15 @@ function Tabs({
|
|
|
9865
10432
|
}) {
|
|
9866
10433
|
const vertical = orientation === "vertical";
|
|
9867
10434
|
const __twcStyles = useScopedStyles("twc-tabs-styles", TABS_CSS);
|
|
9868
|
-
const [internal, setInternal] =
|
|
10435
|
+
const [internal, setInternal] = React25__namespace.default.useState(defaultValue ?? items[0]?.value);
|
|
9869
10436
|
const active = value ?? internal;
|
|
9870
|
-
const listRef =
|
|
9871
|
-
const [ind, setInd] =
|
|
9872
|
-
const baseId =
|
|
10437
|
+
const listRef = React25__namespace.default.useRef(null);
|
|
10438
|
+
const [ind, setInd] = React25__namespace.default.useState({ left: 0, width: 0, top: 0, height: 0 });
|
|
10439
|
+
const baseId = React25__namespace.default.useId();
|
|
9873
10440
|
const tabIdAt = (i) => `${baseId}-tab-${i}`;
|
|
9874
10441
|
const panelId = `${baseId}-panel`;
|
|
9875
10442
|
const activeIndex = items.findIndex((it) => it.value === active);
|
|
9876
|
-
const updateIndicator =
|
|
10443
|
+
const updateIndicator = React25__namespace.default.useCallback(() => {
|
|
9877
10444
|
const list = listRef.current;
|
|
9878
10445
|
if (!list) return;
|
|
9879
10446
|
const el = list.querySelector('[data-active="true"]');
|
|
@@ -9882,10 +10449,10 @@ function Tabs({
|
|
|
9882
10449
|
if (!vertical) el.scrollIntoView?.({ inline: "nearest", block: "nearest" });
|
|
9883
10450
|
}
|
|
9884
10451
|
}, [vertical]);
|
|
9885
|
-
|
|
10452
|
+
React25__namespace.default.useEffect(() => {
|
|
9886
10453
|
updateIndicator();
|
|
9887
10454
|
}, [active, updateIndicator, items, orientation]);
|
|
9888
|
-
|
|
10455
|
+
React25__namespace.default.useEffect(() => {
|
|
9889
10456
|
const r = () => updateIndicator();
|
|
9890
10457
|
window.addEventListener("resize", r);
|
|
9891
10458
|
if (typeof document !== "undefined" && document.fonts && document.fonts.ready) {
|
|
@@ -10030,20 +10597,8 @@ function Tag({
|
|
|
10030
10597
|
}, "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
|
|
10031
10598
|
] });
|
|
10032
10599
|
}
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
hint,
|
|
10036
|
-
error,
|
|
10037
|
-
required = false,
|
|
10038
|
-
size = "md",
|
|
10039
|
-
tone = "primary",
|
|
10040
|
-
rows = 4,
|
|
10041
|
-
disabled = false,
|
|
10042
|
-
id,
|
|
10043
|
-
className = "",
|
|
10044
|
-
...rest
|
|
10045
|
-
}) {
|
|
10046
|
-
const __twcStyles = useScopedStyles("twc-textarea-styles", `
|
|
10600
|
+
var useIso = typeof document !== "undefined" ? React25__namespace.default.useLayoutEffect : React25__namespace.default.useEffect;
|
|
10601
|
+
var TEXTAREA_CSS = `
|
|
10047
10602
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
10048
10603
|
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
10049
10604
|
.twc-field__req { color: var(--color-danger); }
|
|
@@ -10072,11 +10627,74 @@ function Textarea({
|
|
|
10072
10627
|
.twc-textarea__el:focus { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
10073
10628
|
.twc-textarea__el[aria-invalid="true"] { border-color: var(--color-danger); }
|
|
10074
10629
|
.twc-textarea__el:disabled { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
10075
|
-
|
|
10076
|
-
|
|
10630
|
+
.twc-textarea__el[data-readonly] { background: var(--color-surface-sunken); }
|
|
10631
|
+
.twc-textarea__el[data-autosize="true"] { resize: none; overflow: hidden; }
|
|
10632
|
+
.twc-field__footer { display: flex; align-items: center; gap: var(--space-2); }
|
|
10633
|
+
.twc-field__count { margin-inline-start: auto; font-size: var(--text-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; flex: none; }
|
|
10634
|
+
.twc-field__count[data-danger="true"] { color: var(--color-danger-subtle-fg); }
|
|
10635
|
+
`;
|
|
10636
|
+
var Textarea = React25__namespace.default.forwardRef(function Textarea2({
|
|
10637
|
+
label,
|
|
10638
|
+
hint,
|
|
10639
|
+
error,
|
|
10640
|
+
required = false,
|
|
10641
|
+
size = "md",
|
|
10642
|
+
tone = "primary",
|
|
10643
|
+
rows = 4,
|
|
10644
|
+
autosize = false,
|
|
10645
|
+
minRows,
|
|
10646
|
+
maxRows,
|
|
10647
|
+
showCount = false,
|
|
10648
|
+
disabled = false,
|
|
10649
|
+
id,
|
|
10650
|
+
className = "",
|
|
10651
|
+
...rest
|
|
10652
|
+
}, ref) {
|
|
10653
|
+
const __twcStyles = useScopedStyles("twc-textarea-styles", TEXTAREA_CSS);
|
|
10654
|
+
const autoId = React25__namespace.default.useId();
|
|
10077
10655
|
const fieldId = id || autoId;
|
|
10078
10656
|
const descId = `${fieldId}-desc`;
|
|
10657
|
+
const countId = `${fieldId}-count`;
|
|
10079
10658
|
const invalid = Boolean(error);
|
|
10659
|
+
const innerRef = React25__namespace.default.useRef(null);
|
|
10660
|
+
const setRef = (el) => {
|
|
10661
|
+
innerRef.current = el;
|
|
10662
|
+
if (typeof ref === "function") ref(el);
|
|
10663
|
+
else if (ref) ref.current = el;
|
|
10664
|
+
};
|
|
10665
|
+
const countControlled = rest.value !== void 0;
|
|
10666
|
+
const [len2, setLen] = React25__namespace.default.useState(() => String(rest.defaultValue ?? "").length);
|
|
10667
|
+
const count = countControlled ? String(rest.value ?? "").length : len2;
|
|
10668
|
+
const max = rest.maxLength;
|
|
10669
|
+
const showCounter = showCount && max != null;
|
|
10670
|
+
const near = showCounter && count >= Math.floor(max * 0.9);
|
|
10671
|
+
const resize = () => {
|
|
10672
|
+
const el = innerRef.current;
|
|
10673
|
+
if (!el) return;
|
|
10674
|
+
el.style.height = "auto";
|
|
10675
|
+
const cs = getComputedStyle(el);
|
|
10676
|
+
const line = parseFloat(cs.lineHeight) || 20;
|
|
10677
|
+
const vPad = (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0);
|
|
10678
|
+
const vBorder = (parseFloat(cs.borderTopWidth) || 0) + (parseFloat(cs.borderBottomWidth) || 0);
|
|
10679
|
+
const min = (minRows ?? rows) * line + vPad + vBorder;
|
|
10680
|
+
const maxH = maxRows ? maxRows * line + vPad + vBorder : Infinity;
|
|
10681
|
+
const next = Math.min(Math.max(el.scrollHeight + vBorder, min), maxH);
|
|
10682
|
+
el.style.height = `${next}px`;
|
|
10683
|
+
el.style.overflowY = el.scrollHeight + vBorder > maxH ? "auto" : "hidden";
|
|
10684
|
+
};
|
|
10685
|
+
useIso(() => {
|
|
10686
|
+
if (autosize && innerRef.current) resize();
|
|
10687
|
+
}, [autosize, rest.value, minRows, maxRows, rows]);
|
|
10688
|
+
const handleInput = (e) => {
|
|
10689
|
+
rest.onInput?.(e);
|
|
10690
|
+
if (autosize) resize();
|
|
10691
|
+
};
|
|
10692
|
+
const handleChange = (e) => {
|
|
10693
|
+
rest.onChange?.(e);
|
|
10694
|
+
if (showCount && !countControlled) setLen(e.target.value.length);
|
|
10695
|
+
};
|
|
10696
|
+
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
10697
|
+
const describedBy = [error || hint ? descId : null, showCounter ? countId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
10080
10698
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-field ${className}`, children: [
|
|
10081
10699
|
__twcStyles,
|
|
10082
10700
|
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
@@ -10086,22 +10704,34 @@ function Textarea({
|
|
|
10086
10704
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10087
10705
|
"textarea",
|
|
10088
10706
|
{
|
|
10707
|
+
ref: setRef,
|
|
10089
10708
|
id: fieldId,
|
|
10090
10709
|
className: "twc-textarea__el",
|
|
10091
10710
|
"data-size": size,
|
|
10092
10711
|
"data-tone": tone,
|
|
10093
|
-
|
|
10712
|
+
"data-autosize": autosize || void 0,
|
|
10713
|
+
"data-readonly": rest.readOnly || void 0,
|
|
10714
|
+
rows: autosize ? minRows ?? rows : rows,
|
|
10094
10715
|
disabled,
|
|
10095
10716
|
required: required || void 0,
|
|
10096
10717
|
"aria-required": required || void 0,
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10718
|
+
...rest,
|
|
10719
|
+
onInput: handleInput,
|
|
10720
|
+
onChange: handleChange,
|
|
10721
|
+
"aria-invalid": ariaInvalid,
|
|
10722
|
+
"aria-describedby": describedBy
|
|
10100
10723
|
}
|
|
10101
10724
|
),
|
|
10102
|
-
error
|
|
10725
|
+
error || hint || showCounter ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-field__footer", children: [
|
|
10726
|
+
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,
|
|
10727
|
+
showCounter ? /* @__PURE__ */ jsxRuntime.jsxs("span", { id: countId, className: "twc-field__count", "data-danger": near || void 0, "aria-live": "polite", children: [
|
|
10728
|
+
count,
|
|
10729
|
+
" / ",
|
|
10730
|
+
max
|
|
10731
|
+
] }) : null
|
|
10732
|
+
] }) : null
|
|
10103
10733
|
] });
|
|
10104
|
-
}
|
|
10734
|
+
});
|
|
10105
10735
|
var TIMELINE_CSS = `
|
|
10106
10736
|
.twc-timeline { display: flex; flex-direction: column; font-family: var(--font-sans); margin: 0; padding: 0; list-style: none; }
|
|
10107
10737
|
.twc-timeline__item { position: relative; display: flex; gap: var(--space-4); padding-bottom: var(--space-6); }
|
|
@@ -10211,28 +10841,29 @@ function Toast({
|
|
|
10211
10841
|
}) {
|
|
10212
10842
|
const resolvedTone = tone === "neutral" ? "default" : tone;
|
|
10213
10843
|
const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
|
|
10214
|
-
const onCloseRef =
|
|
10215
|
-
|
|
10844
|
+
const onCloseRef = React25__namespace.default.useRef(onClose);
|
|
10845
|
+
React25__namespace.default.useEffect(() => {
|
|
10216
10846
|
onCloseRef.current = onClose;
|
|
10217
10847
|
}, [onClose]);
|
|
10218
|
-
const timer =
|
|
10219
|
-
const stop =
|
|
10220
|
-
const start =
|
|
10848
|
+
const timer = React25__namespace.default.useRef();
|
|
10849
|
+
const stop = React25__namespace.default.useCallback(() => clearTimeout(timer.current), []);
|
|
10850
|
+
const start = React25__namespace.default.useCallback(() => {
|
|
10221
10851
|
stop();
|
|
10222
10852
|
if (duration && duration !== Infinity && onCloseRef.current) {
|
|
10223
10853
|
timer.current = setTimeout(() => onCloseRef.current && onCloseRef.current(), duration);
|
|
10224
10854
|
}
|
|
10225
10855
|
}, [duration, stop]);
|
|
10226
|
-
|
|
10856
|
+
React25__namespace.default.useEffect(() => {
|
|
10227
10857
|
start();
|
|
10228
10858
|
return stop;
|
|
10229
10859
|
}, [start, stop]);
|
|
10860
|
+
const role = resolvedTone === "danger" || resolvedTone === "warning" ? "alert" : "status";
|
|
10230
10861
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10231
10862
|
"div",
|
|
10232
10863
|
{
|
|
10233
10864
|
className: `twc-toast ${className}`,
|
|
10234
10865
|
"data-tone": resolvedTone,
|
|
10235
|
-
role
|
|
10866
|
+
role,
|
|
10236
10867
|
...rest,
|
|
10237
10868
|
onMouseEnter: (e) => {
|
|
10238
10869
|
onMouseEnter?.(e);
|
|
@@ -10267,30 +10898,30 @@ function Toast({
|
|
|
10267
10898
|
}
|
|
10268
10899
|
function ToastViewport({ children, limit, className = "", ...rest }) {
|
|
10269
10900
|
const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
|
|
10270
|
-
const shown = limit && limit > 0 ?
|
|
10271
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-toast-viewport ${className}`, ...rest, children: [
|
|
10901
|
+
const shown = limit && limit > 0 ? React25__namespace.default.Children.toArray(children).slice(-limit) : children;
|
|
10902
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-toast-viewport ${className}`, role: "region", "aria-label": "Notifications", ...rest, children: [
|
|
10272
10903
|
__twcStyles,
|
|
10273
10904
|
shown
|
|
10274
10905
|
] });
|
|
10275
10906
|
}
|
|
10276
|
-
var ToastContext =
|
|
10907
|
+
var ToastContext = React25__namespace.default.createContext(null);
|
|
10277
10908
|
function useToast() {
|
|
10278
|
-
const ctx =
|
|
10909
|
+
const ctx = React25__namespace.default.useContext(ToastContext);
|
|
10279
10910
|
if (!ctx) throw new Error("useToast must be used within a <ToastProvider>.");
|
|
10280
10911
|
return ctx;
|
|
10281
10912
|
}
|
|
10282
10913
|
function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps }) {
|
|
10283
|
-
const [toasts, setToasts] =
|
|
10284
|
-
const idRef =
|
|
10285
|
-
const limitRef =
|
|
10286
|
-
|
|
10914
|
+
const [toasts, setToasts] = React25__namespace.default.useState([]);
|
|
10915
|
+
const idRef = React25__namespace.default.useRef(0);
|
|
10916
|
+
const limitRef = React25__namespace.default.useRef(limit);
|
|
10917
|
+
React25__namespace.default.useEffect(() => {
|
|
10287
10918
|
limitRef.current = limit;
|
|
10288
10919
|
}, [limit]);
|
|
10289
|
-
const dismiss =
|
|
10920
|
+
const dismiss = React25__namespace.default.useCallback((id) => {
|
|
10290
10921
|
setToasts((s) => s.filter((t) => t.id !== id));
|
|
10291
10922
|
}, []);
|
|
10292
|
-
const clear =
|
|
10293
|
-
const api =
|
|
10923
|
+
const clear = React25__namespace.default.useCallback(() => setToasts([]), []);
|
|
10924
|
+
const api = React25__namespace.default.useMemo(() => {
|
|
10294
10925
|
const push = (opts) => {
|
|
10295
10926
|
const id = idRef.current += 1;
|
|
10296
10927
|
const next = typeof opts === "string" ? { title: opts } : opts && typeof opts === "object" ? opts : {};
|
|
@@ -10311,7 +10942,7 @@ function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps
|
|
|
10311
10942
|
toast.show = withTone("default");
|
|
10312
10943
|
return { toast, dismiss, clear };
|
|
10313
10944
|
}, [dismiss, clear]);
|
|
10314
|
-
const value =
|
|
10945
|
+
const value = React25__namespace.default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
|
|
10315
10946
|
return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value, children: [
|
|
10316
10947
|
children,
|
|
10317
10948
|
/* @__PURE__ */ jsxRuntime.jsx(ToastViewport, { limit, ...viewportProps, children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -10419,13 +11050,13 @@ function TreeView({
|
|
|
10419
11050
|
}) {
|
|
10420
11051
|
const nodes = items;
|
|
10421
11052
|
const __twcStyles = useScopedStyles("twc-tree-styles", TREE_CSS);
|
|
10422
|
-
const [expInternal, setExpInternal] =
|
|
11053
|
+
const [expInternal, setExpInternal] = React25__namespace.default.useState(() => new Set(defaultExpanded));
|
|
10423
11054
|
const expanded = expandedProp !== void 0 ? new Set(expandedProp) : expInternal;
|
|
10424
|
-
const [selInternal, setSelInternal] =
|
|
11055
|
+
const [selInternal, setSelInternal] = React25__namespace.default.useState(defaultSelectedId);
|
|
10425
11056
|
const selectedId = selectedProp !== void 0 ? selectedProp : selInternal;
|
|
10426
|
-
const [focusId, setFocusId] =
|
|
10427
|
-
const rowRefs =
|
|
10428
|
-
const taRef =
|
|
11057
|
+
const [focusId, setFocusId] = React25__namespace.default.useState(null);
|
|
11058
|
+
const rowRefs = React25__namespace.default.useRef(/* @__PURE__ */ new Map());
|
|
11059
|
+
const taRef = React25__namespace.default.useRef({ str: "", t: 0 });
|
|
10429
11060
|
const toggle = (id) => {
|
|
10430
11061
|
const n = new Set(expanded);
|
|
10431
11062
|
n.has(id) ? n.delete(id) : n.add(id);
|
|
@@ -10557,7 +11188,7 @@ function AppShell({
|
|
|
10557
11188
|
...rest
|
|
10558
11189
|
}) {
|
|
10559
11190
|
const __twcStyles = useScopedStyles("twc-shell-styles", SHELL_CSS);
|
|
10560
|
-
const wiredSidebar =
|
|
11191
|
+
const wiredSidebar = React25__namespace.default.isValidElement(sidebar) && (sidebarOpen !== void 0 || onSidebarOpenChange !== void 0) ? React25__namespace.default.cloneElement(sidebar, {
|
|
10561
11192
|
overlay: sidebar.props.overlay !== void 0 ? sidebar.props.overlay : true,
|
|
10562
11193
|
open: sidebar.props.open !== void 0 ? sidebar.props.open : sidebarOpen,
|
|
10563
11194
|
onOpenChange: sidebar.props.onOpenChange !== void 0 ? sidebar.props.onOpenChange : onSidebarOpenChange
|
|
@@ -10699,7 +11330,7 @@ function Grid({
|
|
|
10699
11330
|
...rest
|
|
10700
11331
|
}) {
|
|
10701
11332
|
const responsive = columns != null && typeof columns === "object";
|
|
10702
|
-
const uid =
|
|
11333
|
+
const uid = React25__namespace.default.useId();
|
|
10703
11334
|
const gridId = responsive ? `g${uid.replace(/[^a-zA-Z0-9]/g, "")}` : null;
|
|
10704
11335
|
let css = "";
|
|
10705
11336
|
if (responsive) {
|
|
@@ -10770,7 +11401,7 @@ function Stack({
|
|
|
10770
11401
|
...rest
|
|
10771
11402
|
}) {
|
|
10772
11403
|
if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
|
|
10773
|
-
const kids = divider != null ?
|
|
11404
|
+
const kids = divider != null ? React25__namespace.default.Children.toArray(children).flatMap((child, i, arr) => i < arr.length - 1 ? [child, /* @__PURE__ */ jsxRuntime.jsx(React25__namespace.default.Fragment, { children: divider }, `twc-stack-div-${i}`)] : [child]) : children;
|
|
10774
11405
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10775
11406
|
Tag2,
|
|
10776
11407
|
{
|
|
@@ -10835,10 +11466,10 @@ function Code({
|
|
|
10835
11466
|
const __twcStyles = useScopedStyles("twc-code-styles", CODE_CSS);
|
|
10836
11467
|
const Tag2 = as ?? (block ? "pre" : "code");
|
|
10837
11468
|
if (Tag2 === "a" && rest.href != null) rest.href = safeHref9(rest.href);
|
|
10838
|
-
const rootRef =
|
|
10839
|
-
const [copied, setCopied] =
|
|
10840
|
-
const timerRef =
|
|
10841
|
-
|
|
11469
|
+
const rootRef = React25__namespace.default.useRef(null);
|
|
11470
|
+
const [copied, setCopied] = React25__namespace.default.useState(false);
|
|
11471
|
+
const timerRef = React25__namespace.default.useRef(null);
|
|
11472
|
+
React25__namespace.default.useEffect(() => () => clearTimeout(timerRef.current), []);
|
|
10842
11473
|
const doCopy = () => {
|
|
10843
11474
|
if (typeof navigator === "undefined" || !navigator.clipboard) return;
|
|
10844
11475
|
const text = typeof children === "string" ? children : rootRef.current?.textContent ?? "";
|
|
@@ -10957,45 +11588,45 @@ function Text({
|
|
|
10957
11588
|
);
|
|
10958
11589
|
}
|
|
10959
11590
|
var canUseDOM2 = typeof window !== "undefined" && typeof document !== "undefined";
|
|
10960
|
-
var useIsomorphicLayoutEffect = canUseDOM2 ?
|
|
11591
|
+
var useIsomorphicLayoutEffect = canUseDOM2 ? React25__namespace.default.useLayoutEffect : React25__namespace.default.useEffect;
|
|
10961
11592
|
function useMounted() {
|
|
10962
|
-
const [mounted, setMounted] =
|
|
10963
|
-
|
|
11593
|
+
const [mounted, setMounted] = React25__namespace.default.useState(false);
|
|
11594
|
+
React25__namespace.default.useEffect(() => {
|
|
10964
11595
|
setMounted(true);
|
|
10965
11596
|
}, []);
|
|
10966
11597
|
return mounted;
|
|
10967
11598
|
}
|
|
10968
11599
|
function usePrevious(value) {
|
|
10969
|
-
const ref =
|
|
10970
|
-
|
|
11600
|
+
const ref = React25__namespace.default.useRef(void 0);
|
|
11601
|
+
React25__namespace.default.useEffect(() => {
|
|
10971
11602
|
ref.current = value;
|
|
10972
11603
|
}, [value]);
|
|
10973
11604
|
return ref.current;
|
|
10974
11605
|
}
|
|
10975
11606
|
function useToggle(initial = false) {
|
|
10976
|
-
const [on, setOn] =
|
|
10977
|
-
const toggle =
|
|
11607
|
+
const [on, setOn] = React25__namespace.default.useState(initial);
|
|
11608
|
+
const toggle = React25__namespace.default.useCallback((next) => {
|
|
10978
11609
|
setOn((prev) => typeof next === "boolean" ? next : !prev);
|
|
10979
11610
|
}, []);
|
|
10980
11611
|
return [on, toggle, setOn];
|
|
10981
11612
|
}
|
|
10982
11613
|
function useDisclosure(initial = false) {
|
|
10983
|
-
const [open, setOpen] =
|
|
10984
|
-
const onOpen =
|
|
10985
|
-
const onClose =
|
|
10986
|
-
const onToggle =
|
|
11614
|
+
const [open, setOpen] = React25__namespace.default.useState(initial);
|
|
11615
|
+
const onOpen = React25__namespace.default.useCallback(() => setOpen(true), []);
|
|
11616
|
+
const onClose = React25__namespace.default.useCallback(() => setOpen(false), []);
|
|
11617
|
+
const onToggle = React25__namespace.default.useCallback(() => setOpen((p) => !p), []);
|
|
10987
11618
|
return { open, onOpen, onClose, onToggle, setOpen };
|
|
10988
11619
|
}
|
|
10989
11620
|
function useControllableState({ value, defaultValue, onChange } = {}) {
|
|
10990
11621
|
const isControlled = value !== void 0;
|
|
10991
|
-
const [uncontrolled, setUncontrolled] =
|
|
11622
|
+
const [uncontrolled, setUncontrolled] = React25__namespace.default.useState(defaultValue);
|
|
10992
11623
|
const current = isControlled ? value : uncontrolled;
|
|
10993
|
-
const ref =
|
|
11624
|
+
const ref = React25__namespace.default.useRef({ current, isControlled, onChange });
|
|
10994
11625
|
useIsomorphicLayoutEffect(() => {
|
|
10995
11626
|
ref.current = { current, isControlled, onChange };
|
|
10996
11627
|
});
|
|
10997
|
-
const wasControlled =
|
|
10998
|
-
|
|
11628
|
+
const wasControlled = React25__namespace.default.useRef(isControlled);
|
|
11629
|
+
React25__namespace.default.useEffect(() => {
|
|
10999
11630
|
if (wasControlled.current !== isControlled) {
|
|
11000
11631
|
warnOnce(
|
|
11001
11632
|
"useControllableState:switch",
|
|
@@ -11004,7 +11635,7 @@ function useControllableState({ value, defaultValue, onChange } = {}) {
|
|
|
11004
11635
|
wasControlled.current = isControlled;
|
|
11005
11636
|
}
|
|
11006
11637
|
});
|
|
11007
|
-
const setValue =
|
|
11638
|
+
const setValue = React25__namespace.default.useCallback((next) => {
|
|
11008
11639
|
const { current: cur, isControlled: ctrl, onChange: cb } = ref.current;
|
|
11009
11640
|
const resolved = typeof next === "function" ? next(cur) : next;
|
|
11010
11641
|
if (resolved === cur) return;
|
|
@@ -11015,7 +11646,7 @@ function useControllableState({ value, defaultValue, onChange } = {}) {
|
|
|
11015
11646
|
}
|
|
11016
11647
|
function useMediaQuery(query, { defaultValue = false, initializeWithValue = false } = {}) {
|
|
11017
11648
|
const get = () => canUseDOM2 ? window.matchMedia(query).matches : defaultValue;
|
|
11018
|
-
const [matches3, setMatches] =
|
|
11649
|
+
const [matches3, setMatches] = React25__namespace.default.useState(initializeWithValue ? get : defaultValue);
|
|
11019
11650
|
useIsomorphicLayoutEffect(() => {
|
|
11020
11651
|
if (!canUseDOM2) return void 0;
|
|
11021
11652
|
const mql = window.matchMedia(query);
|
|
@@ -11031,7 +11662,7 @@ function usePrefersReducedMotion() {
|
|
|
11031
11662
|
}
|
|
11032
11663
|
function useColorScheme({ storageKey = "twico-theme", attribute = "class", element, disableTransitionsOnChange = true } = {}) {
|
|
11033
11664
|
const getTarget = () => element || (canUseDOM2 ? document.documentElement : null);
|
|
11034
|
-
const firstApply =
|
|
11665
|
+
const firstApply = React25__namespace.default.useRef(true);
|
|
11035
11666
|
const read = () => {
|
|
11036
11667
|
if (!canUseDOM2) return "light";
|
|
11037
11668
|
try {
|
|
@@ -11041,8 +11672,8 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
|
|
|
11041
11672
|
}
|
|
11042
11673
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
11043
11674
|
};
|
|
11044
|
-
const [theme, setThemeState] =
|
|
11045
|
-
const apply =
|
|
11675
|
+
const [theme, setThemeState] = React25__namespace.default.useState(read);
|
|
11676
|
+
const apply = React25__namespace.default.useCallback(
|
|
11046
11677
|
(t) => {
|
|
11047
11678
|
const target = getTarget();
|
|
11048
11679
|
if (!target) return;
|
|
@@ -11068,11 +11699,11 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
|
|
|
11068
11699
|
useIsomorphicLayoutEffect(() => {
|
|
11069
11700
|
apply(theme);
|
|
11070
11701
|
}, [theme, apply]);
|
|
11071
|
-
const themeRef =
|
|
11702
|
+
const themeRef = React25__namespace.default.useRef(theme);
|
|
11072
11703
|
useIsomorphicLayoutEffect(() => {
|
|
11073
11704
|
themeRef.current = theme;
|
|
11074
11705
|
}, [theme]);
|
|
11075
|
-
const setTheme =
|
|
11706
|
+
const setTheme = React25__namespace.default.useCallback(
|
|
11076
11707
|
(t) => {
|
|
11077
11708
|
setThemeState(t);
|
|
11078
11709
|
try {
|
|
@@ -11083,10 +11714,10 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
|
|
|
11083
11714
|
},
|
|
11084
11715
|
[storageKey]
|
|
11085
11716
|
);
|
|
11086
|
-
const toggle =
|
|
11717
|
+
const toggle = React25__namespace.default.useCallback(() => {
|
|
11087
11718
|
setTheme(themeRef.current === "dark" ? "light" : "dark");
|
|
11088
11719
|
}, [setTheme]);
|
|
11089
|
-
|
|
11720
|
+
React25__namespace.default.useEffect(() => {
|
|
11090
11721
|
if (!canUseDOM2) return void 0;
|
|
11091
11722
|
const sync = () => setThemeState(read());
|
|
11092
11723
|
const onStorage = (e) => {
|
|
@@ -11102,14 +11733,14 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
|
|
|
11102
11733
|
return { theme, setTheme, toggle, isDark: theme === "dark" };
|
|
11103
11734
|
}
|
|
11104
11735
|
function useEventListener(eventName, handler, element, options) {
|
|
11105
|
-
const saved =
|
|
11736
|
+
const saved = React25__namespace.default.useRef(handler);
|
|
11106
11737
|
useIsomorphicLayoutEffect(() => {
|
|
11107
11738
|
saved.current = handler;
|
|
11108
11739
|
}, [handler]);
|
|
11109
11740
|
const capture = typeof options === "boolean" ? options : options && options.capture;
|
|
11110
11741
|
const passive = typeof options === "object" && options ? options.passive : void 0;
|
|
11111
11742
|
const once = typeof options === "object" && options ? options.once : void 0;
|
|
11112
|
-
|
|
11743
|
+
React25__namespace.default.useEffect(() => {
|
|
11113
11744
|
const target = element && element.current || element || (canUseDOM2 ? window : null);
|
|
11114
11745
|
if (!target || !target.addEventListener) return void 0;
|
|
11115
11746
|
const opts = typeof options === "boolean" ? options : { capture, passive, once };
|
|
@@ -11119,11 +11750,11 @@ function useEventListener(eventName, handler, element, options) {
|
|
|
11119
11750
|
}, [eventName, element, capture, passive, once]);
|
|
11120
11751
|
}
|
|
11121
11752
|
function useClickOutside(ref, handler, events = ["mousedown", "touchstart"]) {
|
|
11122
|
-
const saved =
|
|
11753
|
+
const saved = React25__namespace.default.useRef(handler);
|
|
11123
11754
|
useIsomorphicLayoutEffect(() => {
|
|
11124
11755
|
saved.current = handler;
|
|
11125
11756
|
}, [handler]);
|
|
11126
|
-
|
|
11757
|
+
React25__namespace.default.useEffect(() => {
|
|
11127
11758
|
if (!canUseDOM2) return void 0;
|
|
11128
11759
|
const listener = (e) => {
|
|
11129
11760
|
const el = ref && ref.current;
|
|
@@ -11158,8 +11789,8 @@ function useLocalStorage(key, initialValue) {
|
|
|
11158
11789
|
return initialValue;
|
|
11159
11790
|
}
|
|
11160
11791
|
};
|
|
11161
|
-
const [stored, setStored] =
|
|
11162
|
-
const setValue =
|
|
11792
|
+
const [stored, setStored] = React25__namespace.default.useState(read);
|
|
11793
|
+
const setValue = React25__namespace.default.useCallback(
|
|
11163
11794
|
(value) => {
|
|
11164
11795
|
setStored((prev) => {
|
|
11165
11796
|
const next = typeof value === "function" ? value(prev) : value;
|
|
@@ -11175,8 +11806,8 @@ function useLocalStorage(key, initialValue) {
|
|
|
11175
11806
|
return [stored, setValue];
|
|
11176
11807
|
}
|
|
11177
11808
|
function useCopyToClipboard(timeout = 1500) {
|
|
11178
|
-
const [copied, setCopied] =
|
|
11179
|
-
const copy =
|
|
11809
|
+
const [copied, setCopied] = React25__namespace.default.useState(false);
|
|
11810
|
+
const copy = React25__namespace.default.useCallback(async (text) => {
|
|
11180
11811
|
if (!canUseDOM2 || !navigator.clipboard) {
|
|
11181
11812
|
setCopied(false);
|
|
11182
11813
|
return false;
|
|
@@ -11190,7 +11821,7 @@ function useCopyToClipboard(timeout = 1500) {
|
|
|
11190
11821
|
return false;
|
|
11191
11822
|
}
|
|
11192
11823
|
}, []);
|
|
11193
|
-
|
|
11824
|
+
React25__namespace.default.useEffect(() => {
|
|
11194
11825
|
if (!copied) return void 0;
|
|
11195
11826
|
const t = setTimeout(() => setCopied(false), timeout);
|
|
11196
11827
|
return () => clearTimeout(t);
|
|
@@ -11198,23 +11829,23 @@ function useCopyToClipboard(timeout = 1500) {
|
|
|
11198
11829
|
return { copied, copy };
|
|
11199
11830
|
}
|
|
11200
11831
|
function useDebouncedValue(value, delay = 200) {
|
|
11201
|
-
const [debounced, setDebounced] =
|
|
11202
|
-
|
|
11832
|
+
const [debounced, setDebounced] = React25__namespace.default.useState(value);
|
|
11833
|
+
React25__namespace.default.useEffect(() => {
|
|
11203
11834
|
const t = setTimeout(() => setDebounced(value), delay);
|
|
11204
11835
|
return () => clearTimeout(t);
|
|
11205
11836
|
}, [value, delay]);
|
|
11206
11837
|
return debounced;
|
|
11207
11838
|
}
|
|
11208
11839
|
function useDebouncedCallback(callback, delay = 200) {
|
|
11209
|
-
const saved =
|
|
11210
|
-
const timer =
|
|
11840
|
+
const saved = React25__namespace.default.useRef(callback);
|
|
11841
|
+
const timer = React25__namespace.default.useRef(null);
|
|
11211
11842
|
useIsomorphicLayoutEffect(() => {
|
|
11212
11843
|
saved.current = callback;
|
|
11213
11844
|
}, [callback]);
|
|
11214
|
-
|
|
11845
|
+
React25__namespace.default.useEffect(() => () => {
|
|
11215
11846
|
if (timer.current) clearTimeout(timer.current);
|
|
11216
11847
|
}, []);
|
|
11217
|
-
return
|
|
11848
|
+
return React25__namespace.default.useCallback(
|
|
11218
11849
|
(...args) => {
|
|
11219
11850
|
if (timer.current) clearTimeout(timer.current);
|
|
11220
11851
|
timer.current = setTimeout(() => saved.current(...args), delay);
|
|
@@ -11223,33 +11854,33 @@ function useDebouncedCallback(callback, delay = 200) {
|
|
|
11223
11854
|
);
|
|
11224
11855
|
}
|
|
11225
11856
|
function useInterval(callback, delay) {
|
|
11226
|
-
const saved =
|
|
11857
|
+
const saved = React25__namespace.default.useRef(callback);
|
|
11227
11858
|
useIsomorphicLayoutEffect(() => {
|
|
11228
11859
|
saved.current = callback;
|
|
11229
11860
|
}, [callback]);
|
|
11230
|
-
|
|
11861
|
+
React25__namespace.default.useEffect(() => {
|
|
11231
11862
|
if (delay == null) return void 0;
|
|
11232
11863
|
const id = setInterval(() => saved.current(), delay);
|
|
11233
11864
|
return () => clearInterval(id);
|
|
11234
11865
|
}, [delay]);
|
|
11235
11866
|
}
|
|
11236
11867
|
function useTimeout(callback, delay) {
|
|
11237
|
-
const saved =
|
|
11868
|
+
const saved = React25__namespace.default.useRef(callback);
|
|
11238
11869
|
useIsomorphicLayoutEffect(() => {
|
|
11239
11870
|
saved.current = callback;
|
|
11240
11871
|
}, [callback]);
|
|
11241
|
-
|
|
11872
|
+
React25__namespace.default.useEffect(() => {
|
|
11242
11873
|
if (delay == null) return void 0;
|
|
11243
11874
|
const id = setTimeout(() => saved.current(), delay);
|
|
11244
11875
|
return () => clearTimeout(id);
|
|
11245
11876
|
}, [delay]);
|
|
11246
11877
|
}
|
|
11247
11878
|
function useWindowSize() {
|
|
11248
|
-
const [size, setSize] =
|
|
11879
|
+
const [size, setSize] = React25__namespace.default.useState(() => ({
|
|
11249
11880
|
width: canUseDOM2 ? window.innerWidth : 0,
|
|
11250
11881
|
height: canUseDOM2 ? window.innerHeight : 0
|
|
11251
11882
|
}));
|
|
11252
|
-
|
|
11883
|
+
React25__namespace.default.useEffect(() => {
|
|
11253
11884
|
if (!canUseDOM2) return void 0;
|
|
11254
11885
|
const onResize = () => setSize({ width: window.innerWidth, height: window.innerHeight });
|
|
11255
11886
|
onResize();
|
|
@@ -11259,8 +11890,8 @@ function useWindowSize() {
|
|
|
11259
11890
|
return size;
|
|
11260
11891
|
}
|
|
11261
11892
|
function useHover(ref) {
|
|
11262
|
-
const [hovered, setHovered] =
|
|
11263
|
-
|
|
11893
|
+
const [hovered, setHovered] = React25__namespace.default.useState(false);
|
|
11894
|
+
React25__namespace.default.useEffect(() => {
|
|
11264
11895
|
const el = ref && ref.current;
|
|
11265
11896
|
if (!el) return void 0;
|
|
11266
11897
|
const on = () => setHovered(true);
|
|
@@ -11276,8 +11907,8 @@ function useHover(ref) {
|
|
|
11276
11907
|
}
|
|
11277
11908
|
function useIntersectionObserver(ref, options = {}) {
|
|
11278
11909
|
const { root = null, rootMargin = "0px", threshold = 0 } = options;
|
|
11279
|
-
const [entry, setEntry] =
|
|
11280
|
-
|
|
11910
|
+
const [entry, setEntry] = React25__namespace.default.useState(null);
|
|
11911
|
+
React25__namespace.default.useEffect(() => {
|
|
11281
11912
|
const el = ref && ref.current;
|
|
11282
11913
|
if (!canUseDOM2 || !el || typeof IntersectionObserver === "undefined") return void 0;
|
|
11283
11914
|
const obs = new IntersectionObserver(([e]) => setEntry(e), { root, rootMargin, threshold });
|
|
@@ -11286,30 +11917,13 @@ function useIntersectionObserver(ref, options = {}) {
|
|
|
11286
11917
|
}, [ref, root, rootMargin, JSON.stringify(threshold)]);
|
|
11287
11918
|
return entry;
|
|
11288
11919
|
}
|
|
11289
|
-
var __scrollLockCount = 0;
|
|
11290
|
-
var __scrollLockSaved = "";
|
|
11291
|
-
function useScrollLock(locked = true) {
|
|
11292
|
-
useIsomorphicLayoutEffect(() => {
|
|
11293
|
-
if (!canUseDOM2 || !locked) return void 0;
|
|
11294
|
-
if (__scrollLockCount === 0) {
|
|
11295
|
-
__scrollLockSaved = document.body.style.overflow;
|
|
11296
|
-
document.body.style.overflow = "hidden";
|
|
11297
|
-
}
|
|
11298
|
-
__scrollLockCount += 1;
|
|
11299
|
-
return () => {
|
|
11300
|
-
__scrollLockCount -= 1;
|
|
11301
|
-
if (__scrollLockCount === 0) {
|
|
11302
|
-
document.body.style.overflow = __scrollLockSaved;
|
|
11303
|
-
}
|
|
11304
|
-
};
|
|
11305
|
-
}, [locked]);
|
|
11306
|
-
}
|
|
11307
11920
|
function useId(prefix = "twc") {
|
|
11308
|
-
const raw =
|
|
11921
|
+
const raw = React25__namespace.default.useId();
|
|
11309
11922
|
return prefix ? `${prefix}-${raw.replace(/:/g, "")}` : raw;
|
|
11310
11923
|
}
|
|
11311
11924
|
var useFocusTrap2 = useFocusTrap;
|
|
11312
11925
|
var usePortal2 = usePortal;
|
|
11926
|
+
var useScrollLock2 = useScrollLock;
|
|
11313
11927
|
|
|
11314
11928
|
exports.Accordion = Accordion;
|
|
11315
11929
|
exports.Alert = Alert;
|
|
@@ -11353,6 +11967,7 @@ exports.Pagination = Pagination;
|
|
|
11353
11967
|
exports.Popover = Popover;
|
|
11354
11968
|
exports.Progress = Progress;
|
|
11355
11969
|
exports.Radio = Radio;
|
|
11970
|
+
exports.RadioGroup = RadioGroup;
|
|
11356
11971
|
exports.Rating = Rating;
|
|
11357
11972
|
exports.Select = Select;
|
|
11358
11973
|
exports.Sidebar = Sidebar;
|
|
@@ -11396,7 +12011,7 @@ exports.useMounted = useMounted;
|
|
|
11396
12011
|
exports.usePortal = usePortal2;
|
|
11397
12012
|
exports.usePrefersReducedMotion = usePrefersReducedMotion;
|
|
11398
12013
|
exports.usePrevious = usePrevious;
|
|
11399
|
-
exports.useScrollLock =
|
|
12014
|
+
exports.useScrollLock = useScrollLock2;
|
|
11400
12015
|
exports.useTimeout = useTimeout;
|
|
11401
12016
|
exports.useToast = useToast;
|
|
11402
12017
|
exports.useToggle = useToggle;
|