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.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
2
|
+
import * as React25 from 'react';
|
|
3
|
+
import React25__default from 'react';
|
|
4
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
|
|
7
7
|
// components/navigation/Accordion.jsx
|
|
8
|
-
var SUPPORTS_STYLE_HOIST = parseInt(String(
|
|
8
|
+
var SUPPORTS_STYLE_HOIST = parseInt(String(React25.version), 10) >= 19;
|
|
9
9
|
function useScopedStyles(id, css) {
|
|
10
|
-
|
|
10
|
+
React25.useInsertionEffect(() => {
|
|
11
11
|
if (SUPPORTS_STYLE_HOIST) return;
|
|
12
12
|
if (typeof document === "undefined" || document.getElementById(id)) return;
|
|
13
13
|
const el = document.createElement("style");
|
|
@@ -15,7 +15,7 @@ function useScopedStyles(id, css) {
|
|
|
15
15
|
el.textContent = css;
|
|
16
16
|
document.head.appendChild(el);
|
|
17
17
|
}, [id, css]);
|
|
18
|
-
return SUPPORTS_STYLE_HOIST ?
|
|
18
|
+
return SUPPORTS_STYLE_HOIST ? React25.createElement("style", { href: id, precedence: "twc-ui" }, css) : null;
|
|
19
19
|
}
|
|
20
20
|
var ACCORDION_CSS = `
|
|
21
21
|
.twc-accordion { display: flex; flex-direction: column; font-family: var(--font-sans);
|
|
@@ -56,10 +56,10 @@ function Accordion({
|
|
|
56
56
|
...rest
|
|
57
57
|
}) {
|
|
58
58
|
const __twcStyles = useScopedStyles("twc-accordion-styles", ACCORDION_CSS);
|
|
59
|
-
const rootRef =
|
|
60
|
-
const [internal, setInternal] =
|
|
59
|
+
const rootRef = React25__default.useRef(null);
|
|
60
|
+
const [internal, setInternal] = React25__default.useState(() => new Set(defaultOpen));
|
|
61
61
|
const open = openProp !== void 0 ? new Set(openProp) : internal;
|
|
62
|
-
const baseId =
|
|
62
|
+
const baseId = React25__default.useId();
|
|
63
63
|
function toggle(val) {
|
|
64
64
|
const item = items.find((x) => x.value === val);
|
|
65
65
|
if (item?.disabled) return;
|
|
@@ -245,7 +245,7 @@ function Avatar({
|
|
|
245
245
|
...rest
|
|
246
246
|
}) {
|
|
247
247
|
const __twcStyles = useScopedStyles("twc-avatar-styles", AVATAR_CSS);
|
|
248
|
-
const [errored, setErrored] =
|
|
248
|
+
const [errored, setErrored] = React25__default.useState(false);
|
|
249
249
|
const cleanSrc = safeSrc(src);
|
|
250
250
|
const showImg = cleanSrc && !errored;
|
|
251
251
|
const _statusLabel = status ? statusLabel ?? statusLabels?.[status] ?? STATUS_LABELS[status] : void 0;
|
|
@@ -270,7 +270,7 @@ function Avatar({
|
|
|
270
270
|
var MENU_CSS = `
|
|
271
271
|
.twc-menu-wrap { position: relative; display: inline-flex; }
|
|
272
272
|
.twc-menu {
|
|
273
|
-
position: fixed; z-index: var(--z-
|
|
273
|
+
position: fixed; z-index: var(--z-popover); min-width: 200px;
|
|
274
274
|
padding: var(--space-1-5); background: var(--color-surface-raised);
|
|
275
275
|
border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg);
|
|
276
276
|
box-shadow: var(--shadow-lg); font-family: var(--font-sans);
|
|
@@ -323,23 +323,25 @@ function Menu({
|
|
|
323
323
|
...rest
|
|
324
324
|
}) {
|
|
325
325
|
const __twcStyles = useScopedStyles("twc-menu-styles", MENU_CSS);
|
|
326
|
-
const [openState, setOpenState] =
|
|
327
|
-
const [render, setRender] =
|
|
328
|
-
const [pos, setPos] =
|
|
329
|
-
const [active, setActive] =
|
|
330
|
-
const wrapRef =
|
|
331
|
-
const menuRef =
|
|
332
|
-
const
|
|
326
|
+
const [openState, setOpenState] = React25__default.useState(defaultOpen);
|
|
327
|
+
const [render, setRender] = React25__default.useState(false);
|
|
328
|
+
const [pos, setPos] = React25__default.useState(null);
|
|
329
|
+
const [active, setActive] = React25__default.useState(-1);
|
|
330
|
+
const wrapRef = React25__default.useRef(null);
|
|
331
|
+
const menuRef = React25__default.useRef(null);
|
|
332
|
+
const typeBufRef = React25__default.useRef("");
|
|
333
|
+
const typeTimerRef = React25__default.useRef(null);
|
|
334
|
+
const menuId = React25__default.useId();
|
|
333
335
|
const headerId = `${menuId}-header`;
|
|
334
336
|
const controlled = openProp !== void 0;
|
|
335
337
|
const open = controlled ? !!openProp : openState;
|
|
336
|
-
const openRef =
|
|
338
|
+
const openRef = React25__default.useRef(open);
|
|
337
339
|
openRef.current = open;
|
|
338
|
-
const controlledRef =
|
|
340
|
+
const controlledRef = React25__default.useRef(controlled);
|
|
339
341
|
controlledRef.current = controlled;
|
|
340
|
-
const onOpenChangeRef =
|
|
342
|
+
const onOpenChangeRef = React25__default.useRef(onOpenChange);
|
|
341
343
|
onOpenChangeRef.current = onOpenChange;
|
|
342
|
-
const setOpen =
|
|
344
|
+
const setOpen = React25__default.useCallback((next) => {
|
|
343
345
|
const value = typeof next === "function" ? next(openRef.current) : next;
|
|
344
346
|
if (value === openRef.current) return;
|
|
345
347
|
if (!controlledRef.current) setOpenState(value);
|
|
@@ -347,7 +349,7 @@ function Menu({
|
|
|
347
349
|
}, []);
|
|
348
350
|
const RD = { createPortal: typeof createPortal === "function" ? createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
|
|
349
351
|
const interactiveIdx = items.map((it, i) => !it.separator && !it.heading ? i : -1).filter((i) => i >= 0);
|
|
350
|
-
const place =
|
|
352
|
+
const place = React25__default.useCallback(() => {
|
|
351
353
|
const t = wrapRef.current;
|
|
352
354
|
if (!t) return;
|
|
353
355
|
const r = t.getBoundingClientRect();
|
|
@@ -362,7 +364,7 @@ function Menu({
|
|
|
362
364
|
const avail = (flip ? r.top : vh - r.bottom) - gap - M;
|
|
363
365
|
setPos({ top, bottom, left, width: w, flip, maxHeight: Math.max(120, avail) });
|
|
364
366
|
}, [align, width]);
|
|
365
|
-
|
|
367
|
+
React25__default.useEffect(() => {
|
|
366
368
|
if (!open) return;
|
|
367
369
|
place();
|
|
368
370
|
const onMove = () => place();
|
|
@@ -380,7 +382,7 @@ function Menu({
|
|
|
380
382
|
document.removeEventListener("mousedown", onDown);
|
|
381
383
|
};
|
|
382
384
|
}, [open, place]);
|
|
383
|
-
|
|
385
|
+
React25__default.useEffect(() => {
|
|
384
386
|
if (open) {
|
|
385
387
|
setRender(true);
|
|
386
388
|
return;
|
|
@@ -397,7 +399,7 @@ function Menu({
|
|
|
397
399
|
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
398
400
|
e.preventDefault();
|
|
399
401
|
setOpen(true);
|
|
400
|
-
setActive(-1);
|
|
402
|
+
setActive(interactiveIdx[0] ?? -1);
|
|
401
403
|
}
|
|
402
404
|
return;
|
|
403
405
|
}
|
|
@@ -418,6 +420,24 @@ function Menu({
|
|
|
418
420
|
if (next < 0) next = list.length - 1;
|
|
419
421
|
if (next >= list.length) next = 0;
|
|
420
422
|
setActive(list[next]);
|
|
423
|
+
} else if (e.key === "PageDown" || e.key === "PageUp") {
|
|
424
|
+
e.preventDefault();
|
|
425
|
+
const list = interactiveIdx;
|
|
426
|
+
if (list.length) {
|
|
427
|
+
const curPos = Math.max(0, list.indexOf(active));
|
|
428
|
+
const next = Math.min(list.length - 1, Math.max(0, curPos + (e.key === "PageDown" ? 5 : -5)));
|
|
429
|
+
setActive(list[next]);
|
|
430
|
+
}
|
|
431
|
+
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
432
|
+
typeBufRef.current += e.key.toLowerCase();
|
|
433
|
+
clearTimeout(typeTimerRef.current);
|
|
434
|
+
typeTimerRef.current = setTimeout(() => {
|
|
435
|
+
typeBufRef.current = "";
|
|
436
|
+
}, 500);
|
|
437
|
+
const b = typeBufRef.current;
|
|
438
|
+
const labelOf = (i) => String(items[i]?.label ?? "").toLowerCase();
|
|
439
|
+
const hit = interactiveIdx.find((i) => labelOf(i).startsWith(b));
|
|
440
|
+
if (hit != null) setActive(hit);
|
|
421
441
|
} else if (e.key === "Home" || e.key === "End") {
|
|
422
442
|
e.preventDefault();
|
|
423
443
|
const list = interactiveIdx;
|
|
@@ -445,12 +465,13 @@ function Menu({
|
|
|
445
465
|
"data-align": align,
|
|
446
466
|
"data-flip": pos.flip || void 0,
|
|
447
467
|
role: "menu",
|
|
468
|
+
"aria-orientation": "vertical",
|
|
448
469
|
"aria-label": ariaLabel,
|
|
449
470
|
"aria-labelledby": ariaLabelledby ?? (ariaLabel ? void 0 : header ? headerId : void 0),
|
|
450
471
|
style: { top: pos.top, bottom: pos.bottom, left: pos.left, minWidth: pos.width, width: pos.width, maxHeight: pos.maxHeight },
|
|
451
472
|
children: [
|
|
452
473
|
__twcStyles,
|
|
453
|
-
header ? /* @__PURE__ */ jsx("div", { className: "twc-menu__header", id: headerId, children: header }) : null,
|
|
474
|
+
header ? /* @__PURE__ */ jsx("div", { className: "twc-menu__header", id: headerId, role: "presentation", children: header }) : null,
|
|
454
475
|
items.map((it, i) => {
|
|
455
476
|
if (it.separator) return /* @__PURE__ */ jsx("div", { className: "twc-menu__sep", role: "separator" }, `s${i}`);
|
|
456
477
|
if (it.label && it.heading) return /* @__PURE__ */ jsx("div", { className: "twc-menu__label", children: it.label }, `h${i}`);
|
|
@@ -484,7 +505,7 @@ function Menu({
|
|
|
484
505
|
}
|
|
485
506
|
) : null;
|
|
486
507
|
const activeDescId = open && active >= 0 ? `${menuId}-item-${active}` : void 0;
|
|
487
|
-
const triggerEl =
|
|
508
|
+
const triggerEl = React25__default.isValidElement(trigger) ? React25__default.cloneElement(trigger, {
|
|
488
509
|
onClick: (e) => {
|
|
489
510
|
trigger.props.onClick?.(e);
|
|
490
511
|
toggle();
|
|
@@ -624,8 +645,9 @@ function Badge({
|
|
|
624
645
|
}
|
|
625
646
|
var BREADCRUMB_CSS = `
|
|
626
647
|
.twc-breadcrumb { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; font-family: var(--font-sans); font-size: var(--text-sm); }
|
|
627
|
-
.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); }
|
|
628
|
-
.twc-breadcrumb__item
|
|
648
|
+
.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); }
|
|
649
|
+
a.twc-breadcrumb__item, button.twc-breadcrumb__item { cursor: pointer; }
|
|
650
|
+
a.twc-breadcrumb__item:hover, button.twc-breadcrumb__item:hover { color: var(--color-text); background: var(--color-surface-sunken); }
|
|
629
651
|
.twc-breadcrumb__item[aria-current="page"] { color: var(--color-text); font-weight: var(--font-semibold); cursor: default; }
|
|
630
652
|
.twc-breadcrumb__item svg { width: 15px; height: 15px; flex: none; }
|
|
631
653
|
.twc-breadcrumb__sep { display: inline-flex; align-items: center; color: var(--color-text-subtle); pointer-events: none; }
|
|
@@ -648,7 +670,7 @@ function Breadcrumb({
|
|
|
648
670
|
...rest
|
|
649
671
|
}) {
|
|
650
672
|
const __twcStyles = useScopedStyles("twc-breadcrumb-styles", BREADCRUMB_CSS);
|
|
651
|
-
const [expanded, setExpanded] =
|
|
673
|
+
const [expanded, setExpanded] = React25__default.useState(false);
|
|
652
674
|
const sep = separator || /* @__PURE__ */ jsx(ChevronSep, {});
|
|
653
675
|
let display = items;
|
|
654
676
|
if (maxItems > 0 && items.length > maxItems && !expanded) {
|
|
@@ -661,7 +683,7 @@ function Breadcrumb({
|
|
|
661
683
|
__twcStyles,
|
|
662
684
|
display.map((it, i) => {
|
|
663
685
|
const last = i === display.length - 1;
|
|
664
|
-
return /* @__PURE__ */ jsxs(
|
|
686
|
+
return /* @__PURE__ */ jsxs(React25__default.Fragment, { children: [
|
|
665
687
|
it.ellipsis ? /* @__PURE__ */ jsx("button", { className: "twc-breadcrumb__ellipsis", "aria-label": "Show more", onClick: () => setExpanded(true), children: "\u2026" }) : last ? /* @__PURE__ */ jsxs(
|
|
666
688
|
"span",
|
|
667
689
|
{
|
|
@@ -673,17 +695,18 @@ function Breadcrumb({
|
|
|
673
695
|
it.label
|
|
674
696
|
]
|
|
675
697
|
}
|
|
676
|
-
) : /* @__PURE__ */ jsxs(
|
|
677
|
-
"
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
698
|
+
) : safeHref2(it.href) ? /* @__PURE__ */ jsxs("a", { className: "twc-breadcrumb__item", href: safeHref2(it.href), onClick: it.onClick, children: [
|
|
699
|
+
it.icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
|
|
700
|
+
it.label
|
|
701
|
+
] }) : it.onClick ? /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-breadcrumb__item", onClick: it.onClick, children: [
|
|
702
|
+
it.icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
|
|
703
|
+
it.label
|
|
704
|
+
] }) : (
|
|
705
|
+
// #46: no href and no onClick → inert plain-text crumb (not a fake <a href="#">).
|
|
706
|
+
/* @__PURE__ */ jsxs("span", { className: "twc-breadcrumb__item", children: [
|
|
707
|
+
it.icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: it.icon }) : null,
|
|
708
|
+
it.label
|
|
709
|
+
] })
|
|
687
710
|
),
|
|
688
711
|
!last ? /* @__PURE__ */ jsx("span", { className: "twc-breadcrumb__sep", "aria-hidden": "true", children: sep }) : null
|
|
689
712
|
] }, i);
|
|
@@ -802,7 +825,7 @@ function Button({
|
|
|
802
825
|
...rest
|
|
803
826
|
}) {
|
|
804
827
|
const __twcStyles = useScopedStyles("twc-btn-styles", CSS2);
|
|
805
|
-
const [ripples, setRipples] =
|
|
828
|
+
const [ripples, setRipples] = React25__default.useState([]);
|
|
806
829
|
const Tag2 = as;
|
|
807
830
|
const inert = Tag2 === "a" && (disabled || loading);
|
|
808
831
|
function handleClick(e) {
|
|
@@ -878,7 +901,9 @@ var CARD_CSS = `
|
|
|
878
901
|
.twc-card[data-pad="md"] { padding: var(--space-5); }
|
|
879
902
|
.twc-card[data-pad="lg"] { padding: var(--space-6); }
|
|
880
903
|
.twc-card[data-pad="none"] { padding: 0; }
|
|
881
|
-
.twc-card__header { display: flex; flex-
|
|
904
|
+
.twc-card__header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
|
|
905
|
+
.twc-card__heading { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
906
|
+
.twc-card__actions { flex: none; display: flex; align-items: center; gap: var(--space-2); }
|
|
882
907
|
.twc-card__title { font-size: var(--text-lg); font-weight: var(--font-bold); letter-spacing: -0.01em; }
|
|
883
908
|
.twc-card__subtitle { font-size: var(--text-sm); color: var(--color-text-muted); }
|
|
884
909
|
.twc-card__body { font-size: var(--text-sm); color: var(--color-text-muted); line-height: var(--leading-normal); }
|
|
@@ -888,6 +913,7 @@ function Card({
|
|
|
888
913
|
children,
|
|
889
914
|
title,
|
|
890
915
|
subtitle,
|
|
916
|
+
actions,
|
|
891
917
|
footer,
|
|
892
918
|
variant = "elevated",
|
|
893
919
|
padding = "md",
|
|
@@ -908,9 +934,12 @@ function Card({
|
|
|
908
934
|
...rest,
|
|
909
935
|
children: [
|
|
910
936
|
__twcStyles,
|
|
911
|
-
title || subtitle ? /* @__PURE__ */ jsxs("div", { className: "twc-card__header", children: [
|
|
912
|
-
|
|
913
|
-
|
|
937
|
+
title || subtitle || actions ? /* @__PURE__ */ jsxs("div", { className: "twc-card__header", children: [
|
|
938
|
+
/* @__PURE__ */ jsxs("div", { className: "twc-card__heading", children: [
|
|
939
|
+
title ? /* @__PURE__ */ jsx("div", { className: "twc-card__title", children: title }) : null,
|
|
940
|
+
subtitle ? /* @__PURE__ */ jsx("div", { className: "twc-card__subtitle", children: subtitle }) : null
|
|
941
|
+
] }),
|
|
942
|
+
actions ? /* @__PURE__ */ jsx("div", { className: "twc-card__actions", children: actions }) : null
|
|
914
943
|
] }) : null,
|
|
915
944
|
children ? /* @__PURE__ */ jsx("div", { className: "twc-card__body", children }) : null,
|
|
916
945
|
footer ? /* @__PURE__ */ jsx("div", { className: "twc-card__footer", children: footer }) : null
|
|
@@ -970,14 +999,14 @@ function Carousel({
|
|
|
970
999
|
...rest
|
|
971
1000
|
}) {
|
|
972
1001
|
const __twcStyles = useScopedStyles("twc-carousel-styles", CAROUSEL_CSS);
|
|
973
|
-
const slides =
|
|
1002
|
+
const slides = React25__default.Children.toArray(children);
|
|
974
1003
|
const count = slides.length;
|
|
975
|
-
const [internal, setInternal] =
|
|
1004
|
+
const [internal, setInternal] = React25__default.useState(defaultIndex);
|
|
976
1005
|
const index = indexProp !== void 0 ? indexProp : internal;
|
|
977
|
-
const [paused, setPaused] =
|
|
978
|
-
const [userPaused, setUserPaused] =
|
|
979
|
-
const [prefersReduced, setPrefersReduced] =
|
|
980
|
-
|
|
1006
|
+
const [paused, setPaused] = React25__default.useState(false);
|
|
1007
|
+
const [userPaused, setUserPaused] = React25__default.useState(false);
|
|
1008
|
+
const [prefersReduced, setPrefersReduced] = React25__default.useState(false);
|
|
1009
|
+
React25__default.useEffect(() => {
|
|
981
1010
|
if (typeof window === "undefined" || !window.matchMedia) return void 0;
|
|
982
1011
|
const mql = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
983
1012
|
const on = () => setPrefersReduced(mql.matches);
|
|
@@ -985,15 +1014,15 @@ function Carousel({
|
|
|
985
1014
|
mql.addEventListener("change", on);
|
|
986
1015
|
return () => mql.removeEventListener("change", on);
|
|
987
1016
|
}, []);
|
|
988
|
-
const setIndex =
|
|
1017
|
+
const setIndex = React25__default.useCallback((i) => {
|
|
989
1018
|
if (indexProp === void 0) setInternal(i);
|
|
990
1019
|
onIndexChange?.(i);
|
|
991
1020
|
}, [indexProp, onIndexChange]);
|
|
992
|
-
const go =
|
|
1021
|
+
const go = React25__default.useCallback((i) => {
|
|
993
1022
|
setIndex(loop ? (i + count) % count : Math.min(Math.max(i, 0), count - 1));
|
|
994
1023
|
}, [count, loop, setIndex]);
|
|
995
1024
|
const autoRotating = autoPlay && !paused && !userPaused && !prefersReduced && count > 1;
|
|
996
|
-
|
|
1025
|
+
React25__default.useEffect(() => {
|
|
997
1026
|
if (!autoRotating) return void 0;
|
|
998
1027
|
const t = setInterval(() => {
|
|
999
1028
|
const next = loop ? (index + 1) % count : index + 1 >= count ? index : index + 1;
|
|
@@ -1088,7 +1117,7 @@ function Chart({
|
|
|
1088
1117
|
...rest
|
|
1089
1118
|
}) {
|
|
1090
1119
|
const __twcStyles = useScopedStyles("twc-chart-styles", CHART_CSS);
|
|
1091
|
-
const uid =
|
|
1120
|
+
const uid = React25__default.useId();
|
|
1092
1121
|
const tableId = tableFallback ? `${uid}-table` : void 0;
|
|
1093
1122
|
const keys = series || ["value"];
|
|
1094
1123
|
const palette = colors && colors.length ? colors : SERIES_COLORS;
|
|
@@ -1180,6 +1209,15 @@ function shortNum(v) {
|
|
|
1180
1209
|
if (v >= 1e3) return (v / 1e3).toFixed(v % 1e3 ? 1 : 0) + "k";
|
|
1181
1210
|
return String(Math.round(v));
|
|
1182
1211
|
}
|
|
1212
|
+
|
|
1213
|
+
// components/_warn.js
|
|
1214
|
+
var seen = /* @__PURE__ */ new Set();
|
|
1215
|
+
function warnOnce(key, message) {
|
|
1216
|
+
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production") return;
|
|
1217
|
+
if (seen.has(key)) return;
|
|
1218
|
+
seen.add(key);
|
|
1219
|
+
if (typeof console !== "undefined" && console.warn) console.warn(message);
|
|
1220
|
+
}
|
|
1183
1221
|
function Checkbox({
|
|
1184
1222
|
label,
|
|
1185
1223
|
description,
|
|
@@ -1235,14 +1273,18 @@ function Checkbox({
|
|
|
1235
1273
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
1236
1274
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
1237
1275
|
`);
|
|
1238
|
-
const autoId =
|
|
1276
|
+
const autoId = React25__default.useId();
|
|
1239
1277
|
const fieldId = id || autoId;
|
|
1240
1278
|
const errId = `${fieldId}-error`;
|
|
1241
1279
|
const invalid = Boolean(error);
|
|
1242
|
-
const ref =
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1280
|
+
const ref = React25__default.useRef(null);
|
|
1281
|
+
const mixed = indeterminate && !checked;
|
|
1282
|
+
React25__default.useEffect(() => {
|
|
1283
|
+
if (ref.current) ref.current.indeterminate = mixed;
|
|
1284
|
+
}, [mixed]);
|
|
1285
|
+
if (process.env.NODE_ENV !== "production" && !label && !description && !rest["aria-label"] && !rest["aria-labelledby"]) {
|
|
1286
|
+
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).");
|
|
1287
|
+
}
|
|
1246
1288
|
const describedBy = [rest["aria-describedby"], error ? errId : null].filter(Boolean).join(" ") || void 0;
|
|
1247
1289
|
const control = /* @__PURE__ */ 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: [
|
|
1248
1290
|
__twcStyles,
|
|
@@ -1258,12 +1300,14 @@ function Checkbox({
|
|
|
1258
1300
|
disabled,
|
|
1259
1301
|
onChange,
|
|
1260
1302
|
...rest,
|
|
1303
|
+
required: required || void 0,
|
|
1261
1304
|
"aria-required": required || void 0,
|
|
1305
|
+
"aria-checked": mixed ? "mixed" : void 0,
|
|
1262
1306
|
"aria-invalid": invalid || void 0,
|
|
1263
1307
|
"aria-describedby": describedBy
|
|
1264
1308
|
}
|
|
1265
1309
|
),
|
|
1266
|
-
/* @__PURE__ */ jsx("span", { className: "twc-check__box", "aria-hidden": "true", children: /* @__PURE__ */ jsx("svg", { className: "twc-check__svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3.5", strokeLinecap: "round", strokeLinejoin: "round", children:
|
|
1310
|
+
/* @__PURE__ */ jsx("span", { className: "twc-check__box", "aria-hidden": "true", children: /* @__PURE__ */ 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__ */ jsx("path", { d: "M5 12h14" }) : /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) }) }),
|
|
1267
1311
|
label || description ? /* @__PURE__ */ jsxs("span", { className: "twc-check__text", children: [
|
|
1268
1312
|
label ? /* @__PURE__ */ jsx("span", { className: "twc-check__label", children: label }) : null,
|
|
1269
1313
|
description ? /* @__PURE__ */ jsx("span", { className: "twc-check__desc", children: description }) : null
|
|
@@ -1319,6 +1363,7 @@ var COLORPICKER_CSS = `
|
|
|
1319
1363
|
.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); }
|
|
1320
1364
|
.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); }
|
|
1321
1365
|
.twc-cp__hex:focus { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
1366
|
+
.twc-cp__hex[data-invalid="true"] { border-color: var(--color-danger); }
|
|
1322
1367
|
.twc-cp__presets { display: flex; flex-wrap: wrap; gap: 5px; margin-top: var(--space-3); }
|
|
1323
1368
|
.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;
|
|
1324
1369
|
transition: transform var(--duration-fast) var(--ease-spring); }
|
|
@@ -1377,20 +1422,20 @@ function ColorPicker({
|
|
|
1377
1422
|
}) {
|
|
1378
1423
|
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS);
|
|
1379
1424
|
const __twcStyles1 = useScopedStyles("twc-colorpicker-styles", COLORPICKER_CSS);
|
|
1380
|
-
const [internal, setInternal] =
|
|
1425
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
1381
1426
|
const hex = (value !== void 0 ? value : internal) || "#000000";
|
|
1382
|
-
const lastValidRef =
|
|
1427
|
+
const lastValidRef = React25__default.useRef(hex);
|
|
1383
1428
|
if (/^#[0-9a-f]{6}$/i.test(hex)) lastValidRef.current = hex;
|
|
1384
|
-
const [open, setOpen] =
|
|
1385
|
-
const [hsv, setHsv] =
|
|
1386
|
-
const [coords, setCoords] =
|
|
1387
|
-
const wrapRef =
|
|
1388
|
-
const triggerRef =
|
|
1389
|
-
const popRef =
|
|
1390
|
-
const areaRef =
|
|
1391
|
-
const hueRef =
|
|
1429
|
+
const [open, setOpen] = React25__default.useState(false);
|
|
1430
|
+
const [hsv, setHsv] = React25__default.useState(() => hexToHsv(hex) || { h: 239, s: 60, v: 94 });
|
|
1431
|
+
const [coords, setCoords] = React25__default.useState(null);
|
|
1432
|
+
const wrapRef = React25__default.useRef(null);
|
|
1433
|
+
const triggerRef = React25__default.useRef(null);
|
|
1434
|
+
const popRef = React25__default.useRef(null);
|
|
1435
|
+
const areaRef = React25__default.useRef(null);
|
|
1436
|
+
const hueRef = React25__default.useRef(null);
|
|
1392
1437
|
const POP_W = 240;
|
|
1393
|
-
const place =
|
|
1438
|
+
const place = React25__default.useCallback(() => {
|
|
1394
1439
|
const el = triggerRef.current;
|
|
1395
1440
|
if (!el) return;
|
|
1396
1441
|
const r = el.getBoundingClientRect();
|
|
@@ -1401,7 +1446,7 @@ function ColorPicker({
|
|
|
1401
1446
|
left = Math.max(8, left);
|
|
1402
1447
|
setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
|
|
1403
1448
|
}, []);
|
|
1404
|
-
|
|
1449
|
+
React25__default.useEffect(() => {
|
|
1405
1450
|
if (!open) return void 0;
|
|
1406
1451
|
place();
|
|
1407
1452
|
const onMove = () => place();
|
|
@@ -1412,17 +1457,17 @@ function ColorPicker({
|
|
|
1412
1457
|
window.removeEventListener("resize", onMove);
|
|
1413
1458
|
};
|
|
1414
1459
|
}, [open, place]);
|
|
1415
|
-
const labelId =
|
|
1460
|
+
const labelId = React25__default.useId();
|
|
1416
1461
|
const descId = `${labelId}-desc`;
|
|
1417
1462
|
const invalid = Boolean(error);
|
|
1418
|
-
|
|
1463
|
+
React25__default.useEffect(() => {
|
|
1419
1464
|
if (disabled) setOpen(false);
|
|
1420
1465
|
}, [disabled]);
|
|
1421
|
-
|
|
1466
|
+
React25__default.useEffect(() => {
|
|
1422
1467
|
const v = hexToHsv(hex);
|
|
1423
1468
|
if (v && hsvToHex(v.h, v.s, v.v).toLowerCase() !== hsvToHex(hsv.h, hsv.s, hsv.v).toLowerCase()) setHsv(v);
|
|
1424
1469
|
}, [hex]);
|
|
1425
|
-
|
|
1470
|
+
React25__default.useEffect(() => {
|
|
1426
1471
|
if (!open) return;
|
|
1427
1472
|
const onDown = (e) => {
|
|
1428
1473
|
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
@@ -1439,8 +1484,8 @@ function ColorPicker({
|
|
|
1439
1484
|
document.removeEventListener("keydown", onKey);
|
|
1440
1485
|
};
|
|
1441
1486
|
}, [open]);
|
|
1442
|
-
const prevOpen =
|
|
1443
|
-
|
|
1487
|
+
const prevOpen = React25__default.useRef(false);
|
|
1488
|
+
React25__default.useEffect(() => {
|
|
1444
1489
|
let id;
|
|
1445
1490
|
if (!prevOpen.current && open) {
|
|
1446
1491
|
id = setTimeout(() => areaRef.current?.focus({ preventScroll: true }), 20);
|
|
@@ -1594,6 +1639,8 @@ function ColorPicker({
|
|
|
1594
1639
|
value: hex,
|
|
1595
1640
|
maxLength: 7,
|
|
1596
1641
|
"aria-label": "Hex color",
|
|
1642
|
+
"aria-invalid": !/^#[0-9a-f]{6}$/i.test(hex) || void 0,
|
|
1643
|
+
"data-invalid": !/^#[0-9a-f]{6}$/i.test(hex) || void 0,
|
|
1597
1644
|
onChange: (e) => {
|
|
1598
1645
|
let v = e.target.value;
|
|
1599
1646
|
if (!v.startsWith("#")) v = "#" + v;
|
|
@@ -1704,6 +1751,9 @@ var COMBO_CSS = `
|
|
|
1704
1751
|
.twc-opt__check { flex: none; color: var(--color-primary); display: inline-flex; }
|
|
1705
1752
|
.twc-opt__check svg { width: 16px; height: 16px; }
|
|
1706
1753
|
.twc-pop__empty { padding: 14px 12px; text-align: center; font-size: var(--text-sm); color: var(--color-text-subtle); }
|
|
1754
|
+
.twc-opt[data-disabled="true"] { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
|
|
1755
|
+
.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); }
|
|
1756
|
+
.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; }
|
|
1707
1757
|
`;
|
|
1708
1758
|
function toOpt(o) {
|
|
1709
1759
|
return typeof o === "string" ? { value: o, label: o } : o;
|
|
@@ -1753,6 +1803,11 @@ function Combobox({
|
|
|
1753
1803
|
placement = "bottom",
|
|
1754
1804
|
portal = true,
|
|
1755
1805
|
minWidth = 0,
|
|
1806
|
+
onInputChange,
|
|
1807
|
+
filter,
|
|
1808
|
+
loading = false,
|
|
1809
|
+
emptyText = "No results found",
|
|
1810
|
+
name,
|
|
1756
1811
|
id,
|
|
1757
1812
|
className = "",
|
|
1758
1813
|
onFocus,
|
|
@@ -1760,29 +1815,38 @@ function Combobox({
|
|
|
1760
1815
|
...rest
|
|
1761
1816
|
}) {
|
|
1762
1817
|
const __twcStyles = useScopedStyles("twc-combo-styles", COMBO_CSS);
|
|
1763
|
-
const groups =
|
|
1764
|
-
const flat =
|
|
1765
|
-
const autoId =
|
|
1818
|
+
const groups = React25__default.useMemo(() => normalizeGroups(options), [options]);
|
|
1819
|
+
const flat = React25__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
|
|
1820
|
+
const autoId = React25__default.useId();
|
|
1766
1821
|
const fieldId = id || autoId;
|
|
1767
|
-
const [internal, setInternal] =
|
|
1822
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
1768
1823
|
const current = value !== void 0 ? value : internal;
|
|
1769
1824
|
const selected = flat.find((o) => o.value === current);
|
|
1770
|
-
const [open, setOpen] =
|
|
1771
|
-
const [query, setQuery] =
|
|
1772
|
-
const [active, setActive] =
|
|
1773
|
-
const [coords, setCoords] =
|
|
1774
|
-
const wrapRef =
|
|
1775
|
-
const controlRef =
|
|
1776
|
-
const inputRef =
|
|
1777
|
-
const popRef =
|
|
1778
|
-
const listRef =
|
|
1779
|
-
const activeRef =
|
|
1780
|
-
const fGroups =
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
const
|
|
1825
|
+
const [open, setOpen] = React25__default.useState(false);
|
|
1826
|
+
const [query, setQuery] = React25__default.useState("");
|
|
1827
|
+
const [active, setActive] = React25__default.useState(0);
|
|
1828
|
+
const [coords, setCoords] = React25__default.useState(null);
|
|
1829
|
+
const wrapRef = React25__default.useRef(null);
|
|
1830
|
+
const controlRef = React25__default.useRef(null);
|
|
1831
|
+
const inputRef = React25__default.useRef(null);
|
|
1832
|
+
const popRef = React25__default.useRef(null);
|
|
1833
|
+
const listRef = React25__default.useRef(null);
|
|
1834
|
+
const activeRef = React25__default.useRef(null);
|
|
1835
|
+
const fGroups = React25__default.useMemo(() => {
|
|
1836
|
+
const q = query.trim();
|
|
1837
|
+
const fn = filter === false ? null : typeof filter === "function" ? filter : matches;
|
|
1838
|
+
return groups.map((g) => ({ group: g.group, options: fn ? g.options.filter((o) => fn(o, q)) : g.options })).filter((g) => g.options.length);
|
|
1839
|
+
}, [groups, query, filter]);
|
|
1840
|
+
const visible = React25__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
|
|
1841
|
+
const nextEnabled = (from, dir) => {
|
|
1842
|
+
let i = from + dir;
|
|
1843
|
+
while (i >= 0 && i < visible.length) {
|
|
1844
|
+
if (!visible[i]?.disabled) return i;
|
|
1845
|
+
i += dir;
|
|
1846
|
+
}
|
|
1847
|
+
return from;
|
|
1848
|
+
};
|
|
1849
|
+
const place = React25__default.useCallback(() => {
|
|
1786
1850
|
const el = controlRef.current;
|
|
1787
1851
|
if (!el) return;
|
|
1788
1852
|
const r = el.getBoundingClientRect();
|
|
@@ -1797,7 +1861,7 @@ function Combobox({
|
|
|
1797
1861
|
flip
|
|
1798
1862
|
});
|
|
1799
1863
|
}, [placement, minWidth]);
|
|
1800
|
-
|
|
1864
|
+
React25__default.useEffect(() => {
|
|
1801
1865
|
if (!open || !portal) return;
|
|
1802
1866
|
place();
|
|
1803
1867
|
const onMove = () => place();
|
|
@@ -1808,7 +1872,7 @@ function Combobox({
|
|
|
1808
1872
|
window.removeEventListener("resize", onMove);
|
|
1809
1873
|
};
|
|
1810
1874
|
}, [open, portal, place]);
|
|
1811
|
-
|
|
1875
|
+
React25__default.useEffect(() => {
|
|
1812
1876
|
if (!open) return;
|
|
1813
1877
|
const onDown = (e) => {
|
|
1814
1878
|
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
@@ -1818,10 +1882,15 @@ function Combobox({
|
|
|
1818
1882
|
document.addEventListener("mousedown", onDown);
|
|
1819
1883
|
return () => document.removeEventListener("mousedown", onDown);
|
|
1820
1884
|
}, [open]);
|
|
1821
|
-
|
|
1885
|
+
React25__default.useEffect(() => {
|
|
1822
1886
|
setActive(0);
|
|
1823
1887
|
}, [query]);
|
|
1824
|
-
|
|
1888
|
+
React25__default.useEffect(() => {
|
|
1889
|
+
if (!open) return;
|
|
1890
|
+
const idx = flat.findIndex((o) => o.value === current);
|
|
1891
|
+
setActive(idx >= 0 ? idx : 0);
|
|
1892
|
+
}, [open]);
|
|
1893
|
+
React25__default.useEffect(() => {
|
|
1825
1894
|
if (open) ensureVisible(listRef.current, activeRef.current);
|
|
1826
1895
|
}, [active, open]);
|
|
1827
1896
|
function openMenu() {
|
|
@@ -1834,6 +1903,8 @@ function Combobox({
|
|
|
1834
1903
|
setQuery("");
|
|
1835
1904
|
}
|
|
1836
1905
|
function commit(v) {
|
|
1906
|
+
const o = flat.find((x) => x.value === v);
|
|
1907
|
+
if (o && o.disabled) return;
|
|
1837
1908
|
if (value === void 0) setInternal(v);
|
|
1838
1909
|
onChange?.(v);
|
|
1839
1910
|
close();
|
|
@@ -1845,17 +1916,20 @@ function Combobox({
|
|
|
1845
1916
|
openMenu();
|
|
1846
1917
|
return;
|
|
1847
1918
|
}
|
|
1848
|
-
setActive((a) =>
|
|
1919
|
+
setActive((a) => nextEnabled(a, 1));
|
|
1849
1920
|
} else if (e.key === "ArrowUp") {
|
|
1850
1921
|
e.preventDefault();
|
|
1851
|
-
setActive((a) =>
|
|
1922
|
+
setActive((a) => nextEnabled(a, -1));
|
|
1852
1923
|
} else if (e.key === "Enter") {
|
|
1853
1924
|
e.preventDefault();
|
|
1854
1925
|
if (open && visible[active]) commit(visible[active].value);
|
|
1855
1926
|
} else if (e.key === "Escape") {
|
|
1856
1927
|
close();
|
|
1857
1928
|
inputRef.current?.blur();
|
|
1858
|
-
} else if (e.key === "Backspace" && !query && selected)
|
|
1929
|
+
} else if (e.key === "Backspace" && !query && selected) {
|
|
1930
|
+
e.preventDefault();
|
|
1931
|
+
commit(null);
|
|
1932
|
+
}
|
|
1859
1933
|
}
|
|
1860
1934
|
const displayValue = open ? query : selected ? selected.label : "";
|
|
1861
1935
|
const listboxId = `${fieldId}-listbox`;
|
|
@@ -1864,7 +1938,10 @@ function Combobox({
|
|
|
1864
1938
|
const descId = `${fieldId}-desc`;
|
|
1865
1939
|
const describedBy = error || hint ? descId : void 0;
|
|
1866
1940
|
let counter = -1;
|
|
1867
|
-
const popInner = /* @__PURE__ */ jsx("div", { className: "twc-pop__list", ref: listRef, children:
|
|
1941
|
+
const popInner = /* @__PURE__ */ jsx("div", { className: "twc-pop__list", ref: listRef, children: loading ? /* @__PURE__ */ jsxs("div", { className: "twc-pop__loading", role: "status", children: [
|
|
1942
|
+
/* @__PURE__ */ jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
|
|
1943
|
+
"Loading\u2026"
|
|
1944
|
+
] }) : visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React25__default.Fragment, { children: [
|
|
1868
1945
|
g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
1869
1946
|
g.options.map((o) => {
|
|
1870
1947
|
counter += 1;
|
|
@@ -1879,9 +1956,14 @@ function Combobox({
|
|
|
1879
1956
|
role: "option",
|
|
1880
1957
|
"aria-selected": isSel,
|
|
1881
1958
|
ref: idx === active ? activeRef : null,
|
|
1959
|
+
disabled: o.disabled || void 0,
|
|
1960
|
+
"aria-disabled": o.disabled || void 0,
|
|
1961
|
+
"data-disabled": o.disabled || void 0,
|
|
1882
1962
|
"data-selected": isSel || void 0,
|
|
1883
1963
|
"data-active": idx === active || void 0,
|
|
1884
|
-
onMouseEnter: () =>
|
|
1964
|
+
onMouseEnter: () => {
|
|
1965
|
+
if (!o.disabled) setActive(idx);
|
|
1966
|
+
},
|
|
1885
1967
|
onMouseDown: (e) => e.preventDefault(),
|
|
1886
1968
|
onClick: () => commit(o.value),
|
|
1887
1969
|
children: [
|
|
@@ -1909,7 +1991,7 @@ function Combobox({
|
|
|
1909
1991
|
id: listboxId,
|
|
1910
1992
|
role: "listbox",
|
|
1911
1993
|
ref: popRef,
|
|
1912
|
-
"data-placement": coords.flip ? "top" :
|
|
1994
|
+
"data-placement": coords.flip ? "top" : "bottom",
|
|
1913
1995
|
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-tooltip)" },
|
|
1914
1996
|
children: popInner
|
|
1915
1997
|
}
|
|
@@ -1922,6 +2004,7 @@ function Combobox({
|
|
|
1922
2004
|
}
|
|
1923
2005
|
return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, ref: wrapRef, children: [
|
|
1924
2006
|
__twcStyles,
|
|
2007
|
+
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: current ?? "" }) : null,
|
|
1925
2008
|
label ? /* @__PURE__ */ jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
1926
2009
|
label,
|
|
1927
2010
|
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
@@ -1967,6 +2050,7 @@ function Combobox({
|
|
|
1967
2050
|
onChange: (e) => {
|
|
1968
2051
|
setQuery(e.target.value);
|
|
1969
2052
|
setOpen(true);
|
|
2053
|
+
onInputChange?.(e.target.value);
|
|
1970
2054
|
},
|
|
1971
2055
|
onKeyDown: (e) => {
|
|
1972
2056
|
onKeyDown?.(e);
|
|
@@ -2003,9 +2087,10 @@ function Combobox({
|
|
|
2003
2087
|
] });
|
|
2004
2088
|
}
|
|
2005
2089
|
var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
|
|
2090
|
+
var useIsoLayoutEffect = canUseDOM ? React25__default.useLayoutEffect : React25__default.useEffect;
|
|
2006
2091
|
var FOCUSABLE = 'a[href]:not([tabindex="-1"]), button:not([disabled]):not([tabindex="-1"]), textarea:not([disabled]):not([tabindex="-1"]), input:not([disabled]):not([tabindex="-1"]), select:not([disabled]):not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])';
|
|
2007
2092
|
function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
|
|
2008
|
-
|
|
2093
|
+
React25__default.useEffect(() => {
|
|
2009
2094
|
if (!active || !canUseDOM) return void 0;
|
|
2010
2095
|
const node = ref.current;
|
|
2011
2096
|
if (!node) return void 0;
|
|
@@ -2016,7 +2101,7 @@ function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
|
|
|
2016
2101
|
if (restoreFocus && prevFocused && typeof prevFocused.focus === "function") prevFocused.focus();
|
|
2017
2102
|
};
|
|
2018
2103
|
}, [active]);
|
|
2019
|
-
|
|
2104
|
+
React25__default.useEffect(() => {
|
|
2020
2105
|
if (!active || !canUseDOM) return void 0;
|
|
2021
2106
|
const node = ref.current;
|
|
2022
2107
|
const onKey = (e) => {
|
|
@@ -2043,11 +2128,53 @@ function useFocusTrap(ref, active = true, { restoreFocus = true } = {}) {
|
|
|
2043
2128
|
}, [active]);
|
|
2044
2129
|
}
|
|
2045
2130
|
function usePortal() {
|
|
2046
|
-
return
|
|
2131
|
+
return React25__default.useCallback((node) => {
|
|
2047
2132
|
if (typeof document === "undefined") return null;
|
|
2048
2133
|
return typeof createPortal === "function" ? createPortal(node, document.body) : node;
|
|
2049
2134
|
}, []);
|
|
2050
2135
|
}
|
|
2136
|
+
var __scrollLockCount = 0;
|
|
2137
|
+
var __scrollLockSaved = { overflow: "", paddingRight: "" };
|
|
2138
|
+
function useScrollLock(locked = true) {
|
|
2139
|
+
useIsoLayoutEffect(() => {
|
|
2140
|
+
if (!canUseDOM || !locked) return void 0;
|
|
2141
|
+
if (__scrollLockCount === 0) {
|
|
2142
|
+
const b = document.body;
|
|
2143
|
+
__scrollLockSaved = { overflow: b.style.overflow, paddingRight: b.style.paddingRight };
|
|
2144
|
+
const gutter = window.innerWidth - document.documentElement.clientWidth;
|
|
2145
|
+
b.style.overflow = "hidden";
|
|
2146
|
+
if (gutter > 0) b.style.paddingRight = `${(parseFloat(getComputedStyle(b).paddingRight) || 0) + gutter}px`;
|
|
2147
|
+
}
|
|
2148
|
+
__scrollLockCount += 1;
|
|
2149
|
+
return () => {
|
|
2150
|
+
__scrollLockCount -= 1;
|
|
2151
|
+
if (__scrollLockCount === 0) {
|
|
2152
|
+
document.body.style.overflow = __scrollLockSaved.overflow;
|
|
2153
|
+
document.body.style.paddingRight = __scrollLockSaved.paddingRight;
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
2156
|
+
}, [locked]);
|
|
2157
|
+
}
|
|
2158
|
+
function useInertBackground(ref, active) {
|
|
2159
|
+
React25__default.useEffect(() => {
|
|
2160
|
+
if (!active || !canUseDOM) return void 0;
|
|
2161
|
+
const node = ref.current;
|
|
2162
|
+
if (!node) return void 0;
|
|
2163
|
+
const changed = [];
|
|
2164
|
+
Array.from(document.body.children).forEach((el) => {
|
|
2165
|
+
if (el.contains(node) || el.hasAttribute("aria-hidden") || el.inert) return;
|
|
2166
|
+
el.inert = true;
|
|
2167
|
+
el.setAttribute("aria-hidden", "true");
|
|
2168
|
+
changed.push(el);
|
|
2169
|
+
});
|
|
2170
|
+
return () => {
|
|
2171
|
+
changed.forEach((el) => {
|
|
2172
|
+
el.inert = false;
|
|
2173
|
+
el.removeAttribute("aria-hidden");
|
|
2174
|
+
});
|
|
2175
|
+
};
|
|
2176
|
+
}, [active]);
|
|
2177
|
+
}
|
|
2051
2178
|
var COMMAND_CSS = `
|
|
2052
2179
|
.twc-cmdk__overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: var(--color-overlay); backdrop-filter: blur(3px);
|
|
2053
2180
|
display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
|
|
@@ -2089,19 +2216,20 @@ function CommandPalette({
|
|
|
2089
2216
|
commands,
|
|
2090
2217
|
placeholder = "Type a command or search\u2026",
|
|
2091
2218
|
emptyText = "No results found",
|
|
2219
|
+
searchLabel = "Command palette search",
|
|
2092
2220
|
className = "",
|
|
2093
2221
|
...rest
|
|
2094
2222
|
}) {
|
|
2095
2223
|
const __twcStyles = useScopedStyles("twc-cmdk-styles", COMMAND_CSS);
|
|
2096
2224
|
const renderPortal = usePortal();
|
|
2097
|
-
const [query, setQuery] =
|
|
2098
|
-
const [active, setActive] =
|
|
2099
|
-
const inputRef =
|
|
2100
|
-
const listRef =
|
|
2101
|
-
const paletteRef =
|
|
2102
|
-
const baseId =
|
|
2103
|
-
const [mounted, setMounted] =
|
|
2104
|
-
|
|
2225
|
+
const [query, setQuery] = React25__default.useState("");
|
|
2226
|
+
const [active, setActive] = React25__default.useState(0);
|
|
2227
|
+
const inputRef = React25__default.useRef(null);
|
|
2228
|
+
const listRef = React25__default.useRef(null);
|
|
2229
|
+
const paletteRef = React25__default.useRef(null);
|
|
2230
|
+
const baseId = React25__default.useId();
|
|
2231
|
+
const [mounted, setMounted] = React25__default.useState(open);
|
|
2232
|
+
React25__default.useEffect(() => {
|
|
2105
2233
|
if (open) {
|
|
2106
2234
|
setMounted(true);
|
|
2107
2235
|
return;
|
|
@@ -2109,22 +2237,15 @@ function CommandPalette({
|
|
|
2109
2237
|
const t = setTimeout(() => setMounted(false), 170);
|
|
2110
2238
|
return () => clearTimeout(t);
|
|
2111
2239
|
}, [open]);
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
const prev = document.body.style.overflow;
|
|
2115
|
-
document.body.style.overflow = "hidden";
|
|
2116
|
-
return () => {
|
|
2117
|
-
document.body.style.overflow = prev;
|
|
2118
|
-
};
|
|
2119
|
-
}, [open]);
|
|
2120
|
-
React24__default.useEffect(() => {
|
|
2240
|
+
useScrollLock(open);
|
|
2241
|
+
React25__default.useEffect(() => {
|
|
2121
2242
|
if (open) {
|
|
2122
2243
|
setQuery("");
|
|
2123
2244
|
setActive(0);
|
|
2124
2245
|
}
|
|
2125
2246
|
}, [open]);
|
|
2126
2247
|
useFocusTrap(paletteRef, open && mounted);
|
|
2127
|
-
|
|
2248
|
+
React25__default.useEffect(() => {
|
|
2128
2249
|
if (!open) return void 0;
|
|
2129
2250
|
const onKey = (e) => {
|
|
2130
2251
|
if (e.key === "Escape") {
|
|
@@ -2136,7 +2257,7 @@ function CommandPalette({
|
|
|
2136
2257
|
return () => document.removeEventListener("keydown", onKey);
|
|
2137
2258
|
}, [open, onClose]);
|
|
2138
2259
|
const q = query.trim().toLowerCase();
|
|
2139
|
-
const filtered =
|
|
2260
|
+
const filtered = React25__default.useMemo(() => commands.filter(
|
|
2140
2261
|
(c) => !q || c.label.toLowerCase().includes(q) || (c.keywords || "").toLowerCase().includes(q) || (c.group || "").toLowerCase().includes(q)
|
|
2141
2262
|
), [commands, q]);
|
|
2142
2263
|
const groups = [];
|
|
@@ -2151,7 +2272,7 @@ function CommandPalette({
|
|
|
2151
2272
|
g.items.push(c);
|
|
2152
2273
|
flat.push(c);
|
|
2153
2274
|
});
|
|
2154
|
-
|
|
2275
|
+
React25__default.useEffect(() => {
|
|
2155
2276
|
setActive(0);
|
|
2156
2277
|
}, [query]);
|
|
2157
2278
|
const run = (cmd) => {
|
|
@@ -2171,7 +2292,7 @@ function CommandPalette({
|
|
|
2171
2292
|
if (cmd) run(cmd);
|
|
2172
2293
|
}
|
|
2173
2294
|
}
|
|
2174
|
-
|
|
2295
|
+
React25__default.useEffect(() => {
|
|
2175
2296
|
const node = listRef.current?.querySelector('[data-active="true"]');
|
|
2176
2297
|
if (node) node.scrollIntoView({ block: "nearest" });
|
|
2177
2298
|
}, [active]);
|
|
@@ -2199,7 +2320,8 @@ function CommandPalette({
|
|
|
2199
2320
|
value: query,
|
|
2200
2321
|
placeholder,
|
|
2201
2322
|
role: "combobox",
|
|
2202
|
-
"aria-
|
|
2323
|
+
"aria-label": searchLabel,
|
|
2324
|
+
"aria-expanded": flat.length > 0 ? "true" : "false",
|
|
2203
2325
|
"aria-controls": listId,
|
|
2204
2326
|
"aria-activedescendant": activeId,
|
|
2205
2327
|
onChange: (e) => setQuery(e.target.value),
|
|
@@ -2301,7 +2423,9 @@ var CUR_CSS = `
|
|
|
2301
2423
|
.twc-cur:focus-within { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
2302
2424
|
.twc-cur[data-invalid="true"] { border-color: var(--color-danger); }
|
|
2303
2425
|
.twc-cur[data-invalid="true"]:focus-within { box-shadow: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 28%, transparent); }
|
|
2304
|
-
.twc-cur[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; }
|
|
2426
|
+
.twc-cur[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
2427
|
+
.twc-cur[data-readonly="true"] { background: var(--color-surface-sunken); }
|
|
2428
|
+
.twc-cur__el:disabled { cursor: not-allowed; }
|
|
2305
2429
|
.twc-cur__sym, .twc-cur__code {
|
|
2306
2430
|
display: inline-flex; align-items: center; padding: 0 var(--space-3);
|
|
2307
2431
|
background: var(--color-surface-sunken); color: var(--color-text-muted);
|
|
@@ -2344,18 +2468,29 @@ function Currency({
|
|
|
2344
2468
|
const prec = precision != null ? precision : meta.precision;
|
|
2345
2469
|
const sym = symbol != null ? symbol : meta.symbol;
|
|
2346
2470
|
const cur = code != null ? code : meta.code;
|
|
2347
|
-
const autoId =
|
|
2471
|
+
const autoId = React25__default.useId();
|
|
2348
2472
|
const fieldId = id || autoId;
|
|
2349
2473
|
const invalid = Boolean(error);
|
|
2350
2474
|
const controlled = value !== void 0;
|
|
2351
|
-
const [internal, setInternal] =
|
|
2475
|
+
const [internal, setInternal] = React25__default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
|
|
2352
2476
|
const shown = controlled ? clampPrecision(String(value ?? ""), prec) : internal;
|
|
2353
|
-
|
|
2477
|
+
React25__default.useEffect(() => {
|
|
2478
|
+
if (!controlled) return;
|
|
2479
|
+
const raw = String(value ?? "");
|
|
2480
|
+
if (shown !== raw) {
|
|
2481
|
+
const n = Number(shown);
|
|
2482
|
+
onValueChange?.(shown === "" || Number.isNaN(n) ? null : n, shown);
|
|
2483
|
+
}
|
|
2484
|
+
}, [controlled, shown, value]);
|
|
2485
|
+
const descId = `${fieldId}-desc`;
|
|
2486
|
+
const describedBy = [error || hint ? descId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
2487
|
+
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
2354
2488
|
function handleChange(e) {
|
|
2355
2489
|
const next = clampPrecision(e.target.value, prec);
|
|
2356
2490
|
if (!controlled) setInternal(next);
|
|
2357
2491
|
onChange?.(e);
|
|
2358
|
-
|
|
2492
|
+
const n = Number(next);
|
|
2493
|
+
onValueChange?.(next === "" || Number.isNaN(n) ? null : n, next);
|
|
2359
2494
|
}
|
|
2360
2495
|
function handleBlur(e) {
|
|
2361
2496
|
rest.onBlur?.(e);
|
|
@@ -2372,7 +2507,7 @@ function Currency({
|
|
|
2372
2507
|
label,
|
|
2373
2508
|
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
2374
2509
|
] }) : null,
|
|
2375
|
-
/* @__PURE__ */ jsxs("div", { className: "twc-cur", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, children: [
|
|
2510
|
+
/* @__PURE__ */ 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: [
|
|
2376
2511
|
/* @__PURE__ */ jsx("span", { className: "twc-cur__sym", "aria-hidden": "true", children: sym }),
|
|
2377
2512
|
/* @__PURE__ */ jsx(
|
|
2378
2513
|
"input",
|
|
@@ -2385,16 +2520,16 @@ function Currency({
|
|
|
2385
2520
|
placeholder,
|
|
2386
2521
|
disabled,
|
|
2387
2522
|
required: required || void 0,
|
|
2388
|
-
"aria-invalid": invalid || void 0,
|
|
2389
2523
|
...rest,
|
|
2390
2524
|
onChange: handleChange,
|
|
2391
2525
|
onBlur: handleBlur,
|
|
2526
|
+
"aria-invalid": ariaInvalid,
|
|
2392
2527
|
"aria-describedby": describedBy
|
|
2393
2528
|
}
|
|
2394
2529
|
),
|
|
2395
2530
|
/* @__PURE__ */ jsx("span", { className: "twc-cur__code", children: cur })
|
|
2396
2531
|
] }),
|
|
2397
|
-
error ? /* @__PURE__ */ jsx("span", { id:
|
|
2532
|
+
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
|
|
2398
2533
|
] });
|
|
2399
2534
|
}
|
|
2400
2535
|
var SELECT_CSS = `
|
|
@@ -2469,6 +2604,13 @@ var SELECT_CSS = `
|
|
|
2469
2604
|
.twc-opt__check { flex: none; color: var(--color-primary); display: inline-flex; }
|
|
2470
2605
|
.twc-opt__check svg { width: 16px; height: 16px; }
|
|
2471
2606
|
.twc-pop__empty { padding: 14px 12px; text-align: center; font-size: var(--text-sm); color: var(--color-text-subtle); }
|
|
2607
|
+
.twc-opt[data-disabled="true"] { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
|
|
2608
|
+
.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); }
|
|
2609
|
+
.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; }
|
|
2610
|
+
.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); }
|
|
2611
|
+
.twc-pop__search-clear:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
2612
|
+
.twc-pop__search-clear svg { width: 13px; height: 13px; }
|
|
2613
|
+
.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; }
|
|
2472
2614
|
`;
|
|
2473
2615
|
function toOpt2(o) {
|
|
2474
2616
|
return typeof o === "string" ? { value: o, label: o } : o;
|
|
@@ -2515,6 +2657,10 @@ function Select({
|
|
|
2515
2657
|
placement = "bottom",
|
|
2516
2658
|
portal = true,
|
|
2517
2659
|
minWidth = 0,
|
|
2660
|
+
matchTriggerWidth = true,
|
|
2661
|
+
loading = false,
|
|
2662
|
+
emptyText = "No results found",
|
|
2663
|
+
name,
|
|
2518
2664
|
id,
|
|
2519
2665
|
className = "",
|
|
2520
2666
|
onClick,
|
|
@@ -2522,47 +2668,58 @@ function Select({
|
|
|
2522
2668
|
...rest
|
|
2523
2669
|
}) {
|
|
2524
2670
|
const __twcStyles = useScopedStyles("twc-select-styles", SELECT_CSS);
|
|
2525
|
-
const
|
|
2526
|
-
const
|
|
2527
|
-
const
|
|
2671
|
+
const bufferRef = React25__default.useRef("");
|
|
2672
|
+
const bufferTimerRef = React25__default.useRef(null);
|
|
2673
|
+
const groups = React25__default.useMemo(() => normalizeGroups2(options), [options]);
|
|
2674
|
+
const flat = React25__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
|
|
2675
|
+
const autoId = React25__default.useId();
|
|
2528
2676
|
const fieldId = id || autoId;
|
|
2529
|
-
const [internal, setInternal] =
|
|
2677
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
2530
2678
|
const current = value !== void 0 ? value : internal;
|
|
2531
|
-
const [open, setOpen] =
|
|
2532
|
-
const [render, setRender] =
|
|
2533
|
-
const [active, setActive] =
|
|
2534
|
-
const [coords, setCoords] =
|
|
2535
|
-
const [query, setQuery] =
|
|
2536
|
-
const wrapRef =
|
|
2537
|
-
const triggerRef =
|
|
2538
|
-
const popRef =
|
|
2539
|
-
const listRef =
|
|
2540
|
-
const activeRef =
|
|
2541
|
-
const searchRef =
|
|
2679
|
+
const [open, setOpen] = React25__default.useState(false);
|
|
2680
|
+
const [render, setRender] = React25__default.useState(false);
|
|
2681
|
+
const [active, setActive] = React25__default.useState(0);
|
|
2682
|
+
const [coords, setCoords] = React25__default.useState(null);
|
|
2683
|
+
const [query, setQuery] = React25__default.useState("");
|
|
2684
|
+
const wrapRef = React25__default.useRef(null);
|
|
2685
|
+
const triggerRef = React25__default.useRef(null);
|
|
2686
|
+
const popRef = React25__default.useRef(null);
|
|
2687
|
+
const listRef = React25__default.useRef(null);
|
|
2688
|
+
const activeRef = React25__default.useRef(null);
|
|
2689
|
+
const searchRef = React25__default.useRef(null);
|
|
2542
2690
|
const showSearch = searchable === void 0 ? flat.length > 5 : searchable;
|
|
2543
|
-
const fGroups =
|
|
2691
|
+
const fGroups = React25__default.useMemo(() => {
|
|
2544
2692
|
const q = query.trim().toLowerCase();
|
|
2545
2693
|
if (!q) return groups;
|
|
2546
2694
|
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);
|
|
2547
2695
|
}, [groups, query]);
|
|
2548
|
-
const visible =
|
|
2696
|
+
const visible = React25__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
|
|
2549
2697
|
const selected = flat.find((o) => o.value === current);
|
|
2550
|
-
const
|
|
2698
|
+
const nextEnabled = (from, dir) => {
|
|
2699
|
+
let i = from + dir;
|
|
2700
|
+
while (i >= 0 && i < visible.length) {
|
|
2701
|
+
if (!visible[i]?.disabled) return i;
|
|
2702
|
+
i += dir;
|
|
2703
|
+
}
|
|
2704
|
+
return from;
|
|
2705
|
+
};
|
|
2706
|
+
const place = React25__default.useCallback(() => {
|
|
2551
2707
|
const el = triggerRef.current;
|
|
2552
2708
|
if (!el) return;
|
|
2553
2709
|
const r = el.getBoundingClientRect();
|
|
2554
2710
|
const vh = window.innerHeight;
|
|
2555
2711
|
const below = vh - r.bottom;
|
|
2556
2712
|
const flip = placement === "top" || below < 260 && r.top > below;
|
|
2713
|
+
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) };
|
|
2557
2714
|
setCoords({
|
|
2558
2715
|
left: r.left,
|
|
2559
|
-
|
|
2716
|
+
...widthStyle,
|
|
2560
2717
|
top: flip ? void 0 : Math.round(r.bottom + 6),
|
|
2561
2718
|
bottom: flip ? Math.round(vh - r.top + 6) : void 0,
|
|
2562
2719
|
flip
|
|
2563
2720
|
});
|
|
2564
|
-
}, [placement, minWidth]);
|
|
2565
|
-
|
|
2721
|
+
}, [placement, minWidth, matchTriggerWidth]);
|
|
2722
|
+
React25__default.useEffect(() => {
|
|
2566
2723
|
if (!open || !portal) return;
|
|
2567
2724
|
place();
|
|
2568
2725
|
const onMove = () => place();
|
|
@@ -2573,7 +2730,7 @@ function Select({
|
|
|
2573
2730
|
window.removeEventListener("resize", onMove);
|
|
2574
2731
|
};
|
|
2575
2732
|
}, [open, portal, place]);
|
|
2576
|
-
|
|
2733
|
+
React25__default.useEffect(() => {
|
|
2577
2734
|
if (!open) return;
|
|
2578
2735
|
const idx = flat.findIndex((o) => o.value === current);
|
|
2579
2736
|
setActive(idx >= 0 ? idx : 0);
|
|
@@ -2589,13 +2746,13 @@ function Select({
|
|
|
2589
2746
|
document.addEventListener("mousedown", onDown);
|
|
2590
2747
|
return () => document.removeEventListener("mousedown", onDown);
|
|
2591
2748
|
}, [open]);
|
|
2592
|
-
|
|
2749
|
+
React25__default.useEffect(() => {
|
|
2593
2750
|
setActive(0);
|
|
2594
2751
|
}, [query]);
|
|
2595
|
-
|
|
2752
|
+
React25__default.useEffect(() => {
|
|
2596
2753
|
if (open) ensureVisible2(listRef.current, activeRef.current);
|
|
2597
2754
|
}, [active, open]);
|
|
2598
|
-
|
|
2755
|
+
React25__default.useEffect(() => {
|
|
2599
2756
|
if (open) {
|
|
2600
2757
|
setRender(true);
|
|
2601
2758
|
return;
|
|
@@ -2603,8 +2760,8 @@ function Select({
|
|
|
2603
2760
|
const t = setTimeout(() => setRender(false), 170);
|
|
2604
2761
|
return () => clearTimeout(t);
|
|
2605
2762
|
}, [open]);
|
|
2606
|
-
const prevOpen =
|
|
2607
|
-
|
|
2763
|
+
const prevOpen = React25__default.useRef(false);
|
|
2764
|
+
React25__default.useEffect(() => {
|
|
2608
2765
|
if (prevOpen.current && !open) {
|
|
2609
2766
|
const ae = typeof document !== "undefined" ? document.activeElement : null;
|
|
2610
2767
|
if (popRef.current && ae && popRef.current.contains(ae)) triggerRef.current?.focus();
|
|
@@ -2612,6 +2769,8 @@ function Select({
|
|
|
2612
2769
|
prevOpen.current = open;
|
|
2613
2770
|
}, [open]);
|
|
2614
2771
|
function commit(v) {
|
|
2772
|
+
const o = flat.find((x) => x.value === v);
|
|
2773
|
+
if (o && o.disabled) return;
|
|
2615
2774
|
if (value === void 0) setInternal(v);
|
|
2616
2775
|
onChange?.(v);
|
|
2617
2776
|
setOpen(false);
|
|
@@ -2632,6 +2791,18 @@ function Select({
|
|
|
2632
2791
|
setOpen(true);
|
|
2633
2792
|
return;
|
|
2634
2793
|
}
|
|
2794
|
+
if (!open && !showSearch && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
2795
|
+
e.preventDefault();
|
|
2796
|
+
bufferRef.current += e.key.toLowerCase();
|
|
2797
|
+
clearTimeout(bufferTimerRef.current);
|
|
2798
|
+
bufferTimerRef.current = setTimeout(() => {
|
|
2799
|
+
bufferRef.current = "";
|
|
2800
|
+
}, 500);
|
|
2801
|
+
const b = bufferRef.current;
|
|
2802
|
+
const match = flat.find((o) => !o.disabled && o.label.toLowerCase().startsWith(b)) || flat.find((o) => !o.disabled && o.label.toLowerCase().includes(b));
|
|
2803
|
+
if (match) commit(match.value);
|
|
2804
|
+
return;
|
|
2805
|
+
}
|
|
2635
2806
|
if (!open) return;
|
|
2636
2807
|
if (e.key === "Tab") {
|
|
2637
2808
|
setOpen(false);
|
|
@@ -2640,10 +2811,10 @@ function Select({
|
|
|
2640
2811
|
if (e.key === "Escape") setOpen(false);
|
|
2641
2812
|
else if (e.key === "ArrowDown") {
|
|
2642
2813
|
e.preventDefault();
|
|
2643
|
-
setActive((a) =>
|
|
2814
|
+
setActive((a) => nextEnabled(a, 1));
|
|
2644
2815
|
} else if (e.key === "ArrowUp") {
|
|
2645
2816
|
e.preventDefault();
|
|
2646
|
-
setActive((a) =>
|
|
2817
|
+
setActive((a) => nextEnabled(a, -1));
|
|
2647
2818
|
} else if (e.key === "Enter") {
|
|
2648
2819
|
e.preventDefault();
|
|
2649
2820
|
if (visible[active]) commit(visible[active].value);
|
|
@@ -2675,9 +2846,16 @@ function Select({
|
|
|
2675
2846
|
"aria-controls": listboxId,
|
|
2676
2847
|
"aria-activedescendant": activeId
|
|
2677
2848
|
}
|
|
2678
|
-
)
|
|
2849
|
+
),
|
|
2850
|
+
query ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-pop__search-clear", "aria-label": "Clear search", onClick: () => {
|
|
2851
|
+
setQuery("");
|
|
2852
|
+
searchRef.current?.focus();
|
|
2853
|
+
}, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
|
|
2679
2854
|
] }) : null,
|
|
2680
|
-
/* @__PURE__ */ jsx("div", { className: "twc-pop__list", ref: listRef, children:
|
|
2855
|
+
/* @__PURE__ */ jsx("div", { className: "twc-pop__list", ref: listRef, children: loading ? /* @__PURE__ */ jsxs("div", { className: "twc-pop__loading", role: "status", children: [
|
|
2856
|
+
/* @__PURE__ */ jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
|
|
2857
|
+
"Loading\u2026"
|
|
2858
|
+
] }) : visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React25__default.Fragment, { children: [
|
|
2681
2859
|
g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
2682
2860
|
g.options.map((o) => {
|
|
2683
2861
|
counter += 1;
|
|
@@ -2692,9 +2870,14 @@ function Select({
|
|
|
2692
2870
|
role: "option",
|
|
2693
2871
|
"aria-selected": isSel,
|
|
2694
2872
|
ref: idx === active ? activeRef : null,
|
|
2873
|
+
disabled: o.disabled || void 0,
|
|
2874
|
+
"aria-disabled": o.disabled || void 0,
|
|
2875
|
+
"data-disabled": o.disabled || void 0,
|
|
2695
2876
|
"data-selected": isSel || void 0,
|
|
2696
2877
|
"data-active": idx === active || void 0,
|
|
2697
|
-
onMouseEnter: () =>
|
|
2878
|
+
onMouseEnter: () => {
|
|
2879
|
+
if (!o.disabled) setActive(idx);
|
|
2880
|
+
},
|
|
2698
2881
|
onClick: () => commit(o.value),
|
|
2699
2882
|
children: [
|
|
2700
2883
|
/* @__PURE__ */ jsxs("span", { className: "twc-opt__main", children: [
|
|
@@ -2707,7 +2890,8 @@ function Select({
|
|
|
2707
2890
|
o.value
|
|
2708
2891
|
);
|
|
2709
2892
|
})
|
|
2710
|
-
] }, gi)) })
|
|
2893
|
+
] }, gi)) }),
|
|
2894
|
+
/* @__PURE__ */ 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"}` })
|
|
2711
2895
|
] });
|
|
2712
2896
|
const RD = { createPortal: typeof createPortal === "function" ? createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
|
|
2713
2897
|
const canPortal = portal && RD && RD.createPortal;
|
|
@@ -2724,19 +2908,20 @@ function Select({
|
|
|
2724
2908
|
role: "listbox",
|
|
2725
2909
|
ref: popRef,
|
|
2726
2910
|
"data-state": popState,
|
|
2727
|
-
"data-placement": coords.flip ? "top" :
|
|
2728
|
-
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-tooltip)" },
|
|
2911
|
+
"data-placement": coords.flip ? "top" : "bottom",
|
|
2912
|
+
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)" },
|
|
2729
2913
|
children: popInner
|
|
2730
2914
|
}
|
|
2731
2915
|
),
|
|
2732
2916
|
document.body
|
|
2733
2917
|
);
|
|
2734
2918
|
} else if (!portal) {
|
|
2735
|
-
popEl = /* @__PURE__ */ jsx("div", { className: "twc-pop", id: listboxId, role: "listbox", ref: popRef, "data-state": popState, "data-placement": placement === "top" ? "top" :
|
|
2919
|
+
popEl = /* @__PURE__ */ jsx("div", { className: "twc-pop", id: listboxId, role: "listbox", ref: popRef, "data-state": popState, "data-placement": placement === "top" ? "top" : "bottom", children: popInner });
|
|
2736
2920
|
}
|
|
2737
2921
|
}
|
|
2738
2922
|
return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, ref: wrapRef, children: [
|
|
2739
2923
|
__twcStyles,
|
|
2924
|
+
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: current ?? "" }) : null,
|
|
2740
2925
|
label ? /* @__PURE__ */ jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
2741
2926
|
label,
|
|
2742
2927
|
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
@@ -2807,7 +2992,9 @@ var CURF_CSS = `
|
|
|
2807
2992
|
.twc-cur:focus-within { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
2808
2993
|
.twc-cur[data-invalid="true"] { border-color: var(--color-danger); }
|
|
2809
2994
|
.twc-cur[data-invalid="true"]:focus-within { box-shadow: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 28%, transparent); }
|
|
2810
|
-
.twc-cur[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; }
|
|
2995
|
+
.twc-cur[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
2996
|
+
.twc-cur[data-readonly="true"] { background: var(--color-surface-sunken); }
|
|
2997
|
+
.twc-cur__el:disabled { cursor: not-allowed; }
|
|
2811
2998
|
.twc-cur__sym, .twc-cur__code {
|
|
2812
2999
|
display: inline-flex; align-items: center; padding: 0 var(--space-3);
|
|
2813
3000
|
background: var(--color-surface-sunken); color: var(--color-text-muted);
|
|
@@ -2851,19 +3038,37 @@ function CurrencyField({
|
|
|
2851
3038
|
...rest
|
|
2852
3039
|
}) {
|
|
2853
3040
|
const __twcStyles = useScopedStyles("twc-curf-styles", CURF_CSS);
|
|
2854
|
-
const autoId =
|
|
3041
|
+
const autoId = React25__default.useId();
|
|
2855
3042
|
const fieldId = id || autoId;
|
|
2856
3043
|
const invalid = Boolean(error);
|
|
2857
3044
|
const curControlled = currency !== void 0;
|
|
2858
|
-
const [curInternal, setCurInternal] =
|
|
3045
|
+
const [curInternal, setCurInternal] = React25__default.useState(defaultCurrency);
|
|
2859
3046
|
const cur = curControlled ? currency : curInternal;
|
|
2860
3047
|
const meta = CURRENCIES[cur] || CURRENCIES.USD;
|
|
2861
3048
|
const prec = meta.precision;
|
|
2862
3049
|
const valControlled = value !== void 0;
|
|
2863
|
-
const [valInternal, setValInternal] =
|
|
3050
|
+
const [valInternal, setValInternal] = React25__default.useState(() => clampPrecision(String(defaultValue ?? ""), prec));
|
|
2864
3051
|
const shown = valControlled ? clampPrecision(String(value ?? ""), prec) : valInternal;
|
|
2865
|
-
const
|
|
2866
|
-
const
|
|
3052
|
+
const descId = `${fieldId}-desc`;
|
|
3053
|
+
const describedBy = [error || hint ? descId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
3054
|
+
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
3055
|
+
React25__default.useEffect(() => {
|
|
3056
|
+
if (!valControlled) {
|
|
3057
|
+
const clamped = clampPrecision(valInternal, prec);
|
|
3058
|
+
if (clamped !== valInternal) {
|
|
3059
|
+
setValInternal(clamped);
|
|
3060
|
+
const n = Number(clamped);
|
|
3061
|
+
onValueChange?.(clamped === "" || Number.isNaN(n) ? null : n, clamped, cur);
|
|
3062
|
+
}
|
|
3063
|
+
} else {
|
|
3064
|
+
const raw = String(value ?? "");
|
|
3065
|
+
if (shown !== raw) {
|
|
3066
|
+
const n = Number(shown);
|
|
3067
|
+
onValueChange?.(shown === "" || Number.isNaN(n) ? null : n, shown, cur);
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
}, [prec, cur, shown, value, valControlled, valInternal]);
|
|
3071
|
+
const options = React25__default.useMemo(() => {
|
|
2867
3072
|
if (!currencies) return CURRENCY_OPTIONS;
|
|
2868
3073
|
return currencies.map((c) => typeof c === "string" ? { value: c, label: `${c} \u2014 ${(CURRENCIES[c] || {}).label || c}` } : c);
|
|
2869
3074
|
}, [currencies]);
|
|
@@ -2872,13 +3077,15 @@ function CurrencyField({
|
|
|
2872
3077
|
onCurrencyChange?.(next);
|
|
2873
3078
|
const reclamped = clampPrecision(shown, (CURRENCIES[next] || CURRENCIES.USD).precision);
|
|
2874
3079
|
if (!valControlled) setValInternal(reclamped);
|
|
2875
|
-
|
|
3080
|
+
const rn = Number(reclamped);
|
|
3081
|
+
onValueChange?.(reclamped === "" || Number.isNaN(rn) ? null : rn, reclamped, next);
|
|
2876
3082
|
}
|
|
2877
3083
|
function handleChange(e) {
|
|
2878
3084
|
onChange?.(e);
|
|
2879
3085
|
const next = clampPrecision(e.target.value, prec);
|
|
2880
3086
|
if (!valControlled) setValInternal(next);
|
|
2881
|
-
|
|
3087
|
+
const n = Number(next);
|
|
3088
|
+
onValueChange?.(next === "" || Number.isNaN(n) ? null : n, next, cur);
|
|
2882
3089
|
}
|
|
2883
3090
|
function handleBlur(e) {
|
|
2884
3091
|
rest.onBlur?.(e);
|
|
@@ -2889,13 +3096,14 @@ function CurrencyField({
|
|
|
2889
3096
|
if (!valControlled) setValInternal(fixed);
|
|
2890
3097
|
onValueChange?.(Number(fixed), fixed, cur);
|
|
2891
3098
|
}
|
|
3099
|
+
const curLabel = typeof label === "string" && label ? `${label} currency` : "Currency";
|
|
2892
3100
|
return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, children: [
|
|
2893
3101
|
__twcStyles,
|
|
2894
3102
|
label ? /* @__PURE__ */ jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
2895
3103
|
label,
|
|
2896
3104
|
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
2897
3105
|
] }) : null,
|
|
2898
|
-
/* @__PURE__ */ jsxs("div", { className: "twc-cur", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, children: [
|
|
3106
|
+
/* @__PURE__ */ 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: [
|
|
2899
3107
|
/* @__PURE__ */ jsx("span", { className: "twc-curf__pick", children: /* @__PURE__ */ jsx(
|
|
2900
3108
|
Select,
|
|
2901
3109
|
{
|
|
@@ -2906,7 +3114,7 @@ function CurrencyField({
|
|
|
2906
3114
|
searchable: true,
|
|
2907
3115
|
portal: true,
|
|
2908
3116
|
minWidth: 260,
|
|
2909
|
-
"aria-label":
|
|
3117
|
+
"aria-label": curLabel,
|
|
2910
3118
|
onChange: setCurrency
|
|
2911
3119
|
}
|
|
2912
3120
|
) }),
|
|
@@ -2922,16 +3130,16 @@ function CurrencyField({
|
|
|
2922
3130
|
placeholder,
|
|
2923
3131
|
disabled,
|
|
2924
3132
|
required: required || void 0,
|
|
2925
|
-
"aria-invalid": invalid || void 0,
|
|
2926
3133
|
...rest,
|
|
2927
3134
|
onChange: handleChange,
|
|
2928
3135
|
onBlur: handleBlur,
|
|
3136
|
+
"aria-invalid": ariaInvalid,
|
|
2929
3137
|
"aria-describedby": describedBy
|
|
2930
3138
|
}
|
|
2931
3139
|
),
|
|
2932
3140
|
/* @__PURE__ */ jsx("span", { className: "twc-cur__code", children: meta.code })
|
|
2933
3141
|
] }),
|
|
2934
|
-
error ? /* @__PURE__ */ jsx("span", { id:
|
|
3142
|
+
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
|
|
2935
3143
|
] });
|
|
2936
3144
|
}
|
|
2937
3145
|
var FIELD_CSS2 = `
|
|
@@ -2967,6 +3175,7 @@ var FIELD_CSS2 = `
|
|
|
2967
3175
|
.twc-input[data-invalid="true"] { border-color: var(--color-danger); }
|
|
2968
3176
|
.twc-input[data-invalid="true"]:focus-within { box-shadow: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 28%, transparent); }
|
|
2969
3177
|
.twc-input[data-disabled] { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
3178
|
+
.twc-input[data-readonly] { background: var(--color-surface-sunken); }
|
|
2970
3179
|
.twc-input__el {
|
|
2971
3180
|
flex: 1; min-width: 0; border: none; outline: none; background: transparent;
|
|
2972
3181
|
font-family: inherit; font-size: var(--text-sm); color: var(--color-text); height: 100%;
|
|
@@ -2982,6 +3191,17 @@ var FIELD_CSS2 = `
|
|
|
2982
3191
|
.twc-input__reveal:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
2983
3192
|
.twc-input__reveal svg { width: 17px; height: 17px; }
|
|
2984
3193
|
`;
|
|
3194
|
+
var INPUT_EXTRA_CSS = `
|
|
3195
|
+
.twc-input { overflow: hidden; }
|
|
3196
|
+
.twc-input__addon { align-self: stretch; display: inline-flex; align-items: center; padding-inline: var(--space-3);
|
|
3197
|
+
background: var(--color-surface-sunken); color: var(--color-text-muted); font-size: var(--text-sm);
|
|
3198
|
+
font-weight: var(--font-semibold); white-space: nowrap; flex: none; }
|
|
3199
|
+
.twc-input__addon--start { border-inline-end: var(--border-thin) solid var(--color-border); margin-inline-start: calc(-1 * var(--space-3)); }
|
|
3200
|
+
.twc-input__addon--end { border-inline-start: var(--border-thin) solid var(--color-border); margin-inline-end: calc(-1 * var(--space-3)); }
|
|
3201
|
+
.twc-field__footer { display: flex; align-items: center; gap: var(--space-2); }
|
|
3202
|
+
.twc-field__count { margin-inline-start: auto; font-size: var(--text-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; flex: none; }
|
|
3203
|
+
.twc-field__count[data-danger="true"] { color: var(--color-danger-subtle-fg); }
|
|
3204
|
+
`;
|
|
2985
3205
|
function Input({
|
|
2986
3206
|
label,
|
|
2987
3207
|
hint,
|
|
@@ -2991,6 +3211,9 @@ function Input({
|
|
|
2991
3211
|
tone = "primary",
|
|
2992
3212
|
leftIcon,
|
|
2993
3213
|
rightIcon,
|
|
3214
|
+
leftAddon,
|
|
3215
|
+
rightAddon,
|
|
3216
|
+
showCount = false,
|
|
2994
3217
|
type = "text",
|
|
2995
3218
|
disabled = false,
|
|
2996
3219
|
id,
|
|
@@ -2998,12 +3221,26 @@ function Input({
|
|
|
2998
3221
|
...rest
|
|
2999
3222
|
}) {
|
|
3000
3223
|
const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS2);
|
|
3001
|
-
const
|
|
3224
|
+
const __twcExtra = useScopedStyles("twc-input-extra-styles", INPUT_EXTRA_CSS);
|
|
3225
|
+
const autoId = React25__default.useId();
|
|
3002
3226
|
const fieldId = id || autoId;
|
|
3003
3227
|
const descId = `${fieldId}-desc`;
|
|
3228
|
+
const countId = `${fieldId}-count`;
|
|
3004
3229
|
const invalid = Boolean(error);
|
|
3230
|
+
const countControlled = rest.value !== void 0;
|
|
3231
|
+
const [len2, setLen] = React25__default.useState(() => String(rest.defaultValue ?? "").length);
|
|
3232
|
+
const count = countControlled ? String(rest.value ?? "").length : len2;
|
|
3233
|
+
const max = rest.maxLength;
|
|
3234
|
+
const showCounter = showCount && max != null;
|
|
3235
|
+
const near = showCounter && count >= Math.floor(max * 0.9);
|
|
3236
|
+
const handleChange = (e) => {
|
|
3237
|
+
rest.onChange?.(e);
|
|
3238
|
+
if (showCount && !countControlled) setLen(e.target.value.length);
|
|
3239
|
+
};
|
|
3240
|
+
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
3241
|
+
const describedBy = [error || hint ? descId : null, showCounter ? countId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
3005
3242
|
const isPassword = type === "password";
|
|
3006
|
-
const [revealed, setRevealed] =
|
|
3243
|
+
const [revealed, setRevealed] = React25__default.useState(false);
|
|
3007
3244
|
const effectiveType = isPassword && revealed ? "text" : type;
|
|
3008
3245
|
const suffix = rightIcon ? /* @__PURE__ */ jsx("span", { className: "twc-input__affix", children: rightIcon }) : isPassword ? /* @__PURE__ */ jsx(
|
|
3009
3246
|
"button",
|
|
@@ -3028,11 +3265,13 @@ function Input({
|
|
|
3028
3265
|
) : null;
|
|
3029
3266
|
return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, children: [
|
|
3030
3267
|
__twcStyles,
|
|
3268
|
+
__twcExtra,
|
|
3031
3269
|
label ? /* @__PURE__ */ jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
3032
3270
|
label,
|
|
3033
3271
|
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
3034
3272
|
] }) : null,
|
|
3035
|
-
/* @__PURE__ */ jsxs("div", { className: "twc-input", "data-size": size, "data-tone": tone, "data-invalid": invalid || void 0, "data-disabled": disabled || void 0, children: [
|
|
3273
|
+
/* @__PURE__ */ 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: [
|
|
3274
|
+
leftAddon != null ? /* @__PURE__ */ jsx("span", { className: "twc-input__addon twc-input__addon--start", children: leftAddon }) : null,
|
|
3036
3275
|
leftIcon ? /* @__PURE__ */ jsx("span", { className: "twc-input__affix", children: leftIcon }) : null,
|
|
3037
3276
|
/* @__PURE__ */ jsx(
|
|
3038
3277
|
"input",
|
|
@@ -3043,14 +3282,23 @@ function Input({
|
|
|
3043
3282
|
disabled,
|
|
3044
3283
|
required: required || void 0,
|
|
3045
3284
|
"aria-required": required || void 0,
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3285
|
+
...rest,
|
|
3286
|
+
onChange: handleChange,
|
|
3287
|
+
"aria-invalid": ariaInvalid,
|
|
3288
|
+
"aria-describedby": describedBy
|
|
3049
3289
|
}
|
|
3050
3290
|
),
|
|
3051
|
-
suffix
|
|
3291
|
+
suffix,
|
|
3292
|
+
rightAddon != null ? /* @__PURE__ */ jsx("span", { className: "twc-input__addon twc-input__addon--end", children: rightAddon }) : null
|
|
3052
3293
|
] }),
|
|
3053
|
-
error
|
|
3294
|
+
error || hint || showCounter ? /* @__PURE__ */ jsxs("div", { className: "twc-field__footer", children: [
|
|
3295
|
+
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null,
|
|
3296
|
+
showCounter ? /* @__PURE__ */ jsxs("span", { id: countId, className: "twc-field__count", "data-danger": near || void 0, "aria-live": "polite", children: [
|
|
3297
|
+
count,
|
|
3298
|
+
" / ",
|
|
3299
|
+
max
|
|
3300
|
+
] }) : null
|
|
3301
|
+
] }) : null
|
|
3054
3302
|
] });
|
|
3055
3303
|
}
|
|
3056
3304
|
var MULTI_CSS = `
|
|
@@ -3128,6 +3376,10 @@ var MULTI_CSS = `
|
|
|
3128
3376
|
.twc-opt__label { line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3129
3377
|
.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; }
|
|
3130
3378
|
.twc-pop__empty { padding: 14px 12px; text-align: center; font-size: var(--text-sm); color: var(--color-text-subtle); }
|
|
3379
|
+
.twc-opt[data-disabled="true"] { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
|
|
3380
|
+
.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); }
|
|
3381
|
+
.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; }
|
|
3382
|
+
.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; }
|
|
3131
3383
|
`;
|
|
3132
3384
|
function toOpt3(o) {
|
|
3133
3385
|
return typeof o === "string" ? { value: o, label: o } : o;
|
|
@@ -3177,6 +3429,11 @@ function MultiSelect({
|
|
|
3177
3429
|
placement = "bottom",
|
|
3178
3430
|
portal = true,
|
|
3179
3431
|
minWidth = 0,
|
|
3432
|
+
loading = false,
|
|
3433
|
+
emptyText = "No results found",
|
|
3434
|
+
name,
|
|
3435
|
+
max,
|
|
3436
|
+
maxTagCount,
|
|
3180
3437
|
id,
|
|
3181
3438
|
className = "",
|
|
3182
3439
|
onFocus,
|
|
@@ -3184,28 +3441,38 @@ function MultiSelect({
|
|
|
3184
3441
|
...rest
|
|
3185
3442
|
}) {
|
|
3186
3443
|
const __twcStyles = useScopedStyles("twc-ms-styles", MULTI_CSS);
|
|
3187
|
-
const groups =
|
|
3188
|
-
const flat =
|
|
3189
|
-
const autoId =
|
|
3444
|
+
const groups = React25__default.useMemo(() => normalizeGroups3(options), [options]);
|
|
3445
|
+
const flat = React25__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
|
|
3446
|
+
const autoId = React25__default.useId();
|
|
3190
3447
|
const fieldId = id || autoId;
|
|
3191
|
-
const [internal, setInternal] =
|
|
3448
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
3192
3449
|
const selected = value !== void 0 ? value : internal;
|
|
3193
|
-
const [open, setOpen] =
|
|
3194
|
-
const [query, setQuery] =
|
|
3195
|
-
const [active, setActive] =
|
|
3196
|
-
const [coords, setCoords] =
|
|
3197
|
-
const wrapRef =
|
|
3198
|
-
const controlRef =
|
|
3199
|
-
const inputRef =
|
|
3200
|
-
const popRef =
|
|
3201
|
-
const listRef =
|
|
3202
|
-
const activeRef =
|
|
3203
|
-
const fGroups =
|
|
3450
|
+
const [open, setOpen] = React25__default.useState(false);
|
|
3451
|
+
const [query, setQuery] = React25__default.useState("");
|
|
3452
|
+
const [active, setActive] = React25__default.useState(0);
|
|
3453
|
+
const [coords, setCoords] = React25__default.useState(null);
|
|
3454
|
+
const wrapRef = React25__default.useRef(null);
|
|
3455
|
+
const controlRef = React25__default.useRef(null);
|
|
3456
|
+
const inputRef = React25__default.useRef(null);
|
|
3457
|
+
const popRef = React25__default.useRef(null);
|
|
3458
|
+
const listRef = React25__default.useRef(null);
|
|
3459
|
+
const activeRef = React25__default.useRef(null);
|
|
3460
|
+
const fGroups = React25__default.useMemo(
|
|
3204
3461
|
() => groups.map((g) => ({ group: g.group, options: g.options.filter((o) => matches2(o, query.trim())) })).filter((g) => g.options.length),
|
|
3205
3462
|
[groups, query]
|
|
3206
3463
|
);
|
|
3207
|
-
const visible =
|
|
3208
|
-
const
|
|
3464
|
+
const visible = React25__default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
|
|
3465
|
+
const capReached = max != null && (value !== void 0 ? value : internal).length >= max;
|
|
3466
|
+
const isOptDisabled = (o) => o.disabled || capReached && !(value !== void 0 ? value : internal).includes(o.value);
|
|
3467
|
+
const nextEnabled = (from, dir) => {
|
|
3468
|
+
let i = from + dir;
|
|
3469
|
+
while (i >= 0 && i < visible.length) {
|
|
3470
|
+
if (!isOptDisabled(visible[i])) return i;
|
|
3471
|
+
i += dir;
|
|
3472
|
+
}
|
|
3473
|
+
return from;
|
|
3474
|
+
};
|
|
3475
|
+
const place = React25__default.useCallback(() => {
|
|
3209
3476
|
const el = controlRef.current;
|
|
3210
3477
|
if (!el) return;
|
|
3211
3478
|
const r = el.getBoundingClientRect();
|
|
@@ -3220,7 +3487,7 @@ function MultiSelect({
|
|
|
3220
3487
|
flip
|
|
3221
3488
|
});
|
|
3222
3489
|
}, [placement, minWidth]);
|
|
3223
|
-
|
|
3490
|
+
React25__default.useEffect(() => {
|
|
3224
3491
|
if (!open || !portal) return;
|
|
3225
3492
|
place();
|
|
3226
3493
|
const onMove = () => place();
|
|
@@ -3231,7 +3498,7 @@ function MultiSelect({
|
|
|
3231
3498
|
window.removeEventListener("resize", onMove);
|
|
3232
3499
|
};
|
|
3233
3500
|
}, [open, portal, place]);
|
|
3234
|
-
|
|
3501
|
+
React25__default.useEffect(() => {
|
|
3235
3502
|
if (!open) return;
|
|
3236
3503
|
const onDown = (e) => {
|
|
3237
3504
|
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
@@ -3242,10 +3509,10 @@ function MultiSelect({
|
|
|
3242
3509
|
document.addEventListener("mousedown", onDown);
|
|
3243
3510
|
return () => document.removeEventListener("mousedown", onDown);
|
|
3244
3511
|
}, [open]);
|
|
3245
|
-
|
|
3512
|
+
React25__default.useEffect(() => {
|
|
3246
3513
|
setActive(0);
|
|
3247
3514
|
}, [query]);
|
|
3248
|
-
|
|
3515
|
+
React25__default.useEffect(() => {
|
|
3249
3516
|
if (open) ensureVisible3(listRef.current, activeRef.current);
|
|
3250
3517
|
}, [active, open]);
|
|
3251
3518
|
function commit(next) {
|
|
@@ -3253,7 +3520,10 @@ function MultiSelect({
|
|
|
3253
3520
|
onChange?.(next);
|
|
3254
3521
|
}
|
|
3255
3522
|
function toggle(v) {
|
|
3256
|
-
|
|
3523
|
+
const o = flat.find((x) => x.value === v);
|
|
3524
|
+
const isSel = selected.includes(v);
|
|
3525
|
+
if (!isSel && o && isOptDisabled(o)) return;
|
|
3526
|
+
commit(isSel ? selected.filter((x) => x !== v) : [...selected, v]);
|
|
3257
3527
|
setQuery("");
|
|
3258
3528
|
inputRef.current?.focus();
|
|
3259
3529
|
}
|
|
@@ -3261,10 +3531,10 @@ function MultiSelect({
|
|
|
3261
3531
|
if (e.key === "ArrowDown") {
|
|
3262
3532
|
e.preventDefault();
|
|
3263
3533
|
if (!open) setOpen(true);
|
|
3264
|
-
else setActive((a) =>
|
|
3534
|
+
else setActive((a) => nextEnabled(a, 1));
|
|
3265
3535
|
} else if (e.key === "ArrowUp") {
|
|
3266
3536
|
e.preventDefault();
|
|
3267
|
-
setActive((a) =>
|
|
3537
|
+
setActive((a) => nextEnabled(a, -1));
|
|
3268
3538
|
} else if (e.key === "Enter") {
|
|
3269
3539
|
e.preventDefault();
|
|
3270
3540
|
if (open && visible[active]) toggle(visible[active].value);
|
|
@@ -3282,12 +3552,16 @@ function MultiSelect({
|
|
|
3282
3552
|
const descId = `${fieldId}-desc`;
|
|
3283
3553
|
const describedBy = error || hint ? descId : void 0;
|
|
3284
3554
|
let counter = -1;
|
|
3285
|
-
const popInner = /* @__PURE__ */ jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children:
|
|
3555
|
+
const popInner = /* @__PURE__ */ jsx("div", { className: "twc-pop__list", id: listboxId, ref: listRef, role: "listbox", "aria-multiselectable": "true", children: loading ? /* @__PURE__ */ jsxs("div", { className: "twc-pop__loading", role: "status", children: [
|
|
3556
|
+
/* @__PURE__ */ jsx("span", { className: "twc-pop__spinner", "aria-hidden": "true" }),
|
|
3557
|
+
"Loading\u2026"
|
|
3558
|
+
] }) : visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: emptyText }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React25__default.Fragment, { children: [
|
|
3286
3559
|
g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
3287
3560
|
g.options.map((o) => {
|
|
3288
3561
|
counter += 1;
|
|
3289
3562
|
const idx = counter;
|
|
3290
3563
|
const isSel = selected.includes(o.value);
|
|
3564
|
+
const optDisabled = isOptDisabled(o);
|
|
3291
3565
|
return /* @__PURE__ */ jsxs(
|
|
3292
3566
|
"button",
|
|
3293
3567
|
{
|
|
@@ -3297,9 +3571,14 @@ function MultiSelect({
|
|
|
3297
3571
|
role: "option",
|
|
3298
3572
|
"aria-selected": isSel,
|
|
3299
3573
|
ref: idx === active ? activeRef : null,
|
|
3574
|
+
disabled: optDisabled || void 0,
|
|
3575
|
+
"aria-disabled": optDisabled || void 0,
|
|
3576
|
+
"data-disabled": optDisabled || void 0,
|
|
3300
3577
|
"data-selected": isSel || void 0,
|
|
3301
3578
|
"data-active": idx === active || void 0,
|
|
3302
|
-
onMouseEnter: () =>
|
|
3579
|
+
onMouseEnter: () => {
|
|
3580
|
+
if (!optDisabled) setActive(idx);
|
|
3581
|
+
},
|
|
3303
3582
|
onMouseDown: (e) => e.preventDefault(),
|
|
3304
3583
|
onClick: () => toggle(o.value),
|
|
3305
3584
|
children: [
|
|
@@ -3325,7 +3604,7 @@ function MultiSelect({
|
|
|
3325
3604
|
{
|
|
3326
3605
|
className: "twc-pop twc-pop--portal",
|
|
3327
3606
|
ref: popRef,
|
|
3328
|
-
"data-placement": coords.flip ? "top" :
|
|
3607
|
+
"data-placement": coords.flip ? "top" : "bottom",
|
|
3329
3608
|
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-tooltip)" },
|
|
3330
3609
|
children: popInner
|
|
3331
3610
|
}
|
|
@@ -3338,6 +3617,7 @@ function MultiSelect({
|
|
|
3338
3617
|
}
|
|
3339
3618
|
return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, ref: wrapRef, children: [
|
|
3340
3619
|
__twcStyles,
|
|
3620
|
+
name ? selected.map((v, i) => /* @__PURE__ */ jsx("input", { type: "hidden", name, value: v }, i)) : null,
|
|
3341
3621
|
label ? /* @__PURE__ */ jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
3342
3622
|
label,
|
|
3343
3623
|
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
@@ -3360,13 +3640,18 @@ function MultiSelect({
|
|
|
3360
3640
|
}
|
|
3361
3641
|
},
|
|
3362
3642
|
children: [
|
|
3363
|
-
selectedOpts.map((o) => /* @__PURE__ */ jsxs("span", { className: "twc-ms__chip", children: [
|
|
3643
|
+
(maxTagCount != null ? selectedOpts.slice(0, maxTagCount) : selectedOpts).map((o) => /* @__PURE__ */ jsxs("span", { className: "twc-ms__chip", children: [
|
|
3364
3644
|
o.label,
|
|
3365
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "twc-ms__chip-x", "aria-label": `Remove ${o.label}`, onClick: (e) => {
|
|
3645
|
+
/* @__PURE__ */ jsx("button", { type: "button", tabIndex: -1, className: "twc-ms__chip-x", "aria-label": `Remove ${o.label}`, onClick: (e) => {
|
|
3366
3646
|
e.stopPropagation();
|
|
3367
3647
|
toggle(o.value);
|
|
3368
3648
|
}, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) })
|
|
3369
3649
|
] }, o.value)),
|
|
3650
|
+
maxTagCount != null && selectedOpts.length > maxTagCount ? /* @__PURE__ */ jsxs("span", { className: "twc-ms__more", title: selectedOpts.slice(maxTagCount).map((o) => o.label).join(", "), children: [
|
|
3651
|
+
"+",
|
|
3652
|
+
selectedOpts.length - maxTagCount,
|
|
3653
|
+
" more"
|
|
3654
|
+
] }) : null,
|
|
3370
3655
|
/* @__PURE__ */ jsx(
|
|
3371
3656
|
"input",
|
|
3372
3657
|
{
|
|
@@ -3398,7 +3683,7 @@ function MultiSelect({
|
|
|
3398
3683
|
...rest
|
|
3399
3684
|
}
|
|
3400
3685
|
),
|
|
3401
|
-
clearable && selected.length > 0 && !disabled ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-ms__clear", "aria-label": "Clear all", onClick: (e) => {
|
|
3686
|
+
clearable && selected.length > 0 && !disabled ? /* @__PURE__ */ jsx("button", { type: "button", tabIndex: -1, className: "twc-ms__clear", "aria-label": "Clear all", onClick: (e) => {
|
|
3402
3687
|
e.stopPropagation();
|
|
3403
3688
|
commit([]);
|
|
3404
3689
|
setQuery("");
|
|
@@ -3426,15 +3711,6 @@ function MultiSelect({
|
|
|
3426
3711
|
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
|
|
3427
3712
|
] });
|
|
3428
3713
|
}
|
|
3429
|
-
|
|
3430
|
-
// components/_warn.js
|
|
3431
|
-
var seen = /* @__PURE__ */ new Set();
|
|
3432
|
-
function warnOnce(key, message) {
|
|
3433
|
-
if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production") return;
|
|
3434
|
-
if (seen.has(key)) return;
|
|
3435
|
-
seen.add(key);
|
|
3436
|
-
if (typeof console !== "undefined" && console.warn) console.warn(message);
|
|
3437
|
-
}
|
|
3438
3714
|
var PAGINATION_CSS = `
|
|
3439
3715
|
.twc-pagination { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-sans); }
|
|
3440
3716
|
.twc-page {
|
|
@@ -3500,6 +3776,7 @@ function Pagination({
|
|
|
3500
3776
|
showJumper,
|
|
3501
3777
|
showPageJumper,
|
|
3502
3778
|
jumperLabel = "Go to",
|
|
3779
|
+
getPageLabel,
|
|
3503
3780
|
className = "",
|
|
3504
3781
|
...rest
|
|
3505
3782
|
}) {
|
|
@@ -3508,7 +3785,7 @@ function Pagination({
|
|
|
3508
3785
|
}
|
|
3509
3786
|
const jumperEnabled = showPageJumper ?? showJumper;
|
|
3510
3787
|
const __twcStyles = useScopedStyles("twc-pagination-styles", PAGINATION_CSS);
|
|
3511
|
-
const [internal, setInternal] =
|
|
3788
|
+
const [internal, setInternal] = React25__default.useState(defaultPage);
|
|
3512
3789
|
const page = pageProp !== void 0 ? pageProp : internal;
|
|
3513
3790
|
const pages = buildPages(page, total, siblings, boundaries);
|
|
3514
3791
|
const go = (p) => {
|
|
@@ -3516,7 +3793,7 @@ function Pagination({
|
|
|
3516
3793
|
if (pageProp === void 0) setInternal(p);
|
|
3517
3794
|
onChange?.(p);
|
|
3518
3795
|
};
|
|
3519
|
-
const [jump, setJump] =
|
|
3796
|
+
const [jump, setJump] = React25__default.useState("");
|
|
3520
3797
|
const submitJump = () => {
|
|
3521
3798
|
const n = parseInt(jump, 10);
|
|
3522
3799
|
if (!Number.isNaN(n)) go(Math.min(Math.max(n, 1), total));
|
|
@@ -3533,6 +3810,7 @@ function Pagination({
|
|
|
3533
3810
|
className: "twc-page",
|
|
3534
3811
|
"data-size": size,
|
|
3535
3812
|
"data-active": p === page || void 0,
|
|
3813
|
+
"aria-label": getPageLabel ? getPageLabel(p) : `Page ${p}`,
|
|
3536
3814
|
"aria-current": p === page ? "page" : void 0,
|
|
3537
3815
|
onClick: () => go(p),
|
|
3538
3816
|
children: p
|
|
@@ -3565,6 +3843,154 @@ function Pagination({
|
|
|
3565
3843
|
] }) : null
|
|
3566
3844
|
] });
|
|
3567
3845
|
}
|
|
3846
|
+
var TOOLTIP_CSS = `
|
|
3847
|
+
.twc-tooltip-wrap { display: inline-flex; }
|
|
3848
|
+
.twc-tooltip {
|
|
3849
|
+
position: fixed; z-index: var(--z-tooltip);
|
|
3850
|
+
padding: 6px 10px; border-radius: var(--radius-md);
|
|
3851
|
+
background: var(--color-text); color: var(--color-surface);
|
|
3852
|
+
font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--font-medium);
|
|
3853
|
+
line-height: 1.3; white-space: normal; max-width: var(--_tw-maxw, 260px); box-shadow: var(--shadow-md);
|
|
3854
|
+
opacity: 0; transform: scale(0.9); transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-spring);
|
|
3855
|
+
}
|
|
3856
|
+
.twc-tooltip[data-show="true"] { pointer-events: auto; }
|
|
3857
|
+
.twc-tooltip[data-show="true"] { opacity: 1; transform: scale(1); }
|
|
3858
|
+
.twc-tooltip[data-place="top"] { transform-origin: bottom center; translate: -50% 0; }
|
|
3859
|
+
.twc-tooltip[data-place="bottom"] { transform-origin: top center; translate: -50% 0; }
|
|
3860
|
+
.twc-tooltip[data-place="left"] { transform-origin: right center; translate: 0 -50%; }
|
|
3861
|
+
.twc-tooltip[data-place="right"] { transform-origin: left center; translate: 0 -50%; }
|
|
3862
|
+
.twc-tooltip[data-show="true"][data-place="top"], .twc-tooltip[data-show="true"][data-place="bottom"] { transform: scale(1); }
|
|
3863
|
+
.twc-tooltip__arrow { position: absolute; width: 7px; height: 7px; background: var(--color-text); transform: rotate(45deg); }
|
|
3864
|
+
.twc-tooltip[data-place="top"] .twc-tooltip__arrow { bottom: -3px; left: 50%; margin-left: -3.5px; }
|
|
3865
|
+
.twc-tooltip[data-place="bottom"] .twc-tooltip__arrow { top: -3px; left: 50%; margin-left: -3.5px; }
|
|
3866
|
+
.twc-tooltip[data-place="left"] .twc-tooltip__arrow { right: -3px; top: 50%; margin-top: -3.5px; }
|
|
3867
|
+
.twc-tooltip[data-place="right"] .twc-tooltip__arrow { left: -3px; top: 50%; margin-top: -3.5px; }
|
|
3868
|
+
@media (prefers-reduced-motion: reduce) { .twc-tooltip { transition: opacity var(--duration-fast) linear; transform: none; } }
|
|
3869
|
+
`;
|
|
3870
|
+
function Tooltip({
|
|
3871
|
+
children,
|
|
3872
|
+
label,
|
|
3873
|
+
placement = "top",
|
|
3874
|
+
delay = 120,
|
|
3875
|
+
className = "",
|
|
3876
|
+
...rest
|
|
3877
|
+
}) {
|
|
3878
|
+
const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
|
|
3879
|
+
const id = React25__default.useId();
|
|
3880
|
+
const [show, setShow] = React25__default.useState(false);
|
|
3881
|
+
const [coords, setCoords] = React25__default.useState(null);
|
|
3882
|
+
const timer = React25__default.useRef(null);
|
|
3883
|
+
const closeTimer = React25__default.useRef(null);
|
|
3884
|
+
const wrapRef = React25__default.useRef(null);
|
|
3885
|
+
const tipRef = React25__default.useRef(null);
|
|
3886
|
+
const open = () => {
|
|
3887
|
+
clearTimeout(closeTimer.current);
|
|
3888
|
+
clearTimeout(timer.current);
|
|
3889
|
+
timer.current = setTimeout(() => setShow(true), delay);
|
|
3890
|
+
};
|
|
3891
|
+
const close = () => {
|
|
3892
|
+
clearTimeout(timer.current);
|
|
3893
|
+
clearTimeout(closeTimer.current);
|
|
3894
|
+
closeTimer.current = setTimeout(() => setShow(false), 120);
|
|
3895
|
+
};
|
|
3896
|
+
const cancelClose = () => {
|
|
3897
|
+
clearTimeout(closeTimer.current);
|
|
3898
|
+
};
|
|
3899
|
+
React25__default.useEffect(() => () => {
|
|
3900
|
+
clearTimeout(timer.current);
|
|
3901
|
+
clearTimeout(closeTimer.current);
|
|
3902
|
+
}, []);
|
|
3903
|
+
const place = React25__default.useCallback(() => {
|
|
3904
|
+
const el = wrapRef.current;
|
|
3905
|
+
if (!el) return;
|
|
3906
|
+
const r = el.getBoundingClientRect();
|
|
3907
|
+
const cx = Math.round(r.left + r.width / 2), cy = Math.round(r.top + r.height / 2);
|
|
3908
|
+
const vw = window.innerWidth, vh = window.innerHeight, gap = 8, margin = 8;
|
|
3909
|
+
const tip = tipRef.current;
|
|
3910
|
+
const tw = tip ? tip.offsetWidth : 0, th = tip ? tip.offsetHeight : 0;
|
|
3911
|
+
const clampX = (c) => tw ? Math.round(Math.min(Math.max(c, margin + tw / 2), vw - margin - tw / 2)) : c;
|
|
3912
|
+
const clampY = (c) => th ? Math.round(Math.min(Math.max(c, margin + th / 2), vh - margin - th / 2)) : c;
|
|
3913
|
+
const spaceAbove = r.top - gap - margin, spaceBelow = vh - r.bottom - gap - margin;
|
|
3914
|
+
const spaceLeft = r.left - gap - margin, spaceRight = vw - r.right - gap - margin;
|
|
3915
|
+
let side = placement;
|
|
3916
|
+
if (placement === "top" && spaceAbove < th && spaceBelow > spaceAbove) side = "bottom";
|
|
3917
|
+
else if (placement === "bottom" && spaceBelow < th && spaceAbove > spaceBelow) side = "top";
|
|
3918
|
+
else if (placement === "left" && spaceLeft < tw && spaceRight > spaceLeft) side = "right";
|
|
3919
|
+
else if (placement === "right" && spaceRight < tw && spaceLeft > spaceRight) side = "left";
|
|
3920
|
+
const base = { left: "auto", right: "auto", top: "auto", bottom: "auto", place: side };
|
|
3921
|
+
if (side === "bottom") setCoords({ ...base, left: clampX(cx), top: Math.round(r.bottom + gap) });
|
|
3922
|
+
else if (side === "left") setCoords({ ...base, top: clampY(cy), right: Math.round(vw - r.left + gap) });
|
|
3923
|
+
else if (side === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
|
|
3924
|
+
else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
|
|
3925
|
+
}, [placement]);
|
|
3926
|
+
React25__default.useEffect(() => {
|
|
3927
|
+
place();
|
|
3928
|
+
}, [place]);
|
|
3929
|
+
React25__default.useEffect(() => {
|
|
3930
|
+
if (!show) return void 0;
|
|
3931
|
+
place();
|
|
3932
|
+
const onMove = () => place();
|
|
3933
|
+
window.addEventListener("scroll", onMove, true);
|
|
3934
|
+
window.addEventListener("resize", onMove);
|
|
3935
|
+
return () => {
|
|
3936
|
+
window.removeEventListener("scroll", onMove, true);
|
|
3937
|
+
window.removeEventListener("resize", onMove);
|
|
3938
|
+
};
|
|
3939
|
+
}, [show, place]);
|
|
3940
|
+
React25__default.useEffect(() => {
|
|
3941
|
+
if (!show) return;
|
|
3942
|
+
const onKeyDown = (e) => {
|
|
3943
|
+
if (e.key === "Escape") {
|
|
3944
|
+
clearTimeout(timer.current);
|
|
3945
|
+
setShow(false);
|
|
3946
|
+
}
|
|
3947
|
+
};
|
|
3948
|
+
document.addEventListener("keydown", onKeyDown);
|
|
3949
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
3950
|
+
}, [show]);
|
|
3951
|
+
const describedBy = show ? id : void 0;
|
|
3952
|
+
const trigger = React25__default.isValidElement(children) && children.type !== React25__default.Fragment ? React25__default.cloneElement(children, {
|
|
3953
|
+
"aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
|
|
3954
|
+
}) : /* @__PURE__ */ jsx("span", { "aria-describedby": describedBy, children });
|
|
3955
|
+
return /* @__PURE__ */ jsxs(
|
|
3956
|
+
"span",
|
|
3957
|
+
{
|
|
3958
|
+
ref: wrapRef,
|
|
3959
|
+
className: `twc-tooltip-wrap ${className}`,
|
|
3960
|
+
onMouseEnter: open,
|
|
3961
|
+
onMouseLeave: close,
|
|
3962
|
+
onFocus: open,
|
|
3963
|
+
onBlur: close,
|
|
3964
|
+
...rest,
|
|
3965
|
+
children: [
|
|
3966
|
+
__twcStyles,
|
|
3967
|
+
trigger,
|
|
3968
|
+
coords ? createPortal(
|
|
3969
|
+
/* @__PURE__ */ jsxs(
|
|
3970
|
+
"span",
|
|
3971
|
+
{
|
|
3972
|
+
ref: tipRef,
|
|
3973
|
+
id,
|
|
3974
|
+
className: "twc-tooltip",
|
|
3975
|
+
"data-place": coords.place || placement,
|
|
3976
|
+
"data-show": show || void 0,
|
|
3977
|
+
role: "tooltip",
|
|
3978
|
+
"aria-hidden": show ? void 0 : "true",
|
|
3979
|
+
onMouseEnter: cancelClose,
|
|
3980
|
+
onMouseLeave: close,
|
|
3981
|
+
style: { position: "fixed", left: coords.left, right: coords.right, top: coords.top, bottom: coords.bottom },
|
|
3982
|
+
children: [
|
|
3983
|
+
label,
|
|
3984
|
+
/* @__PURE__ */ jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
|
|
3985
|
+
]
|
|
3986
|
+
}
|
|
3987
|
+
),
|
|
3988
|
+
document.body
|
|
3989
|
+
) : null
|
|
3990
|
+
]
|
|
3991
|
+
}
|
|
3992
|
+
);
|
|
3993
|
+
}
|
|
3568
3994
|
var DT_CSS = `
|
|
3569
3995
|
.twc-dt { display: flex; flex-direction: column; font-family: var(--font-sans); color: var(--color-text);
|
|
3570
3996
|
border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg);
|
|
@@ -4127,9 +4553,9 @@ function runDatatableQuery(rows, query, options = {}) {
|
|
|
4127
4553
|
return { rows: page, total, filtered: out };
|
|
4128
4554
|
}
|
|
4129
4555
|
function useFloating() {
|
|
4130
|
-
const [pos, setPos] =
|
|
4131
|
-
const cfg =
|
|
4132
|
-
const place =
|
|
4556
|
+
const [pos, setPos] = React25__default.useState(null);
|
|
4557
|
+
const cfg = React25__default.useRef(null);
|
|
4558
|
+
const place = React25__default.useCallback(() => {
|
|
4133
4559
|
const c = cfg.current;
|
|
4134
4560
|
if (!c || !c.el || !c.el.isConnected) return null;
|
|
4135
4561
|
const r = c.el.getBoundingClientRect();
|
|
@@ -4140,17 +4566,17 @@ function useFloating() {
|
|
|
4140
4566
|
const top = r.bottom + 6;
|
|
4141
4567
|
return { top, left, width: c.width, anchorX: r.left + r.width / 2, maxHeight: Math.max(180, vh - top - M) };
|
|
4142
4568
|
}, []);
|
|
4143
|
-
const open =
|
|
4569
|
+
const open = React25__default.useCallback((el, align = "left", width = 220) => {
|
|
4144
4570
|
cfg.current = { el, align, width };
|
|
4145
4571
|
const p = place();
|
|
4146
4572
|
if (p) setPos(p);
|
|
4147
4573
|
}, [place]);
|
|
4148
|
-
const close =
|
|
4574
|
+
const close = React25__default.useCallback(() => {
|
|
4149
4575
|
cfg.current = null;
|
|
4150
4576
|
setPos(null);
|
|
4151
4577
|
}, []);
|
|
4152
4578
|
const isOpen = pos != null;
|
|
4153
|
-
|
|
4579
|
+
React25__default.useEffect(() => {
|
|
4154
4580
|
if (!isOpen) return void 0;
|
|
4155
4581
|
const update = () => {
|
|
4156
4582
|
const p = place();
|
|
@@ -4174,9 +4600,9 @@ function Caret({ pos }) {
|
|
|
4174
4600
|
return /* @__PURE__ */ jsx("span", { className: "twc-dt__caret", style: { left } });
|
|
4175
4601
|
}
|
|
4176
4602
|
function EditCell({ col, value, options, onChange, onCommit, onCommitValue, onCancel, onKeyDown }) {
|
|
4177
|
-
const ref =
|
|
4603
|
+
const ref = React25__default.useRef(null);
|
|
4178
4604
|
const isSelect = col.editType === "select" || options && col.editType !== "text";
|
|
4179
|
-
|
|
4605
|
+
React25__default.useEffect(() => {
|
|
4180
4606
|
if (isSelect) {
|
|
4181
4607
|
const t = setTimeout(() => ref.current?.querySelector(".twc-sel__trigger")?.click(), 0);
|
|
4182
4608
|
return () => clearTimeout(t);
|
|
@@ -4352,6 +4778,8 @@ function Datatable({
|
|
|
4352
4778
|
aggregationValues = null,
|
|
4353
4779
|
disableColumnReorder = false,
|
|
4354
4780
|
disableColumnResize = false,
|
|
4781
|
+
emptyMessage,
|
|
4782
|
+
renderEmpty,
|
|
4355
4783
|
editMode = false,
|
|
4356
4784
|
onRowUpdate,
|
|
4357
4785
|
onRowsChange,
|
|
@@ -4379,7 +4807,7 @@ function Datatable({
|
|
|
4379
4807
|
...rest
|
|
4380
4808
|
}) {
|
|
4381
4809
|
const __twcStyles = useScopedStyles("twc-dt-styles", DT_CSS);
|
|
4382
|
-
const cols =
|
|
4810
|
+
const cols = React25__default.useMemo(() => {
|
|
4383
4811
|
const out = columns.map((c) => {
|
|
4384
4812
|
const isActions = c.type === "actions";
|
|
4385
4813
|
return {
|
|
@@ -4414,7 +4842,7 @@ function Datatable({
|
|
|
4414
4842
|
}
|
|
4415
4843
|
return out;
|
|
4416
4844
|
}, [columns, rowPinning]);
|
|
4417
|
-
const _autoKey =
|
|
4845
|
+
const _autoKey = React25__default.useRef();
|
|
4418
4846
|
if (!_autoKey.current) _autoKey.current = { map: /* @__PURE__ */ new WeakMap(), n: 0 };
|
|
4419
4847
|
const keyOf = rowKey || ((r, i) => {
|
|
4420
4848
|
if (r != null && r.id != null) return r.id;
|
|
@@ -4429,17 +4857,17 @@ function Datatable({
|
|
|
4429
4857
|
}
|
|
4430
4858
|
return i;
|
|
4431
4859
|
});
|
|
4432
|
-
const [sort, setSort] =
|
|
4433
|
-
const [filters, setFilters] =
|
|
4434
|
-
const [hidden, setHidden] =
|
|
4435
|
-
const [showRowNum, setShowRowNum] =
|
|
4436
|
-
const [wrapped, setWrapped] =
|
|
4860
|
+
const [sort, setSort] = React25__default.useState(null);
|
|
4861
|
+
const [filters, setFilters] = React25__default.useState([]);
|
|
4862
|
+
const [hidden, setHidden] = React25__default.useState(() => /* @__PURE__ */ new Set());
|
|
4863
|
+
const [showRowNum, setShowRowNum] = React25__default.useState(rowNumbers);
|
|
4864
|
+
const [wrapped, setWrapped] = React25__default.useState(() => new Set((columns || []).filter((c) => c.wrapText).map((c) => c.field)));
|
|
4437
4865
|
const toggleWrap = (field) => setWrapped((w) => {
|
|
4438
4866
|
const n = new Set(w);
|
|
4439
4867
|
n.has(field) ? n.delete(field) : n.add(field);
|
|
4440
4868
|
return n;
|
|
4441
4869
|
});
|
|
4442
|
-
const [pins, setPins] =
|
|
4870
|
+
const [pins, setPins] = React25__default.useState(() => {
|
|
4443
4871
|
const left = [], right = [];
|
|
4444
4872
|
columns.forEach((c) => {
|
|
4445
4873
|
if (c.pinned === "left") left.push(c.field);
|
|
@@ -4447,34 +4875,34 @@ function Datatable({
|
|
|
4447
4875
|
});
|
|
4448
4876
|
return { left, right };
|
|
4449
4877
|
});
|
|
4450
|
-
const [density, setDensity] =
|
|
4451
|
-
const [quick, setQuick] =
|
|
4452
|
-
const [selected, setSelected] =
|
|
4453
|
-
const [activeRow, setActiveRow] =
|
|
4454
|
-
const [activeCell, setActiveCell] =
|
|
4455
|
-
const [page, setPage] =
|
|
4456
|
-
const [rowsPerPage, setRowsPerPage] =
|
|
4457
|
-
const [colQuery, setColQuery] =
|
|
4458
|
-
const [widths, setWidths] =
|
|
4459
|
-
const [order, setOrder] =
|
|
4460
|
-
const [drag, setDrag] =
|
|
4461
|
-
const [aggOn, setAggOn] =
|
|
4462
|
-
const [focus, setFocus] =
|
|
4463
|
-
const gridRef =
|
|
4464
|
-
const [groupBy, setGroupBy] =
|
|
4465
|
-
const [collapsed, setCollapsed] =
|
|
4466
|
-
const [pinnedRows, setPinnedRows] =
|
|
4467
|
-
const [headH, setHeadH] =
|
|
4468
|
-
const theadRef =
|
|
4469
|
-
const [rowOrder, setRowOrder] =
|
|
4470
|
-
const [rowHeights, setRowHeights] =
|
|
4471
|
-
const [rowDrag, setRowDrag] =
|
|
4472
|
-
const [rowGrab, setRowGrab] =
|
|
4473
|
-
const [reorderMsg, setReorderMsg] =
|
|
4474
|
-
const rowFocusRef =
|
|
4475
|
-
const rootRef =
|
|
4476
|
-
const [compact, setCompact] =
|
|
4477
|
-
|
|
4878
|
+
const [density, setDensity] = React25__default.useState(densityProp);
|
|
4879
|
+
const [quick, setQuick] = React25__default.useState("");
|
|
4880
|
+
const [selected, setSelected] = React25__default.useState(() => /* @__PURE__ */ new Set());
|
|
4881
|
+
const [activeRow, setActiveRow] = React25__default.useState(null);
|
|
4882
|
+
const [activeCell, setActiveCell] = React25__default.useState(null);
|
|
4883
|
+
const [page, setPage] = React25__default.useState(0);
|
|
4884
|
+
const [rowsPerPage, setRowsPerPage] = React25__default.useState(pageSize > 0 ? pageSize : 10);
|
|
4885
|
+
const [colQuery, setColQuery] = React25__default.useState("");
|
|
4886
|
+
const [widths, setWidths] = React25__default.useState({});
|
|
4887
|
+
const [order, setOrder] = React25__default.useState(() => columns.map((c) => c.field));
|
|
4888
|
+
const [drag, setDrag] = React25__default.useState({ from: null, over: null, after: false });
|
|
4889
|
+
const [aggOn, setAggOn] = React25__default.useState(showAggregation);
|
|
4890
|
+
const [focus, setFocus] = React25__default.useState({ r: 0, c: 0 });
|
|
4891
|
+
const gridRef = React25__default.useRef(null);
|
|
4892
|
+
const [groupBy, setGroupBy] = React25__default.useState(rowGrouping || []);
|
|
4893
|
+
const [collapsed, setCollapsed] = React25__default.useState(() => /* @__PURE__ */ new Set());
|
|
4894
|
+
const [pinnedRows, setPinnedRows] = React25__default.useState({ top: [], bottom: [] });
|
|
4895
|
+
const [headH, setHeadH] = React25__default.useState(41);
|
|
4896
|
+
const theadRef = React25__default.useRef(null);
|
|
4897
|
+
const [rowOrder, setRowOrder] = React25__default.useState(null);
|
|
4898
|
+
const [rowHeights, setRowHeights] = React25__default.useState({});
|
|
4899
|
+
const [rowDrag, setRowDrag] = React25__default.useState({ from: null, over: null, after: false });
|
|
4900
|
+
const [rowGrab, setRowGrab] = React25__default.useState(null);
|
|
4901
|
+
const [reorderMsg, setReorderMsg] = React25__default.useState("");
|
|
4902
|
+
const rowFocusRef = React25__default.useRef(null);
|
|
4903
|
+
const rootRef = React25__default.useRef(null);
|
|
4904
|
+
const [compact, setCompact] = React25__default.useState(false);
|
|
4905
|
+
React25__default.useEffect(() => {
|
|
4478
4906
|
const el = rootRef.current;
|
|
4479
4907
|
if (!el) return void 0;
|
|
4480
4908
|
const measure = () => setCompact((el.clientWidth || 0) < 720);
|
|
@@ -4487,11 +4915,11 @@ function Datatable({
|
|
|
4487
4915
|
else if (typeof window !== "undefined") window.removeEventListener("resize", measure);
|
|
4488
4916
|
};
|
|
4489
4917
|
}, []);
|
|
4490
|
-
const scrollRef =
|
|
4491
|
-
const [scrollTop, setScrollTop] =
|
|
4492
|
-
const [viewportH, setViewportH] =
|
|
4493
|
-
const [pivotOn, setPivotOn] =
|
|
4494
|
-
const [aggConfig, setAggConfig] =
|
|
4918
|
+
const scrollRef = React25__default.useRef(null);
|
|
4919
|
+
const [scrollTop, setScrollTop] = React25__default.useState(0);
|
|
4920
|
+
const [viewportH, setViewportH] = React25__default.useState(0);
|
|
4921
|
+
const [pivotOn, setPivotOn] = React25__default.useState(pivotMode);
|
|
4922
|
+
const [aggConfig, setAggConfig] = React25__default.useState(() => {
|
|
4495
4923
|
const m = {};
|
|
4496
4924
|
(columns || []).forEach((c) => {
|
|
4497
4925
|
if (typeof c.aggregation === "string") m[c.field] = c.aggregation;
|
|
@@ -4499,13 +4927,13 @@ function Datatable({
|
|
|
4499
4927
|
return m;
|
|
4500
4928
|
});
|
|
4501
4929
|
const aggOf = (c) => aggConfig[c.field] || (typeof c.aggregation === "function" ? c.aggregation : null);
|
|
4502
|
-
const [pivotConfig, setPivotConfig] =
|
|
4930
|
+
const [pivotConfig, setPivotConfig] = React25__default.useState(() => ({
|
|
4503
4931
|
rows: pivot && pivot.rows || [],
|
|
4504
4932
|
columns: pivot && pivot.columns || [],
|
|
4505
4933
|
values: pivot && pivot.values || []
|
|
4506
4934
|
}));
|
|
4507
4935
|
const pivotActive = pivotOn && pivotConfig.rows.length > 0 && pivotConfig.values.length > 0;
|
|
4508
|
-
|
|
4936
|
+
React25__default.useEffect(() => {
|
|
4509
4937
|
setOrder((prev) => {
|
|
4510
4938
|
const fields = columns.map((c) => c.field);
|
|
4511
4939
|
const kept = prev.filter((f) => fields.includes(f));
|
|
@@ -4513,32 +4941,32 @@ function Datatable({
|
|
|
4513
4941
|
return [...kept, ...added];
|
|
4514
4942
|
});
|
|
4515
4943
|
}, [columns]);
|
|
4516
|
-
|
|
4944
|
+
React25__default.useEffect(() => {
|
|
4517
4945
|
setDensity(densityProp);
|
|
4518
4946
|
}, [densityProp]);
|
|
4519
|
-
|
|
4947
|
+
React25__default.useEffect(() => {
|
|
4520
4948
|
setAggOn(showAggregation);
|
|
4521
4949
|
}, [showAggregation]);
|
|
4522
4950
|
const rowGroupingKey = (rowGrouping || []).join("\0");
|
|
4523
|
-
const rowGroupingKeyRef =
|
|
4524
|
-
|
|
4951
|
+
const rowGroupingKeyRef = React25__default.useRef(rowGroupingKey);
|
|
4952
|
+
React25__default.useEffect(() => {
|
|
4525
4953
|
if (rowGroupingKeyRef.current === rowGroupingKey) return;
|
|
4526
4954
|
rowGroupingKeyRef.current = rowGroupingKey;
|
|
4527
4955
|
setGroupBy(rowGrouping || []);
|
|
4528
4956
|
}, [rowGroupingKey]);
|
|
4529
4957
|
const widthOf = (c) => widths[c.field] ?? c.width ?? 160;
|
|
4530
|
-
const [colMenu, setColMenu] =
|
|
4958
|
+
const [colMenu, setColMenu] = React25__default.useState(null);
|
|
4531
4959
|
const [menuPos, openMenu, closeMenu] = useFloating();
|
|
4532
|
-
const [panel, setPanel] =
|
|
4960
|
+
const [panel, setPanel] = React25__default.useState(null);
|
|
4533
4961
|
const [panelPos, openPanel, closePanel] = useFloating();
|
|
4534
|
-
const [rowMenu, setRowMenu] =
|
|
4962
|
+
const [rowMenu, setRowMenu] = React25__default.useState(null);
|
|
4535
4963
|
const [rowMenuPos, openRowMenu, closeRowMenu] = useFloating();
|
|
4536
|
-
const [exportOpen, setExportOpen] =
|
|
4964
|
+
const [exportOpen, setExportOpen] = React25__default.useState(false);
|
|
4537
4965
|
const [exportPos, openExport, closeExport] = useFloating();
|
|
4538
|
-
const menuTriggerRef =
|
|
4539
|
-
const colMenuRef =
|
|
4540
|
-
const rowMenuRef =
|
|
4541
|
-
const exportMenuRef =
|
|
4966
|
+
const menuTriggerRef = React25__default.useRef(null);
|
|
4967
|
+
const colMenuRef = React25__default.useRef(null);
|
|
4968
|
+
const rowMenuRef = React25__default.useRef(null);
|
|
4969
|
+
const exportMenuRef = React25__default.useRef(null);
|
|
4542
4970
|
function focusFirstItem(container) {
|
|
4543
4971
|
if (!container) return;
|
|
4544
4972
|
const first = container.querySelector('[role="menuitem"]:not([disabled])');
|
|
@@ -4577,16 +5005,16 @@ function Datatable({
|
|
|
4577
5005
|
restoreTriggerFocus();
|
|
4578
5006
|
}
|
|
4579
5007
|
}
|
|
4580
|
-
|
|
5008
|
+
React25__default.useEffect(() => {
|
|
4581
5009
|
if (colMenu) focusFirstItem(colMenuRef.current);
|
|
4582
5010
|
}, [colMenu]);
|
|
4583
|
-
|
|
5011
|
+
React25__default.useEffect(() => {
|
|
4584
5012
|
if (rowMenu) focusFirstItem(rowMenuRef.current);
|
|
4585
5013
|
}, [rowMenu]);
|
|
4586
|
-
|
|
5014
|
+
React25__default.useEffect(() => {
|
|
4587
5015
|
if (exportOpen) focusFirstItem(exportMenuRef.current);
|
|
4588
5016
|
}, [exportOpen]);
|
|
4589
|
-
|
|
5017
|
+
React25__default.useEffect(() => {
|
|
4590
5018
|
if (!colMenu && !panel && !rowMenu) return;
|
|
4591
5019
|
const closeAll = () => {
|
|
4592
5020
|
setColMenu(null);
|
|
@@ -4609,7 +5037,7 @@ function Datatable({
|
|
|
4609
5037
|
document.removeEventListener("keydown", onKey);
|
|
4610
5038
|
};
|
|
4611
5039
|
}, [colMenu, panel, rowMenu]);
|
|
4612
|
-
|
|
5040
|
+
React25__default.useEffect(() => {
|
|
4613
5041
|
if (!exportOpen) return;
|
|
4614
5042
|
const close = () => {
|
|
4615
5043
|
setExportOpen(false);
|
|
@@ -4628,9 +5056,9 @@ function Datatable({
|
|
|
4628
5056
|
document.removeEventListener("keydown", onKey);
|
|
4629
5057
|
};
|
|
4630
5058
|
}, [exportOpen]);
|
|
4631
|
-
const colByField =
|
|
5059
|
+
const colByField = React25__default.useMemo(() => Object.fromEntries(cols.map((c) => [c.field, c])), [cols]);
|
|
4632
5060
|
const visibleCols = cols.filter((c) => !hidden.has(c.field));
|
|
4633
|
-
const ordered =
|
|
5061
|
+
const ordered = React25__default.useMemo(() => {
|
|
4634
5062
|
const orderIdx = (f) => {
|
|
4635
5063
|
const i = order.indexOf(f);
|
|
4636
5064
|
return i === -1 ? 9999 : i;
|
|
@@ -4665,7 +5093,7 @@ function Datatable({
|
|
|
4665
5093
|
}
|
|
4666
5094
|
return {};
|
|
4667
5095
|
};
|
|
4668
|
-
const processed =
|
|
5096
|
+
const processed = React25__default.useMemo(() => {
|
|
4669
5097
|
if (serverMode) {
|
|
4670
5098
|
if (rowOrder) {
|
|
4671
5099
|
const idx = new Map(rowOrder.map((k, i) => [k, i]));
|
|
@@ -4704,10 +5132,10 @@ function Datatable({
|
|
|
4704
5132
|
const totalRows = serverMode ? serverTotal : processed.length;
|
|
4705
5133
|
const totalPages = paginated ? Math.max(1, Math.ceil(totalRows / rowsPerPage)) : 1;
|
|
4706
5134
|
const paged = !paginated || serverMode ? processed : processed.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
|
|
4707
|
-
|
|
5135
|
+
React25__default.useEffect(() => {
|
|
4708
5136
|
if (page > totalPages - 1) setPage(0);
|
|
4709
5137
|
}, [totalPages]);
|
|
4710
|
-
const activeGroupBy =
|
|
5138
|
+
const activeGroupBy = React25__default.useMemo(() => groupBy.filter((f) => colByField[f]), [groupBy, colByField]);
|
|
4711
5139
|
function subtotalText(rowsIn) {
|
|
4712
5140
|
const parts = [];
|
|
4713
5141
|
for (const c of ordered) {
|
|
@@ -4734,7 +5162,7 @@ function Datatable({
|
|
|
4734
5162
|
if (agg === "max") return Math.max(...nums);
|
|
4735
5163
|
return null;
|
|
4736
5164
|
}
|
|
4737
|
-
const displayItems =
|
|
5165
|
+
const displayItems = React25__default.useMemo(() => {
|
|
4738
5166
|
if (!activeGroupBy.length) return null;
|
|
4739
5167
|
const build = (rowsIn, depth, prefix) => {
|
|
4740
5168
|
if (depth >= activeGroupBy.length) return rowsIn.map((row) => ({ kind: "leaf", row }));
|
|
@@ -4776,7 +5204,7 @@ function Datatable({
|
|
|
4776
5204
|
return { top, bottom };
|
|
4777
5205
|
});
|
|
4778
5206
|
}
|
|
4779
|
-
|
|
5207
|
+
React25__default.useEffect(() => {
|
|
4780
5208
|
if (!rowPinning) return;
|
|
4781
5209
|
const measure = () => {
|
|
4782
5210
|
if (theadRef.current) setHeadH(theadRef.current.offsetHeight || 41);
|
|
@@ -4790,12 +5218,12 @@ function Datatable({
|
|
|
4790
5218
|
const pinnedTopRows = canPinRows ? pinnedRows.top.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
|
|
4791
5219
|
const pinnedBottomRows = canPinRows ? pinnedRows.bottom.map((k) => leafRows.find((r, i) => keyOf(r, i) === k)).filter(Boolean) : [];
|
|
4792
5220
|
const middleRows = canPinRows ? leafRows.filter((r, i) => !pinSideOf(keyOf(r, i))) : leafRows;
|
|
4793
|
-
const keyIndex =
|
|
5221
|
+
const keyIndex = React25__default.useMemo(() => {
|
|
4794
5222
|
const m = /* @__PURE__ */ new Map();
|
|
4795
5223
|
leafRows.forEach((r, i) => m.set(keyOf(r, i), i));
|
|
4796
5224
|
return m;
|
|
4797
5225
|
}, [leafRows]);
|
|
4798
|
-
const keyIndexMid =
|
|
5226
|
+
const keyIndexMid = React25__default.useMemo(() => {
|
|
4799
5227
|
const m = /* @__PURE__ */ new Map();
|
|
4800
5228
|
middleRows.forEach((r, i) => m.set(keyOf(r, keyIndex.get(keyOf(r)) ?? i), i));
|
|
4801
5229
|
return m;
|
|
@@ -4880,7 +5308,7 @@ function Datatable({
|
|
|
4880
5308
|
setReorderMsg("Reorder cancelled.");
|
|
4881
5309
|
}
|
|
4882
5310
|
}
|
|
4883
|
-
|
|
5311
|
+
React25__default.useEffect(() => {
|
|
4884
5312
|
if (rowFocusRef.current == null) return;
|
|
4885
5313
|
const key = rowFocusRef.current;
|
|
4886
5314
|
rowFocusRef.current = null;
|
|
@@ -4892,7 +5320,7 @@ function Datatable({
|
|
|
4892
5320
|
});
|
|
4893
5321
|
const estRowH = rowHeight ?? (density === "compact" ? 36 : density === "comfortable" ? 56 : 44);
|
|
4894
5322
|
const virtualizing = virtualized && !paginated && !activeGroupBy.length && !loading;
|
|
4895
|
-
|
|
5323
|
+
React25__default.useEffect(() => {
|
|
4896
5324
|
if (!virtualizing) return;
|
|
4897
5325
|
const el = scrollRef.current;
|
|
4898
5326
|
if (!el) return;
|
|
@@ -4902,13 +5330,13 @@ function Datatable({
|
|
|
4902
5330
|
if (ro) ro.observe(el);
|
|
4903
5331
|
return () => ro && ro.disconnect();
|
|
4904
5332
|
}, [virtualizing, height]);
|
|
4905
|
-
const onScrollVirtual =
|
|
5333
|
+
const onScrollVirtual = React25__default.useCallback((e) => {
|
|
4906
5334
|
setScrollTop(e.currentTarget.scrollTop);
|
|
4907
5335
|
}, []);
|
|
4908
5336
|
const vh = viewportH || (typeof height === "number" ? height : 440);
|
|
4909
|
-
const rowHRef =
|
|
4910
|
-
const [measureTick, setMeasureTick] =
|
|
4911
|
-
const offsets =
|
|
5337
|
+
const rowHRef = React25__default.useRef(/* @__PURE__ */ new Map());
|
|
5338
|
+
const [measureTick, setMeasureTick] = React25__default.useState(0);
|
|
5339
|
+
const offsets = React25__default.useMemo(() => {
|
|
4912
5340
|
if (!virtualizing) return null;
|
|
4913
5341
|
const total = middleRows.length;
|
|
4914
5342
|
const arr = new Float64Array(total + 1);
|
|
@@ -4918,7 +5346,7 @@ function Datatable({
|
|
|
4918
5346
|
}
|
|
4919
5347
|
return arr;
|
|
4920
5348
|
}, [virtualizing, middleRows, estRowH, measureTick]);
|
|
4921
|
-
const vWindow =
|
|
5349
|
+
const vWindow = React25__default.useMemo(() => {
|
|
4922
5350
|
if (!virtualizing || !offsets) return null;
|
|
4923
5351
|
const total = middleRows.length;
|
|
4924
5352
|
const totalH = offsets[total];
|
|
@@ -4947,7 +5375,7 @@ function Datatable({
|
|
|
4947
5375
|
if (start > end) start = end;
|
|
4948
5376
|
return { start, end, padTop: offsets[start], padBottom: Math.max(0, totalH - offsets[end]) };
|
|
4949
5377
|
}, [virtualizing, offsets, middleRows.length, vh, scrollTop, overscan]);
|
|
4950
|
-
|
|
5378
|
+
React25__default.useLayoutEffect(() => {
|
|
4951
5379
|
if (!virtualizing) return;
|
|
4952
5380
|
const el = scrollRef.current;
|
|
4953
5381
|
if (!el) return;
|
|
@@ -4962,9 +5390,9 @@ function Datatable({
|
|
|
4962
5390
|
}
|
|
4963
5391
|
if (changed) setMeasureTick((t) => t + 1);
|
|
4964
5392
|
});
|
|
4965
|
-
const onServerChangeRef =
|
|
5393
|
+
const onServerChangeRef = React25__default.useRef(onServerChange);
|
|
4966
5394
|
onServerChangeRef.current = onServerChange;
|
|
4967
|
-
|
|
5395
|
+
React25__default.useEffect(() => {
|
|
4968
5396
|
if (!serverMode) return;
|
|
4969
5397
|
const t = setTimeout(() => {
|
|
4970
5398
|
onServerChangeRef.current?.({
|
|
@@ -4999,8 +5427,8 @@ function Datatable({
|
|
|
4999
5427
|
return n;
|
|
5000
5428
|
});
|
|
5001
5429
|
}
|
|
5002
|
-
const movableMidFields =
|
|
5003
|
-
() => ordered.filter((c) => !pins.left.includes(c.field) && !pins.right.includes(c.field)).map((c) => c.field),
|
|
5430
|
+
const movableMidFields = React25__default.useMemo(
|
|
5431
|
+
() => ordered.filter((c) => !pins.left.includes(c.field) && !pins.right.includes(c.field) && c.reorderable !== false).map((c) => c.field),
|
|
5004
5432
|
[ordered, pins]
|
|
5005
5433
|
);
|
|
5006
5434
|
function moveCol(field, dir) {
|
|
@@ -5030,7 +5458,7 @@ function Datatable({
|
|
|
5030
5458
|
}
|
|
5031
5459
|
return [...set].sort((a, b) => a.localeCompare(b)).map((v) => ({ value: v, label: v }));
|
|
5032
5460
|
}
|
|
5033
|
-
const [resizing, setResizing] =
|
|
5461
|
+
const [resizing, setResizing] = React25__default.useState(false);
|
|
5034
5462
|
function startResize(e, field) {
|
|
5035
5463
|
e.preventDefault();
|
|
5036
5464
|
e.stopPropagation();
|
|
@@ -5137,7 +5565,7 @@ function Datatable({
|
|
|
5137
5565
|
if (!agg) return null;
|
|
5138
5566
|
if (aggregationValues && col.field in aggregationValues) {
|
|
5139
5567
|
const pre = aggregationValues[col.field];
|
|
5140
|
-
if (pre && typeof pre === "object" && !
|
|
5568
|
+
if (pre && typeof pre === "object" && !React25__default.isValidElement(pre)) {
|
|
5141
5569
|
if (typeof agg === "string" && agg in pre) return pre[agg];
|
|
5142
5570
|
} else {
|
|
5143
5571
|
return pre;
|
|
@@ -5255,14 +5683,14 @@ function Datatable({
|
|
|
5255
5683
|
focusCell(r, c);
|
|
5256
5684
|
}
|
|
5257
5685
|
}
|
|
5258
|
-
|
|
5686
|
+
React25__default.useEffect(() => {
|
|
5259
5687
|
setFocus((f) => ({ r: Math.min(f.r, Math.max(0, leafRows.length - 1)), c: Math.min(f.c, Math.max(0, ordered.length - 1)) }));
|
|
5260
5688
|
}, [leafRows.length, ordered.length, page]);
|
|
5261
|
-
const selectedRows =
|
|
5689
|
+
const selectedRows = React25__default.useMemo(() => rows.filter((r, i) => selected.has(keyOf(r, i))), [rows, selected]);
|
|
5262
5690
|
function clearSelection() {
|
|
5263
5691
|
setSelected(/* @__PURE__ */ new Set());
|
|
5264
5692
|
}
|
|
5265
|
-
const [editing, setEditing] =
|
|
5693
|
+
const [editing, setEditing] = React25__default.useState(null);
|
|
5266
5694
|
const isColEditable = (c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false));
|
|
5267
5695
|
function beginEdit(rowK, col, row) {
|
|
5268
5696
|
if (!isColEditable(col)) return;
|
|
@@ -5297,17 +5725,17 @@ function Datatable({
|
|
|
5297
5725
|
cancelEdit();
|
|
5298
5726
|
}
|
|
5299
5727
|
}
|
|
5300
|
-
const batchEditableCols =
|
|
5728
|
+
const batchEditableCols = React25__default.useMemo(
|
|
5301
5729
|
() => cols.filter((c) => c.type !== "actions" && (c.editable ?? (editMode && c.editable !== false))),
|
|
5302
5730
|
[cols, editMode]
|
|
5303
5731
|
);
|
|
5304
|
-
const [batchEdit, setBatchEdit] =
|
|
5732
|
+
const [batchEdit, setBatchEdit] = React25__default.useState(null);
|
|
5305
5733
|
const [batchEditPos, openBatchEdit, closeBatchEdit] = useFloating();
|
|
5306
5734
|
function openBatchEditor(el) {
|
|
5307
5735
|
setBatchEdit({ fields: {}, values: {} });
|
|
5308
5736
|
openBatchEdit(el, "left", 320);
|
|
5309
5737
|
}
|
|
5310
|
-
|
|
5738
|
+
React25__default.useEffect(() => {
|
|
5311
5739
|
if (!batchEdit) return;
|
|
5312
5740
|
const close = () => {
|
|
5313
5741
|
setBatchEdit(null);
|
|
@@ -5326,7 +5754,7 @@ function Datatable({
|
|
|
5326
5754
|
document.removeEventListener("keydown", onKey);
|
|
5327
5755
|
};
|
|
5328
5756
|
}, [batchEdit]);
|
|
5329
|
-
|
|
5757
|
+
React25__default.useEffect(() => {
|
|
5330
5758
|
if (batchEdit && selected.size === 0) {
|
|
5331
5759
|
setBatchEdit(null);
|
|
5332
5760
|
closeBatchEdit();
|
|
@@ -5363,7 +5791,7 @@ function Datatable({
|
|
|
5363
5791
|
setBatchEdit(null);
|
|
5364
5792
|
closeBatchEdit();
|
|
5365
5793
|
}
|
|
5366
|
-
|
|
5794
|
+
React25__default.useEffect(() => {
|
|
5367
5795
|
if (!editing) return;
|
|
5368
5796
|
const onDown = (e) => {
|
|
5369
5797
|
if (e.target.closest(".twc-dt__editor-wrap") || e.target.closest(".twc-pop")) return;
|
|
@@ -5385,13 +5813,12 @@ function Datatable({
|
|
|
5385
5813
|
})() : [];
|
|
5386
5814
|
const menu = [...items.filter((a) => a.showInMenu), ...pinItems];
|
|
5387
5815
|
return /* @__PURE__ */ jsxs("div", { className: "twc-dt__actions", style: { justifyContent: col.align === "right" ? "flex-end" : "flex-start" }, children: [
|
|
5388
|
-
inline.map((a, i) => /* @__PURE__ */ jsx(
|
|
5816
|
+
inline.map((a, i) => /* @__PURE__ */ jsx(Tooltip, { label: a.label, placement: "top", children: /* @__PURE__ */ jsx(
|
|
5389
5817
|
"button",
|
|
5390
5818
|
{
|
|
5391
5819
|
type: "button",
|
|
5392
5820
|
className: "twc-dt__act",
|
|
5393
5821
|
"data-danger": a.danger || void 0,
|
|
5394
|
-
title: a.label,
|
|
5395
5822
|
"aria-label": a.label,
|
|
5396
5823
|
disabled: a.disabled,
|
|
5397
5824
|
onClick: (e) => {
|
|
@@ -5399,16 +5826,14 @@ function Datatable({
|
|
|
5399
5826
|
a.onClick?.(row);
|
|
5400
5827
|
},
|
|
5401
5828
|
children: a.icon
|
|
5402
|
-
}
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
menu.length ? /* @__PURE__ */ jsx(
|
|
5829
|
+
}
|
|
5830
|
+
) }, i)),
|
|
5831
|
+
menu.length ? /* @__PURE__ */ jsx(Tooltip, { label: "More actions", placement: "top", children: /* @__PURE__ */ jsx(
|
|
5406
5832
|
"button",
|
|
5407
5833
|
{
|
|
5408
5834
|
type: "button",
|
|
5409
5835
|
className: "twc-dt__act",
|
|
5410
5836
|
"aria-label": "More actions",
|
|
5411
|
-
title: "More",
|
|
5412
5837
|
"aria-haspopup": "menu",
|
|
5413
5838
|
"aria-expanded": rowMenu && rowMenu.row === row || void 0,
|
|
5414
5839
|
onClick: (e) => {
|
|
@@ -5425,7 +5850,7 @@ function Datatable({
|
|
|
5425
5850
|
},
|
|
5426
5851
|
children: /* @__PURE__ */ jsx(Svg, { d: I.more })
|
|
5427
5852
|
}
|
|
5428
|
-
) : null
|
|
5853
|
+
) }) : null
|
|
5429
5854
|
] });
|
|
5430
5855
|
}
|
|
5431
5856
|
const tableMinWidth = leadW + ordered.reduce((a, c) => a + widthOf(c), 0);
|
|
@@ -5969,7 +6394,7 @@ function Datatable({
|
|
|
5969
6394
|
const st = stickyOf(c.field);
|
|
5970
6395
|
const sorted = sort && sort.field === c.field ? sort.dir : void 0;
|
|
5971
6396
|
const w = widthOf(c);
|
|
5972
|
-
const reorderable = !disableColumnReorder && st.pin == null && c.type !== "actions";
|
|
6397
|
+
const reorderable = !disableColumnReorder && st.pin == null && c.type !== "actions" && c.reorderable !== false;
|
|
5973
6398
|
const resizable = !disableColumnResize && c.resizable !== false;
|
|
5974
6399
|
const hasMenu = !c.disableColumnMenu && (c.sortable || c.filterable || c.pinnable || c.hideable);
|
|
5975
6400
|
return /* @__PURE__ */ jsxs(
|
|
@@ -6093,14 +6518,17 @@ function Datatable({
|
|
|
6093
6518
|
);
|
|
6094
6519
|
})
|
|
6095
6520
|
] }) }),
|
|
6096
|
-
/* @__PURE__ */ jsx("tbody", { children: loading ? Array.from({ length: paginated ? Math.min(rowsPerPage, 8) : 8 }).map((_, ri) => /* @__PURE__ */ jsxs("tr", { className: "twc-dt__row", children: [
|
|
6097
|
-
checkboxSelection ? /* @__PURE__ */ jsx("td", { className: "twc-dt__td", "data-pin": "left", style: { insetInlineStart: 0, width: 44 }, children: /* @__PURE__ */ jsx("span", { className: "twc-dt__sk", style: { "--_w": "18px", height: 18, borderRadius: 4 } }) }) : null,
|
|
6098
|
-
showRowNum ? /* @__PURE__ */ jsx("td", { className: "twc-dt__td twc-dt__rownum", "aria-hidden": "true", "data-pin": "left", style: { insetInlineStart: numLeft, width: NUM_W }, children: /* @__PURE__ */ jsx("span", { className: "twc-dt__sk", style: { "--_w": "16px", height: 14, borderRadius: 4 } }) }) : null,
|
|
6521
|
+
/* @__PURE__ */ jsx("tbody", { children: loading ? Array.from({ length: paginated ? Math.min(rowsPerPage, 8) : 8 }).map((_, ri) => /* @__PURE__ */ jsxs("tr", { className: "twc-dt__row", role: "row", children: [
|
|
6522
|
+
checkboxSelection ? /* @__PURE__ */ jsx("td", { className: "twc-dt__td", role: "gridcell", "data-pin": "left", style: { insetInlineStart: 0, width: 44 }, children: /* @__PURE__ */ jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "18px", height: 18, borderRadius: 4 } }) }) : null,
|
|
6523
|
+
showRowNum ? /* @__PURE__ */ 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__ */ jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "16px", height: 14, borderRadius: 4 } }) }) : null,
|
|
6099
6524
|
ordered.map((c, ci) => {
|
|
6100
6525
|
const st = stickyOf(c.field);
|
|
6101
|
-
return /* @__PURE__ */ 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__ */ jsx("span", { className: "twc-dt__sk", style: { "--_w": `${45 + (ri * 13 + ci * 29) % 45}%` } }) }, c.field);
|
|
6526
|
+
return /* @__PURE__ */ 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__ */ jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": `${45 + (ri * 13 + ci * 29) % 45}%` } }) }, c.field);
|
|
6102
6527
|
})
|
|
6103
|
-
] }, ri)) : (displayItems ? displayItems.length === 0 : paged.length === 0) ?
|
|
6528
|
+
] }, ri)) : (displayItems ? displayItems.length === 0 : paged.length === 0) ? (
|
|
6529
|
+
// #121: customizable, filter-aware empty state. #122: grid roles on the empty row.
|
|
6530
|
+
/* @__PURE__ */ jsx("tr", { role: "row", "aria-rowindex": 2, children: /* @__PURE__ */ jsx("td", { className: "twc-dt__td", role: "gridcell", colSpan: totalCols, style: { maxWidth: "none" }, children: /* @__PURE__ */ jsx("div", { className: "twc-dt__empty", children: renderEmpty ? renderEmpty() : emptyMessage ?? (filters.length > 0 || quick.trim() !== "" ? "No rows match your filters" : "No rows") }) }) })
|
|
6531
|
+
) : displayItems ? (() => {
|
|
6104
6532
|
let li = -1;
|
|
6105
6533
|
return displayItems.map((item) => item.kind === "group" ? renderGroupRow(item) : renderLeaf(item.row, ++li));
|
|
6106
6534
|
})() : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -6113,13 +6541,13 @@ function Datatable({
|
|
|
6113
6541
|
pinnedBottomRows.map((row) => renderLeaf(row, keyIndex.get(keyOf(row)), "bottom"))
|
|
6114
6542
|
] }) }),
|
|
6115
6543
|
hasAggregation && aggOn && !loading && paged.length > 0 ? /* @__PURE__ */ jsx("tfoot", { children: /* @__PURE__ */ jsxs("tr", { role: "row", children: [
|
|
6116
|
-
checkboxSelection ? /* @__PURE__ */ jsx("td", { "data-pin": "left", "data-pin-edge": pins.left.length || showRowNum ? void 0 : "left", style: { insetInlineStart: 0, width: 44 } }) : null,
|
|
6117
|
-
showRowNum ? /* @__PURE__ */ 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,
|
|
6544
|
+
checkboxSelection ? /* @__PURE__ */ jsx("td", { role: "gridcell", "data-pin": "left", "data-pin-edge": pins.left.length || showRowNum ? void 0 : "left", style: { insetInlineStart: 0, width: 44 } }) : null,
|
|
6545
|
+
showRowNum ? /* @__PURE__ */ 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,
|
|
6118
6546
|
ordered.map((c) => {
|
|
6119
6547
|
const st = stickyOf(c.field);
|
|
6120
6548
|
const v = aggregate(c);
|
|
6121
6549
|
const display = v == null ? null : c.aggregationFormatter ? c.aggregationFormatter(v) : c.valueFormatter ? c.valueFormatter(v, null) : typeof v === "number" ? v.toLocaleString() : v;
|
|
6122
|
-
return /* @__PURE__ */ 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__ */ jsxs(Fragment, { children: [
|
|
6550
|
+
return /* @__PURE__ */ 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__ */ jsxs(Fragment, { children: [
|
|
6123
6551
|
typeof aggOf(c) === "string" ? /* @__PURE__ */ jsx("span", { className: "twc-dt__agg-label", children: aggLabels[aggOf(c)] }) : null,
|
|
6124
6552
|
/* @__PURE__ */ jsx("span", { className: "twc-dt__agg-val", children: display })
|
|
6125
6553
|
] }) }, c.field);
|
|
@@ -6162,7 +6590,7 @@ function Datatable({
|
|
|
6162
6590
|
})() }),
|
|
6163
6591
|
paginated ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__rpp", children: [
|
|
6164
6592
|
/* @__PURE__ */ jsx("span", { className: "twc-dt__rpp-label", children: "Rows per page" }),
|
|
6165
|
-
/* @__PURE__ */ jsx("div", { style: { width: 78 }, children: /* @__PURE__ */ jsx(Select, { size: "sm", portal: true, value: String(rowsPerPage), options: rppOptions, placement: "top", onChange: (v) => {
|
|
6593
|
+
/* @__PURE__ */ jsx("div", { style: { width: 78 }, children: /* @__PURE__ */ jsx(Select, { size: "sm", portal: true, searchable: false, value: String(rowsPerPage), options: rppOptions, placement: "top", onChange: (v) => {
|
|
6166
6594
|
setRowsPerPage(Number(v));
|
|
6167
6595
|
setPage(0);
|
|
6168
6596
|
} }) })
|
|
@@ -6463,7 +6891,7 @@ function Datatable({
|
|
|
6463
6891
|
)
|
|
6464
6892
|
] }) : null,
|
|
6465
6893
|
shownColRows.length === 0 ? rowNumMatch ? null : /* @__PURE__ */ jsx("div", { className: "twc-dt__empty", style: { padding: "18px 12px" }, children: "No columns found" }) : shownColRows.map((c) => {
|
|
6466
|
-
const canDrag = !disableColumnReorder && !colQuery.trim();
|
|
6894
|
+
const canDrag = !disableColumnReorder && c.reorderable !== false && !colQuery.trim();
|
|
6467
6895
|
return /* @__PURE__ */ jsxs(
|
|
6468
6896
|
"div",
|
|
6469
6897
|
{
|
|
@@ -6840,6 +7268,7 @@ var DATEPICKER_CSS = `
|
|
|
6840
7268
|
.twc-dp__day[data-today="true"] { font-weight: var(--font-bold); box-shadow: inset 0 0 0 1px var(--color-primary-border); }
|
|
6841
7269
|
.twc-dp__day[data-selected="true"] { background: var(--color-primary); color: var(--color-primary-fg); font-weight: var(--font-bold); }
|
|
6842
7270
|
.twc-dp__day:disabled { color: var(--color-text-subtle); opacity: 0.4; cursor: not-allowed; }
|
|
7271
|
+
.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; }
|
|
6843
7272
|
.twc-dp__day:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
6844
7273
|
.twc-dp__months { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
|
|
6845
7274
|
.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); }
|
|
@@ -6885,23 +7314,23 @@ function DatePicker({
|
|
|
6885
7314
|
}) {
|
|
6886
7315
|
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS3);
|
|
6887
7316
|
const __twcStyles1 = useScopedStyles("twc-datepicker-styles", DATEPICKER_CSS);
|
|
6888
|
-
const autoId =
|
|
7317
|
+
const autoId = React25__default.useId();
|
|
6889
7318
|
const fieldId = id || autoId;
|
|
6890
7319
|
const descId = `${fieldId}-desc`;
|
|
6891
7320
|
const invalid = Boolean(error);
|
|
6892
|
-
const [internal, setInternal] =
|
|
7321
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
6893
7322
|
const selected = value !== void 0 ? value : internal;
|
|
6894
|
-
const [open, setOpen] =
|
|
6895
|
-
const [view, setView] =
|
|
6896
|
-
const [mode, setMode] =
|
|
6897
|
-
const [focusDate, setFocusDate] =
|
|
6898
|
-
const [coords, setCoords] =
|
|
6899
|
-
const wrapRef =
|
|
6900
|
-
const triggerRef =
|
|
6901
|
-
const popRef =
|
|
6902
|
-
const gridRef =
|
|
7323
|
+
const [open, setOpen] = React25__default.useState(false);
|
|
7324
|
+
const [view, setView] = React25__default.useState(selected || /* @__PURE__ */ new Date());
|
|
7325
|
+
const [mode, setMode] = React25__default.useState("days");
|
|
7326
|
+
const [focusDate, setFocusDate] = React25__default.useState(null);
|
|
7327
|
+
const [coords, setCoords] = React25__default.useState(null);
|
|
7328
|
+
const wrapRef = React25__default.useRef(null);
|
|
7329
|
+
const triggerRef = React25__default.useRef(null);
|
|
7330
|
+
const popRef = React25__default.useRef(null);
|
|
7331
|
+
const gridRef = React25__default.useRef(null);
|
|
6903
7332
|
const POP_W = 280;
|
|
6904
|
-
const place =
|
|
7333
|
+
const place = React25__default.useCallback(() => {
|
|
6905
7334
|
const el = triggerRef.current;
|
|
6906
7335
|
if (!el) return;
|
|
6907
7336
|
const r = el.getBoundingClientRect();
|
|
@@ -6912,7 +7341,7 @@ function DatePicker({
|
|
|
6912
7341
|
left = Math.max(8, left);
|
|
6913
7342
|
setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
|
|
6914
7343
|
}, []);
|
|
6915
|
-
|
|
7344
|
+
React25__default.useEffect(() => {
|
|
6916
7345
|
if (!open) return void 0;
|
|
6917
7346
|
place();
|
|
6918
7347
|
const onMove = () => place();
|
|
@@ -6923,7 +7352,7 @@ function DatePicker({
|
|
|
6923
7352
|
window.removeEventListener("resize", onMove);
|
|
6924
7353
|
};
|
|
6925
7354
|
}, [open, place]);
|
|
6926
|
-
|
|
7355
|
+
React25__default.useEffect(() => {
|
|
6927
7356
|
if (!open) return;
|
|
6928
7357
|
setView(selected || /* @__PURE__ */ new Date());
|
|
6929
7358
|
setMode("days");
|
|
@@ -6943,8 +7372,8 @@ function DatePicker({
|
|
|
6943
7372
|
document.removeEventListener("keydown", onKey);
|
|
6944
7373
|
};
|
|
6945
7374
|
}, [open]);
|
|
6946
|
-
const prevOpen =
|
|
6947
|
-
|
|
7375
|
+
const prevOpen = React25__default.useRef(false);
|
|
7376
|
+
React25__default.useEffect(() => {
|
|
6948
7377
|
let id2;
|
|
6949
7378
|
if (!prevOpen.current && open) {
|
|
6950
7379
|
id2 = setTimeout(() => gridRef.current?.querySelector('[tabindex="0"]')?.focus({ preventScroll: true }), 30);
|
|
@@ -6955,9 +7384,9 @@ function DatePicker({
|
|
|
6955
7384
|
prevOpen.current = open;
|
|
6956
7385
|
return () => clearTimeout(id2);
|
|
6957
7386
|
}, [open]);
|
|
6958
|
-
const months =
|
|
6959
|
-
const monthsShort =
|
|
6960
|
-
const dows =
|
|
7387
|
+
const months = React25__default.useMemo(() => locale === void 0 ? MONTHS : monthNames(locale), [locale]);
|
|
7388
|
+
const monthsShort = React25__default.useMemo(() => locale === void 0 ? MONTHS.map((n) => n.slice(0, 3)) : monthShortNames(locale), [locale]);
|
|
7389
|
+
const dows = React25__default.useMemo(
|
|
6961
7390
|
() => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW[(i + weekStartsOn) % 7]) : weekdayNames(locale, weekStartsOn),
|
|
6962
7391
|
[locale, weekStartsOn]
|
|
6963
7392
|
);
|
|
@@ -6985,7 +7414,7 @@ function DatePicker({
|
|
|
6985
7414
|
};
|
|
6986
7415
|
const cells = Array.from({ length: 42 }, (_, i) => new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i));
|
|
6987
7416
|
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);
|
|
6988
|
-
|
|
7417
|
+
React25__default.useEffect(() => {
|
|
6989
7418
|
if (!open || mode !== "days" || !focusDate) return;
|
|
6990
7419
|
gridRef.current?.querySelector(`[data-key="${keyOf(focusDate)}"]`)?.focus();
|
|
6991
7420
|
}, [focusDate, open, mode]);
|
|
@@ -7075,6 +7504,7 @@ function DatePicker({
|
|
|
7075
7504
|
/* @__PURE__ */ jsxs("div", { className: "twc-dp__head", children: [
|
|
7076
7505
|
/* @__PURE__ */ 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__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
7077
7506
|
/* @__PURE__ */ jsx("button", { type: "button", className: "twc-dp__title", onClick: () => setMode(mode === "days" ? "months" : "days"), children: mode === "days" ? `${months[m]} ${y}` : y }),
|
|
7507
|
+
/* @__PURE__ */ jsx("span", { className: "twc-dp__sr", "aria-live": "polite", children: mode === "days" ? `${months[m]} ${y}` : y }),
|
|
7078
7508
|
/* @__PURE__ */ 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__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) }) })
|
|
7079
7509
|
] }),
|
|
7080
7510
|
mode === "days" ? /* @__PURE__ */ jsxs("div", { className: "twc-dp__grid", ref: gridRef, onKeyDown: onGridKeyDown, children: [
|
|
@@ -7175,6 +7605,7 @@ var RANGE_CSS = `
|
|
|
7175
7605
|
.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); }
|
|
7176
7606
|
.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); }
|
|
7177
7607
|
.twc-drp__day:disabled { opacity: 0.3; cursor: not-allowed; }
|
|
7608
|
+
.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; }
|
|
7178
7609
|
[dir="rtl"] .twc-drp__nav svg { transform: scaleX(-1); }
|
|
7179
7610
|
`;
|
|
7180
7611
|
var MONTHS2 = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
@@ -7200,6 +7631,9 @@ function DateRangePicker({
|
|
|
7200
7631
|
presets = true,
|
|
7201
7632
|
locale,
|
|
7202
7633
|
weekStartsOn = 0,
|
|
7634
|
+
min,
|
|
7635
|
+
max,
|
|
7636
|
+
disabledDate,
|
|
7203
7637
|
disabled = false,
|
|
7204
7638
|
tone = "primary",
|
|
7205
7639
|
onChange,
|
|
@@ -7208,23 +7642,23 @@ function DateRangePicker({
|
|
|
7208
7642
|
}) {
|
|
7209
7643
|
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS4);
|
|
7210
7644
|
const __twcStyles1 = useScopedStyles("twc-drp-styles", RANGE_CSS);
|
|
7211
|
-
const [internal, setInternal] =
|
|
7645
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
7212
7646
|
const range = value !== void 0 ? value : internal;
|
|
7213
|
-
const [open, setOpen] =
|
|
7214
|
-
const [view, setView] =
|
|
7215
|
-
const [hover, setHover] =
|
|
7216
|
-
const [coords, setCoords] =
|
|
7217
|
-
const wrapRef =
|
|
7218
|
-
const triggerRef =
|
|
7219
|
-
const popRef =
|
|
7220
|
-
const labelId =
|
|
7647
|
+
const [open, setOpen] = React25__default.useState(false);
|
|
7648
|
+
const [view, setView] = React25__default.useState(range.start || /* @__PURE__ */ new Date());
|
|
7649
|
+
const [hover, setHover] = React25__default.useState(null);
|
|
7650
|
+
const [coords, setCoords] = React25__default.useState(null);
|
|
7651
|
+
const wrapRef = React25__default.useRef(null);
|
|
7652
|
+
const triggerRef = React25__default.useRef(null);
|
|
7653
|
+
const popRef = React25__default.useRef(null);
|
|
7654
|
+
const labelId = React25__default.useId();
|
|
7221
7655
|
const descId = `${labelId}-desc`;
|
|
7222
7656
|
const invalid = Boolean(error);
|
|
7223
|
-
|
|
7657
|
+
React25__default.useEffect(() => {
|
|
7224
7658
|
if (disabled) setOpen(false);
|
|
7225
7659
|
}, [disabled]);
|
|
7226
7660
|
const POP_W = 420;
|
|
7227
|
-
const place =
|
|
7661
|
+
const place = React25__default.useCallback(() => {
|
|
7228
7662
|
const el = triggerRef.current;
|
|
7229
7663
|
if (!el) return;
|
|
7230
7664
|
const r = el.getBoundingClientRect();
|
|
@@ -7235,7 +7669,7 @@ function DateRangePicker({
|
|
|
7235
7669
|
left = Math.max(8, left);
|
|
7236
7670
|
setCoords({ left, top: flip ? void 0 : Math.round(r.bottom + 6), bottom: flip ? Math.round(vh - r.top + 6) : void 0 });
|
|
7237
7671
|
}, []);
|
|
7238
|
-
|
|
7672
|
+
React25__default.useEffect(() => {
|
|
7239
7673
|
if (!open) return void 0;
|
|
7240
7674
|
place();
|
|
7241
7675
|
const onMove = () => place();
|
|
@@ -7246,7 +7680,7 @@ function DateRangePicker({
|
|
|
7246
7680
|
window.removeEventListener("resize", onMove);
|
|
7247
7681
|
};
|
|
7248
7682
|
}, [open, place]);
|
|
7249
|
-
|
|
7683
|
+
React25__default.useEffect(() => {
|
|
7250
7684
|
if (!open) return;
|
|
7251
7685
|
const onDown = (e) => {
|
|
7252
7686
|
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
@@ -7267,7 +7701,9 @@ function DateRangePicker({
|
|
|
7267
7701
|
if (value === void 0) setInternal(r);
|
|
7268
7702
|
onChange?.(r);
|
|
7269
7703
|
};
|
|
7704
|
+
const outOfRange = (d) => min && ymd(d) < ymd(min) || max && ymd(d) > ymd(max) || Boolean(disabledDate && disabledDate(d));
|
|
7270
7705
|
const clickDay = (d) => {
|
|
7706
|
+
if (outOfRange(d)) return;
|
|
7271
7707
|
if (!range.start || range.start && range.end) {
|
|
7272
7708
|
set({ start: d, end: null });
|
|
7273
7709
|
} else {
|
|
@@ -7284,8 +7720,8 @@ function DateRangePicker({
|
|
|
7284
7720
|
setView(start);
|
|
7285
7721
|
setOpen(false);
|
|
7286
7722
|
};
|
|
7287
|
-
const months =
|
|
7288
|
-
const dows =
|
|
7723
|
+
const months = React25__default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
|
|
7724
|
+
const dows = React25__default.useMemo(
|
|
7289
7725
|
() => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW2[(i + weekStartsOn) % 7]) : weekdayNames2(locale, weekStartsOn),
|
|
7290
7726
|
[locale, weekStartsOn]
|
|
7291
7727
|
);
|
|
@@ -7367,6 +7803,11 @@ function DateRangePicker({
|
|
|
7367
7803
|
" ",
|
|
7368
7804
|
y
|
|
7369
7805
|
] }),
|
|
7806
|
+
/* @__PURE__ */ jsxs("span", { className: "twc-drp__sr", "aria-live": "polite", children: [
|
|
7807
|
+
months[m],
|
|
7808
|
+
" ",
|
|
7809
|
+
y
|
|
7810
|
+
] }),
|
|
7370
7811
|
/* @__PURE__ */ jsx("button", { type: "button", className: "twc-drp__nav", "aria-label": "Next month", onClick: () => setView(new Date(y, m + 1, 1)), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) }) })
|
|
7371
7812
|
] }),
|
|
7372
7813
|
/* @__PURE__ */ jsxs("div", { className: "twc-drp__grid", children: [
|
|
@@ -7380,6 +7821,7 @@ function DateRangePicker({
|
|
|
7380
7821
|
type: "button",
|
|
7381
7822
|
className: "twc-drp__day",
|
|
7382
7823
|
"data-outside": outside || void 0,
|
|
7824
|
+
disabled: outOfRange(d) || void 0,
|
|
7383
7825
|
"data-in": inRange(t) || void 0,
|
|
7384
7826
|
"data-edge": edgeOf(t) || void 0,
|
|
7385
7827
|
"aria-pressed": !!edgeOf(t),
|
|
@@ -7466,14 +7908,14 @@ function Dialog({
|
|
|
7466
7908
|
className = "",
|
|
7467
7909
|
...rest
|
|
7468
7910
|
}) {
|
|
7469
|
-
const autoId =
|
|
7911
|
+
const autoId = React25__default.useId();
|
|
7470
7912
|
const titleId = `${autoId}-title`;
|
|
7471
7913
|
const descId = `${autoId}-desc`;
|
|
7472
|
-
const dialogRef =
|
|
7914
|
+
const dialogRef = React25__default.useRef(null);
|
|
7473
7915
|
const __twcStyles = useScopedStyles("twc-dialog-styles", DIALOG_CSS);
|
|
7474
7916
|
const renderPortal = usePortal();
|
|
7475
|
-
const [mounted, setMounted] =
|
|
7476
|
-
|
|
7917
|
+
const [mounted, setMounted] = React25__default.useState(open);
|
|
7918
|
+
React25__default.useEffect(() => {
|
|
7477
7919
|
if (open) {
|
|
7478
7920
|
setMounted(true);
|
|
7479
7921
|
return;
|
|
@@ -7481,16 +7923,10 @@ function Dialog({
|
|
|
7481
7923
|
const t = setTimeout(() => setMounted(false), 170);
|
|
7482
7924
|
return () => clearTimeout(t);
|
|
7483
7925
|
}, [open]);
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
const prev = document.body.style.overflow;
|
|
7487
|
-
document.body.style.overflow = "hidden";
|
|
7488
|
-
return () => {
|
|
7489
|
-
document.body.style.overflow = prev;
|
|
7490
|
-
};
|
|
7491
|
-
}, [open]);
|
|
7926
|
+
useScrollLock(open);
|
|
7927
|
+
useInertBackground(dialogRef, open && mounted);
|
|
7492
7928
|
useFocusTrap(dialogRef, open && mounted);
|
|
7493
|
-
|
|
7929
|
+
React25__default.useEffect(() => {
|
|
7494
7930
|
if (!open) return void 0;
|
|
7495
7931
|
const onKey = (e) => {
|
|
7496
7932
|
if (e.key === "Escape") {
|
|
@@ -7637,14 +8073,14 @@ function Drawer({
|
|
|
7637
8073
|
style,
|
|
7638
8074
|
...rest
|
|
7639
8075
|
}) {
|
|
7640
|
-
const autoId =
|
|
8076
|
+
const autoId = React25__default.useId();
|
|
7641
8077
|
const titleId = `${autoId}-title`;
|
|
7642
8078
|
const descId = `${autoId}-desc`;
|
|
7643
|
-
const panelRef =
|
|
8079
|
+
const panelRef = React25__default.useRef(null);
|
|
7644
8080
|
const __twcStyles = useScopedStyles("twc-drawer-styles", DRAWER_CSS);
|
|
7645
8081
|
const renderPortal = usePortal();
|
|
7646
|
-
const [mounted, setMounted] =
|
|
7647
|
-
|
|
8082
|
+
const [mounted, setMounted] = React25__default.useState(open);
|
|
8083
|
+
React25__default.useEffect(() => {
|
|
7648
8084
|
if (open) {
|
|
7649
8085
|
setMounted(true);
|
|
7650
8086
|
return;
|
|
@@ -7652,16 +8088,10 @@ function Drawer({
|
|
|
7652
8088
|
const t = setTimeout(() => setMounted(false), 170);
|
|
7653
8089
|
return () => clearTimeout(t);
|
|
7654
8090
|
}, [open]);
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
return () => {
|
|
7660
|
-
document.body.style.overflow = prev;
|
|
7661
|
-
};
|
|
7662
|
-
}, [open]);
|
|
7663
|
-
useFocusTrap(panelRef, open && mounted);
|
|
7664
|
-
React24__default.useEffect(() => {
|
|
8091
|
+
useScrollLock(open);
|
|
8092
|
+
useInertBackground(panelRef, open && mounted);
|
|
8093
|
+
useFocusTrap(panelRef, open && mounted);
|
|
8094
|
+
React25__default.useEffect(() => {
|
|
7665
8095
|
if (!open) return void 0;
|
|
7666
8096
|
const onKey = (e) => {
|
|
7667
8097
|
if (e.key === "Escape") {
|
|
@@ -7750,16 +8180,21 @@ function Field({
|
|
|
7750
8180
|
...rest
|
|
7751
8181
|
}) {
|
|
7752
8182
|
const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS5);
|
|
7753
|
-
const autoId =
|
|
8183
|
+
const autoId = React25__default.useId();
|
|
7754
8184
|
const fieldId = id || autoId;
|
|
7755
8185
|
const descId = `${fieldId}-desc`;
|
|
8186
|
+
const hasMsg = Boolean(error || hint);
|
|
8187
|
+
const control = React25__default.isValidElement(children) ? React25__default.cloneElement(children, {
|
|
8188
|
+
"aria-describedby": [children.props["aria-describedby"], hasMsg ? descId : null].filter(Boolean).join(" ") || void 0,
|
|
8189
|
+
"aria-invalid": children.props["aria-invalid"] !== void 0 ? children.props["aria-invalid"] : error ? true : void 0
|
|
8190
|
+
}) : children;
|
|
7756
8191
|
return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, "data-size": size, ...rest, children: [
|
|
7757
8192
|
__twcStyles,
|
|
7758
8193
|
label ? /* @__PURE__ */ jsxs("label", { className: "twc-field__label", htmlFor, children: [
|
|
7759
8194
|
label,
|
|
7760
8195
|
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
7761
8196
|
] }) : null,
|
|
7762
|
-
|
|
8197
|
+
control,
|
|
7763
8198
|
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
|
|
7764
8199
|
] });
|
|
7765
8200
|
}
|
|
@@ -7813,6 +8248,14 @@ function fmtSize(bytes) {
|
|
|
7813
8248
|
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
|
7814
8249
|
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
|
7815
8250
|
}
|
|
8251
|
+
function matchesAccept(file, accept) {
|
|
8252
|
+
if (!accept) return true;
|
|
8253
|
+
const toks = accept.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
|
|
8254
|
+
if (!toks.length) return true;
|
|
8255
|
+
const name = file.name.toLowerCase(), type = (file.type || "").toLowerCase();
|
|
8256
|
+
return toks.some((t) => t.startsWith(".") ? name.endsWith(t) : t.endsWith("/*") ? type.startsWith(t.slice(0, -1)) : type === t);
|
|
8257
|
+
}
|
|
8258
|
+
var fileKey = (f) => `${f.name}-${f.size}-${f.lastModified}`;
|
|
7816
8259
|
function FileUpload({
|
|
7817
8260
|
accept,
|
|
7818
8261
|
multiple = false,
|
|
@@ -7824,17 +8267,20 @@ function FileUpload({
|
|
|
7824
8267
|
required = false,
|
|
7825
8268
|
value,
|
|
7826
8269
|
defaultValue = [],
|
|
8270
|
+
maxSize,
|
|
8271
|
+
maxFiles,
|
|
8272
|
+
onReject,
|
|
7827
8273
|
onChange,
|
|
7828
8274
|
id,
|
|
7829
8275
|
className = "",
|
|
7830
8276
|
...rest
|
|
7831
8277
|
}) {
|
|
7832
8278
|
const __twcStyles = useScopedStyles("twc-upload-styles", UPLOAD_CSS);
|
|
7833
|
-
const [internal, setInternal] =
|
|
8279
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
7834
8280
|
const files = value !== void 0 ? value : internal;
|
|
7835
|
-
const [drag, setDrag] =
|
|
7836
|
-
const inputRef =
|
|
7837
|
-
const autoId =
|
|
8281
|
+
const [drag, setDrag] = React25__default.useState(false);
|
|
8282
|
+
const inputRef = React25__default.useRef(null);
|
|
8283
|
+
const autoId = React25__default.useId();
|
|
7838
8284
|
const fieldId = id || autoId;
|
|
7839
8285
|
const descId = `${fieldId}-desc`;
|
|
7840
8286
|
const invalid = Boolean(error);
|
|
@@ -7843,8 +8289,28 @@ function FileUpload({
|
|
|
7843
8289
|
onChange?.(next);
|
|
7844
8290
|
};
|
|
7845
8291
|
function addFiles(list) {
|
|
7846
|
-
const
|
|
7847
|
-
|
|
8292
|
+
const incoming = Array.from(list);
|
|
8293
|
+
const retained = multiple ? files.slice() : [];
|
|
8294
|
+
const seen2 = new Set(retained.map(fileKey));
|
|
8295
|
+
const accepted = [];
|
|
8296
|
+
const rejections = [];
|
|
8297
|
+
for (const f of incoming) {
|
|
8298
|
+
if (multiple && seen2.has(fileKey(f))) continue;
|
|
8299
|
+
let reason = null;
|
|
8300
|
+
if (accept && !matchesAccept(f, accept)) reason = "type";
|
|
8301
|
+
else if (maxSize && f.size > maxSize) reason = "size";
|
|
8302
|
+
else if (multiple && maxFiles && retained.length + accepted.length >= maxFiles) reason = "count";
|
|
8303
|
+
if (reason) {
|
|
8304
|
+
rejections.push({ file: f, reason });
|
|
8305
|
+
continue;
|
|
8306
|
+
}
|
|
8307
|
+
accepted.push(f);
|
|
8308
|
+
if (multiple) seen2.add(fileKey(f));
|
|
8309
|
+
}
|
|
8310
|
+
if (rejections.length) onReject?.(rejections);
|
|
8311
|
+
if (multiple) {
|
|
8312
|
+
if (accepted.length) set([...retained, ...accepted]);
|
|
8313
|
+
} else if (accepted.length) set(accepted.slice(0, 1));
|
|
7848
8314
|
}
|
|
7849
8315
|
function remove(i) {
|
|
7850
8316
|
set(files.filter((_, idx) => idx !== i));
|
|
@@ -7918,7 +8384,7 @@ function FileUpload({
|
|
|
7918
8384
|
/* @__PURE__ */ jsx("span", { className: "twc-upload__file-size", children: fmtSize(f.size) })
|
|
7919
8385
|
] }),
|
|
7920
8386
|
/* @__PURE__ */ jsx("button", { className: "twc-upload__file-x", "aria-label": `Remove ${f.name}`, onClick: () => remove(i), type: "button", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) })
|
|
7921
|
-
] },
|
|
8387
|
+
] }, fileKey(f))) }) : null,
|
|
7922
8388
|
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : null
|
|
7923
8389
|
] });
|
|
7924
8390
|
}
|
|
@@ -8037,15 +8503,15 @@ function Kanban({
|
|
|
8037
8503
|
...rest
|
|
8038
8504
|
}) {
|
|
8039
8505
|
const __twcStyles = useScopedStyles("twc-kanban-styles", KANBAN_CSS);
|
|
8040
|
-
const [internal, setInternal] =
|
|
8506
|
+
const [internal, setInternal] = React25__default.useState(cards ?? defaultCards ?? []);
|
|
8041
8507
|
const items = cards !== void 0 ? cards : internal;
|
|
8042
|
-
const [drag, setDrag] =
|
|
8043
|
-
const [overCol, setOverCol] =
|
|
8044
|
-
const [grab, setGrab] =
|
|
8045
|
-
const [announce, setAnnounce] =
|
|
8046
|
-
const rootRef =
|
|
8047
|
-
const focusIdRef =
|
|
8048
|
-
|
|
8508
|
+
const [drag, setDrag] = React25__default.useState(null);
|
|
8509
|
+
const [overCol, setOverCol] = React25__default.useState(null);
|
|
8510
|
+
const [grab, setGrab] = React25__default.useState(null);
|
|
8511
|
+
const [announce, setAnnounce] = React25__default.useState("");
|
|
8512
|
+
const rootRef = React25__default.useRef(null);
|
|
8513
|
+
const focusIdRef = React25__default.useRef(null);
|
|
8514
|
+
React25__default.useEffect(() => {
|
|
8049
8515
|
if (focusIdRef.current == null) return void 0;
|
|
8050
8516
|
const raf = requestAnimationFrame(() => {
|
|
8051
8517
|
const id = focusIdRef.current;
|
|
@@ -8190,42 +8656,49 @@ var LIST_CSS = `
|
|
|
8190
8656
|
.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; }
|
|
8191
8657
|
.twc-list__desc { font-size: var(--text-xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
8192
8658
|
.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); }
|
|
8659
|
+
.twc-list__empty { padding: 30px 12px; text-align: center; color: var(--color-text-subtle); font-size: var(--text-sm); }
|
|
8193
8660
|
`;
|
|
8194
|
-
function List({ items, plain = false, className = "", ...rest }) {
|
|
8661
|
+
function List({ items, plain = false, emptyMessage, className = "", ...rest }) {
|
|
8195
8662
|
const __twcStyles = useScopedStyles("twc-list-styles", LIST_CSS);
|
|
8196
8663
|
const safeHref12 = (url) => {
|
|
8197
8664
|
if (url == null) return void 0;
|
|
8198
8665
|
const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
|
|
8199
8666
|
return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
|
|
8200
8667
|
};
|
|
8201
|
-
return
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8668
|
+
return (
|
|
8669
|
+
// role="list" before {...rest} so a consumer can still override it (e.g. role="menu");
|
|
8670
|
+
// list-style:none + display:contents on the <li> drop the implicit list/listitem roles
|
|
8671
|
+
// in some engines, so we set them explicitly (#123).
|
|
8672
|
+
/* @__PURE__ */ jsxs("ul", { className: `twc-list ${className}`, role: "list", "data-plain": plain || void 0, ...rest, children: [
|
|
8673
|
+
__twcStyles,
|
|
8674
|
+
items.length === 0 ? /* @__PURE__ */ jsx("li", { role: "presentation", style: { display: "contents" }, children: /* @__PURE__ */ jsx("div", { className: "twc-list__empty", children: emptyMessage ?? "Nothing here yet" }) }) : items.map((it, i) => {
|
|
8675
|
+
const href = safeHref12(it.href);
|
|
8676
|
+
const interactive = Boolean(it.onClick || href);
|
|
8677
|
+
const Tag2 = href ? "a" : interactive ? "button" : "div";
|
|
8678
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8679
|
+
it.leading ? /* @__PURE__ */ jsx("span", { className: "twc-list__lead", "aria-hidden": "true", children: it.leading }) : null,
|
|
8680
|
+
/* @__PURE__ */ jsxs("span", { className: "twc-list__main", children: [
|
|
8681
|
+
/* @__PURE__ */ jsx("span", { className: "twc-list__title", children: it.title }),
|
|
8682
|
+
it.description ? /* @__PURE__ */ jsx("span", { className: "twc-list__desc", children: it.description }) : null
|
|
8683
|
+
] }),
|
|
8684
|
+
it.trailing ? /* @__PURE__ */ jsx("span", { className: "twc-list__trail", children: it.trailing }) : null
|
|
8685
|
+
] });
|
|
8686
|
+
return /* @__PURE__ */ jsx("li", { role: "listitem", style: { display: "contents" }, children: /* @__PURE__ */ jsx(
|
|
8687
|
+
Tag2,
|
|
8688
|
+
{
|
|
8689
|
+
className: "twc-list__item",
|
|
8690
|
+
"data-interactive": interactive || void 0,
|
|
8691
|
+
"data-active": it.active || void 0,
|
|
8692
|
+
"aria-current": it.active ? "page" : void 0,
|
|
8693
|
+
href,
|
|
8694
|
+
type: Tag2 === "button" ? "button" : void 0,
|
|
8695
|
+
onClick: it.onClick,
|
|
8696
|
+
children: content
|
|
8697
|
+
}
|
|
8698
|
+
) }, i);
|
|
8699
|
+
})
|
|
8700
|
+
] })
|
|
8701
|
+
);
|
|
8229
8702
|
}
|
|
8230
8703
|
var NAVBAR_CSS = `
|
|
8231
8704
|
.twc-navbar { display: flex; align-items: center; gap: var(--space-4); height: 60px; padding: 0 var(--space-5);
|
|
@@ -8348,21 +8821,21 @@ function Popover({
|
|
|
8348
8821
|
...rest
|
|
8349
8822
|
}) {
|
|
8350
8823
|
const __twcStyles = useScopedStyles("twc-popover-styles", POPOVER_CSS);
|
|
8351
|
-
const [openState, setOpenState] =
|
|
8352
|
-
const [render, setRender] =
|
|
8353
|
-
const [pos, setPos] =
|
|
8354
|
-
const wrapRef =
|
|
8355
|
-
const popRef =
|
|
8356
|
-
const popId =
|
|
8824
|
+
const [openState, setOpenState] = React25__default.useState(defaultOpen);
|
|
8825
|
+
const [render, setRender] = React25__default.useState(false);
|
|
8826
|
+
const [pos, setPos] = React25__default.useState(null);
|
|
8827
|
+
const wrapRef = React25__default.useRef(null);
|
|
8828
|
+
const popRef = React25__default.useRef(null);
|
|
8829
|
+
const popId = React25__default.useId();
|
|
8357
8830
|
const controlled = openProp !== void 0;
|
|
8358
8831
|
const open = controlled ? !!openProp : openState;
|
|
8359
|
-
const openRef =
|
|
8832
|
+
const openRef = React25__default.useRef(open);
|
|
8360
8833
|
openRef.current = open;
|
|
8361
|
-
const controlledRef =
|
|
8834
|
+
const controlledRef = React25__default.useRef(controlled);
|
|
8362
8835
|
controlledRef.current = controlled;
|
|
8363
|
-
const onOpenChangeRef =
|
|
8836
|
+
const onOpenChangeRef = React25__default.useRef(onOpenChange);
|
|
8364
8837
|
onOpenChangeRef.current = onOpenChange;
|
|
8365
|
-
const setOpen =
|
|
8838
|
+
const setOpen = React25__default.useCallback((next) => {
|
|
8366
8839
|
const value = typeof next === "function" ? next(openRef.current) : next;
|
|
8367
8840
|
if (value === openRef.current) return;
|
|
8368
8841
|
if (!controlledRef.current) setOpenState(value);
|
|
@@ -8370,7 +8843,7 @@ function Popover({
|
|
|
8370
8843
|
}, []);
|
|
8371
8844
|
const toggle = () => setOpen((o) => !o);
|
|
8372
8845
|
const RD = { createPortal: typeof createPortal === "function" ? createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
|
|
8373
|
-
const place =
|
|
8846
|
+
const place = React25__default.useCallback(() => {
|
|
8374
8847
|
const t = wrapRef.current;
|
|
8375
8848
|
if (!t) return;
|
|
8376
8849
|
const r = t.getBoundingClientRect();
|
|
@@ -8380,7 +8853,13 @@ function Popover({
|
|
|
8380
8853
|
let top, left, flip = false, arrow = {};
|
|
8381
8854
|
const vertical = placement === "top" || placement === "bottom";
|
|
8382
8855
|
if (vertical) {
|
|
8383
|
-
|
|
8856
|
+
const ph2 = popRef.current ? popRef.current.offsetHeight : 120;
|
|
8857
|
+
const spaceAbove = r.top - gap - M;
|
|
8858
|
+
const spaceBelow = vh - r.bottom - gap - M;
|
|
8859
|
+
let openUp = placement === "top";
|
|
8860
|
+
if (openUp && spaceAbove < ph2 && spaceBelow > spaceAbove) openUp = false;
|
|
8861
|
+
else if (!openUp && spaceBelow < ph2 && spaceAbove > spaceBelow) openUp = true;
|
|
8862
|
+
flip = openUp;
|
|
8384
8863
|
top = flip ? void 0 : r.bottom + gap;
|
|
8385
8864
|
const bottom = flip ? vh - r.top + gap : void 0;
|
|
8386
8865
|
let l = align === "start" ? r.left : align === "end" ? r.right - w : r.left + r.width / 2 - w / 2;
|
|
@@ -8401,7 +8880,7 @@ function Popover({
|
|
|
8401
8880
|
arrow = { top: Math.min(Math.max(cy - top - 5.5, 8), ph - 18), [onRight ? "left" : "right"]: -6 };
|
|
8402
8881
|
setPos({ top, left, width: w, flip: false, arrow });
|
|
8403
8882
|
}, [placement, align, width]);
|
|
8404
|
-
|
|
8883
|
+
React25__default.useEffect(() => {
|
|
8405
8884
|
if (!open) return;
|
|
8406
8885
|
place();
|
|
8407
8886
|
const onMove = () => place();
|
|
@@ -8424,7 +8903,7 @@ function Popover({
|
|
|
8424
8903
|
document.removeEventListener("keydown", onKey);
|
|
8425
8904
|
};
|
|
8426
8905
|
}, [open, place]);
|
|
8427
|
-
|
|
8906
|
+
React25__default.useEffect(() => {
|
|
8428
8907
|
if (open) {
|
|
8429
8908
|
setRender(true);
|
|
8430
8909
|
return;
|
|
@@ -8432,12 +8911,12 @@ function Popover({
|
|
|
8432
8911
|
const t = setTimeout(() => setRender(false), 170);
|
|
8433
8912
|
return () => clearTimeout(t);
|
|
8434
8913
|
}, [open]);
|
|
8435
|
-
|
|
8914
|
+
React25__default.useEffect(() => {
|
|
8436
8915
|
if (render && open) place();
|
|
8437
8916
|
}, [render, place]);
|
|
8438
|
-
const restoreRef =
|
|
8439
|
-
const needFocusRef =
|
|
8440
|
-
|
|
8917
|
+
const restoreRef = React25__default.useRef(null);
|
|
8918
|
+
const needFocusRef = React25__default.useRef(false);
|
|
8919
|
+
React25__default.useEffect(() => {
|
|
8441
8920
|
if (open) {
|
|
8442
8921
|
restoreRef.current = document.activeElement;
|
|
8443
8922
|
needFocusRef.current = true;
|
|
@@ -8448,12 +8927,7 @@ function Popover({
|
|
|
8448
8927
|
needFocusRef.current = false;
|
|
8449
8928
|
if (prev && typeof prev.focus === "function" && popRef.current?.contains(document.activeElement)) prev.focus();
|
|
8450
8929
|
}, [open]);
|
|
8451
|
-
|
|
8452
|
-
if (open && render && pos && needFocusRef.current) {
|
|
8453
|
-
needFocusRef.current = false;
|
|
8454
|
-
popRef.current?.focus({ preventScroll: true });
|
|
8455
|
-
}
|
|
8456
|
-
}, [open, render, pos]);
|
|
8930
|
+
useFocusTrap(popRef, open && render && !!pos, { restoreFocus: false });
|
|
8457
8931
|
const pop = render && pos ? /* @__PURE__ */ jsxs(
|
|
8458
8932
|
"div",
|
|
8459
8933
|
{
|
|
@@ -8464,6 +8938,7 @@ function Popover({
|
|
|
8464
8938
|
"data-state": open ? "open" : "closed",
|
|
8465
8939
|
"data-flip": pos.flip || void 0,
|
|
8466
8940
|
role: "dialog",
|
|
8941
|
+
"aria-modal": "true",
|
|
8467
8942
|
"aria-labelledby": title ? `${popId}-title` : void 0,
|
|
8468
8943
|
style: { top: pos.top, bottom: pos.bottom, left: pos.left, width: pos.width },
|
|
8469
8944
|
children: [
|
|
@@ -8476,7 +8951,7 @@ function Popover({
|
|
|
8476
8951
|
]
|
|
8477
8952
|
}
|
|
8478
8953
|
) : null;
|
|
8479
|
-
const triggerEl =
|
|
8954
|
+
const triggerEl = React25__default.isValidElement(trigger) ? React25__default.cloneElement(trigger, {
|
|
8480
8955
|
onClick: (e) => {
|
|
8481
8956
|
trigger.props.onClick?.(e);
|
|
8482
8957
|
toggle();
|
|
@@ -8519,7 +8994,7 @@ function Progress({
|
|
|
8519
8994
|
className = "",
|
|
8520
8995
|
...rest
|
|
8521
8996
|
}) {
|
|
8522
|
-
const labelId =
|
|
8997
|
+
const labelId = React25__default.useId();
|
|
8523
8998
|
const { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...restProps } = rest;
|
|
8524
8999
|
const __twcStyles = useScopedStyles("twc-progress-styles", `
|
|
8525
9000
|
.twc-progress-wrap { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-sans); }
|
|
@@ -8642,10 +9117,13 @@ function Radio({
|
|
|
8642
9117
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
8643
9118
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
8644
9119
|
`);
|
|
8645
|
-
const autoId =
|
|
9120
|
+
const autoId = React25__default.useId();
|
|
8646
9121
|
const fieldId = id || autoId;
|
|
8647
9122
|
const errId = `${fieldId}-error`;
|
|
8648
9123
|
const invalid = Boolean(error);
|
|
9124
|
+
if (process.env.NODE_ENV !== "production" && !label && !description && !rest["aria-label"] && !rest["aria-labelledby"]) {
|
|
9125
|
+
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).");
|
|
9126
|
+
}
|
|
8649
9127
|
const describedBy = [rest["aria-describedby"], error ? errId : null].filter(Boolean).join(" ") || void 0;
|
|
8650
9128
|
const control = /* @__PURE__ */ 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: [
|
|
8651
9129
|
__twcStyles,
|
|
@@ -8662,6 +9140,7 @@ function Radio({
|
|
|
8662
9140
|
disabled,
|
|
8663
9141
|
onChange,
|
|
8664
9142
|
...rest,
|
|
9143
|
+
required: required || void 0,
|
|
8665
9144
|
"aria-required": required || void 0,
|
|
8666
9145
|
"aria-invalid": invalid || void 0,
|
|
8667
9146
|
"aria-describedby": describedBy
|
|
@@ -8679,11 +9158,103 @@ function Radio({
|
|
|
8679
9158
|
/* @__PURE__ */ jsx("span", { id: errId, className: "twc-field__error", children: error })
|
|
8680
9159
|
] });
|
|
8681
9160
|
}
|
|
9161
|
+
var RADIO_GROUP_CSS = `
|
|
9162
|
+
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
9163
|
+
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
9164
|
+
.twc-field__req { color: var(--color-danger); }
|
|
9165
|
+
.twc-field__hint { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
9166
|
+
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
9167
|
+
.twc-radio-group__items { display: flex; flex-direction: column; gap: var(--space-2-5); }
|
|
9168
|
+
.twc-radio-group__items[data-orientation="horizontal"] { flex-direction: row; flex-wrap: wrap; gap: var(--space-4); }
|
|
9169
|
+
`;
|
|
9170
|
+
function RadioGroup({
|
|
9171
|
+
name,
|
|
9172
|
+
value,
|
|
9173
|
+
defaultValue,
|
|
9174
|
+
onChange,
|
|
9175
|
+
options,
|
|
9176
|
+
children,
|
|
9177
|
+
label,
|
|
9178
|
+
hint,
|
|
9179
|
+
error,
|
|
9180
|
+
orientation = "vertical",
|
|
9181
|
+
disabled = false,
|
|
9182
|
+
required = false,
|
|
9183
|
+
size = "md",
|
|
9184
|
+
tone = "primary",
|
|
9185
|
+
id,
|
|
9186
|
+
className = "",
|
|
9187
|
+
...rest
|
|
9188
|
+
}) {
|
|
9189
|
+
const __twcStyles = useScopedStyles("twc-radio-group-styles", RADIO_GROUP_CSS);
|
|
9190
|
+
const autoId = React25__default.useId();
|
|
9191
|
+
const fieldId = id || autoId;
|
|
9192
|
+
const labelId = `${fieldId}-label`;
|
|
9193
|
+
const descId = `${fieldId}-desc`;
|
|
9194
|
+
const groupName = name || `${fieldId}-name`;
|
|
9195
|
+
const invalid = Boolean(error);
|
|
9196
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
9197
|
+
const current = value !== void 0 ? value : internal;
|
|
9198
|
+
const select = (v) => {
|
|
9199
|
+
if (value === void 0) setInternal(v);
|
|
9200
|
+
onChange?.(v);
|
|
9201
|
+
};
|
|
9202
|
+
const radios = options ? options.map((o) => /* @__PURE__ */ jsx(
|
|
9203
|
+
Radio,
|
|
9204
|
+
{
|
|
9205
|
+
name: groupName,
|
|
9206
|
+
value: o.value,
|
|
9207
|
+
label: o.label,
|
|
9208
|
+
description: o.description,
|
|
9209
|
+
checked: current === o.value,
|
|
9210
|
+
onChange: () => select(o.value),
|
|
9211
|
+
disabled: disabled || o.disabled,
|
|
9212
|
+
required,
|
|
9213
|
+
size,
|
|
9214
|
+
tone
|
|
9215
|
+
},
|
|
9216
|
+
o.value
|
|
9217
|
+
)) : React25__default.Children.map(children, (child) => {
|
|
9218
|
+
if (!React25__default.isValidElement(child)) return child;
|
|
9219
|
+
const v = child.props.value;
|
|
9220
|
+
return React25__default.cloneElement(child, {
|
|
9221
|
+
name: child.props.name ?? groupName,
|
|
9222
|
+
checked: child.props.checked ?? current === v,
|
|
9223
|
+
onChange: child.props.onChange ?? (() => select(v)),
|
|
9224
|
+
disabled: child.props.disabled ?? disabled,
|
|
9225
|
+
required: child.props.required ?? required,
|
|
9226
|
+
size: child.props.size ?? size,
|
|
9227
|
+
tone: child.props.tone ?? tone
|
|
9228
|
+
});
|
|
9229
|
+
});
|
|
9230
|
+
return /* @__PURE__ */ jsxs(
|
|
9231
|
+
"div",
|
|
9232
|
+
{
|
|
9233
|
+
className: `twc-field ${className}`,
|
|
9234
|
+
role: "radiogroup",
|
|
9235
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
9236
|
+
"aria-describedby": error || hint ? descId : void 0,
|
|
9237
|
+
"aria-invalid": invalid || void 0,
|
|
9238
|
+
"aria-required": required || void 0,
|
|
9239
|
+
"data-orientation": orientation,
|
|
9240
|
+
...rest,
|
|
9241
|
+
children: [
|
|
9242
|
+
__twcStyles,
|
|
9243
|
+
label ? /* @__PURE__ */ jsxs("span", { id: labelId, className: "twc-field__label", children: [
|
|
9244
|
+
label,
|
|
9245
|
+
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
9246
|
+
] }) : null,
|
|
9247
|
+
/* @__PURE__ */ jsx("div", { className: "twc-radio-group__items", "data-orientation": orientation === "horizontal" ? "horizontal" : void 0, children: radios }),
|
|
9248
|
+
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
|
|
9249
|
+
]
|
|
9250
|
+
}
|
|
9251
|
+
);
|
|
9252
|
+
}
|
|
8682
9253
|
var RATING_CSS = `
|
|
8683
9254
|
.twc-rating { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-sans); }
|
|
8684
9255
|
.twc-rating__stars { display: inline-flex; gap: 2px; }
|
|
8685
|
-
.twc-rating__btn { border: none; background: transparent; padding: 1px; cursor: pointer;
|
|
8686
|
-
transition: transform var(--duration-fast) var(--ease-spring)
|
|
9256
|
+
.twc-rating__btn { border: none; background: transparent; padding: 1px; cursor: pointer; line-height: 0;
|
|
9257
|
+
transition: transform var(--duration-fast) var(--ease-spring); }
|
|
8687
9258
|
.twc-rating__btn:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius-sm); }
|
|
8688
9259
|
.twc-rating[data-readonly="true"] .twc-rating__btn { cursor: default; }
|
|
8689
9260
|
.twc-rating[data-disabled="true"] { opacity: 0.55; }
|
|
@@ -8697,8 +9268,11 @@ var RATING_CSS = `
|
|
|
8697
9268
|
.twc-rating[data-tone="danger"] { --_accent: var(--color-danger); }
|
|
8698
9269
|
.twc-rating[data-tone="info"] { --_accent: var(--color-info); }
|
|
8699
9270
|
.twc-rating[data-tone="neutral"] { --_accent: var(--color-text); }
|
|
8700
|
-
|
|
8701
|
-
.twc-
|
|
9271
|
+
/* Per-star partial fill: an accent-colored star clipped to var(--twc-fill) over an empty star. */
|
|
9272
|
+
.twc-rating__star { position: relative; display: inline-block; line-height: 0; }
|
|
9273
|
+
.twc-rating__bg { color: var(--color-border-strong); }
|
|
9274
|
+
.twc-rating__fg { position: absolute; inset-block: 0; inset-inline-start: 0; width: var(--twc-fill, 0%); overflow: hidden; color: var(--_c, var(--_accent)); }
|
|
9275
|
+
.twc-rating svg { width: var(--_sz, 24px); height: var(--_sz, 24px); display: block; }
|
|
8702
9276
|
.twc-rating[data-size="sm"] { --_sz: 18px; }
|
|
8703
9277
|
.twc-rating[data-size="lg"] { --_sz: 32px; }
|
|
8704
9278
|
.twc-rating__value { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
|
|
@@ -8714,19 +9288,26 @@ function Rating({
|
|
|
8714
9288
|
readOnly = false,
|
|
8715
9289
|
disabled = false,
|
|
8716
9290
|
showValue = false,
|
|
9291
|
+
clearable = true,
|
|
9292
|
+
format,
|
|
9293
|
+
name,
|
|
8717
9294
|
onChange,
|
|
8718
9295
|
className = "",
|
|
8719
9296
|
style,
|
|
8720
9297
|
...rest
|
|
8721
9298
|
}) {
|
|
8722
9299
|
const __twcStyles = useScopedStyles("twc-rating-styles", RATING_CSS);
|
|
8723
|
-
const [internal, setInternal] =
|
|
8724
|
-
const [hover, setHover] =
|
|
9300
|
+
const [internal, setInternal] = React25__default.useState(defaultValue);
|
|
9301
|
+
const [hover, setHover] = React25__default.useState(0);
|
|
8725
9302
|
const val = value !== void 0 ? value : internal;
|
|
8726
9303
|
const shown = hover || val;
|
|
8727
9304
|
const interactive = !readOnly && !disabled;
|
|
8728
|
-
const btnRefs =
|
|
9305
|
+
const btnRefs = React25__default.useRef([]);
|
|
8729
9306
|
const tabStar = Math.min(count, Math.max(1, Math.round(val) || 1));
|
|
9307
|
+
const fmt = (v) => format ? format(v) : Number.isInteger(v) ? String(v) : v.toFixed(1);
|
|
9308
|
+
if (process.env.NODE_ENV !== "production" && interactive && !Number.isInteger(val)) {
|
|
9309
|
+
warnOnce("Rating.fractional-interactive", "Rating: a fractional value only renders (partial-fill display) in readOnly mode \u2014 interactive selection is integer-only.");
|
|
9310
|
+
}
|
|
8730
9311
|
const set = (v) => {
|
|
8731
9312
|
if (!interactive) return;
|
|
8732
9313
|
if (value === void 0) setInternal(v);
|
|
@@ -8739,18 +9320,46 @@ function Rating({
|
|
|
8739
9320
|
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next = Math.max(1, val - 1);
|
|
8740
9321
|
else if (e.key === "Home") next = 1;
|
|
8741
9322
|
else if (e.key === "End") next = count;
|
|
9323
|
+
else if (clearable && (e.key === "Delete" || e.key === "Backspace")) next = 0;
|
|
8742
9324
|
else return;
|
|
8743
9325
|
e.preventDefault();
|
|
8744
9326
|
set(next);
|
|
8745
|
-
btnRefs.current[next - 1]?.focus();
|
|
9327
|
+
btnRefs.current[Math.max(0, next - 1)]?.focus();
|
|
9328
|
+
};
|
|
9329
|
+
const star = (n) => {
|
|
9330
|
+
const fill = Math.max(0, Math.min(1, shown - (n - 1)));
|
|
9331
|
+
return /* @__PURE__ */ jsxs("span", { className: "twc-rating__star", style: { "--twc-fill": `${fill * 100}%` }, children: [
|
|
9332
|
+
/* @__PURE__ */ jsx("svg", { className: "twc-rating__bg", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: StarPath }) }),
|
|
9333
|
+
/* @__PURE__ */ jsx("span", { className: "twc-rating__fg", "aria-hidden": "true", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: StarPath }) }) })
|
|
9334
|
+
] });
|
|
8746
9335
|
};
|
|
9336
|
+
if (readOnly) {
|
|
9337
|
+
return /* @__PURE__ */ jsxs(
|
|
9338
|
+
"div",
|
|
9339
|
+
{
|
|
9340
|
+
className: `twc-rating ${className}`,
|
|
9341
|
+
"data-size": size,
|
|
9342
|
+
"data-tone": tone,
|
|
9343
|
+
"data-readonly": "true",
|
|
9344
|
+
style: color ? { "--_c": color, ...style } : style,
|
|
9345
|
+
role: "img",
|
|
9346
|
+
"aria-label": `${fmt(val)} out of ${count} stars`,
|
|
9347
|
+
...rest,
|
|
9348
|
+
children: [
|
|
9349
|
+
__twcStyles,
|
|
9350
|
+
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: val, disabled: disabled || void 0 }) : null,
|
|
9351
|
+
/* @__PURE__ */ jsx("span", { className: "twc-rating__stars", children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ jsx("span", { className: "twc-rating__btn", children: star(i + 1) }, i + 1)) }),
|
|
9352
|
+
showValue ? /* @__PURE__ */ jsx("span", { className: "twc-rating__value", children: fmt(val) }) : null
|
|
9353
|
+
]
|
|
9354
|
+
}
|
|
9355
|
+
);
|
|
9356
|
+
}
|
|
8747
9357
|
return /* @__PURE__ */ jsxs(
|
|
8748
9358
|
"div",
|
|
8749
9359
|
{
|
|
8750
9360
|
className: `twc-rating ${className}`,
|
|
8751
9361
|
"data-size": size,
|
|
8752
9362
|
"data-tone": tone,
|
|
8753
|
-
"data-readonly": readOnly || void 0,
|
|
8754
9363
|
"data-disabled": disabled || void 0,
|
|
8755
9364
|
style: color ? { "--_c": color, ...style } : style,
|
|
8756
9365
|
role: "radiogroup",
|
|
@@ -8759,6 +9368,7 @@ function Rating({
|
|
|
8759
9368
|
...rest,
|
|
8760
9369
|
children: [
|
|
8761
9370
|
__twcStyles,
|
|
9371
|
+
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: val, disabled: disabled || void 0 }) : null,
|
|
8762
9372
|
/* @__PURE__ */ jsx("span", { className: "twc-rating__stars", onMouseLeave: () => setHover(0), onKeyDown, children: Array.from({ length: count }).map((_, i) => {
|
|
8763
9373
|
const n = i + 1;
|
|
8764
9374
|
return /* @__PURE__ */ jsx(
|
|
@@ -8769,149 +9379,19 @@ function Rating({
|
|
|
8769
9379
|
},
|
|
8770
9380
|
type: "button",
|
|
8771
9381
|
className: "twc-rating__btn",
|
|
8772
|
-
"data-on": n <= shown || void 0,
|
|
8773
9382
|
role: "radio",
|
|
8774
9383
|
"aria-label": `${n} star${n > 1 ? "s" : ""}`,
|
|
8775
9384
|
"aria-checked": n === val,
|
|
8776
|
-
disabled
|
|
9385
|
+
disabled,
|
|
8777
9386
|
tabIndex: interactive && n === tabStar ? 0 : -1,
|
|
8778
9387
|
onMouseEnter: () => interactive && setHover(n),
|
|
8779
|
-
onClick: () => set(n === val ? 0 : n),
|
|
8780
|
-
children:
|
|
9388
|
+
onClick: () => set(n === val && clearable ? 0 : n),
|
|
9389
|
+
children: star(n)
|
|
8781
9390
|
},
|
|
8782
9391
|
n
|
|
8783
9392
|
);
|
|
8784
9393
|
}) }),
|
|
8785
|
-
showValue ? /* @__PURE__ */ jsx("span", { className: "twc-rating__value", children: val
|
|
8786
|
-
]
|
|
8787
|
-
}
|
|
8788
|
-
);
|
|
8789
|
-
}
|
|
8790
|
-
var TOOLTIP_CSS = `
|
|
8791
|
-
.twc-tooltip-wrap { display: inline-flex; }
|
|
8792
|
-
.twc-tooltip {
|
|
8793
|
-
position: fixed; z-index: var(--z-tooltip); pointer-events: none;
|
|
8794
|
-
padding: 6px 10px; border-radius: var(--radius-md);
|
|
8795
|
-
background: var(--color-text); color: var(--color-surface);
|
|
8796
|
-
font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--font-medium);
|
|
8797
|
-
line-height: 1.3; white-space: nowrap; box-shadow: var(--shadow-md);
|
|
8798
|
-
opacity: 0; transform: scale(0.9); transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-spring);
|
|
8799
|
-
}
|
|
8800
|
-
.twc-tooltip[data-show="true"] { opacity: 1; transform: scale(1); }
|
|
8801
|
-
.twc-tooltip[data-place="top"] { transform-origin: bottom center; translate: -50% 0; }
|
|
8802
|
-
.twc-tooltip[data-place="bottom"] { transform-origin: top center; translate: -50% 0; }
|
|
8803
|
-
.twc-tooltip[data-place="left"] { transform-origin: right center; translate: 0 -50%; }
|
|
8804
|
-
.twc-tooltip[data-place="right"] { transform-origin: left center; translate: 0 -50%; }
|
|
8805
|
-
.twc-tooltip[data-show="true"][data-place="top"], .twc-tooltip[data-show="true"][data-place="bottom"] { transform: scale(1); }
|
|
8806
|
-
.twc-tooltip__arrow { position: absolute; width: 7px; height: 7px; background: var(--color-text); transform: rotate(45deg); }
|
|
8807
|
-
.twc-tooltip[data-place="top"] .twc-tooltip__arrow { bottom: -3px; left: 50%; margin-left: -3.5px; }
|
|
8808
|
-
.twc-tooltip[data-place="bottom"] .twc-tooltip__arrow { top: -3px; left: 50%; margin-left: -3.5px; }
|
|
8809
|
-
.twc-tooltip[data-place="left"] .twc-tooltip__arrow { right: -3px; top: 50%; margin-top: -3.5px; }
|
|
8810
|
-
.twc-tooltip[data-place="right"] .twc-tooltip__arrow { left: -3px; top: 50%; margin-top: -3.5px; }
|
|
8811
|
-
@media (prefers-reduced-motion: reduce) { .twc-tooltip { transition: opacity var(--duration-fast) linear; transform: none; } }
|
|
8812
|
-
`;
|
|
8813
|
-
function Tooltip({
|
|
8814
|
-
children,
|
|
8815
|
-
label,
|
|
8816
|
-
placement = "top",
|
|
8817
|
-
delay = 120,
|
|
8818
|
-
className = "",
|
|
8819
|
-
...rest
|
|
8820
|
-
}) {
|
|
8821
|
-
const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
|
|
8822
|
-
const id = React24__default.useId();
|
|
8823
|
-
const [show, setShow] = React24__default.useState(false);
|
|
8824
|
-
const [coords, setCoords] = React24__default.useState(null);
|
|
8825
|
-
const timer = React24__default.useRef(null);
|
|
8826
|
-
const wrapRef = React24__default.useRef(null);
|
|
8827
|
-
const tipRef = React24__default.useRef(null);
|
|
8828
|
-
const open = () => {
|
|
8829
|
-
clearTimeout(timer.current);
|
|
8830
|
-
timer.current = setTimeout(() => setShow(true), delay);
|
|
8831
|
-
};
|
|
8832
|
-
const close = () => {
|
|
8833
|
-
clearTimeout(timer.current);
|
|
8834
|
-
setShow(false);
|
|
8835
|
-
};
|
|
8836
|
-
React24__default.useEffect(() => () => clearTimeout(timer.current), []);
|
|
8837
|
-
const place = React24__default.useCallback(() => {
|
|
8838
|
-
const el = wrapRef.current;
|
|
8839
|
-
if (!el) return;
|
|
8840
|
-
const r = el.getBoundingClientRect();
|
|
8841
|
-
const cx = Math.round(r.left + r.width / 2), cy = Math.round(r.top + r.height / 2);
|
|
8842
|
-
const vw = window.innerWidth, vh = window.innerHeight, gap = 8, margin = 8;
|
|
8843
|
-
const tip = tipRef.current;
|
|
8844
|
-
const tw = tip ? tip.offsetWidth : 0, th = tip ? tip.offsetHeight : 0;
|
|
8845
|
-
const clampX = (c) => tw ? Math.round(Math.min(Math.max(c, margin + tw / 2), vw - margin - tw / 2)) : c;
|
|
8846
|
-
const clampY = (c) => th ? Math.round(Math.min(Math.max(c, margin + th / 2), vh - margin - th / 2)) : c;
|
|
8847
|
-
const base = { left: "auto", right: "auto", top: "auto", bottom: "auto" };
|
|
8848
|
-
if (placement === "bottom") setCoords({ ...base, left: clampX(cx), top: Math.round(r.bottom + gap) });
|
|
8849
|
-
else if (placement === "left") setCoords({ ...base, top: clampY(cy), right: Math.round(vw - r.left + gap) });
|
|
8850
|
-
else if (placement === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
|
|
8851
|
-
else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
|
|
8852
|
-
}, [placement]);
|
|
8853
|
-
React24__default.useEffect(() => {
|
|
8854
|
-
place();
|
|
8855
|
-
}, [place]);
|
|
8856
|
-
React24__default.useEffect(() => {
|
|
8857
|
-
if (!show) return void 0;
|
|
8858
|
-
place();
|
|
8859
|
-
const onMove = () => place();
|
|
8860
|
-
window.addEventListener("scroll", onMove, true);
|
|
8861
|
-
window.addEventListener("resize", onMove);
|
|
8862
|
-
return () => {
|
|
8863
|
-
window.removeEventListener("scroll", onMove, true);
|
|
8864
|
-
window.removeEventListener("resize", onMove);
|
|
8865
|
-
};
|
|
8866
|
-
}, [show, place]);
|
|
8867
|
-
React24__default.useEffect(() => {
|
|
8868
|
-
if (!show) return;
|
|
8869
|
-
const onKeyDown = (e) => {
|
|
8870
|
-
if (e.key === "Escape") {
|
|
8871
|
-
clearTimeout(timer.current);
|
|
8872
|
-
setShow(false);
|
|
8873
|
-
}
|
|
8874
|
-
};
|
|
8875
|
-
document.addEventListener("keydown", onKeyDown);
|
|
8876
|
-
return () => document.removeEventListener("keydown", onKeyDown);
|
|
8877
|
-
}, [show]);
|
|
8878
|
-
const describedBy = show ? id : void 0;
|
|
8879
|
-
const trigger = React24__default.isValidElement(children) && children.type !== React24__default.Fragment ? React24__default.cloneElement(children, {
|
|
8880
|
-
"aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
|
|
8881
|
-
}) : /* @__PURE__ */ jsx("span", { "aria-describedby": describedBy, children });
|
|
8882
|
-
return /* @__PURE__ */ jsxs(
|
|
8883
|
-
"span",
|
|
8884
|
-
{
|
|
8885
|
-
ref: wrapRef,
|
|
8886
|
-
className: `twc-tooltip-wrap ${className}`,
|
|
8887
|
-
onMouseEnter: open,
|
|
8888
|
-
onMouseLeave: close,
|
|
8889
|
-
onFocus: open,
|
|
8890
|
-
onBlur: close,
|
|
8891
|
-
...rest,
|
|
8892
|
-
children: [
|
|
8893
|
-
__twcStyles,
|
|
8894
|
-
trigger,
|
|
8895
|
-
coords ? createPortal(
|
|
8896
|
-
/* @__PURE__ */ jsxs(
|
|
8897
|
-
"span",
|
|
8898
|
-
{
|
|
8899
|
-
ref: tipRef,
|
|
8900
|
-
id,
|
|
8901
|
-
className: "twc-tooltip",
|
|
8902
|
-
"data-place": placement,
|
|
8903
|
-
"data-show": show || void 0,
|
|
8904
|
-
role: "tooltip",
|
|
8905
|
-
"aria-hidden": show ? void 0 : "true",
|
|
8906
|
-
style: { position: "fixed", left: coords.left, right: coords.right, top: coords.top, bottom: coords.bottom },
|
|
8907
|
-
children: [
|
|
8908
|
-
label,
|
|
8909
|
-
/* @__PURE__ */ jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
|
|
8910
|
-
]
|
|
8911
|
-
}
|
|
8912
|
-
),
|
|
8913
|
-
document.body
|
|
8914
|
-
) : null
|
|
9394
|
+
showValue ? /* @__PURE__ */ jsx("span", { className: "twc-rating__value", children: fmt(val) }) : null
|
|
8915
9395
|
]
|
|
8916
9396
|
}
|
|
8917
9397
|
);
|
|
@@ -9009,24 +9489,24 @@ function Sidebar({
|
|
|
9009
9489
|
...rest
|
|
9010
9490
|
}) {
|
|
9011
9491
|
const __twcStyles = useScopedStyles("twc-sidebar-styles", SIDEBAR_CSS);
|
|
9012
|
-
const navId =
|
|
9013
|
-
const panelRef =
|
|
9492
|
+
const navId = React25__default.useId();
|
|
9493
|
+
const panelRef = React25__default.useRef(null);
|
|
9014
9494
|
const renderPortal = usePortal();
|
|
9015
|
-
const [internal, setInternal] =
|
|
9495
|
+
const [internal, setInternal] = React25__default.useState(defaultCollapsed);
|
|
9016
9496
|
const collapsed = collapsedProp !== void 0 ? collapsedProp : internal;
|
|
9017
9497
|
const toggle = () => {
|
|
9018
9498
|
const next = !collapsed;
|
|
9019
9499
|
if (collapsedProp === void 0) setInternal(next);
|
|
9020
9500
|
onCollapsedChange?.(next);
|
|
9021
9501
|
};
|
|
9022
|
-
const [openInternal, setOpenInternal] =
|
|
9502
|
+
const [openInternal, setOpenInternal] = React25__default.useState(defaultOpen);
|
|
9023
9503
|
const open = openProp !== void 0 ? openProp : openInternal;
|
|
9024
9504
|
const setOpen = (next) => {
|
|
9025
9505
|
if (openProp === void 0) setOpenInternal(next);
|
|
9026
9506
|
onOpenChange?.(next);
|
|
9027
9507
|
};
|
|
9028
|
-
const [mounted, setMounted] =
|
|
9029
|
-
|
|
9508
|
+
const [mounted, setMounted] = React25__default.useState(open);
|
|
9509
|
+
React25__default.useEffect(() => {
|
|
9030
9510
|
if (!overlay) return void 0;
|
|
9031
9511
|
if (open) {
|
|
9032
9512
|
setMounted(true);
|
|
@@ -9035,7 +9515,7 @@ function Sidebar({
|
|
|
9035
9515
|
const t = setTimeout(() => setMounted(false), 170);
|
|
9036
9516
|
return () => clearTimeout(t);
|
|
9037
9517
|
}, [overlay, open]);
|
|
9038
|
-
|
|
9518
|
+
React25__default.useEffect(() => {
|
|
9039
9519
|
if (!overlay || !open) return void 0;
|
|
9040
9520
|
const prev = document.body.style.overflow;
|
|
9041
9521
|
document.body.style.overflow = "hidden";
|
|
@@ -9044,7 +9524,7 @@ function Sidebar({
|
|
|
9044
9524
|
};
|
|
9045
9525
|
}, [overlay, open]);
|
|
9046
9526
|
useFocusTrap(panelRef, overlay && open && mounted);
|
|
9047
|
-
|
|
9527
|
+
React25__default.useEffect(() => {
|
|
9048
9528
|
if (!overlay || !open) return void 0;
|
|
9049
9529
|
const onKey = (e) => {
|
|
9050
9530
|
if (e.key === "Escape") {
|
|
@@ -9096,7 +9576,7 @@ function Sidebar({
|
|
|
9096
9576
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9097
9577
|
__twcStyles,
|
|
9098
9578
|
brand ? /* @__PURE__ */ jsx("div", { className: "twc-sidebar__head", children: /* @__PURE__ */ jsx("span", { className: "twc-sidebar__brand", children: brand }) }) : null,
|
|
9099
|
-
/* @__PURE__ */ jsx("nav", { id: navId, className: "twc-sidebar__nav", "aria-label": navLabel, children: groups.map((g, gi) => /* @__PURE__ */ jsxs(
|
|
9579
|
+
/* @__PURE__ */ jsx("nav", { id: navId, className: "twc-sidebar__nav", "aria-label": navLabel, children: groups.map((g, gi) => /* @__PURE__ */ jsxs(React25__default.Fragment, { children: [
|
|
9100
9580
|
g.section != null ? /* @__PURE__ */ jsx("div", { className: "twc-sidebar__section", id: g.sid, children: g.section }) : null,
|
|
9101
9581
|
/* @__PURE__ */ jsx("ul", { className: "twc-sidebar__list", ...g.section != null ? { "aria-labelledby": g.sid } : {}, children: g.entries.map(({ it, i }) => /* @__PURE__ */ jsx("li", { children: renderItem(it) }, i)) })
|
|
9102
9582
|
] }, gi)) }),
|
|
@@ -9235,11 +9715,16 @@ function Slider({
|
|
|
9235
9715
|
min: minProp = 0,
|
|
9236
9716
|
max: maxProp = 100,
|
|
9237
9717
|
step: stepProp = 1,
|
|
9718
|
+
pageStep: pageStepProp,
|
|
9719
|
+
precision,
|
|
9238
9720
|
tone = "primary",
|
|
9239
9721
|
disabled = false,
|
|
9722
|
+
range = false,
|
|
9240
9723
|
showValue = true,
|
|
9241
9724
|
showTicks = false,
|
|
9242
9725
|
formatValue,
|
|
9726
|
+
getAriaValueText,
|
|
9727
|
+
name,
|
|
9243
9728
|
onChange,
|
|
9244
9729
|
id,
|
|
9245
9730
|
className = "",
|
|
@@ -9248,38 +9733,73 @@ function Slider({
|
|
|
9248
9733
|
const min = Number.isFinite(minProp) ? minProp : 0;
|
|
9249
9734
|
const max = Number.isFinite(maxProp) && maxProp > min ? maxProp : min + 1;
|
|
9250
9735
|
const step = Number.isFinite(stepProp) && stepProp > 0 ? stepProp : 1;
|
|
9251
|
-
const
|
|
9252
|
-
const
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
const
|
|
9258
|
-
const pct = (val - min) / (max - min) * 100;
|
|
9259
|
-
const fmt = (v) => formatValue ? formatValue(v) : v;
|
|
9736
|
+
const pageStep = Number.isFinite(pageStepProp) && pageStepProp > 0 ? pageStepProp : Math.max(step, (max - min) / 10);
|
|
9737
|
+
const stepDecimals = (() => {
|
|
9738
|
+
const s = String(step);
|
|
9739
|
+
const i = s.indexOf(".");
|
|
9740
|
+
return i === -1 ? 0 : s.length - i - 1;
|
|
9741
|
+
})();
|
|
9742
|
+
const decimals = Number.isInteger(precision) && precision >= 0 ? precision : stepDecimals;
|
|
9260
9743
|
const clampSnap = (raw) => {
|
|
9261
9744
|
const stepped = Math.round((raw - min) / step) * step + min;
|
|
9262
9745
|
return Math.min(max, Math.max(min, Math.round(stepped * 1e6) / 1e6));
|
|
9263
9746
|
};
|
|
9264
|
-
const
|
|
9265
|
-
|
|
9266
|
-
|
|
9747
|
+
const __twcStyles = useScopedStyles("twc-slider-styles", SLIDER_CSS);
|
|
9748
|
+
const autoId = React25__default.useId();
|
|
9749
|
+
const fieldId = id || autoId;
|
|
9750
|
+
const isRange = range || Array.isArray(value) || Array.isArray(defaultValue);
|
|
9751
|
+
const [internal, setInternal] = React25__default.useState(() => {
|
|
9752
|
+
if (isRange) {
|
|
9753
|
+
const dv = Array.isArray(defaultValue) ? defaultValue : [min, max];
|
|
9754
|
+
return [clampSnap(dv[0]), clampSnap(dv[1])];
|
|
9755
|
+
}
|
|
9756
|
+
return clampSnap(Number.isFinite(defaultValue) ? defaultValue : min);
|
|
9757
|
+
});
|
|
9758
|
+
const rawVal = value !== void 0 ? value : internal;
|
|
9759
|
+
const clampedVals = (isRange ? [Number(rawVal[0]), Number(rawVal[1])] : [Number(rawVal)]).map((v) => Math.min(max, Math.max(min, Number.isFinite(v) ? v : min)));
|
|
9760
|
+
const indices = isRange ? [0, 1] : [0];
|
|
9761
|
+
const trackRef = React25__default.useRef(null);
|
|
9762
|
+
const [dragging, setDragging] = React25__default.useState(false);
|
|
9763
|
+
const fmt = (v) => formatValue ? formatValue(v) : v.toFixed(decimals);
|
|
9764
|
+
const valueTextFor = (v) => {
|
|
9765
|
+
if (getAriaValueText) return getAriaValueText(v);
|
|
9766
|
+
if (formatValue) {
|
|
9767
|
+
const d = formatValue(v);
|
|
9768
|
+
return typeof d === "string" || typeof d === "number" ? String(d) : void 0;
|
|
9769
|
+
}
|
|
9770
|
+
return decimals > 0 ? v.toFixed(decimals) : void 0;
|
|
9771
|
+
};
|
|
9772
|
+
const commit = (nextVals) => {
|
|
9773
|
+
const out = isRange ? nextVals : nextVals[0];
|
|
9774
|
+
if (value === void 0) setInternal(out);
|
|
9775
|
+
onChange?.(out);
|
|
9776
|
+
};
|
|
9777
|
+
const setThumb = (i, raw) => {
|
|
9778
|
+
const next = clampedVals.slice();
|
|
9779
|
+
next[i] = clampSnap(raw);
|
|
9780
|
+
if (isRange) {
|
|
9781
|
+
if (i === 0) next[0] = Math.min(next[0], next[1]);
|
|
9782
|
+
else next[1] = Math.max(next[1], next[0]);
|
|
9783
|
+
}
|
|
9784
|
+
commit(next);
|
|
9267
9785
|
};
|
|
9268
9786
|
const fromClientX = (clientX) => {
|
|
9269
9787
|
const node = trackRef.current;
|
|
9270
|
-
if (!node) return
|
|
9788
|
+
if (!node) return clampedVals[0];
|
|
9271
9789
|
const r = node.getBoundingClientRect();
|
|
9272
9790
|
const ratio = Math.min(1, Math.max(0, (clientX - r.left) / r.width));
|
|
9273
9791
|
return clampSnap(min + ratio * (max - min));
|
|
9274
9792
|
};
|
|
9275
|
-
const dragCleanupRef =
|
|
9276
|
-
|
|
9793
|
+
const dragCleanupRef = React25__default.useRef(null);
|
|
9794
|
+
React25__default.useEffect(() => () => dragCleanupRef.current?.(), []);
|
|
9277
9795
|
function onPointerDown(e) {
|
|
9278
9796
|
if (disabled) return;
|
|
9279
9797
|
e.preventDefault();
|
|
9798
|
+
const posVal = fromClientX(e.clientX);
|
|
9799
|
+
const idx = isRange ? Math.abs(posVal - clampedVals[0]) <= Math.abs(posVal - clampedVals[1]) ? 0 : 1 : 0;
|
|
9280
9800
|
setDragging(true);
|
|
9281
|
-
|
|
9282
|
-
const move = (ev) =>
|
|
9801
|
+
setThumb(idx, posVal);
|
|
9802
|
+
const move = (ev) => setThumb(idx, fromClientX(ev.clientX));
|
|
9283
9803
|
const detach = () => {
|
|
9284
9804
|
window.removeEventListener("pointermove", move);
|
|
9285
9805
|
window.removeEventListener("pointerup", up);
|
|
@@ -9293,54 +9813,68 @@ function Slider({
|
|
|
9293
9813
|
window.addEventListener("pointermove", move);
|
|
9294
9814
|
window.addEventListener("pointerup", up);
|
|
9295
9815
|
}
|
|
9296
|
-
function
|
|
9816
|
+
function onThumbKeyDown(e, i) {
|
|
9297
9817
|
if (disabled) return;
|
|
9818
|
+
const cur = clampedVals[i];
|
|
9298
9819
|
let next;
|
|
9299
|
-
if (e.key === "ArrowRight" || e.key === "ArrowUp") next =
|
|
9300
|
-
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next =
|
|
9820
|
+
if (e.key === "ArrowRight" || e.key === "ArrowUp") next = cur + step;
|
|
9821
|
+
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next = cur - step;
|
|
9822
|
+
else if (e.key === "PageUp") next = cur + pageStep;
|
|
9823
|
+
else if (e.key === "PageDown") next = cur - pageStep;
|
|
9301
9824
|
else if (e.key === "Home") next = min;
|
|
9302
9825
|
else if (e.key === "End") next = max;
|
|
9303
9826
|
else return;
|
|
9304
9827
|
e.preventDefault();
|
|
9305
|
-
|
|
9828
|
+
setThumb(i, next);
|
|
9306
9829
|
}
|
|
9307
9830
|
const ticks = showTicks ? Math.floor((max - min) / step) + 1 : 0;
|
|
9308
9831
|
const labelId = label ? `${fieldId}-label` : void 0;
|
|
9309
9832
|
const descId = `${fieldId}-desc`;
|
|
9310
9833
|
const invalid = Boolean(error);
|
|
9311
|
-
const
|
|
9312
|
-
const
|
|
9834
|
+
const headValue = isRange ? `${fmt(clampedVals[0])} \u2013 ${fmt(clampedVals[1])}` : fmt(clampedVals[0]);
|
|
9835
|
+
const fillLo = (Math.min(...clampedVals) - min) / (max - min) * 100;
|
|
9836
|
+
const fillHi = (Math.max(...clampedVals) - min) / (max - min) * 100;
|
|
9837
|
+
const fillStyle = isRange ? { left: `${fillLo}%`, width: `${fillHi - fillLo}%` } : { width: `${fillHi}%` };
|
|
9313
9838
|
return /* @__PURE__ */ jsxs("div", { className: `twc-slider ${className}`, "data-tone": tone, "data-disabled": disabled || void 0, ...rest, children: [
|
|
9314
9839
|
__twcStyles,
|
|
9840
|
+
name ? clampedVals.map((v, i) => /* @__PURE__ */ jsx("input", { type: "hidden", name, value: v, disabled: disabled || void 0 }, i)) : null,
|
|
9315
9841
|
label || showValue ? /* @__PURE__ */ jsxs("div", { className: "twc-slider__head", children: [
|
|
9316
9842
|
label ? /* @__PURE__ */ jsx("label", { className: "twc-slider__label", id: labelId, children: label }) : /* @__PURE__ */ jsx("span", {}),
|
|
9317
|
-
showValue ? /* @__PURE__ */ jsx("span", { className: "twc-slider__value", children:
|
|
9843
|
+
showValue ? /* @__PURE__ */ jsx("span", { className: "twc-slider__value", children: headValue }) : null
|
|
9318
9844
|
] }) : null,
|
|
9319
9845
|
/* @__PURE__ */ jsxs("div", { className: "twc-slider__track", ref: trackRef, "data-show-bubble": dragging || void 0, onPointerDown, children: [
|
|
9320
9846
|
/* @__PURE__ */ jsx("div", { className: "twc-slider__rail" }),
|
|
9321
|
-
/* @__PURE__ */ jsx("div", { className: "twc-slider__fill", style:
|
|
9847
|
+
/* @__PURE__ */ jsx("div", { className: "twc-slider__fill", style: fillStyle }),
|
|
9322
9848
|
showTicks ? /* @__PURE__ */ jsx("div", { className: "twc-slider__ticks", children: Array.from({ length: ticks }).map((_, i) => /* @__PURE__ */ jsx("span", { className: "twc-slider__tick", style: { left: `${ticks > 1 ? i / (ticks - 1) * 100 : 0}%` } }, i)) }) : null,
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9849
|
+
indices.map((i) => {
|
|
9850
|
+
const tv = clampedVals[i];
|
|
9851
|
+
const p = (tv - min) / (max - min) * 100;
|
|
9852
|
+
const tMin = isRange && i === 1 ? clampedVals[0] : min;
|
|
9853
|
+
const tMax = isRange && i === 0 ? clampedVals[1] : max;
|
|
9854
|
+
const thumbLabel = isRange ? i === 0 ? "Minimum" : "Maximum" : labelId ? void 0 : "Slider";
|
|
9855
|
+
return /* @__PURE__ */ jsx(
|
|
9856
|
+
"div",
|
|
9857
|
+
{
|
|
9858
|
+
id: i === 0 ? fieldId : void 0,
|
|
9859
|
+
className: "twc-slider__thumb",
|
|
9860
|
+
style: { left: `${p}%` },
|
|
9861
|
+
role: "slider",
|
|
9862
|
+
tabIndex: disabled ? -1 : 0,
|
|
9863
|
+
"aria-valuemin": tMin,
|
|
9864
|
+
"aria-valuemax": tMax,
|
|
9865
|
+
"aria-valuenow": tv,
|
|
9866
|
+
"aria-valuetext": valueTextFor(tv),
|
|
9867
|
+
"aria-labelledby": isRange ? void 0 : labelId,
|
|
9868
|
+
"aria-label": thumbLabel,
|
|
9869
|
+
"aria-describedby": error || hint ? descId : void 0,
|
|
9870
|
+
"aria-invalid": invalid || void 0,
|
|
9871
|
+
"aria-disabled": disabled || void 0,
|
|
9872
|
+
onKeyDown: (e) => onThumbKeyDown(e, i),
|
|
9873
|
+
children: /* @__PURE__ */ jsx("span", { className: "twc-slider__bubble", children: fmt(tv) })
|
|
9874
|
+
},
|
|
9875
|
+
i
|
|
9876
|
+
);
|
|
9877
|
+
})
|
|
9344
9878
|
] }),
|
|
9345
9879
|
error || hint ? /* @__PURE__ */ jsx("div", { className: "twc-slider__msgs", children: error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) }) : null
|
|
9346
9880
|
] });
|
|
@@ -9488,7 +10022,7 @@ function Stepper({
|
|
|
9488
10022
|
...rest
|
|
9489
10023
|
}) {
|
|
9490
10024
|
const __twcStyles = useScopedStyles("twc-stepper-styles", STEPPER_CSS);
|
|
9491
|
-
const [activeInternal, setActiveInternal] =
|
|
10025
|
+
const [activeInternal, setActiveInternal] = React25__default.useState(defaultActive);
|
|
9492
10026
|
const active = activeProp !== void 0 ? activeProp : activeInternal;
|
|
9493
10027
|
const handleStep = (i) => {
|
|
9494
10028
|
if (activeProp === void 0) setActiveInternal(i);
|
|
@@ -9620,10 +10154,13 @@ function Switch({
|
|
|
9620
10154
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
9621
10155
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
9622
10156
|
`);
|
|
9623
|
-
const autoId =
|
|
10157
|
+
const autoId = React25__default.useId();
|
|
9624
10158
|
const fieldId = id || autoId;
|
|
9625
10159
|
const errId = `${fieldId}-error`;
|
|
9626
10160
|
const invalid = Boolean(error);
|
|
10161
|
+
if (process.env.NODE_ENV !== "production" && !label && !description && !rest["aria-label"] && !rest["aria-labelledby"]) {
|
|
10162
|
+
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).");
|
|
10163
|
+
}
|
|
9627
10164
|
const describedBy = [rest["aria-describedby"], error ? errId : null].filter(Boolean).join(" ") || void 0;
|
|
9628
10165
|
const control = /* @__PURE__ */ 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: [
|
|
9629
10166
|
__twcStyles,
|
|
@@ -9639,6 +10176,7 @@ function Switch({
|
|
|
9639
10176
|
disabled,
|
|
9640
10177
|
onChange,
|
|
9641
10178
|
...rest,
|
|
10179
|
+
required: required || void 0,
|
|
9642
10180
|
"aria-required": required || void 0,
|
|
9643
10181
|
"aria-invalid": invalid || void 0,
|
|
9644
10182
|
"aria-describedby": describedBy
|
|
@@ -9685,6 +10223,13 @@ var TABLE_CSS = `
|
|
|
9685
10223
|
.twc-table[data-size="lg"] thead th { padding: var(--space-4) var(--space-5); }
|
|
9686
10224
|
.twc-table[data-size="lg"] tbody td { padding: var(--space-4) var(--space-5); font-size: var(--text-base); }
|
|
9687
10225
|
.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); }
|
|
10226
|
+
.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; }
|
|
10227
|
+
.twc-table__empty { padding: 30px 12px; text-align: center; color: var(--color-text-subtle); font-size: var(--text-sm); }
|
|
10228
|
+
.twc-table__sk { display: inline-block; height: 12px; border-radius: var(--radius-sm); background: var(--color-surface-sunken);
|
|
10229
|
+
position: relative; overflow: hidden; width: var(--_w, 70%); }
|
|
10230
|
+
.twc-table__sk::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%);
|
|
10231
|
+
background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--color-text) 8%, transparent), transparent);
|
|
10232
|
+
animation: twico-shimmer 1.4s infinite; }
|
|
9688
10233
|
`;
|
|
9689
10234
|
function Table({
|
|
9690
10235
|
columns,
|
|
@@ -9700,18 +10245,26 @@ function Table({
|
|
|
9700
10245
|
selectedKeys,
|
|
9701
10246
|
stickyHeader = false,
|
|
9702
10247
|
maxHeight,
|
|
10248
|
+
loading = false,
|
|
10249
|
+
loadingRows = 8,
|
|
10250
|
+
emptyMessage = "No data",
|
|
10251
|
+
ariaLabel,
|
|
10252
|
+
caption,
|
|
10253
|
+
// Pulled out of `rest` so they land on the <table>, not the wrapper <div> (#128).
|
|
10254
|
+
"aria-label": ariaLabelRaw,
|
|
10255
|
+
"aria-labelledby": ariaLabelledby,
|
|
9703
10256
|
className = "",
|
|
9704
10257
|
...rest
|
|
9705
10258
|
}) {
|
|
9706
10259
|
const __twcStyles = useScopedStyles("twc-table-styles", TABLE_CSS);
|
|
9707
|
-
const cols =
|
|
10260
|
+
const cols = React25__default.useMemo(
|
|
9708
10261
|
() => (columns || []).map((c) => ({ ...c, header: c.headerName, render: c.renderCell })),
|
|
9709
10262
|
[columns]
|
|
9710
10263
|
);
|
|
9711
10264
|
const dataRows = rowsProp || [];
|
|
9712
|
-
const [internalSort, setInternalSort] =
|
|
10265
|
+
const [internalSort, setInternalSort] = React25__default.useState(defaultSort || { field: null, dir: "asc" });
|
|
9713
10266
|
const sort = (sortProp !== void 0 ? sortProp : internalSort) || { field: null, dir: "asc" };
|
|
9714
|
-
const rows =
|
|
10267
|
+
const rows = React25__default.useMemo(() => {
|
|
9715
10268
|
if (!sortable || !sort.field) return dataRows;
|
|
9716
10269
|
const col = cols.find((c) => c.field === sort.field);
|
|
9717
10270
|
if (!col) return dataRows;
|
|
@@ -9734,32 +10287,46 @@ function Table({
|
|
|
9734
10287
|
const wrapStyle = maxHeight !== void 0 ? { ...rest.style, maxHeight, overflowY: "auto" } : rest.style;
|
|
9735
10288
|
return /* @__PURE__ */ jsxs("div", { className: `twc-table-wrap ${className}`, ...rest, style: wrapStyle, children: [
|
|
9736
10289
|
__twcStyles,
|
|
9737
|
-
/* @__PURE__ */ jsxs(
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
10290
|
+
/* @__PURE__ */ jsxs(
|
|
10291
|
+
"table",
|
|
10292
|
+
{
|
|
10293
|
+
className: "twc-table",
|
|
10294
|
+
"data-hover": hover || void 0,
|
|
10295
|
+
"data-striped": striped || void 0,
|
|
10296
|
+
"data-size": size,
|
|
10297
|
+
"data-sticky": stickyHeader || void 0,
|
|
10298
|
+
"aria-label": ariaLabelRaw ?? ariaLabel,
|
|
10299
|
+
"aria-labelledby": ariaLabelledby,
|
|
10300
|
+
"aria-busy": loading || void 0,
|
|
10301
|
+
children: [
|
|
10302
|
+
caption != null ? /* @__PURE__ */ jsx("caption", { className: "twc-table__caption", children: caption }) : null,
|
|
10303
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: cols.map((c) => {
|
|
10304
|
+
const active = sort.field === c.field;
|
|
10305
|
+
const canSort = sortable && c.sortable !== false;
|
|
10306
|
+
return /* @__PURE__ */ jsx(
|
|
10307
|
+
"th",
|
|
10308
|
+
{
|
|
10309
|
+
"data-align": c.align,
|
|
10310
|
+
"data-sortable": canSort || void 0,
|
|
10311
|
+
"data-active": active || void 0,
|
|
10312
|
+
"data-dir": active ? sort.dir : void 0,
|
|
10313
|
+
style: c.width ? { width: c.width } : void 0,
|
|
10314
|
+
"aria-sort": active ? sort.dir === "asc" ? "ascending" : "descending" : canSort ? "none" : void 0,
|
|
10315
|
+
children: canSort ? /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-table__sort", onClick: () => toggleSort(c.field), children: [
|
|
10316
|
+
c.header,
|
|
10317
|
+
/* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "m18 15-6-6-6 6" }) })
|
|
10318
|
+
] }) : c.header
|
|
10319
|
+
},
|
|
10320
|
+
c.field
|
|
10321
|
+
);
|
|
10322
|
+
}) }) }),
|
|
10323
|
+
/* @__PURE__ */ jsx("tbody", { children: loading ? Array.from({ length: loadingRows }).map((_, ri) => /* @__PURE__ */ jsx("tr", { children: cols.map((c) => /* @__PURE__ */ jsx("td", { "data-align": c.align, children: /* @__PURE__ */ jsx("span", { className: "twc-table__sk" }) }, c.field)) }, `sk${ri}`)) : rows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: cols.length || 1, className: "twc-table__empty", children: emptyMessage }) }) : rows.map((row, i) => {
|
|
10324
|
+
const k = keyFn(row, i);
|
|
10325
|
+
return /* @__PURE__ */ jsx("tr", { "data-selected": selected.has(k) || void 0, children: cols.map((c) => /* @__PURE__ */ jsx("td", { "data-align": c.align, children: c.render ? c.render(row[c.field], row, i) : row[c.field] }, c.field)) }, k);
|
|
10326
|
+
}) })
|
|
10327
|
+
]
|
|
10328
|
+
}
|
|
10329
|
+
)
|
|
9763
10330
|
] });
|
|
9764
10331
|
}
|
|
9765
10332
|
var TABS_CSS = `
|
|
@@ -9844,15 +10411,15 @@ function Tabs({
|
|
|
9844
10411
|
}) {
|
|
9845
10412
|
const vertical = orientation === "vertical";
|
|
9846
10413
|
const __twcStyles = useScopedStyles("twc-tabs-styles", TABS_CSS);
|
|
9847
|
-
const [internal, setInternal] =
|
|
10414
|
+
const [internal, setInternal] = React25__default.useState(defaultValue ?? items[0]?.value);
|
|
9848
10415
|
const active = value ?? internal;
|
|
9849
|
-
const listRef =
|
|
9850
|
-
const [ind, setInd] =
|
|
9851
|
-
const baseId =
|
|
10416
|
+
const listRef = React25__default.useRef(null);
|
|
10417
|
+
const [ind, setInd] = React25__default.useState({ left: 0, width: 0, top: 0, height: 0 });
|
|
10418
|
+
const baseId = React25__default.useId();
|
|
9852
10419
|
const tabIdAt = (i) => `${baseId}-tab-${i}`;
|
|
9853
10420
|
const panelId = `${baseId}-panel`;
|
|
9854
10421
|
const activeIndex = items.findIndex((it) => it.value === active);
|
|
9855
|
-
const updateIndicator =
|
|
10422
|
+
const updateIndicator = React25__default.useCallback(() => {
|
|
9856
10423
|
const list = listRef.current;
|
|
9857
10424
|
if (!list) return;
|
|
9858
10425
|
const el = list.querySelector('[data-active="true"]');
|
|
@@ -9861,10 +10428,10 @@ function Tabs({
|
|
|
9861
10428
|
if (!vertical) el.scrollIntoView?.({ inline: "nearest", block: "nearest" });
|
|
9862
10429
|
}
|
|
9863
10430
|
}, [vertical]);
|
|
9864
|
-
|
|
10431
|
+
React25__default.useEffect(() => {
|
|
9865
10432
|
updateIndicator();
|
|
9866
10433
|
}, [active, updateIndicator, items, orientation]);
|
|
9867
|
-
|
|
10434
|
+
React25__default.useEffect(() => {
|
|
9868
10435
|
const r = () => updateIndicator();
|
|
9869
10436
|
window.addEventListener("resize", r);
|
|
9870
10437
|
if (typeof document !== "undefined" && document.fonts && document.fonts.ready) {
|
|
@@ -10009,20 +10576,8 @@ function Tag({
|
|
|
10009
10576
|
}, "aria-label": _removeLabel, type: "button", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
|
|
10010
10577
|
] });
|
|
10011
10578
|
}
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
hint,
|
|
10015
|
-
error,
|
|
10016
|
-
required = false,
|
|
10017
|
-
size = "md",
|
|
10018
|
-
tone = "primary",
|
|
10019
|
-
rows = 4,
|
|
10020
|
-
disabled = false,
|
|
10021
|
-
id,
|
|
10022
|
-
className = "",
|
|
10023
|
-
...rest
|
|
10024
|
-
}) {
|
|
10025
|
-
const __twcStyles = useScopedStyles("twc-textarea-styles", `
|
|
10579
|
+
var useIso = typeof document !== "undefined" ? React25__default.useLayoutEffect : React25__default.useEffect;
|
|
10580
|
+
var TEXTAREA_CSS = `
|
|
10026
10581
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
10027
10582
|
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
10028
10583
|
.twc-field__req { color: var(--color-danger); }
|
|
@@ -10051,11 +10606,74 @@ function Textarea({
|
|
|
10051
10606
|
.twc-textarea__el:focus { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
10052
10607
|
.twc-textarea__el[aria-invalid="true"] { border-color: var(--color-danger); }
|
|
10053
10608
|
.twc-textarea__el:disabled { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
10054
|
-
|
|
10055
|
-
|
|
10609
|
+
.twc-textarea__el[data-readonly] { background: var(--color-surface-sunken); }
|
|
10610
|
+
.twc-textarea__el[data-autosize="true"] { resize: none; overflow: hidden; }
|
|
10611
|
+
.twc-field__footer { display: flex; align-items: center; gap: var(--space-2); }
|
|
10612
|
+
.twc-field__count { margin-inline-start: auto; font-size: var(--text-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; flex: none; }
|
|
10613
|
+
.twc-field__count[data-danger="true"] { color: var(--color-danger-subtle-fg); }
|
|
10614
|
+
`;
|
|
10615
|
+
var Textarea = React25__default.forwardRef(function Textarea2({
|
|
10616
|
+
label,
|
|
10617
|
+
hint,
|
|
10618
|
+
error,
|
|
10619
|
+
required = false,
|
|
10620
|
+
size = "md",
|
|
10621
|
+
tone = "primary",
|
|
10622
|
+
rows = 4,
|
|
10623
|
+
autosize = false,
|
|
10624
|
+
minRows,
|
|
10625
|
+
maxRows,
|
|
10626
|
+
showCount = false,
|
|
10627
|
+
disabled = false,
|
|
10628
|
+
id,
|
|
10629
|
+
className = "",
|
|
10630
|
+
...rest
|
|
10631
|
+
}, ref) {
|
|
10632
|
+
const __twcStyles = useScopedStyles("twc-textarea-styles", TEXTAREA_CSS);
|
|
10633
|
+
const autoId = React25__default.useId();
|
|
10056
10634
|
const fieldId = id || autoId;
|
|
10057
10635
|
const descId = `${fieldId}-desc`;
|
|
10636
|
+
const countId = `${fieldId}-count`;
|
|
10058
10637
|
const invalid = Boolean(error);
|
|
10638
|
+
const innerRef = React25__default.useRef(null);
|
|
10639
|
+
const setRef = (el) => {
|
|
10640
|
+
innerRef.current = el;
|
|
10641
|
+
if (typeof ref === "function") ref(el);
|
|
10642
|
+
else if (ref) ref.current = el;
|
|
10643
|
+
};
|
|
10644
|
+
const countControlled = rest.value !== void 0;
|
|
10645
|
+
const [len2, setLen] = React25__default.useState(() => String(rest.defaultValue ?? "").length);
|
|
10646
|
+
const count = countControlled ? String(rest.value ?? "").length : len2;
|
|
10647
|
+
const max = rest.maxLength;
|
|
10648
|
+
const showCounter = showCount && max != null;
|
|
10649
|
+
const near = showCounter && count >= Math.floor(max * 0.9);
|
|
10650
|
+
const resize = () => {
|
|
10651
|
+
const el = innerRef.current;
|
|
10652
|
+
if (!el) return;
|
|
10653
|
+
el.style.height = "auto";
|
|
10654
|
+
const cs = getComputedStyle(el);
|
|
10655
|
+
const line = parseFloat(cs.lineHeight) || 20;
|
|
10656
|
+
const vPad = (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0);
|
|
10657
|
+
const vBorder = (parseFloat(cs.borderTopWidth) || 0) + (parseFloat(cs.borderBottomWidth) || 0);
|
|
10658
|
+
const min = (minRows ?? rows) * line + vPad + vBorder;
|
|
10659
|
+
const maxH = maxRows ? maxRows * line + vPad + vBorder : Infinity;
|
|
10660
|
+
const next = Math.min(Math.max(el.scrollHeight + vBorder, min), maxH);
|
|
10661
|
+
el.style.height = `${next}px`;
|
|
10662
|
+
el.style.overflowY = el.scrollHeight + vBorder > maxH ? "auto" : "hidden";
|
|
10663
|
+
};
|
|
10664
|
+
useIso(() => {
|
|
10665
|
+
if (autosize && innerRef.current) resize();
|
|
10666
|
+
}, [autosize, rest.value, minRows, maxRows, rows]);
|
|
10667
|
+
const handleInput = (e) => {
|
|
10668
|
+
rest.onInput?.(e);
|
|
10669
|
+
if (autosize) resize();
|
|
10670
|
+
};
|
|
10671
|
+
const handleChange = (e) => {
|
|
10672
|
+
rest.onChange?.(e);
|
|
10673
|
+
if (showCount && !countControlled) setLen(e.target.value.length);
|
|
10674
|
+
};
|
|
10675
|
+
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
10676
|
+
const describedBy = [error || hint ? descId : null, showCounter ? countId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
10059
10677
|
return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, children: [
|
|
10060
10678
|
__twcStyles,
|
|
10061
10679
|
label ? /* @__PURE__ */ jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
@@ -10065,22 +10683,34 @@ function Textarea({
|
|
|
10065
10683
|
/* @__PURE__ */ jsx(
|
|
10066
10684
|
"textarea",
|
|
10067
10685
|
{
|
|
10686
|
+
ref: setRef,
|
|
10068
10687
|
id: fieldId,
|
|
10069
10688
|
className: "twc-textarea__el",
|
|
10070
10689
|
"data-size": size,
|
|
10071
10690
|
"data-tone": tone,
|
|
10072
|
-
|
|
10691
|
+
"data-autosize": autosize || void 0,
|
|
10692
|
+
"data-readonly": rest.readOnly || void 0,
|
|
10693
|
+
rows: autosize ? minRows ?? rows : rows,
|
|
10073
10694
|
disabled,
|
|
10074
10695
|
required: required || void 0,
|
|
10075
10696
|
"aria-required": required || void 0,
|
|
10076
|
-
|
|
10077
|
-
|
|
10078
|
-
|
|
10697
|
+
...rest,
|
|
10698
|
+
onInput: handleInput,
|
|
10699
|
+
onChange: handleChange,
|
|
10700
|
+
"aria-invalid": ariaInvalid,
|
|
10701
|
+
"aria-describedby": describedBy
|
|
10079
10702
|
}
|
|
10080
10703
|
),
|
|
10081
|
-
error
|
|
10704
|
+
error || hint || showCounter ? /* @__PURE__ */ jsxs("div", { className: "twc-field__footer", children: [
|
|
10705
|
+
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null,
|
|
10706
|
+
showCounter ? /* @__PURE__ */ jsxs("span", { id: countId, className: "twc-field__count", "data-danger": near || void 0, "aria-live": "polite", children: [
|
|
10707
|
+
count,
|
|
10708
|
+
" / ",
|
|
10709
|
+
max
|
|
10710
|
+
] }) : null
|
|
10711
|
+
] }) : null
|
|
10082
10712
|
] });
|
|
10083
|
-
}
|
|
10713
|
+
});
|
|
10084
10714
|
var TIMELINE_CSS = `
|
|
10085
10715
|
.twc-timeline { display: flex; flex-direction: column; font-family: var(--font-sans); margin: 0; padding: 0; list-style: none; }
|
|
10086
10716
|
.twc-timeline__item { position: relative; display: flex; gap: var(--space-4); padding-bottom: var(--space-6); }
|
|
@@ -10190,28 +10820,29 @@ function Toast({
|
|
|
10190
10820
|
}) {
|
|
10191
10821
|
const resolvedTone = tone === "neutral" ? "default" : tone;
|
|
10192
10822
|
const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
|
|
10193
|
-
const onCloseRef =
|
|
10194
|
-
|
|
10823
|
+
const onCloseRef = React25__default.useRef(onClose);
|
|
10824
|
+
React25__default.useEffect(() => {
|
|
10195
10825
|
onCloseRef.current = onClose;
|
|
10196
10826
|
}, [onClose]);
|
|
10197
|
-
const timer =
|
|
10198
|
-
const stop =
|
|
10199
|
-
const start =
|
|
10827
|
+
const timer = React25__default.useRef();
|
|
10828
|
+
const stop = React25__default.useCallback(() => clearTimeout(timer.current), []);
|
|
10829
|
+
const start = React25__default.useCallback(() => {
|
|
10200
10830
|
stop();
|
|
10201
10831
|
if (duration && duration !== Infinity && onCloseRef.current) {
|
|
10202
10832
|
timer.current = setTimeout(() => onCloseRef.current && onCloseRef.current(), duration);
|
|
10203
10833
|
}
|
|
10204
10834
|
}, [duration, stop]);
|
|
10205
|
-
|
|
10835
|
+
React25__default.useEffect(() => {
|
|
10206
10836
|
start();
|
|
10207
10837
|
return stop;
|
|
10208
10838
|
}, [start, stop]);
|
|
10839
|
+
const role = resolvedTone === "danger" || resolvedTone === "warning" ? "alert" : "status";
|
|
10209
10840
|
return /* @__PURE__ */ jsxs(
|
|
10210
10841
|
"div",
|
|
10211
10842
|
{
|
|
10212
10843
|
className: `twc-toast ${className}`,
|
|
10213
10844
|
"data-tone": resolvedTone,
|
|
10214
|
-
role
|
|
10845
|
+
role,
|
|
10215
10846
|
...rest,
|
|
10216
10847
|
onMouseEnter: (e) => {
|
|
10217
10848
|
onMouseEnter?.(e);
|
|
@@ -10246,30 +10877,30 @@ function Toast({
|
|
|
10246
10877
|
}
|
|
10247
10878
|
function ToastViewport({ children, limit, className = "", ...rest }) {
|
|
10248
10879
|
const __twcStyles = useScopedStyles("twc-toast-styles", TOAST_CSS);
|
|
10249
|
-
const shown = limit && limit > 0 ?
|
|
10250
|
-
return /* @__PURE__ */ jsxs("div", { className: `twc-toast-viewport ${className}`, ...rest, children: [
|
|
10880
|
+
const shown = limit && limit > 0 ? React25__default.Children.toArray(children).slice(-limit) : children;
|
|
10881
|
+
return /* @__PURE__ */ jsxs("div", { className: `twc-toast-viewport ${className}`, role: "region", "aria-label": "Notifications", ...rest, children: [
|
|
10251
10882
|
__twcStyles,
|
|
10252
10883
|
shown
|
|
10253
10884
|
] });
|
|
10254
10885
|
}
|
|
10255
|
-
var ToastContext =
|
|
10886
|
+
var ToastContext = React25__default.createContext(null);
|
|
10256
10887
|
function useToast() {
|
|
10257
|
-
const ctx =
|
|
10888
|
+
const ctx = React25__default.useContext(ToastContext);
|
|
10258
10889
|
if (!ctx) throw new Error("useToast must be used within a <ToastProvider>.");
|
|
10259
10890
|
return ctx;
|
|
10260
10891
|
}
|
|
10261
10892
|
function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps }) {
|
|
10262
|
-
const [toasts, setToasts] =
|
|
10263
|
-
const idRef =
|
|
10264
|
-
const limitRef =
|
|
10265
|
-
|
|
10893
|
+
const [toasts, setToasts] = React25__default.useState([]);
|
|
10894
|
+
const idRef = React25__default.useRef(0);
|
|
10895
|
+
const limitRef = React25__default.useRef(limit);
|
|
10896
|
+
React25__default.useEffect(() => {
|
|
10266
10897
|
limitRef.current = limit;
|
|
10267
10898
|
}, [limit]);
|
|
10268
|
-
const dismiss =
|
|
10899
|
+
const dismiss = React25__default.useCallback((id) => {
|
|
10269
10900
|
setToasts((s) => s.filter((t) => t.id !== id));
|
|
10270
10901
|
}, []);
|
|
10271
|
-
const clear =
|
|
10272
|
-
const api =
|
|
10902
|
+
const clear = React25__default.useCallback(() => setToasts([]), []);
|
|
10903
|
+
const api = React25__default.useMemo(() => {
|
|
10273
10904
|
const push = (opts) => {
|
|
10274
10905
|
const id = idRef.current += 1;
|
|
10275
10906
|
const next = typeof opts === "string" ? { title: opts } : opts && typeof opts === "object" ? opts : {};
|
|
@@ -10290,7 +10921,7 @@ function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps
|
|
|
10290
10921
|
toast.show = withTone("default");
|
|
10291
10922
|
return { toast, dismiss, clear };
|
|
10292
10923
|
}, [dismiss, clear]);
|
|
10293
|
-
const value =
|
|
10924
|
+
const value = React25__default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
|
|
10294
10925
|
return /* @__PURE__ */ jsxs(ToastContext.Provider, { value, children: [
|
|
10295
10926
|
children,
|
|
10296
10927
|
/* @__PURE__ */ jsx(ToastViewport, { limit, ...viewportProps, children: toasts.map((t) => /* @__PURE__ */ jsx(
|
|
@@ -10398,13 +11029,13 @@ function TreeView({
|
|
|
10398
11029
|
}) {
|
|
10399
11030
|
const nodes = items;
|
|
10400
11031
|
const __twcStyles = useScopedStyles("twc-tree-styles", TREE_CSS);
|
|
10401
|
-
const [expInternal, setExpInternal] =
|
|
11032
|
+
const [expInternal, setExpInternal] = React25__default.useState(() => new Set(defaultExpanded));
|
|
10402
11033
|
const expanded = expandedProp !== void 0 ? new Set(expandedProp) : expInternal;
|
|
10403
|
-
const [selInternal, setSelInternal] =
|
|
11034
|
+
const [selInternal, setSelInternal] = React25__default.useState(defaultSelectedId);
|
|
10404
11035
|
const selectedId = selectedProp !== void 0 ? selectedProp : selInternal;
|
|
10405
|
-
const [focusId, setFocusId] =
|
|
10406
|
-
const rowRefs =
|
|
10407
|
-
const taRef =
|
|
11036
|
+
const [focusId, setFocusId] = React25__default.useState(null);
|
|
11037
|
+
const rowRefs = React25__default.useRef(/* @__PURE__ */ new Map());
|
|
11038
|
+
const taRef = React25__default.useRef({ str: "", t: 0 });
|
|
10408
11039
|
const toggle = (id) => {
|
|
10409
11040
|
const n = new Set(expanded);
|
|
10410
11041
|
n.has(id) ? n.delete(id) : n.add(id);
|
|
@@ -10536,7 +11167,7 @@ function AppShell({
|
|
|
10536
11167
|
...rest
|
|
10537
11168
|
}) {
|
|
10538
11169
|
const __twcStyles = useScopedStyles("twc-shell-styles", SHELL_CSS);
|
|
10539
|
-
const wiredSidebar =
|
|
11170
|
+
const wiredSidebar = React25__default.isValidElement(sidebar) && (sidebarOpen !== void 0 || onSidebarOpenChange !== void 0) ? React25__default.cloneElement(sidebar, {
|
|
10540
11171
|
overlay: sidebar.props.overlay !== void 0 ? sidebar.props.overlay : true,
|
|
10541
11172
|
open: sidebar.props.open !== void 0 ? sidebar.props.open : sidebarOpen,
|
|
10542
11173
|
onOpenChange: sidebar.props.onOpenChange !== void 0 ? sidebar.props.onOpenChange : onSidebarOpenChange
|
|
@@ -10678,7 +11309,7 @@ function Grid({
|
|
|
10678
11309
|
...rest
|
|
10679
11310
|
}) {
|
|
10680
11311
|
const responsive = columns != null && typeof columns === "object";
|
|
10681
|
-
const uid =
|
|
11312
|
+
const uid = React25__default.useId();
|
|
10682
11313
|
const gridId = responsive ? `g${uid.replace(/[^a-zA-Z0-9]/g, "")}` : null;
|
|
10683
11314
|
let css = "";
|
|
10684
11315
|
if (responsive) {
|
|
@@ -10749,7 +11380,7 @@ function Stack({
|
|
|
10749
11380
|
...rest
|
|
10750
11381
|
}) {
|
|
10751
11382
|
if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
|
|
10752
|
-
const kids = divider != null ?
|
|
11383
|
+
const kids = divider != null ? React25__default.Children.toArray(children).flatMap((child, i, arr) => i < arr.length - 1 ? [child, /* @__PURE__ */ jsx(React25__default.Fragment, { children: divider }, `twc-stack-div-${i}`)] : [child]) : children;
|
|
10753
11384
|
return /* @__PURE__ */ jsx(
|
|
10754
11385
|
Tag2,
|
|
10755
11386
|
{
|
|
@@ -10814,10 +11445,10 @@ function Code({
|
|
|
10814
11445
|
const __twcStyles = useScopedStyles("twc-code-styles", CODE_CSS);
|
|
10815
11446
|
const Tag2 = as ?? (block ? "pre" : "code");
|
|
10816
11447
|
if (Tag2 === "a" && rest.href != null) rest.href = safeHref9(rest.href);
|
|
10817
|
-
const rootRef =
|
|
10818
|
-
const [copied, setCopied] =
|
|
10819
|
-
const timerRef =
|
|
10820
|
-
|
|
11448
|
+
const rootRef = React25__default.useRef(null);
|
|
11449
|
+
const [copied, setCopied] = React25__default.useState(false);
|
|
11450
|
+
const timerRef = React25__default.useRef(null);
|
|
11451
|
+
React25__default.useEffect(() => () => clearTimeout(timerRef.current), []);
|
|
10821
11452
|
const doCopy = () => {
|
|
10822
11453
|
if (typeof navigator === "undefined" || !navigator.clipboard) return;
|
|
10823
11454
|
const text = typeof children === "string" ? children : rootRef.current?.textContent ?? "";
|
|
@@ -10936,45 +11567,45 @@ function Text({
|
|
|
10936
11567
|
);
|
|
10937
11568
|
}
|
|
10938
11569
|
var canUseDOM2 = typeof window !== "undefined" && typeof document !== "undefined";
|
|
10939
|
-
var useIsomorphicLayoutEffect = canUseDOM2 ?
|
|
11570
|
+
var useIsomorphicLayoutEffect = canUseDOM2 ? React25__default.useLayoutEffect : React25__default.useEffect;
|
|
10940
11571
|
function useMounted() {
|
|
10941
|
-
const [mounted, setMounted] =
|
|
10942
|
-
|
|
11572
|
+
const [mounted, setMounted] = React25__default.useState(false);
|
|
11573
|
+
React25__default.useEffect(() => {
|
|
10943
11574
|
setMounted(true);
|
|
10944
11575
|
}, []);
|
|
10945
11576
|
return mounted;
|
|
10946
11577
|
}
|
|
10947
11578
|
function usePrevious(value) {
|
|
10948
|
-
const ref =
|
|
10949
|
-
|
|
11579
|
+
const ref = React25__default.useRef(void 0);
|
|
11580
|
+
React25__default.useEffect(() => {
|
|
10950
11581
|
ref.current = value;
|
|
10951
11582
|
}, [value]);
|
|
10952
11583
|
return ref.current;
|
|
10953
11584
|
}
|
|
10954
11585
|
function useToggle(initial = false) {
|
|
10955
|
-
const [on, setOn] =
|
|
10956
|
-
const toggle =
|
|
11586
|
+
const [on, setOn] = React25__default.useState(initial);
|
|
11587
|
+
const toggle = React25__default.useCallback((next) => {
|
|
10957
11588
|
setOn((prev) => typeof next === "boolean" ? next : !prev);
|
|
10958
11589
|
}, []);
|
|
10959
11590
|
return [on, toggle, setOn];
|
|
10960
11591
|
}
|
|
10961
11592
|
function useDisclosure(initial = false) {
|
|
10962
|
-
const [open, setOpen] =
|
|
10963
|
-
const onOpen =
|
|
10964
|
-
const onClose =
|
|
10965
|
-
const onToggle =
|
|
11593
|
+
const [open, setOpen] = React25__default.useState(initial);
|
|
11594
|
+
const onOpen = React25__default.useCallback(() => setOpen(true), []);
|
|
11595
|
+
const onClose = React25__default.useCallback(() => setOpen(false), []);
|
|
11596
|
+
const onToggle = React25__default.useCallback(() => setOpen((p) => !p), []);
|
|
10966
11597
|
return { open, onOpen, onClose, onToggle, setOpen };
|
|
10967
11598
|
}
|
|
10968
11599
|
function useControllableState({ value, defaultValue, onChange } = {}) {
|
|
10969
11600
|
const isControlled = value !== void 0;
|
|
10970
|
-
const [uncontrolled, setUncontrolled] =
|
|
11601
|
+
const [uncontrolled, setUncontrolled] = React25__default.useState(defaultValue);
|
|
10971
11602
|
const current = isControlled ? value : uncontrolled;
|
|
10972
|
-
const ref =
|
|
11603
|
+
const ref = React25__default.useRef({ current, isControlled, onChange });
|
|
10973
11604
|
useIsomorphicLayoutEffect(() => {
|
|
10974
11605
|
ref.current = { current, isControlled, onChange };
|
|
10975
11606
|
});
|
|
10976
|
-
const wasControlled =
|
|
10977
|
-
|
|
11607
|
+
const wasControlled = React25__default.useRef(isControlled);
|
|
11608
|
+
React25__default.useEffect(() => {
|
|
10978
11609
|
if (wasControlled.current !== isControlled) {
|
|
10979
11610
|
warnOnce(
|
|
10980
11611
|
"useControllableState:switch",
|
|
@@ -10983,7 +11614,7 @@ function useControllableState({ value, defaultValue, onChange } = {}) {
|
|
|
10983
11614
|
wasControlled.current = isControlled;
|
|
10984
11615
|
}
|
|
10985
11616
|
});
|
|
10986
|
-
const setValue =
|
|
11617
|
+
const setValue = React25__default.useCallback((next) => {
|
|
10987
11618
|
const { current: cur, isControlled: ctrl, onChange: cb } = ref.current;
|
|
10988
11619
|
const resolved = typeof next === "function" ? next(cur) : next;
|
|
10989
11620
|
if (resolved === cur) return;
|
|
@@ -10994,7 +11625,7 @@ function useControllableState({ value, defaultValue, onChange } = {}) {
|
|
|
10994
11625
|
}
|
|
10995
11626
|
function useMediaQuery(query, { defaultValue = false, initializeWithValue = false } = {}) {
|
|
10996
11627
|
const get = () => canUseDOM2 ? window.matchMedia(query).matches : defaultValue;
|
|
10997
|
-
const [matches3, setMatches] =
|
|
11628
|
+
const [matches3, setMatches] = React25__default.useState(initializeWithValue ? get : defaultValue);
|
|
10998
11629
|
useIsomorphicLayoutEffect(() => {
|
|
10999
11630
|
if (!canUseDOM2) return void 0;
|
|
11000
11631
|
const mql = window.matchMedia(query);
|
|
@@ -11010,7 +11641,7 @@ function usePrefersReducedMotion() {
|
|
|
11010
11641
|
}
|
|
11011
11642
|
function useColorScheme({ storageKey = "twico-theme", attribute = "class", element, disableTransitionsOnChange = true } = {}) {
|
|
11012
11643
|
const getTarget = () => element || (canUseDOM2 ? document.documentElement : null);
|
|
11013
|
-
const firstApply =
|
|
11644
|
+
const firstApply = React25__default.useRef(true);
|
|
11014
11645
|
const read = () => {
|
|
11015
11646
|
if (!canUseDOM2) return "light";
|
|
11016
11647
|
try {
|
|
@@ -11020,8 +11651,8 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
|
|
|
11020
11651
|
}
|
|
11021
11652
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
11022
11653
|
};
|
|
11023
|
-
const [theme, setThemeState] =
|
|
11024
|
-
const apply =
|
|
11654
|
+
const [theme, setThemeState] = React25__default.useState(read);
|
|
11655
|
+
const apply = React25__default.useCallback(
|
|
11025
11656
|
(t) => {
|
|
11026
11657
|
const target = getTarget();
|
|
11027
11658
|
if (!target) return;
|
|
@@ -11047,11 +11678,11 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
|
|
|
11047
11678
|
useIsomorphicLayoutEffect(() => {
|
|
11048
11679
|
apply(theme);
|
|
11049
11680
|
}, [theme, apply]);
|
|
11050
|
-
const themeRef =
|
|
11681
|
+
const themeRef = React25__default.useRef(theme);
|
|
11051
11682
|
useIsomorphicLayoutEffect(() => {
|
|
11052
11683
|
themeRef.current = theme;
|
|
11053
11684
|
}, [theme]);
|
|
11054
|
-
const setTheme =
|
|
11685
|
+
const setTheme = React25__default.useCallback(
|
|
11055
11686
|
(t) => {
|
|
11056
11687
|
setThemeState(t);
|
|
11057
11688
|
try {
|
|
@@ -11062,10 +11693,10 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
|
|
|
11062
11693
|
},
|
|
11063
11694
|
[storageKey]
|
|
11064
11695
|
);
|
|
11065
|
-
const toggle =
|
|
11696
|
+
const toggle = React25__default.useCallback(() => {
|
|
11066
11697
|
setTheme(themeRef.current === "dark" ? "light" : "dark");
|
|
11067
11698
|
}, [setTheme]);
|
|
11068
|
-
|
|
11699
|
+
React25__default.useEffect(() => {
|
|
11069
11700
|
if (!canUseDOM2) return void 0;
|
|
11070
11701
|
const sync = () => setThemeState(read());
|
|
11071
11702
|
const onStorage = (e) => {
|
|
@@ -11081,14 +11712,14 @@ function useColorScheme({ storageKey = "twico-theme", attribute = "class", eleme
|
|
|
11081
11712
|
return { theme, setTheme, toggle, isDark: theme === "dark" };
|
|
11082
11713
|
}
|
|
11083
11714
|
function useEventListener(eventName, handler, element, options) {
|
|
11084
|
-
const saved =
|
|
11715
|
+
const saved = React25__default.useRef(handler);
|
|
11085
11716
|
useIsomorphicLayoutEffect(() => {
|
|
11086
11717
|
saved.current = handler;
|
|
11087
11718
|
}, [handler]);
|
|
11088
11719
|
const capture = typeof options === "boolean" ? options : options && options.capture;
|
|
11089
11720
|
const passive = typeof options === "object" && options ? options.passive : void 0;
|
|
11090
11721
|
const once = typeof options === "object" && options ? options.once : void 0;
|
|
11091
|
-
|
|
11722
|
+
React25__default.useEffect(() => {
|
|
11092
11723
|
const target = element && element.current || element || (canUseDOM2 ? window : null);
|
|
11093
11724
|
if (!target || !target.addEventListener) return void 0;
|
|
11094
11725
|
const opts = typeof options === "boolean" ? options : { capture, passive, once };
|
|
@@ -11098,11 +11729,11 @@ function useEventListener(eventName, handler, element, options) {
|
|
|
11098
11729
|
}, [eventName, element, capture, passive, once]);
|
|
11099
11730
|
}
|
|
11100
11731
|
function useClickOutside(ref, handler, events = ["mousedown", "touchstart"]) {
|
|
11101
|
-
const saved =
|
|
11732
|
+
const saved = React25__default.useRef(handler);
|
|
11102
11733
|
useIsomorphicLayoutEffect(() => {
|
|
11103
11734
|
saved.current = handler;
|
|
11104
11735
|
}, [handler]);
|
|
11105
|
-
|
|
11736
|
+
React25__default.useEffect(() => {
|
|
11106
11737
|
if (!canUseDOM2) return void 0;
|
|
11107
11738
|
const listener = (e) => {
|
|
11108
11739
|
const el = ref && ref.current;
|
|
@@ -11137,8 +11768,8 @@ function useLocalStorage(key, initialValue) {
|
|
|
11137
11768
|
return initialValue;
|
|
11138
11769
|
}
|
|
11139
11770
|
};
|
|
11140
|
-
const [stored, setStored] =
|
|
11141
|
-
const setValue =
|
|
11771
|
+
const [stored, setStored] = React25__default.useState(read);
|
|
11772
|
+
const setValue = React25__default.useCallback(
|
|
11142
11773
|
(value) => {
|
|
11143
11774
|
setStored((prev) => {
|
|
11144
11775
|
const next = typeof value === "function" ? value(prev) : value;
|
|
@@ -11154,8 +11785,8 @@ function useLocalStorage(key, initialValue) {
|
|
|
11154
11785
|
return [stored, setValue];
|
|
11155
11786
|
}
|
|
11156
11787
|
function useCopyToClipboard(timeout = 1500) {
|
|
11157
|
-
const [copied, setCopied] =
|
|
11158
|
-
const copy =
|
|
11788
|
+
const [copied, setCopied] = React25__default.useState(false);
|
|
11789
|
+
const copy = React25__default.useCallback(async (text) => {
|
|
11159
11790
|
if (!canUseDOM2 || !navigator.clipboard) {
|
|
11160
11791
|
setCopied(false);
|
|
11161
11792
|
return false;
|
|
@@ -11169,7 +11800,7 @@ function useCopyToClipboard(timeout = 1500) {
|
|
|
11169
11800
|
return false;
|
|
11170
11801
|
}
|
|
11171
11802
|
}, []);
|
|
11172
|
-
|
|
11803
|
+
React25__default.useEffect(() => {
|
|
11173
11804
|
if (!copied) return void 0;
|
|
11174
11805
|
const t = setTimeout(() => setCopied(false), timeout);
|
|
11175
11806
|
return () => clearTimeout(t);
|
|
@@ -11177,23 +11808,23 @@ function useCopyToClipboard(timeout = 1500) {
|
|
|
11177
11808
|
return { copied, copy };
|
|
11178
11809
|
}
|
|
11179
11810
|
function useDebouncedValue(value, delay = 200) {
|
|
11180
|
-
const [debounced, setDebounced] =
|
|
11181
|
-
|
|
11811
|
+
const [debounced, setDebounced] = React25__default.useState(value);
|
|
11812
|
+
React25__default.useEffect(() => {
|
|
11182
11813
|
const t = setTimeout(() => setDebounced(value), delay);
|
|
11183
11814
|
return () => clearTimeout(t);
|
|
11184
11815
|
}, [value, delay]);
|
|
11185
11816
|
return debounced;
|
|
11186
11817
|
}
|
|
11187
11818
|
function useDebouncedCallback(callback, delay = 200) {
|
|
11188
|
-
const saved =
|
|
11189
|
-
const timer =
|
|
11819
|
+
const saved = React25__default.useRef(callback);
|
|
11820
|
+
const timer = React25__default.useRef(null);
|
|
11190
11821
|
useIsomorphicLayoutEffect(() => {
|
|
11191
11822
|
saved.current = callback;
|
|
11192
11823
|
}, [callback]);
|
|
11193
|
-
|
|
11824
|
+
React25__default.useEffect(() => () => {
|
|
11194
11825
|
if (timer.current) clearTimeout(timer.current);
|
|
11195
11826
|
}, []);
|
|
11196
|
-
return
|
|
11827
|
+
return React25__default.useCallback(
|
|
11197
11828
|
(...args) => {
|
|
11198
11829
|
if (timer.current) clearTimeout(timer.current);
|
|
11199
11830
|
timer.current = setTimeout(() => saved.current(...args), delay);
|
|
@@ -11202,33 +11833,33 @@ function useDebouncedCallback(callback, delay = 200) {
|
|
|
11202
11833
|
);
|
|
11203
11834
|
}
|
|
11204
11835
|
function useInterval(callback, delay) {
|
|
11205
|
-
const saved =
|
|
11836
|
+
const saved = React25__default.useRef(callback);
|
|
11206
11837
|
useIsomorphicLayoutEffect(() => {
|
|
11207
11838
|
saved.current = callback;
|
|
11208
11839
|
}, [callback]);
|
|
11209
|
-
|
|
11840
|
+
React25__default.useEffect(() => {
|
|
11210
11841
|
if (delay == null) return void 0;
|
|
11211
11842
|
const id = setInterval(() => saved.current(), delay);
|
|
11212
11843
|
return () => clearInterval(id);
|
|
11213
11844
|
}, [delay]);
|
|
11214
11845
|
}
|
|
11215
11846
|
function useTimeout(callback, delay) {
|
|
11216
|
-
const saved =
|
|
11847
|
+
const saved = React25__default.useRef(callback);
|
|
11217
11848
|
useIsomorphicLayoutEffect(() => {
|
|
11218
11849
|
saved.current = callback;
|
|
11219
11850
|
}, [callback]);
|
|
11220
|
-
|
|
11851
|
+
React25__default.useEffect(() => {
|
|
11221
11852
|
if (delay == null) return void 0;
|
|
11222
11853
|
const id = setTimeout(() => saved.current(), delay);
|
|
11223
11854
|
return () => clearTimeout(id);
|
|
11224
11855
|
}, [delay]);
|
|
11225
11856
|
}
|
|
11226
11857
|
function useWindowSize() {
|
|
11227
|
-
const [size, setSize] =
|
|
11858
|
+
const [size, setSize] = React25__default.useState(() => ({
|
|
11228
11859
|
width: canUseDOM2 ? window.innerWidth : 0,
|
|
11229
11860
|
height: canUseDOM2 ? window.innerHeight : 0
|
|
11230
11861
|
}));
|
|
11231
|
-
|
|
11862
|
+
React25__default.useEffect(() => {
|
|
11232
11863
|
if (!canUseDOM2) return void 0;
|
|
11233
11864
|
const onResize = () => setSize({ width: window.innerWidth, height: window.innerHeight });
|
|
11234
11865
|
onResize();
|
|
@@ -11238,8 +11869,8 @@ function useWindowSize() {
|
|
|
11238
11869
|
return size;
|
|
11239
11870
|
}
|
|
11240
11871
|
function useHover(ref) {
|
|
11241
|
-
const [hovered, setHovered] =
|
|
11242
|
-
|
|
11872
|
+
const [hovered, setHovered] = React25__default.useState(false);
|
|
11873
|
+
React25__default.useEffect(() => {
|
|
11243
11874
|
const el = ref && ref.current;
|
|
11244
11875
|
if (!el) return void 0;
|
|
11245
11876
|
const on = () => setHovered(true);
|
|
@@ -11255,8 +11886,8 @@ function useHover(ref) {
|
|
|
11255
11886
|
}
|
|
11256
11887
|
function useIntersectionObserver(ref, options = {}) {
|
|
11257
11888
|
const { root = null, rootMargin = "0px", threshold = 0 } = options;
|
|
11258
|
-
const [entry, setEntry] =
|
|
11259
|
-
|
|
11889
|
+
const [entry, setEntry] = React25__default.useState(null);
|
|
11890
|
+
React25__default.useEffect(() => {
|
|
11260
11891
|
const el = ref && ref.current;
|
|
11261
11892
|
if (!canUseDOM2 || !el || typeof IntersectionObserver === "undefined") return void 0;
|
|
11262
11893
|
const obs = new IntersectionObserver(([e]) => setEntry(e), { root, rootMargin, threshold });
|
|
@@ -11265,31 +11896,14 @@ function useIntersectionObserver(ref, options = {}) {
|
|
|
11265
11896
|
}, [ref, root, rootMargin, JSON.stringify(threshold)]);
|
|
11266
11897
|
return entry;
|
|
11267
11898
|
}
|
|
11268
|
-
var __scrollLockCount = 0;
|
|
11269
|
-
var __scrollLockSaved = "";
|
|
11270
|
-
function useScrollLock(locked = true) {
|
|
11271
|
-
useIsomorphicLayoutEffect(() => {
|
|
11272
|
-
if (!canUseDOM2 || !locked) return void 0;
|
|
11273
|
-
if (__scrollLockCount === 0) {
|
|
11274
|
-
__scrollLockSaved = document.body.style.overflow;
|
|
11275
|
-
document.body.style.overflow = "hidden";
|
|
11276
|
-
}
|
|
11277
|
-
__scrollLockCount += 1;
|
|
11278
|
-
return () => {
|
|
11279
|
-
__scrollLockCount -= 1;
|
|
11280
|
-
if (__scrollLockCount === 0) {
|
|
11281
|
-
document.body.style.overflow = __scrollLockSaved;
|
|
11282
|
-
}
|
|
11283
|
-
};
|
|
11284
|
-
}, [locked]);
|
|
11285
|
-
}
|
|
11286
11899
|
function useId(prefix = "twc") {
|
|
11287
|
-
const raw =
|
|
11900
|
+
const raw = React25__default.useId();
|
|
11288
11901
|
return prefix ? `${prefix}-${raw.replace(/:/g, "")}` : raw;
|
|
11289
11902
|
}
|
|
11290
11903
|
var useFocusTrap2 = useFocusTrap;
|
|
11291
11904
|
var usePortal2 = usePortal;
|
|
11905
|
+
var useScrollLock2 = useScrollLock;
|
|
11292
11906
|
|
|
11293
|
-
export { Accordion, Alert, AppShell, Avatar, AvatarMenu, Badge, Box, Breadcrumb, Button, Card, Carousel, Chart, Checkbox, Code, ColorPicker, Combobox, CommandPalette, Container, Currency, CurrencyField, Datatable, DatePicker, DateRangePicker, Dialog, Divider, Drawer, EmptyState, Field, FileUpload, Grid, Heading, IconButton, Input, Kanban, List, Menu, MultiSelect, Navbar, Pagination, Popover, Progress, Radio, Rating, Select, Sidebar, Skeleton, Slider, Spinner, Stack, Stat, Stepper, Switch, Table, Tabs, Tag, Text, Textarea, Timeline, Toast, ToastProvider, ToastViewport, Tooltip, TreeView, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useFocusTrap2 as useFocusTrap, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePortal2 as usePortal, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
|
|
11907
|
+
export { Accordion, Alert, AppShell, Avatar, AvatarMenu, Badge, Box, Breadcrumb, Button, Card, Carousel, Chart, Checkbox, Code, ColorPicker, Combobox, CommandPalette, Container, Currency, CurrencyField, Datatable, DatePicker, DateRangePicker, Dialog, Divider, Drawer, EmptyState, Field, FileUpload, Grid, Heading, IconButton, Input, Kanban, List, Menu, MultiSelect, Navbar, Pagination, Popover, Progress, Radio, RadioGroup, Rating, Select, Sidebar, Skeleton, Slider, Spinner, Stack, Stat, Stepper, Switch, Table, Tabs, Tag, Text, Textarea, Timeline, Toast, ToastProvider, ToastViewport, Tooltip, TreeView, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useFocusTrap2 as useFocusTrap, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePortal2 as usePortal, usePrefersReducedMotion, usePrevious, useScrollLock2 as useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
|
|
11294
11908
|
//# sourceMappingURL=index.mjs.map
|
|
11295
11909
|
//# sourceMappingURL=index.mjs.map
|