twico-ui 1.11.0 → 1.12.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/CHANGELOG.md +28 -0
- package/dist/index.cjs +1690 -214
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +478 -72
- package/dist/index.d.ts +478 -72
- package/dist/index.mjs +1686 -215
- package/dist/index.mjs.map +1 -1
- package/llms.txt +308 -3
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -384,6 +384,12 @@ var ACCORDION_CSS = `
|
|
|
384
384
|
transition: grid-template-rows var(--duration-base) var(--ease-standard), visibility 0s; }
|
|
385
385
|
.twc-accordion__panel-inner { overflow: hidden; }
|
|
386
386
|
.twc-accordion__content { padding: 0 var(--space-4) var(--space-4); font-size: var(--text-sm); color: var(--color-text-muted); line-height: var(--leading-normal); }
|
|
387
|
+
/* WCAG 2.3.3: panels expand/collapse (and the chevron rotates) instantly under reduced motion
|
|
388
|
+
\u2014 visibility still toggles, so open/closed state is unchanged. */
|
|
389
|
+
@media (prefers-reduced-motion: reduce) {
|
|
390
|
+
.twc-accordion__panel, .twc-accordion__panel[data-open="true"] { transition: none; }
|
|
391
|
+
.twc-accordion__chevron { transition: none; }
|
|
392
|
+
}
|
|
387
393
|
`;
|
|
388
394
|
function Accordion({
|
|
389
395
|
items,
|
|
@@ -1143,6 +1149,9 @@ var CSS2 = `
|
|
|
1143
1149
|
transform: scale(0); pointer-events: none;
|
|
1144
1150
|
animation: twico-ripple var(--duration-slow) var(--ease-out) forwards;
|
|
1145
1151
|
}
|
|
1152
|
+
/* WCAG 2.3.3: suppress the click ripple entirely under reduced motion (display:none, not
|
|
1153
|
+
animation:none, so no static scale(0) dot lingers for the 600ms cleanup window). */
|
|
1154
|
+
@media (prefers-reduced-motion: reduce) { .twc-ripple { display: none; } }
|
|
1146
1155
|
`;
|
|
1147
1156
|
function safeHref4(url) {
|
|
1148
1157
|
if (url == null) return void 0;
|
|
@@ -1502,6 +1511,13 @@ var CAROUSEL_CSS = `
|
|
|
1502
1511
|
.twc-carousel__pause svg { width: 15px; height: 15px; display: block; }
|
|
1503
1512
|
.twc-carousel__live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
|
|
1504
1513
|
overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
|
|
1514
|
+
/* WCAG 2.3.3: no slide/dot/arrow motion when the user asks for reduced motion \u2014 the index
|
|
1515
|
+
still changes, it just jumps rather than tweening. */
|
|
1516
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1517
|
+
.twc-carousel__track { transition: none; }
|
|
1518
|
+
.twc-carousel__dot { transition: none; }
|
|
1519
|
+
.twc-carousel__arrow { transition: none; }
|
|
1520
|
+
}
|
|
1505
1521
|
`;
|
|
1506
1522
|
function Carousel({
|
|
1507
1523
|
children,
|
|
@@ -1603,7 +1619,7 @@ function Carousel({
|
|
|
1603
1619
|
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-carousel__arrow", "data-dir": "prev", "aria-label": "Previous", disabled: atStart, onClick: () => go(index - 1), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
1604
1620
|
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-carousel__arrow", "data-dir": "next", "aria-label": "Next", disabled: atEnd, onClick: () => go(index + 1), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) }) })
|
|
1605
1621
|
] }) : null,
|
|
1606
|
-
showDots && count > 1 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-carousel__dots", children: slides.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-carousel__dot", "data-active": i === index || void 0, "aria-label": `Go to slide ${i + 1}`, onClick: () => go(i) }, i)) }) : null
|
|
1622
|
+
showDots && count > 1 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-carousel__dots", children: slides.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-carousel__dot", "data-active": i === index || void 0, "aria-current": i === index ? "true" : void 0, "aria-label": `Go to slide ${i + 1}`, onClick: () => go(i) }, i)) }) : null
|
|
1607
1623
|
]
|
|
1608
1624
|
}
|
|
1609
1625
|
);
|
|
@@ -1631,9 +1647,9 @@ function niceCeil(v) {
|
|
|
1631
1647
|
const step = n <= 1 ? 1 : n <= 2 ? 2 : n <= 5 ? 5 : 10;
|
|
1632
1648
|
return step * pow;
|
|
1633
1649
|
}
|
|
1634
|
-
function niceNum(
|
|
1635
|
-
const exp = Math.floor(Math.log10(
|
|
1636
|
-
const frac = (
|
|
1650
|
+
function niceNum(range2, round) {
|
|
1651
|
+
const exp = Math.floor(Math.log10(range2 || 1));
|
|
1652
|
+
const frac = (range2 || 1) / Math.pow(10, exp);
|
|
1637
1653
|
let nf;
|
|
1638
1654
|
if (round) nf = frac < 1.5 ? 1 : frac < 3 ? 2 : frac < 7 ? 5 : 10;
|
|
1639
1655
|
else nf = frac <= 1 ? 1 : frac <= 2 ? 2 : frac <= 5 ? 5 : 10;
|
|
@@ -1644,8 +1660,8 @@ function niceScale(min, max, maxTicks = 5) {
|
|
|
1644
1660
|
if (min === max) {
|
|
1645
1661
|
max = min + 1;
|
|
1646
1662
|
}
|
|
1647
|
-
const
|
|
1648
|
-
const step = niceNum(
|
|
1663
|
+
const range2 = niceNum(max - min, false);
|
|
1664
|
+
const step = niceNum(range2 / Math.max(1, maxTicks - 1), true);
|
|
1649
1665
|
const niceMin = Math.floor(min / step) * step;
|
|
1650
1666
|
const niceMax = Math.ceil(max / step) * step;
|
|
1651
1667
|
const ticks = [];
|
|
@@ -2423,7 +2439,7 @@ function PieChart({
|
|
|
2423
2439
|
styles,
|
|
2424
2440
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: `0 0 ${H} ${H}`, role: "img", "aria-label": svgAriaLabel, "aria-describedby": tableId, children: total <= 0 ? /* @__PURE__ */ jsxRuntime.jsx("text", { className: "twc-chart__empty", x: cx, y: cy, textAnchor: "middle", dominantBaseline: "middle", children: "No data" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2425
2441
|
slices.map(({ d, i, v, s0, s1, span, pct, color }) => {
|
|
2426
|
-
const
|
|
2442
|
+
const pad2 = span > padAngle ? padAngle / 2 : 0;
|
|
2427
2443
|
const items = [{ color, label: fmt(v), value: `${pct}%` }];
|
|
2428
2444
|
let explode;
|
|
2429
2445
|
if (selected === i) {
|
|
@@ -2442,7 +2458,7 @@ function PieChart({
|
|
|
2442
2458
|
"data-mark": "",
|
|
2443
2459
|
"data-active": emph === i ? "true" : void 0,
|
|
2444
2460
|
"data-selected": selected === i ? "true" : void 0,
|
|
2445
|
-
d: arcPath(cx, cy, rOuter, rInner, s0 +
|
|
2461
|
+
d: arcPath(cx, cy, rOuter, rInner, s0 + pad2, s1 - pad2),
|
|
2446
2462
|
onMouseMove: (e) => {
|
|
2447
2463
|
setActive(i);
|
|
2448
2464
|
show({ title: d.label, items }, e);
|
|
@@ -2544,9 +2560,9 @@ function Gauge({
|
|
|
2544
2560
|
const cx = size / 2, cy = size / 2;
|
|
2545
2561
|
const span = endAngle - startAngle;
|
|
2546
2562
|
const frac = (v) => {
|
|
2547
|
-
const
|
|
2548
|
-
if (!
|
|
2549
|
-
return Math.max(0, Math.min(1, ((Number(v) || 0) - min) /
|
|
2563
|
+
const range2 = max - min;
|
|
2564
|
+
if (!range2) return 0;
|
|
2565
|
+
return Math.max(0, Math.min(1, ((Number(v) || 0) - min) / range2));
|
|
2550
2566
|
};
|
|
2551
2567
|
const isMulti = Array.isArray(series) && series.length > 0;
|
|
2552
2568
|
const items = isMulti ? series : [{ value: Number(value) || 0, label, color }];
|
|
@@ -2721,9 +2737,9 @@ function Sparkline({
|
|
|
2721
2737
|
const n = values.length;
|
|
2722
2738
|
const W = width, H = height;
|
|
2723
2739
|
const dotR = showDots ? Math.max(2, strokeWidth + 1) : 0;
|
|
2724
|
-
const
|
|
2725
|
-
const innerW = Math.max(1, W -
|
|
2726
|
-
const innerH = Math.max(1, H -
|
|
2740
|
+
const pad2 = Math.max(strokeWidth / 2, dotR) + 1;
|
|
2741
|
+
const innerW = Math.max(1, W - pad2 * 2);
|
|
2742
|
+
const innerH = Math.max(1, H - pad2 * 2);
|
|
2727
2743
|
const dMin = min != null ? min : n ? Math.min(...values) : 0;
|
|
2728
2744
|
const dMax = max != null ? max : n ? Math.max(...values) : 1;
|
|
2729
2745
|
let lo = dMin, hi = dMax;
|
|
@@ -2732,9 +2748,9 @@ function Sparkline({
|
|
|
2732
2748
|
hi = hi + 1;
|
|
2733
2749
|
}
|
|
2734
2750
|
const span = hi - lo;
|
|
2735
|
-
const x = (i) => n <= 1 ?
|
|
2736
|
-
const y = (v) =>
|
|
2737
|
-
const baselineY =
|
|
2751
|
+
const x = (i) => n <= 1 ? pad2 + innerW / 2 : pad2 + innerW / (n - 1) * i;
|
|
2752
|
+
const y = (v) => pad2 + innerH - (v - lo) / span * innerH;
|
|
2753
|
+
const baselineY = pad2 + innerH;
|
|
2738
2754
|
const points = values.map((v, i) => [x(i), y(v)]);
|
|
2739
2755
|
const crv = isBar ? "straight" : curve;
|
|
2740
2756
|
const pathOpts = { smooth: crv === "smooth", step: crv === "stepped" ? "after" : null };
|
|
@@ -2766,7 +2782,7 @@ function Sparkline({
|
|
|
2766
2782
|
"data-mark": true,
|
|
2767
2783
|
"data-selected": selected === i || void 0,
|
|
2768
2784
|
style: { fill: color },
|
|
2769
|
-
x:
|
|
2785
|
+
x: pad2 + band * i + (band - slot) / 2,
|
|
2770
2786
|
y: baselineY - h,
|
|
2771
2787
|
width: Math.max(1, slot),
|
|
2772
2788
|
height: Math.max(1, h),
|
|
@@ -3933,8 +3949,8 @@ function FunnelChart({
|
|
|
3933
3949
|
const n = rows.length;
|
|
3934
3950
|
const fmt = valueFormat || fmtNumber;
|
|
3935
3951
|
const W = 600, H = height;
|
|
3936
|
-
const
|
|
3937
|
-
const innerW = W -
|
|
3952
|
+
const pad2 = 8;
|
|
3953
|
+
const innerW = W - pad2 * 2, innerH = H - pad2 * 2;
|
|
3938
3954
|
const values = rows.map((d) => Number(d.value) || 0);
|
|
3939
3955
|
const maxValue = Math.max(0, ...values);
|
|
3940
3956
|
const denom = maxValue > 0 ? maxValue : 1;
|
|
@@ -3954,16 +3970,16 @@ function FunnelChart({
|
|
|
3954
3970
|
let points, tx, ty;
|
|
3955
3971
|
if (horizontal) {
|
|
3956
3972
|
const bandW = innerW / Math.max(1, n);
|
|
3957
|
-
const x0 =
|
|
3958
|
-
const x1 =
|
|
3973
|
+
const x0 = pad2 + bandW * i + gap / 2;
|
|
3974
|
+
const x1 = pad2 + bandW * (i + 1) - gap / 2;
|
|
3959
3975
|
const cy = H / 2;
|
|
3960
3976
|
points = [[x0, cy - lead], [x1, cy - trail], [x1, cy + trail], [x0, cy + lead]];
|
|
3961
3977
|
tx = (x0 + x1) / 2;
|
|
3962
3978
|
ty = cy;
|
|
3963
3979
|
} else {
|
|
3964
3980
|
const bandH = innerH / Math.max(1, n);
|
|
3965
|
-
const y0 =
|
|
3966
|
-
const y1 =
|
|
3981
|
+
const y0 = pad2 + bandH * i + gap / 2;
|
|
3982
|
+
const y1 = pad2 + bandH * (i + 1) - gap / 2;
|
|
3967
3983
|
const cx = W / 2;
|
|
3968
3984
|
points = [[cx - lead, y0], [cx + lead, y0], [cx + trail, y1], [cx - trail, y1]];
|
|
3969
3985
|
tx = cx;
|
|
@@ -5126,6 +5142,7 @@ function Checkbox({
|
|
|
5126
5142
|
.twc-check[data-invalid="true"] .twc-check__box { border-color: var(--color-danger); }
|
|
5127
5143
|
.twc-check__text { display: flex; flex-direction: column; gap: 2px; }
|
|
5128
5144
|
.twc-check__label { font-size: var(--text-sm); font-weight: var(--font-medium); color: var(--color-text); line-height: 1.3; }
|
|
5145
|
+
.twc-field__req { color: var(--color-danger); }
|
|
5129
5146
|
.twc-check__desc { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
5130
5147
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
5131
5148
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
@@ -5166,7 +5183,10 @@ function Checkbox({
|
|
|
5166
5183
|
),
|
|
5167
5184
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-check__box", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "twc-check__svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3.5", strokeLinecap: "round", strokeLinejoin: "round", children: mixed ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }),
|
|
5168
5185
|
label || description ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-check__text", children: [
|
|
5169
|
-
label ? /* @__PURE__ */ jsxRuntime.
|
|
5186
|
+
label ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-check__label", children: [
|
|
5187
|
+
label,
|
|
5188
|
+
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
5189
|
+
] }) : null,
|
|
5170
5190
|
description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-check__desc", children: description }) : null
|
|
5171
5191
|
] }) : null
|
|
5172
5192
|
] });
|
|
@@ -5186,9 +5206,11 @@ var FIELD_CSS = `
|
|
|
5186
5206
|
var COLORPICKER_CSS = `
|
|
5187
5207
|
.twc-cp { position: relative; font-family: var(--font-sans); display: flex; flex-direction: column; gap: var(--space-1-5); }
|
|
5188
5208
|
.twc-cp__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); }
|
|
5189
|
-
.twc-cp__trigger { display: flex; align-items: center; gap: var(--space-2-5);
|
|
5209
|
+
.twc-cp__trigger { display: flex; align-items: center; gap: var(--space-2-5); --_h: var(--control-h-md); height: var(--_h); padding: 0 var(--space-2) 0 var(--space-2);
|
|
5190
5210
|
background: var(--color-surface); border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md); cursor: pointer;
|
|
5191
5211
|
transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); }
|
|
5212
|
+
.twc-cp__trigger[data-size="sm"] { --_h: var(--control-h-sm); }
|
|
5213
|
+
.twc-cp__trigger[data-size="lg"] { --_h: var(--control-h-lg); }
|
|
5192
5214
|
.twc-cp__trigger:hover:not([data-open="true"]):not([data-disabled="true"]) { border-color: var(--color-border-strong); }
|
|
5193
5215
|
.twc-cp__trigger[data-open="true"] { border-color: var(--color-primary); box-shadow: var(--ring); }
|
|
5194
5216
|
.twc-cp__trigger[data-invalid="true"] { border-color: var(--color-danger); }
|
|
@@ -5282,6 +5304,7 @@ function ColorPicker({
|
|
|
5282
5304
|
defaultValue = "#6366F1",
|
|
5283
5305
|
presets = DEFAULT_PRESETS,
|
|
5284
5306
|
disabled = false,
|
|
5307
|
+
size = "md",
|
|
5285
5308
|
alpha = false,
|
|
5286
5309
|
tone = "primary",
|
|
5287
5310
|
onChange,
|
|
@@ -5433,6 +5456,7 @@ function ColorPicker({
|
|
|
5433
5456
|
"data-open": open || void 0,
|
|
5434
5457
|
"data-disabled": disabled || void 0,
|
|
5435
5458
|
"data-invalid": invalid || void 0,
|
|
5459
|
+
"data-size": size,
|
|
5436
5460
|
role: "button",
|
|
5437
5461
|
tabIndex: disabled ? -1 : 0,
|
|
5438
5462
|
"aria-haspopup": "dialog",
|
|
@@ -7353,6 +7377,8 @@ function MultiSelect({
|
|
|
7353
7377
|
name,
|
|
7354
7378
|
max,
|
|
7355
7379
|
maxTagCount,
|
|
7380
|
+
filter,
|
|
7381
|
+
onInputChange,
|
|
7356
7382
|
virtualized = false,
|
|
7357
7383
|
overscan = 8,
|
|
7358
7384
|
id,
|
|
@@ -7380,10 +7406,11 @@ function MultiSelect({
|
|
|
7380
7406
|
const popRef = React51__namespace.default.useRef(null);
|
|
7381
7407
|
const listRef = React51__namespace.default.useRef(null);
|
|
7382
7408
|
const activeRef = React51__namespace.default.useRef(null);
|
|
7383
|
-
const fGroups = React51__namespace.default.useMemo(
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7409
|
+
const fGroups = React51__namespace.default.useMemo(() => {
|
|
7410
|
+
const q = query.trim();
|
|
7411
|
+
const fn = filter === false ? null : typeof filter === "function" ? filter : matches2;
|
|
7412
|
+
return groups.map((g) => ({ group: g.group, options: fn ? g.options.filter((o) => fn(o, q)) : g.options })).filter((g) => g.options.length);
|
|
7413
|
+
}, [groups, query, filter]);
|
|
7387
7414
|
const visible = React51__namespace.default.useMemo(() => fGroups.flatMap((g) => g.options), [fGroups]);
|
|
7388
7415
|
const rowH = React51__namespace.default.useMemo(() => visible.some((o) => o.description) ? 48 : 36, [visible]);
|
|
7389
7416
|
const GROUP_H = 30;
|
|
@@ -7663,6 +7690,7 @@ function MultiSelect({
|
|
|
7663
7690
|
onChange: (e) => {
|
|
7664
7691
|
setQuery(e.target.value);
|
|
7665
7692
|
setOpen(true);
|
|
7693
|
+
onInputChange?.(e.target.value);
|
|
7666
7694
|
},
|
|
7667
7695
|
onKeyDown: (e) => {
|
|
7668
7696
|
onKeyDown?.(e);
|
|
@@ -7838,7 +7866,12 @@ var TOOLTIP_CSS = `
|
|
|
7838
7866
|
padding: 6px 10px; border-radius: var(--radius-md);
|
|
7839
7867
|
background: var(--color-text); color: var(--color-surface);
|
|
7840
7868
|
font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--font-medium);
|
|
7841
|
-
line-height: 1.3; white-space: normal;
|
|
7869
|
+
line-height: 1.3; white-space: normal;
|
|
7870
|
+
/* Grow horizontally to max-width, then wrap. max-content sizes to the content (capped by
|
|
7871
|
+
max-width) and \u2014 unlike shrink-to-fit width:auto \u2014 is NOT constrained by the space between
|
|
7872
|
+
the fixed left edge and the viewport edge, so a tooltip near the right edge no longer
|
|
7873
|
+
collapses to ~1 word per line and stretch vertically. */
|
|
7874
|
+
width: max-content; max-width: var(--_tw-maxw, 320px); box-shadow: var(--shadow-md);
|
|
7842
7875
|
opacity: 0; transform: scale(0.9); transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-spring);
|
|
7843
7876
|
}
|
|
7844
7877
|
.twc-tooltip[data-show="true"] { pointer-events: auto; }
|
|
@@ -7849,10 +7882,13 @@ var TOOLTIP_CSS = `
|
|
|
7849
7882
|
.twc-tooltip[data-place="right"] { transform-origin: left center; translate: 0 -50%; }
|
|
7850
7883
|
.twc-tooltip[data-show="true"][data-place="top"], .twc-tooltip[data-show="true"][data-place="bottom"] { transform: scale(1); }
|
|
7851
7884
|
.twc-tooltip__arrow { position: absolute; width: 7px; height: 7px; background: var(--color-text); transform: rotate(45deg); }
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
.twc-tooltip[data-place="
|
|
7885
|
+
/* Arrow tracks the trigger via --_tw-arrow-x/y (px from the tooltip edge) instead of being
|
|
7886
|
+
locked to the centre, so it still points at the trigger when the bubble is clamped near a
|
|
7887
|
+
viewport edge. Falls back to 50% before measurement / SSR. */
|
|
7888
|
+
.twc-tooltip[data-place="top"] .twc-tooltip__arrow { bottom: -3px; left: var(--_tw-arrow-x, 50%); margin-left: -3.5px; }
|
|
7889
|
+
.twc-tooltip[data-place="bottom"] .twc-tooltip__arrow { top: -3px; left: var(--_tw-arrow-x, 50%); margin-left: -3.5px; }
|
|
7890
|
+
.twc-tooltip[data-place="left"] .twc-tooltip__arrow { right: -3px; top: var(--_tw-arrow-y, 50%); margin-top: -3.5px; }
|
|
7891
|
+
.twc-tooltip[data-place="right"] .twc-tooltip__arrow { left: -3px; top: var(--_tw-arrow-y, 50%); margin-top: -3.5px; }
|
|
7856
7892
|
@media (prefers-reduced-motion: reduce) { .twc-tooltip { transition: opacity var(--duration-fast) linear; transform: none; } }
|
|
7857
7893
|
`;
|
|
7858
7894
|
function Tooltip({
|
|
@@ -7906,10 +7942,22 @@ function Tooltip({
|
|
|
7906
7942
|
else if (placement === "left" && spaceLeft < tw && spaceRight > spaceLeft) side = "right";
|
|
7907
7943
|
else if (placement === "right" && spaceRight < tw && spaceLeft > spaceRight) side = "left";
|
|
7908
7944
|
const base = { left: "auto", right: "auto", top: "auto", bottom: "auto", place: side };
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7945
|
+
const AP = 12;
|
|
7946
|
+
const arrowX = (center) => tw ? Math.round(Math.min(Math.max(cx - (center - tw / 2), AP), tw - AP)) : void 0;
|
|
7947
|
+
const arrowY = (center) => th ? Math.round(Math.min(Math.max(cy - (center - th / 2), AP), th - AP)) : void 0;
|
|
7948
|
+
if (side === "bottom") {
|
|
7949
|
+
const c = clampX(cx);
|
|
7950
|
+
setCoords({ ...base, left: c, top: Math.round(r2.bottom + gap), arrowX: arrowX(c) });
|
|
7951
|
+
} else if (side === "left") {
|
|
7952
|
+
const c = clampY(cy);
|
|
7953
|
+
setCoords({ ...base, top: c, right: Math.round(vw - r2.left + gap), arrowY: arrowY(c) });
|
|
7954
|
+
} else if (side === "right") {
|
|
7955
|
+
const c = clampY(cy);
|
|
7956
|
+
setCoords({ ...base, top: c, left: Math.round(r2.right + gap), arrowY: arrowY(c) });
|
|
7957
|
+
} else {
|
|
7958
|
+
const c = clampX(cx);
|
|
7959
|
+
setCoords({ ...base, left: c, bottom: Math.round(vh - r2.top + gap), arrowX: arrowX(c) });
|
|
7960
|
+
}
|
|
7913
7961
|
}, [placement]);
|
|
7914
7962
|
React51__namespace.default.useEffect(() => {
|
|
7915
7963
|
place();
|
|
@@ -7966,7 +8014,15 @@ function Tooltip({
|
|
|
7966
8014
|
"aria-hidden": show ? void 0 : "true",
|
|
7967
8015
|
onMouseEnter: cancelClose,
|
|
7968
8016
|
onMouseLeave: close,
|
|
7969
|
-
style: {
|
|
8017
|
+
style: {
|
|
8018
|
+
position: "fixed",
|
|
8019
|
+
left: coords.left,
|
|
8020
|
+
right: coords.right,
|
|
8021
|
+
top: coords.top,
|
|
8022
|
+
bottom: coords.bottom,
|
|
8023
|
+
"--_tw-arrow-x": coords.arrowX != null ? `${coords.arrowX}px` : void 0,
|
|
8024
|
+
"--_tw-arrow-y": coords.arrowY != null ? `${coords.arrowY}px` : void 0
|
|
8025
|
+
},
|
|
7970
8026
|
children: [
|
|
7971
8027
|
label,
|
|
7972
8028
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
|
|
@@ -8346,7 +8402,8 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
|
|
|
8346
8402
|
.twc-dt__col-pin:hover { background: var(--color-surface); color: var(--color-text); }
|
|
8347
8403
|
.twc-dt__col-pin[data-on="true"] { color: var(--color-primary); background: var(--color-primary-subtle); }
|
|
8348
8404
|
.twc-dt__col-pin svg { width: 14px; height: 14px; }
|
|
8349
|
-
.twc-dt__sw { width: 32px; height: 18px; border-radius: var(--radius-full); background: var(--color-border-strong); position: relative; flex: none; transition: background-color var(--duration-base); }
|
|
8405
|
+
.twc-dt__sw { width: 32px; height: 18px; border-radius: var(--radius-full); background: var(--color-border-strong); position: relative; flex: none; cursor: pointer; transition: background-color var(--duration-base); }
|
|
8406
|
+
.twc-dt__sw[aria-disabled="true"] { cursor: default; }
|
|
8350
8407
|
.twc-dt__sw[data-on="true"] { background: var(--color-primary); }
|
|
8351
8408
|
.twc-dt__sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: var(--radius-full); background: var(--color-primary-fg); box-shadow: var(--shadow-sm); transition: transform var(--duration-base) var(--ease-spring); }
|
|
8352
8409
|
.twc-dt__sw:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
@@ -8476,6 +8533,7 @@ var NUM_OPS = [
|
|
|
8476
8533
|
];
|
|
8477
8534
|
var opsFor = (type) => type === "number" ? NUM_OPS : STR_OPS;
|
|
8478
8535
|
var isMultiOp = (op) => op === "isAnyOf";
|
|
8536
|
+
var getColVal = (col, row) => col && col.valueGetter ? col.valueGetter(row) : row == null ? void 0 : row[col && col.field];
|
|
8479
8537
|
function testFilter(raw, op, target, type) {
|
|
8480
8538
|
if (op === "isEmpty") return raw == null || raw === "";
|
|
8481
8539
|
if (op === "isNotEmpty") return !(raw == null || raw === "");
|
|
@@ -8521,14 +8579,15 @@ function runDatatableQuery(rows, query, options = {}) {
|
|
|
8521
8579
|
const cols = options.columns || [];
|
|
8522
8580
|
const typeOf = (field) => cols.find((c) => c.field === field)?.type === "number" ? "number" : "string";
|
|
8523
8581
|
const searchFields = options.searchFields || (cols.length ? cols.filter((c) => c.field && c.type !== "actions").map((c) => c.field) : rows && rows[0] ? Object.keys(rows[0]) : []);
|
|
8582
|
+
const gv = (field, r2) => getColVal(cols.find((c) => c.field === field) || { field }, r2);
|
|
8524
8583
|
let out = Array.isArray(rows) ? rows : [];
|
|
8525
8584
|
const quick = String(q.quickFilter || "").trim().toLowerCase();
|
|
8526
|
-
if (quick) out = out.filter((r2) => searchFields.some((f) => String(
|
|
8527
|
-
for (const f of q.filters || []) out = out.filter((r2) => testFilter(
|
|
8585
|
+
if (quick) out = out.filter((r2) => searchFields.some((f) => String(gv(f, r2) ?? "").toLowerCase().includes(quick)));
|
|
8586
|
+
for (const f of q.filters || []) out = out.filter((r2) => testFilter(gv(f.field, r2), f.op, f.value, typeOf(f.field)));
|
|
8528
8587
|
if (q.sort && q.sort.field) {
|
|
8529
8588
|
const { field, dir } = q.sort, numeric = typeOf(field) === "number";
|
|
8530
8589
|
out = [...out].sort((a, b) => {
|
|
8531
|
-
const av =
|
|
8590
|
+
const av = gv(field, a), bv = gv(field, b);
|
|
8532
8591
|
if (av == null) return 1;
|
|
8533
8592
|
if (bv == null) return -1;
|
|
8534
8593
|
const r2 = numeric ? av - bv : String(av).localeCompare(String(bv));
|
|
@@ -8786,6 +8845,7 @@ function Datatable({
|
|
|
8786
8845
|
"aria-label": ariaLabelAttr,
|
|
8787
8846
|
rowGrouping = [],
|
|
8788
8847
|
rowNumbers = false,
|
|
8848
|
+
searchFields = null,
|
|
8789
8849
|
rowPinning = false,
|
|
8790
8850
|
rowReorder = false,
|
|
8791
8851
|
rowResize = false,
|
|
@@ -9127,17 +9187,18 @@ function Datatable({
|
|
|
9127
9187
|
let out = rows;
|
|
9128
9188
|
if (quick.trim()) {
|
|
9129
9189
|
const q = quick.trim().toLowerCase();
|
|
9130
|
-
|
|
9190
|
+
const searchCols = searchFields && searchFields.length ? searchFields.map((f) => colByField[f] || { field: f }) : visibleCols;
|
|
9191
|
+
out = out.filter((r2) => searchCols.some((c) => String(getColVal(c, r2) ?? "").toLowerCase().includes(q)));
|
|
9131
9192
|
}
|
|
9132
9193
|
for (const f of filters) {
|
|
9133
9194
|
const col = colByField[f.field];
|
|
9134
9195
|
if (!col) continue;
|
|
9135
|
-
out = out.filter((r2) => testFilter(r2
|
|
9196
|
+
out = out.filter((r2) => testFilter(getColVal(col, r2), f.op, f.value, col.type));
|
|
9136
9197
|
}
|
|
9137
9198
|
if (sort) {
|
|
9138
9199
|
const col = colByField[sort.field];
|
|
9139
9200
|
out = [...out].sort((a, b) => {
|
|
9140
|
-
const av = a
|
|
9201
|
+
const av = getColVal(col, a), bv = getColVal(col, b);
|
|
9141
9202
|
if (av == null) return 1;
|
|
9142
9203
|
if (bv == null) return -1;
|
|
9143
9204
|
const r2 = col?.type === "number" ? av - bv : String(av).localeCompare(String(bv));
|
|
@@ -9149,7 +9210,7 @@ function Datatable({
|
|
|
9149
9210
|
out = [...out].sort((a, b) => (idx.get(keyOf(a)) ?? 1e9) - (idx.get(keyOf(b)) ?? 1e9));
|
|
9150
9211
|
}
|
|
9151
9212
|
return out;
|
|
9152
|
-
}, [rows, quick, filters, sort, visibleCols, colByField, serverMode, rowOrder]);
|
|
9213
|
+
}, [rows, quick, filters, sort, visibleCols, colByField, serverMode, rowOrder, searchFields]);
|
|
9153
9214
|
const paginated = pageSize > 0;
|
|
9154
9215
|
const serverTotal = rowCount == null ? processed.length : rowCount;
|
|
9155
9216
|
const totalRows = serverMode ? serverTotal : processed.length;
|
|
@@ -9174,7 +9235,7 @@ function Datatable({
|
|
|
9174
9235
|
function computeAgg(col, data) {
|
|
9175
9236
|
const agg = col.aggregation;
|
|
9176
9237
|
if (!agg) return null;
|
|
9177
|
-
const raw = data.map((r2) => r2
|
|
9238
|
+
const raw = data.map((r2) => getColVal(col, r2)).filter((v) => v != null && v !== "");
|
|
9178
9239
|
if (typeof agg === "function") return agg(raw, data);
|
|
9179
9240
|
if (agg === "count") return raw.length;
|
|
9180
9241
|
const nums = raw.map(Number).filter((n) => !Number.isNaN(n));
|
|
@@ -9192,7 +9253,8 @@ function Datatable({
|
|
|
9192
9253
|
const field = activeGroupBy[depth];
|
|
9193
9254
|
const map = /* @__PURE__ */ new Map();
|
|
9194
9255
|
for (const r2 of rowsIn) {
|
|
9195
|
-
const
|
|
9256
|
+
const gvv = getColVal(colByField[field], r2);
|
|
9257
|
+
const v = gvv == null || gvv === "" ? "\u2014" : gvv;
|
|
9196
9258
|
if (!map.has(v)) map.set(v, []);
|
|
9197
9259
|
map.get(v).push(r2);
|
|
9198
9260
|
}
|
|
@@ -9489,13 +9551,17 @@ function Datatable({
|
|
|
9489
9551
|
function optionsForField(field) {
|
|
9490
9552
|
const col = colByField[field];
|
|
9491
9553
|
if (col?.valueOptions) return col.valueOptions.map((o) => typeof o === "string" ? { value: o, label: o } : o);
|
|
9492
|
-
const
|
|
9554
|
+
const seen2 = /* @__PURE__ */ new Map();
|
|
9493
9555
|
for (const r2 of rows) {
|
|
9494
|
-
const
|
|
9495
|
-
if (
|
|
9496
|
-
|
|
9556
|
+
const raw = getColVal(col, r2);
|
|
9557
|
+
if (raw == null || raw === "") continue;
|
|
9558
|
+
const key = String(raw);
|
|
9559
|
+
if (seen2.has(key)) continue;
|
|
9560
|
+
const label = col?.valueFormatter ? col.valueFormatter(raw, r2) : key;
|
|
9561
|
+
seen2.set(key, { value: key, label: typeof label === "string" || typeof label === "number" ? String(label) : key });
|
|
9562
|
+
if (seen2.size > 80) break;
|
|
9497
9563
|
}
|
|
9498
|
-
return [...
|
|
9564
|
+
return [...seen2.values()].sort((a, b) => String(a.label).localeCompare(String(b.label)));
|
|
9499
9565
|
}
|
|
9500
9566
|
const [resizing, setResizing] = React51__namespace.default.useState(false);
|
|
9501
9567
|
function startResize(e, field) {
|
|
@@ -9525,7 +9591,7 @@ function Datatable({
|
|
|
9525
9591
|
meas.setAttribute("aria-hidden", "true");
|
|
9526
9592
|
meas.style.cssText = "position:fixed;left:-9999px;top:-9999px;visibility:hidden;pointer-events:none;white-space:nowrap;display:inline-block;box-sizing:content-box;padding:0;";
|
|
9527
9593
|
document.body.appendChild(meas);
|
|
9528
|
-
let content = 0,
|
|
9594
|
+
let content = 0, pad2 = 0;
|
|
9529
9595
|
try {
|
|
9530
9596
|
for (const cell of cells) {
|
|
9531
9597
|
const src = cell.tagName === "TH" ? cell.querySelector(".twc-dt__th-inner") || cell : cell;
|
|
@@ -9537,13 +9603,13 @@ function Datatable({
|
|
|
9537
9603
|
meas.style.letterSpacing = cs.letterSpacing;
|
|
9538
9604
|
meas.innerHTML = src.innerHTML;
|
|
9539
9605
|
content = Math.max(content, meas.scrollWidth);
|
|
9540
|
-
|
|
9606
|
+
pad2 = Math.max(pad2, (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0));
|
|
9541
9607
|
}
|
|
9542
9608
|
} finally {
|
|
9543
9609
|
meas.innerHTML = "";
|
|
9544
9610
|
document.body.removeChild(meas);
|
|
9545
9611
|
}
|
|
9546
|
-
const w = Math.min(640, Math.max(72, Math.ceil(content) + Math.ceil(
|
|
9612
|
+
const w = Math.min(640, Math.max(72, Math.ceil(content) + Math.ceil(pad2) + 6));
|
|
9547
9613
|
setWidths((m) => ({ ...m, [field]: w }));
|
|
9548
9614
|
}
|
|
9549
9615
|
function onColDrop(targetField) {
|
|
@@ -9562,7 +9628,7 @@ function Datatable({
|
|
|
9562
9628
|
function exportData(format = "csv") {
|
|
9563
9629
|
const expCols = ordered.filter((c) => c.type !== "actions");
|
|
9564
9630
|
const source = serverMode ? paged : processed;
|
|
9565
|
-
const cellValue = (c, row) => c.exportValue ? c.exportValue(row[c.field], row) : row
|
|
9631
|
+
const cellValue = (c, row) => c.exportValue ? c.exportValue(row[c.field], row) : getColVal(c, row);
|
|
9566
9632
|
const fname = (ext) => `${exportFilename}.${ext}`;
|
|
9567
9633
|
const download = (text2, mime, ext) => {
|
|
9568
9634
|
const blob = new Blob([text2], { type: mime });
|
|
@@ -9611,7 +9677,7 @@ function Datatable({
|
|
|
9611
9677
|
}
|
|
9612
9678
|
}
|
|
9613
9679
|
const data = serverMode ? paged : processed;
|
|
9614
|
-
const raw = data.map((r2) => r2
|
|
9680
|
+
const raw = data.map((r2) => getColVal(col, r2)).filter((v) => v != null && v !== "");
|
|
9615
9681
|
if (typeof agg === "function") return agg(raw, data);
|
|
9616
9682
|
if (agg === "count") return raw.length;
|
|
9617
9683
|
const nums = raw.map(Number).filter((n) => !Number.isNaN(n));
|
|
@@ -10030,7 +10096,7 @@ function Datatable({
|
|
|
10030
10096
|
showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td 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 }, children: typeof ri === "number" ? (paginated || serverMode ? pageVal * sizeVal : 0) + ri + 1 : "" }) : null,
|
|
10031
10097
|
ordered.map((c, ci) => {
|
|
10032
10098
|
const st = stickyOf(c.field);
|
|
10033
|
-
const val = row
|
|
10099
|
+
const val = getColVal(c, row);
|
|
10034
10100
|
const isActions = c.type === "actions";
|
|
10035
10101
|
const editable = isColEditable(c);
|
|
10036
10102
|
const isEditing = editing && editing.key === k && editing.field === c.field;
|
|
@@ -10087,9 +10153,9 @@ function Datatable({
|
|
|
10087
10153
|
}
|
|
10088
10154
|
function renderPivot() {
|
|
10089
10155
|
const rFields = pivotConfig.rows, cFields = pivotConfig.columns || [], values = pivotConfig.values;
|
|
10090
|
-
const rowKeyOf = (r2) => rFields.map((f) =>
|
|
10091
|
-
const colPathOf = (r2) => cFields.map((f) => String(
|
|
10092
|
-
const aggOf2 = (subset, v) => computeAgg({ field: v.field, aggregation: v.agg || "sum" }, subset || []);
|
|
10156
|
+
const rowKeyOf = (r2) => rFields.map((f) => getColVal(colByField[f], r2) ?? "\u2014").join(" \xB7 ");
|
|
10157
|
+
const colPathOf = (r2) => cFields.map((f) => String(getColVal(colByField[f], r2) ?? "\u2014"));
|
|
10158
|
+
const aggOf2 = (subset, v) => computeAgg({ ...colByField[v.field], field: v.field, aggregation: v.agg || "sum" }, subset || []);
|
|
10093
10159
|
const fmt = (val, v) => {
|
|
10094
10160
|
if (val == null) return "\u2014";
|
|
10095
10161
|
const col = colByField[v.field];
|
|
@@ -11245,6 +11311,470 @@ function Datatable({
|
|
|
11245
11311
|
] }) : null
|
|
11246
11312
|
] });
|
|
11247
11313
|
}
|
|
11314
|
+
function space(v) {
|
|
11315
|
+
if (v == null) return void 0;
|
|
11316
|
+
if (typeof v === "number") return `var(--space-${String(v).replace(".", "-")})`;
|
|
11317
|
+
return v;
|
|
11318
|
+
}
|
|
11319
|
+
function len(v) {
|
|
11320
|
+
return typeof v === "number" ? `${v}px` : v;
|
|
11321
|
+
}
|
|
11322
|
+
var BP = { sm: 640, md: 768, lg: 1024, xl: 1280 };
|
|
11323
|
+
function safeHref5(url) {
|
|
11324
|
+
if (url == null) return void 0;
|
|
11325
|
+
const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
|
|
11326
|
+
return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
|
|
11327
|
+
}
|
|
11328
|
+
var Grid = React51__namespace.default.forwardRef(function Grid2({
|
|
11329
|
+
as: Tag2 = "div",
|
|
11330
|
+
columns,
|
|
11331
|
+
minChildWidth,
|
|
11332
|
+
gap = 4,
|
|
11333
|
+
rowGap,
|
|
11334
|
+
columnGap,
|
|
11335
|
+
align,
|
|
11336
|
+
justify,
|
|
11337
|
+
justifyItems,
|
|
11338
|
+
alignContent,
|
|
11339
|
+
justifyContent,
|
|
11340
|
+
sx,
|
|
11341
|
+
className = "",
|
|
11342
|
+
style,
|
|
11343
|
+
children,
|
|
11344
|
+
...rest
|
|
11345
|
+
}, ref) {
|
|
11346
|
+
const { flatStyle, styleNode, sxAttr } = useSx(sx);
|
|
11347
|
+
const responsive = columns != null && typeof columns === "object";
|
|
11348
|
+
const uid = React51__namespace.default.useId();
|
|
11349
|
+
const gridId = responsive ? `g${uid.replace(/[^a-zA-Z0-9]/g, "")}` : null;
|
|
11350
|
+
let css = "";
|
|
11351
|
+
if (responsive) {
|
|
11352
|
+
const base = columns.base ?? 1;
|
|
11353
|
+
const sel = `[data-twc-grid-id="${gridId}"]`;
|
|
11354
|
+
css = `${sel} { --twc-grid-cols: ${base}; }`;
|
|
11355
|
+
for (const bp of ["sm", "md", "lg", "xl"]) {
|
|
11356
|
+
if (columns[bp] != null) css += `
|
|
11357
|
+
@media (min-width: ${BP[bp]}px) { ${sel} { --twc-grid-cols: ${columns[bp]}; } }`;
|
|
11358
|
+
}
|
|
11359
|
+
}
|
|
11360
|
+
const __twcStyles = useScopedStyles(gridId ? `twc-grid-${gridId}` : "twc-grid", css);
|
|
11361
|
+
const templateColumns = minChildWidth ? `repeat(auto-fill, minmax(min(${len(minChildWidth)}, 100%), 1fr))` : responsive ? `repeat(var(--twc-grid-cols, ${columns.base ?? 1}), minmax(0, 1fr))` : `repeat(${columns || 1}, minmax(0, 1fr))`;
|
|
11362
|
+
if (Tag2 === "a" && rest.href != null) rest.href = safeHref5(rest.href);
|
|
11363
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11364
|
+
Tag2,
|
|
11365
|
+
{
|
|
11366
|
+
ref,
|
|
11367
|
+
className: `twc-grid ${className}`.trim(),
|
|
11368
|
+
"data-twc-grid-id": gridId || void 0,
|
|
11369
|
+
"data-twc-sx": sxAttr,
|
|
11370
|
+
style: {
|
|
11371
|
+
display: "grid",
|
|
11372
|
+
gridTemplateColumns: templateColumns,
|
|
11373
|
+
rowGap: space(rowGap ?? gap),
|
|
11374
|
+
columnGap: space(columnGap ?? gap),
|
|
11375
|
+
alignItems: align,
|
|
11376
|
+
// #216: `justifyItems` is the explicit, correctly-named prop; `justify` remains a
|
|
11377
|
+
// backward-compatible alias for it (note: on Grid `justify` = justify-**items**, unlike
|
|
11378
|
+
// Stack.justify = justify-**content**). The explicit prop wins when both are set.
|
|
11379
|
+
justifyItems: justifyItems ?? justify,
|
|
11380
|
+
alignContent,
|
|
11381
|
+
justifyContent,
|
|
11382
|
+
...style,
|
|
11383
|
+
...flatStyle
|
|
11384
|
+
},
|
|
11385
|
+
...rest,
|
|
11386
|
+
children: [
|
|
11387
|
+
responsive ? __twcStyles : null,
|
|
11388
|
+
styleNode,
|
|
11389
|
+
children
|
|
11390
|
+
]
|
|
11391
|
+
}
|
|
11392
|
+
);
|
|
11393
|
+
});
|
|
11394
|
+
Grid.displayName = "Grid";
|
|
11395
|
+
var CARDGRID_CSS = `
|
|
11396
|
+
.twc-cardgrid { font-family: var(--font-sans); display: flex; flex-direction: column; gap: var(--space-3); }
|
|
11397
|
+
.twc-cardgrid__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); }
|
|
11398
|
+
.twc-cardgrid__toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
|
|
11399
|
+
.twc-cardgrid__search { flex: 1 1 200px; min-width: 160px; }
|
|
11400
|
+
.twc-cardgrid__spacer { flex: 1 1 auto; }
|
|
11401
|
+
.twc-cardgrid__sort { display: inline-flex; align-items: center; gap: var(--space-1); }
|
|
11402
|
+
.twc-cardgrid__dir { display: inline-grid; place-items: center; width: 32px; height: 32px; border: var(--border-thin) solid var(--color-border); background: var(--color-surface); color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-md); transition: background-color var(--duration-fast), color var(--duration-fast); }
|
|
11403
|
+
.twc-cardgrid__dir:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
11404
|
+
.twc-cardgrid__dir svg { width: 16px; height: 16px; transition: transform var(--duration-fast) var(--ease-standard); }
|
|
11405
|
+
.twc-cardgrid__dir[data-dir="desc"] svg { transform: scaleY(-1); }
|
|
11406
|
+
.twc-cardgrid__body { position: relative; min-height: 60px; }
|
|
11407
|
+
.twc-cardgrid__body[data-loading="true"] .twc-cardgrid__grid { opacity: 0.55; pointer-events: none; }
|
|
11408
|
+
.twc-cardgrid__overlay { position: absolute; inset: 0; display: grid; place-items: center; z-index: 1; }
|
|
11409
|
+
.twc-cardgrid__spinner { width: 26px; height: 26px; border: 3px solid var(--color-border); border-top-color: var(--color-primary); border-radius: var(--radius-full); animation: twc-cardgrid-spin 0.7s linear infinite; }
|
|
11410
|
+
@keyframes twc-cardgrid-spin { to { transform: rotate(360deg); } }
|
|
11411
|
+
@media (prefers-reduced-motion: reduce) { .twc-cardgrid__spinner { animation-duration: 1.6s; } }
|
|
11412
|
+
.twc-cardgrid__empty { padding: var(--space-8) var(--space-4); text-align: center; color: var(--color-text-muted); font-size: var(--text-sm); }
|
|
11413
|
+
.twc-cardgrid__footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); }
|
|
11414
|
+
.twc-cardgrid__count { font-size: var(--text-sm); color: var(--color-text-muted); }
|
|
11415
|
+
.twc-cardgrid__perpage { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--color-text-muted); }
|
|
11416
|
+
`;
|
|
11417
|
+
function CardGrid({
|
|
11418
|
+
rows = [],
|
|
11419
|
+
renderCard,
|
|
11420
|
+
rowKey = "id",
|
|
11421
|
+
minChildWidth = "18rem",
|
|
11422
|
+
gap = 4,
|
|
11423
|
+
columns,
|
|
11424
|
+
// pagination
|
|
11425
|
+
pageSize = 12,
|
|
11426
|
+
pageSizeOptions = [12, 24, 48, 96],
|
|
11427
|
+
page,
|
|
11428
|
+
defaultPage = 0,
|
|
11429
|
+
onPageChange,
|
|
11430
|
+
onPageSizeChange,
|
|
11431
|
+
showPageSize = true,
|
|
11432
|
+
// query / server contract (mirrors Datatable serverMode)
|
|
11433
|
+
serverMode = false,
|
|
11434
|
+
rowCount,
|
|
11435
|
+
loading = false,
|
|
11436
|
+
onServerChange,
|
|
11437
|
+
// filtering & sorting
|
|
11438
|
+
filters = [],
|
|
11439
|
+
quickFilter,
|
|
11440
|
+
defaultQuickFilter = "",
|
|
11441
|
+
onQuickFilterChange,
|
|
11442
|
+
searchable = false,
|
|
11443
|
+
searchFields,
|
|
11444
|
+
searchPlaceholder = "Search\u2026",
|
|
11445
|
+
sort,
|
|
11446
|
+
defaultSort = null,
|
|
11447
|
+
onSortChange,
|
|
11448
|
+
sortOptions,
|
|
11449
|
+
// slots / states
|
|
11450
|
+
toolbar,
|
|
11451
|
+
emptyState = "No results.",
|
|
11452
|
+
label,
|
|
11453
|
+
id,
|
|
11454
|
+
className = "",
|
|
11455
|
+
...rest
|
|
11456
|
+
}) {
|
|
11457
|
+
const styles = useScopedStyles("twc-cardgrid-styles", CARDGRID_CSS);
|
|
11458
|
+
const autoId = React51__namespace.default.useId();
|
|
11459
|
+
const fieldId = id || autoId;
|
|
11460
|
+
const [internalPage, setInternalPage] = React51__namespace.default.useState(defaultPage);
|
|
11461
|
+
const pageVal = page !== void 0 ? page : internalPage;
|
|
11462
|
+
const commitPage = (p) => {
|
|
11463
|
+
onPageChange?.(p);
|
|
11464
|
+
if (page === void 0) setInternalPage(p);
|
|
11465
|
+
};
|
|
11466
|
+
const [internalSize, setInternalSize] = React51__namespace.default.useState(pageSize > 0 ? pageSize : 12);
|
|
11467
|
+
const sizeControlled = onPageSizeChange !== void 0;
|
|
11468
|
+
const sizeVal = sizeControlled ? pageSize > 0 ? pageSize : 12 : internalSize;
|
|
11469
|
+
const commitSize = (n) => {
|
|
11470
|
+
onPageSizeChange?.(n);
|
|
11471
|
+
if (!sizeControlled) setInternalSize(n);
|
|
11472
|
+
commitPage(0);
|
|
11473
|
+
};
|
|
11474
|
+
React51__namespace.default.useEffect(() => {
|
|
11475
|
+
if (!sizeControlled) setInternalSize(pageSize > 0 ? pageSize : 12);
|
|
11476
|
+
}, [pageSize]);
|
|
11477
|
+
const [internalQuick, setInternalQuick] = React51__namespace.default.useState(defaultQuickFilter);
|
|
11478
|
+
const quickVal = quickFilter !== void 0 ? quickFilter : internalQuick;
|
|
11479
|
+
const commitQuick = (q) => {
|
|
11480
|
+
onQuickFilterChange?.(q);
|
|
11481
|
+
if (quickFilter === void 0) setInternalQuick(q);
|
|
11482
|
+
commitPage(0);
|
|
11483
|
+
};
|
|
11484
|
+
const [internalSort, setInternalSort] = React51__namespace.default.useState(defaultSort);
|
|
11485
|
+
const sortVal = sort !== void 0 ? sort : internalSort;
|
|
11486
|
+
const commitSort = (s) => {
|
|
11487
|
+
onSortChange?.(s);
|
|
11488
|
+
if (sort === void 0) setInternalSort(s);
|
|
11489
|
+
commitPage(0);
|
|
11490
|
+
};
|
|
11491
|
+
const filtersKey = JSON.stringify(filters);
|
|
11492
|
+
const mounted = React51__namespace.default.useRef(false);
|
|
11493
|
+
React51__namespace.default.useEffect(() => {
|
|
11494
|
+
if (!mounted.current) {
|
|
11495
|
+
mounted.current = true;
|
|
11496
|
+
return;
|
|
11497
|
+
}
|
|
11498
|
+
commitPage(0);
|
|
11499
|
+
}, [filtersKey]);
|
|
11500
|
+
const paginated = sizeVal > 0;
|
|
11501
|
+
const query = { page: pageVal, pageSize: paginated ? sizeVal : 0, sort: sortVal, filters, quickFilter: String(quickVal || "").trim() };
|
|
11502
|
+
const queryCols = sortOptions ? sortOptions.map((o) => ({ field: o.field, type: o.type })) : columns;
|
|
11503
|
+
const client = serverMode ? null : runDatatableQuery(rows, query, { columns: queryCols, searchFields });
|
|
11504
|
+
const pageRows = serverMode ? rows : client.rows;
|
|
11505
|
+
const total = serverMode ? rowCount == null ? rows.length : rowCount : client.total;
|
|
11506
|
+
const totalPages = Math.max(1, paginated ? Math.ceil(total / sizeVal) : 1);
|
|
11507
|
+
const onServerChangeRef = React51__namespace.default.useRef(onServerChange);
|
|
11508
|
+
onServerChangeRef.current = onServerChange;
|
|
11509
|
+
const queryKey = JSON.stringify(query);
|
|
11510
|
+
React51__namespace.default.useEffect(() => {
|
|
11511
|
+
if (!serverMode) return void 0;
|
|
11512
|
+
const t = setTimeout(() => onServerChangeRef.current?.(JSON.parse(queryKey)), 250);
|
|
11513
|
+
return () => clearTimeout(t);
|
|
11514
|
+
}, [serverMode, queryKey]);
|
|
11515
|
+
const keyOf = typeof rowKey === "function" ? rowKey : (r2) => r2 && r2[rowKey];
|
|
11516
|
+
const from = total === 0 ? 0 : pageVal * sizeVal + 1;
|
|
11517
|
+
const to = paginated ? Math.min((pageVal + 1) * sizeVal, total) : total;
|
|
11518
|
+
const rppOptions = Array.from(new Set([...pageSizeOptions || [], pageSize].filter((n) => n > 0))).sort((a, b) => a - b).map((n) => ({ value: String(n), label: String(n) }));
|
|
11519
|
+
const sortSelectOptions = sortOptions ? [{ value: "", label: "Sort by\u2026" }, ...sortOptions.map((o) => ({ value: o.field, label: o.label || o.field }))] : null;
|
|
11520
|
+
const hasToolbar = searchable || sortSelectOptions || toolbar;
|
|
11521
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-cardgrid ${className}`, id: fieldId, ...rest, children: [
|
|
11522
|
+
styles,
|
|
11523
|
+
label ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-cardgrid__label", id: `${fieldId}-label`, children: label }) : null,
|
|
11524
|
+
hasToolbar ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cardgrid__toolbar", children: [
|
|
11525
|
+
searchable ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-cardgrid__search", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11526
|
+
Input,
|
|
11527
|
+
{
|
|
11528
|
+
size: "sm",
|
|
11529
|
+
type: "search",
|
|
11530
|
+
value: quickVal,
|
|
11531
|
+
placeholder: searchPlaceholder,
|
|
11532
|
+
"aria-label": searchPlaceholder,
|
|
11533
|
+
onChange: (e) => commitQuick(e.target.value)
|
|
11534
|
+
}
|
|
11535
|
+
) }) : null,
|
|
11536
|
+
toolbar,
|
|
11537
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-cardgrid__spacer" }),
|
|
11538
|
+
sortSelectOptions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cardgrid__sort", children: [
|
|
11539
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11540
|
+
Select,
|
|
11541
|
+
{
|
|
11542
|
+
size: "sm",
|
|
11543
|
+
searchable: false,
|
|
11544
|
+
value: sortVal?.field || "",
|
|
11545
|
+
options: sortSelectOptions,
|
|
11546
|
+
placeholder: "Sort by\u2026",
|
|
11547
|
+
"aria-label": "Sort by",
|
|
11548
|
+
onChange: (field) => commitSort(field ? { field, dir: sortVal?.dir || "asc" } : null)
|
|
11549
|
+
}
|
|
11550
|
+
),
|
|
11551
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11552
|
+
"button",
|
|
11553
|
+
{
|
|
11554
|
+
type: "button",
|
|
11555
|
+
className: "twc-cardgrid__dir",
|
|
11556
|
+
"data-dir": sortVal?.dir || "asc",
|
|
11557
|
+
disabled: !sortVal?.field,
|
|
11558
|
+
"aria-label": sortVal?.dir === "desc" ? "Descending \u2014 click to sort ascending" : "Ascending \u2014 click to sort descending",
|
|
11559
|
+
onClick: () => sortVal?.field && commitSort({ field: sortVal.field, dir: sortVal.dir === "desc" ? "asc" : "desc" }),
|
|
11560
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 5v14M6 11l6-6 6 6" }) })
|
|
11561
|
+
}
|
|
11562
|
+
)
|
|
11563
|
+
] }) : null
|
|
11564
|
+
] }) : null,
|
|
11565
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cardgrid__body", "data-loading": loading || void 0, "aria-busy": loading || void 0, children: [
|
|
11566
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-cardgrid__overlay", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-cardgrid__spinner", role: "status", "aria-label": "Loading" }) }) : null,
|
|
11567
|
+
pageRows.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-cardgrid__empty", children: emptyState }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
11568
|
+
Grid,
|
|
11569
|
+
{
|
|
11570
|
+
className: "twc-cardgrid__grid",
|
|
11571
|
+
minChildWidth,
|
|
11572
|
+
columns,
|
|
11573
|
+
gap,
|
|
11574
|
+
role: "list",
|
|
11575
|
+
"aria-labelledby": label ? `${fieldId}-label` : void 0,
|
|
11576
|
+
children: pageRows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listitem", children: renderCard(row, i) }, keyOf(row, i) ?? i))
|
|
11577
|
+
}
|
|
11578
|
+
)
|
|
11579
|
+
] }),
|
|
11580
|
+
paginated && totalPages > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-cardgrid__footer", children: [
|
|
11581
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-cardgrid__count", children: total === 0 ? "No results" : `${from}\u2013${to} of ${total}` }),
|
|
11582
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11583
|
+
Pagination,
|
|
11584
|
+
{
|
|
11585
|
+
size: "sm",
|
|
11586
|
+
page: pageVal + 1,
|
|
11587
|
+
total: totalPages,
|
|
11588
|
+
boundaries: 1,
|
|
11589
|
+
siblings: 1,
|
|
11590
|
+
showPageJumper: totalPages > 7,
|
|
11591
|
+
onChange: (p) => commitPage(p - 1)
|
|
11592
|
+
}
|
|
11593
|
+
),
|
|
11594
|
+
showPageSize ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-cardgrid__perpage", children: [
|
|
11595
|
+
"Per page",
|
|
11596
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11597
|
+
Select,
|
|
11598
|
+
{
|
|
11599
|
+
size: "sm",
|
|
11600
|
+
searchable: false,
|
|
11601
|
+
value: String(sizeVal),
|
|
11602
|
+
options: rppOptions,
|
|
11603
|
+
placement: "top",
|
|
11604
|
+
"aria-label": "Cards per page",
|
|
11605
|
+
onChange: (v) => commitSize(Number(v))
|
|
11606
|
+
}
|
|
11607
|
+
)
|
|
11608
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", {})
|
|
11609
|
+
] }) : null
|
|
11610
|
+
] });
|
|
11611
|
+
}
|
|
11612
|
+
var DIFFTABLE_CSS = `
|
|
11613
|
+
.twc-difft { font-family: var(--font-sans); display: flex; flex-direction: column; gap: var(--space-3); color: var(--color-text); }
|
|
11614
|
+
.twc-difft__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
|
|
11615
|
+
.twc-difft__label { font-size: var(--text-sm); font-weight: var(--font-semibold); }
|
|
11616
|
+
.twc-difft__summary { display: inline-flex; flex-wrap: wrap; gap: var(--space-1-5); }
|
|
11617
|
+
.twc-difft__toggle { margin-inline-start: auto; }
|
|
11618
|
+
.twc-difft__scroll { overflow-x: auto; border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg); }
|
|
11619
|
+
.twc-difft__table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
|
|
11620
|
+
.twc-difft__table th, .twc-difft__table td { text-align: start; padding: var(--space-2) var(--space-3); border-bottom: var(--border-thin) solid var(--color-divider); vertical-align: top; }
|
|
11621
|
+
.twc-difft__table thead th { position: sticky; top: 0; background: var(--color-surface-sunken); font-weight: var(--font-semibold); color: var(--color-text-muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.02em; white-space: nowrap; z-index: 1; }
|
|
11622
|
+
.twc-difft__table tbody tr:last-child td { border-bottom: none; }
|
|
11623
|
+
.twc-difft__table tbody tr[data-op="added"] { background: color-mix(in srgb, var(--color-success) 8%, transparent); }
|
|
11624
|
+
.twc-difft__table tbody tr[data-op="removed"] { background: color-mix(in srgb, var(--color-danger) 8%, transparent); }
|
|
11625
|
+
.twc-difft__table tbody tr[data-op="modified"] { background: color-mix(in srgb, var(--color-warning) 8%, transparent); }
|
|
11626
|
+
.twc-difft__op { white-space: nowrap; }
|
|
11627
|
+
.twc-difft__change { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 2px; }
|
|
11628
|
+
.twc-difft__old { text-decoration: line-through; color: var(--color-text-subtle); }
|
|
11629
|
+
.twc-difft__new { color: var(--color-success-subtle-fg); font-weight: var(--font-medium); }
|
|
11630
|
+
.twc-difft__arrow { margin-inline: 6px; color: var(--color-text-subtle); }
|
|
11631
|
+
.twc-difft__empty { padding: var(--space-8) var(--space-4); text-align: center; color: var(--color-text-muted); }
|
|
11632
|
+
[dir="rtl"] .twc-difft__arrow { transform: scaleX(-1); display: inline-block; }
|
|
11633
|
+
`;
|
|
11634
|
+
var OPS = {
|
|
11635
|
+
added: { label: "Added", tone: "success" },
|
|
11636
|
+
removed: { label: "Removed", tone: "danger" },
|
|
11637
|
+
modified: { label: "Modified", tone: "warning" },
|
|
11638
|
+
moved: { label: "Moved", tone: "info" },
|
|
11639
|
+
unchanged: { label: "Unchanged", tone: "neutral" }
|
|
11640
|
+
};
|
|
11641
|
+
function lisIndexSet(seq) {
|
|
11642
|
+
const n = seq.length;
|
|
11643
|
+
if (n === 0) return /* @__PURE__ */ new Set();
|
|
11644
|
+
const dp = new Array(n).fill(1), prev = new Array(n).fill(-1);
|
|
11645
|
+
let best = 0;
|
|
11646
|
+
for (let i = 0; i < n; i++) {
|
|
11647
|
+
for (let j = 0; j < i; j++) {
|
|
11648
|
+
if (seq[j] < seq[i] && dp[j] + 1 > dp[i]) {
|
|
11649
|
+
dp[i] = dp[j] + 1;
|
|
11650
|
+
prev[i] = j;
|
|
11651
|
+
}
|
|
11652
|
+
}
|
|
11653
|
+
if (dp[i] > dp[best]) best = i;
|
|
11654
|
+
}
|
|
11655
|
+
const set = /* @__PURE__ */ new Set();
|
|
11656
|
+
for (let i = best; i !== -1; i = prev[i]) set.add(i);
|
|
11657
|
+
return set;
|
|
11658
|
+
}
|
|
11659
|
+
var getVal = (col, row) => col.valueGetter ? col.valueGetter(row) : row == null ? void 0 : row[col.field];
|
|
11660
|
+
var fmtVal = (col, v) => col.valueFormatter ? col.valueFormatter(v) : v == null ? "" : String(v);
|
|
11661
|
+
function DiffTable({
|
|
11662
|
+
from = [],
|
|
11663
|
+
to = [],
|
|
11664
|
+
rowKey,
|
|
11665
|
+
columns = [],
|
|
11666
|
+
onlyChanged = true,
|
|
11667
|
+
showToggle = true,
|
|
11668
|
+
showSummary = true,
|
|
11669
|
+
moveDetection = true,
|
|
11670
|
+
compare,
|
|
11671
|
+
emptyState = "No differences.",
|
|
11672
|
+
toggleLabel = "Only changed",
|
|
11673
|
+
label,
|
|
11674
|
+
id,
|
|
11675
|
+
className = "",
|
|
11676
|
+
...rest
|
|
11677
|
+
}) {
|
|
11678
|
+
const styles = useScopedStyles("twc-difftable-styles", DIFFTABLE_CSS);
|
|
11679
|
+
const autoId = React51__namespace.default.useId();
|
|
11680
|
+
const fieldId = id || autoId;
|
|
11681
|
+
const [only, setOnly] = React51__namespace.default.useState(onlyChanged);
|
|
11682
|
+
const valEq = React51__namespace.default.useCallback((a, b, col) => {
|
|
11683
|
+
if (col.compare) return col.compare(a, b);
|
|
11684
|
+
if (compare) return compare(a, b, col.field);
|
|
11685
|
+
if (a === b) return true;
|
|
11686
|
+
if (a == null || b == null) return a === b;
|
|
11687
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
11688
|
+
}, [compare]);
|
|
11689
|
+
const diff = React51__namespace.default.useMemo(() => {
|
|
11690
|
+
const k = rowKey || ((r2) => r2 == null ? r2 : r2.id);
|
|
11691
|
+
const fromMap = /* @__PURE__ */ new Map(), toMap = /* @__PURE__ */ new Map();
|
|
11692
|
+
from.forEach((r2, i) => fromMap.set(k(r2), { row: r2, i }));
|
|
11693
|
+
to.forEach((r2, i) => toMap.set(k(r2), { row: r2, i }));
|
|
11694
|
+
const movedKeys = /* @__PURE__ */ new Set();
|
|
11695
|
+
if (moveDetection) {
|
|
11696
|
+
const commonFrom = from.filter((r2) => toMap.has(k(r2)));
|
|
11697
|
+
const seq = commonFrom.map((r2) => toMap.get(k(r2)).i);
|
|
11698
|
+
const stable = lisIndexSet(seq);
|
|
11699
|
+
commonFrom.forEach((r2, idx) => {
|
|
11700
|
+
if (!stable.has(idx)) movedKeys.add(k(r2));
|
|
11701
|
+
});
|
|
11702
|
+
}
|
|
11703
|
+
const classify = (key) => {
|
|
11704
|
+
const a = fromMap.get(key), b = toMap.get(key);
|
|
11705
|
+
if (a && !b) return { op: "removed", from: a.row, to: null, changed: /* @__PURE__ */ new Set() };
|
|
11706
|
+
if (!a && b) return { op: "added", from: null, to: b.row, changed: /* @__PURE__ */ new Set() };
|
|
11707
|
+
const changed = /* @__PURE__ */ new Set();
|
|
11708
|
+
for (const col of columns) if (!valEq(getVal(col, a.row), getVal(col, b.row), col)) changed.add(col.field);
|
|
11709
|
+
if (changed.size) return { op: "modified", from: a.row, to: b.row, changed };
|
|
11710
|
+
if (movedKeys.has(key)) return { op: "moved", from: a.row, to: b.row, changed };
|
|
11711
|
+
return { op: "unchanged", from: a.row, to: b.row, changed };
|
|
11712
|
+
};
|
|
11713
|
+
const rows = [];
|
|
11714
|
+
to.forEach((r2) => rows.push({ key: k(r2), ...classify(k(r2)) }));
|
|
11715
|
+
from.forEach((r2) => {
|
|
11716
|
+
const key = k(r2);
|
|
11717
|
+
if (!toMap.has(key)) rows.push({ key, ...classify(key) });
|
|
11718
|
+
});
|
|
11719
|
+
const counts = { added: 0, removed: 0, modified: 0, moved: 0, unchanged: 0 };
|
|
11720
|
+
rows.forEach((r2) => {
|
|
11721
|
+
counts[r2.op] += 1;
|
|
11722
|
+
});
|
|
11723
|
+
return { rows, counts };
|
|
11724
|
+
}, [from, to, columns, rowKey, moveDetection, valEq]);
|
|
11725
|
+
const visible = only ? diff.rows.filter((r2) => r2.op !== "unchanged") : diff.rows;
|
|
11726
|
+
const renderCell = (r2, col) => {
|
|
11727
|
+
if (r2.op === "removed") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__old", children: fmtVal(col, getVal(col, r2.from)) });
|
|
11728
|
+
if (r2.op === "added") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__new", children: fmtVal(col, getVal(col, r2.to)) });
|
|
11729
|
+
if (r2.op === "modified" && r2.changed.has(col.field)) {
|
|
11730
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-difft__change", children: [
|
|
11731
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__old", children: fmtVal(col, getVal(col, r2.from)) }),
|
|
11732
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__arrow", "aria-hidden": "true", children: "\u2192" }),
|
|
11733
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__new", children: fmtVal(col, getVal(col, r2.to)) })
|
|
11734
|
+
] });
|
|
11735
|
+
}
|
|
11736
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: fmtVal(col, getVal(col, r2.to ?? r2.from)) });
|
|
11737
|
+
};
|
|
11738
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-difft ${className}`, id: fieldId, ...rest, children: [
|
|
11739
|
+
styles,
|
|
11740
|
+
label || showSummary || showToggle ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-difft__head", children: [
|
|
11741
|
+
label ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-difft__label", children: label }) : null,
|
|
11742
|
+
showSummary ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-difft__summary", children: [
|
|
11743
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "success", children: [
|
|
11744
|
+
"+",
|
|
11745
|
+
diff.counts.added,
|
|
11746
|
+
" added"
|
|
11747
|
+
] }),
|
|
11748
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "warning", children: [
|
|
11749
|
+
"~",
|
|
11750
|
+
diff.counts.modified,
|
|
11751
|
+
" modified"
|
|
11752
|
+
] }),
|
|
11753
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "danger", children: [
|
|
11754
|
+
"-",
|
|
11755
|
+
diff.counts.removed,
|
|
11756
|
+
" removed"
|
|
11757
|
+
] }),
|
|
11758
|
+
diff.counts.moved ? /* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "info", children: [
|
|
11759
|
+
"\u21C5 ",
|
|
11760
|
+
diff.counts.moved,
|
|
11761
|
+
" moved"
|
|
11762
|
+
] }) : null
|
|
11763
|
+
] }) : null,
|
|
11764
|
+
showToggle ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-difft__toggle", children: /* @__PURE__ */ jsxRuntime.jsx(Checkbox, { label: toggleLabel, checked: only, onChange: (e) => setOnly(e.target.checked) }) }) : null
|
|
11765
|
+
] }) : null,
|
|
11766
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-difft__scroll", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "twc-difft__table", children: [
|
|
11767
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
11768
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: "Change" }),
|
|
11769
|
+
columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: c.headerName || c.field }, c.field))
|
|
11770
|
+
] }) }),
|
|
11771
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-difft__empty", colSpan: columns.length + 1, children: emptyState }) }) : visible.map((r2) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { "data-op": r2.op, children: [
|
|
11772
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-difft__op", children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "sm", variant: "soft", tone: OPS[r2.op].tone, children: OPS[r2.op].label }) }),
|
|
11773
|
+
columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("td", { children: renderCell(r2, c) }, c.field))
|
|
11774
|
+
] }, r2.key)) })
|
|
11775
|
+
] }) })
|
|
11776
|
+
] });
|
|
11777
|
+
}
|
|
11248
11778
|
var FIELD_CSS3 = `
|
|
11249
11779
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
11250
11780
|
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
@@ -11256,13 +11786,15 @@ var DATEPICKER_CSS = `
|
|
|
11256
11786
|
.twc-dp { position: relative; font-family: var(--font-sans); display: flex; flex-direction: column; gap: var(--space-1-5); }
|
|
11257
11787
|
.twc-dp__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); }
|
|
11258
11788
|
.twc-dp__control {
|
|
11259
|
-
display: flex; align-items: center; gap: var(--space-2);
|
|
11789
|
+
display: flex; align-items: center; gap: var(--space-2); --_h: var(--control-h-md); height: var(--_h); padding: 0 var(--space-3);
|
|
11260
11790
|
background: var(--color-surface); border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md);
|
|
11261
11791
|
cursor: pointer; transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
|
|
11262
11792
|
}
|
|
11263
11793
|
.twc-dp__control:hover:not([data-open="true"]) { border-color: var(--color-border-strong); }
|
|
11264
11794
|
/* tone \u2192 focus/open accent (default primary; reproduces current look). */
|
|
11265
11795
|
.twc-dp__control { --_accent: var(--color-primary); --_ring: var(--ring); }
|
|
11796
|
+
.twc-dp__control[data-size="sm"] { --_h: var(--control-h-sm); }
|
|
11797
|
+
.twc-dp__control[data-size="lg"] { --_h: var(--control-h-lg); }
|
|
11266
11798
|
.twc-dp__control[data-tone="success"] { --_accent: var(--color-success); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-success) 32%, transparent); }
|
|
11267
11799
|
.twc-dp__control[data-tone="warning"] { --_accent: var(--color-warning); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-warning) 32%, transparent); }
|
|
11268
11800
|
.twc-dp__control[data-tone="danger"] { --_accent: var(--color-danger); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 32%, transparent); }
|
|
@@ -11322,6 +11854,12 @@ var DATEPICKER_CSS = `
|
|
|
11322
11854
|
.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); }
|
|
11323
11855
|
.twc-dp__mo:hover { background: var(--color-surface-sunken); }
|
|
11324
11856
|
.twc-dp__mo[data-selected="true"] { background: var(--color-primary); color: var(--color-primary-fg); font-weight: var(--font-bold); }
|
|
11857
|
+
.twc-dp__years { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
|
|
11858
|
+
.twc-dp__yr { 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); }
|
|
11859
|
+
.twc-dp__yr:hover:not(:disabled) { background: var(--color-surface-sunken); }
|
|
11860
|
+
.twc-dp__yr[data-outside="true"] { color: var(--color-text-subtle); }
|
|
11861
|
+
.twc-dp__yr[data-selected="true"] { background: var(--color-primary); color: var(--color-primary-fg); font-weight: var(--font-bold); }
|
|
11862
|
+
.twc-dp__yr:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
11325
11863
|
[dir="rtl"] .twc-dp__nav svg { transform: scaleX(-1); }
|
|
11326
11864
|
`;
|
|
11327
11865
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
@@ -11349,8 +11887,10 @@ function DatePicker({
|
|
|
11349
11887
|
placeholder = "Select date",
|
|
11350
11888
|
min,
|
|
11351
11889
|
max,
|
|
11890
|
+
disabledDate,
|
|
11352
11891
|
disabled = false,
|
|
11353
11892
|
tone = "primary",
|
|
11893
|
+
size = "md",
|
|
11354
11894
|
clearable = true,
|
|
11355
11895
|
editable = false,
|
|
11356
11896
|
parse,
|
|
@@ -11375,6 +11915,7 @@ function DatePicker({
|
|
|
11375
11915
|
const [mode, setMode] = React51__namespace.default.useState("days");
|
|
11376
11916
|
const [focusDate, setFocusDate] = React51__namespace.default.useState(null);
|
|
11377
11917
|
const [focusMonth, setFocusMonth] = React51__namespace.default.useState(null);
|
|
11918
|
+
const [focusYear, setFocusYear] = React51__namespace.default.useState(null);
|
|
11378
11919
|
const [editText, setEditText] = React51__namespace.default.useState(null);
|
|
11379
11920
|
const [coords, setCoords] = React51__namespace.default.useState(null);
|
|
11380
11921
|
const wrapRef = React51__namespace.default.useRef(null);
|
|
@@ -11467,11 +12008,13 @@ function DatePicker({
|
|
|
11467
12008
|
pick(parsed);
|
|
11468
12009
|
};
|
|
11469
12010
|
const y = view.getFullYear(), m = view.getMonth();
|
|
12011
|
+
const decadeStart = Math.floor(y / 10) * 10;
|
|
12012
|
+
const yearCells = Array.from({ length: 12 }, (_, i) => decadeStart - 1 + i);
|
|
11470
12013
|
const first = new Date(y, m, 1);
|
|
11471
12014
|
const startOffset = (first.getDay() - weekStartsOn + 7) % 7;
|
|
11472
12015
|
const gridStart = new Date(y, m, 1 - startOffset);
|
|
11473
12016
|
const today = /* @__PURE__ */ new Date();
|
|
11474
|
-
const outOfRange = (d) => min && d < new Date(min.getFullYear(), min.getMonth(), min.getDate()) || max && d > new Date(max.getFullYear(), max.getMonth(), max.getDate());
|
|
12017
|
+
const outOfRange = (d) => min && d < new Date(min.getFullYear(), min.getMonth(), min.getDate()) || max && d > new Date(max.getFullYear(), max.getMonth(), max.getDate()) || Boolean(disabledDate && disabledDate(d));
|
|
11475
12018
|
const keyOf = (d) => `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
|
|
11476
12019
|
const addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
|
|
11477
12020
|
const addMonths = (d, n) => {
|
|
@@ -11508,6 +12051,24 @@ function DatePicker({
|
|
|
11508
12051
|
}
|
|
11509
12052
|
setFocusMonth(next);
|
|
11510
12053
|
};
|
|
12054
|
+
React51__namespace.default.useEffect(() => {
|
|
12055
|
+
if (!open || mode !== "years" || focusYear == null) return;
|
|
12056
|
+
gridRef.current?.querySelector(`[data-yr="${focusYear}"]`)?.focus();
|
|
12057
|
+
}, [focusYear, open, mode]);
|
|
12058
|
+
const onYearsKeyDown = (e) => {
|
|
12059
|
+
const cur = focusYear == null ? y : focusYear;
|
|
12060
|
+
let next;
|
|
12061
|
+
if (e.key === "ArrowRight") next = cur + 1;
|
|
12062
|
+
else if (e.key === "ArrowLeft") next = cur - 1;
|
|
12063
|
+
else if (e.key === "ArrowDown") next = cur + 3;
|
|
12064
|
+
else if (e.key === "ArrowUp") next = cur - 3;
|
|
12065
|
+
else if (e.key === "Home") next = decadeStart;
|
|
12066
|
+
else if (e.key === "End") next = decadeStart + 9;
|
|
12067
|
+
else return;
|
|
12068
|
+
e.preventDefault();
|
|
12069
|
+
setView(new Date(next, m, 1));
|
|
12070
|
+
setFocusYear(next);
|
|
12071
|
+
};
|
|
11511
12072
|
const onGridKeyDown = (e) => {
|
|
11512
12073
|
const btn = e.target.closest?.("[data-key]");
|
|
11513
12074
|
if (!btn) return;
|
|
@@ -11552,6 +12113,7 @@ function DatePicker({
|
|
|
11552
12113
|
"data-disabled": disabled || void 0,
|
|
11553
12114
|
"data-tone": tone,
|
|
11554
12115
|
"data-invalid": invalid || void 0,
|
|
12116
|
+
"data-size": size,
|
|
11555
12117
|
children: [
|
|
11556
12118
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11557
12119
|
"input",
|
|
@@ -11625,6 +12187,7 @@ function DatePicker({
|
|
|
11625
12187
|
id: fieldId,
|
|
11626
12188
|
"data-open": open || void 0,
|
|
11627
12189
|
"data-disabled": disabled || void 0,
|
|
12190
|
+
"data-size": size,
|
|
11628
12191
|
"data-tone": tone,
|
|
11629
12192
|
"data-has-clear": clearable && selected && !disabled ? "true" : void 0,
|
|
11630
12193
|
"data-invalid": invalid || void 0,
|
|
@@ -11668,13 +12231,18 @@ function DatePicker({
|
|
|
11668
12231
|
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
|
|
11669
12232
|
children: [
|
|
11670
12233
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dp__head", children: [
|
|
11671
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__nav", "aria-label": "Previous", onClick: () => setView(mode === "months" ? new Date(y - 1, m, 1) : new Date(y, m - 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
12234
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__nav", "aria-label": mode === "years" ? "Previous decade" : mode === "months" ? "Previous year" : "Previous month", onClick: () => setView(mode === "years" ? new Date(y - 10, m, 1) : mode === "months" ? new Date(y - 1, m, 1) : new Date(y, m - 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
11672
12235
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__title", onClick: () => {
|
|
11673
|
-
if (mode === "days")
|
|
11674
|
-
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
12236
|
+
if (mode === "days") {
|
|
12237
|
+
setFocusMonth(m);
|
|
12238
|
+
setMode("months");
|
|
12239
|
+
} else if (mode === "months") {
|
|
12240
|
+
setFocusYear(y);
|
|
12241
|
+
setMode("years");
|
|
12242
|
+
} else setMode("days");
|
|
12243
|
+
}, children: mode === "days" ? `${months[m]} ${y}` : mode === "months" ? y : `${decadeStart}\u2013${decadeStart + 9}` }),
|
|
12244
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dp__sr", "aria-live": "polite", children: mode === "days" ? `${months[m]} ${y}` : mode === "months" ? y : `${decadeStart}\u2013${decadeStart + 9}` }),
|
|
12245
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__nav", "aria-label": mode === "years" ? "Next decade" : mode === "months" ? "Next year" : "Next month", onClick: () => setView(mode === "years" ? new Date(y + 10, m, 1) : mode === "months" ? new Date(y + 1, m, 1) : new Date(y, m + 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) }) })
|
|
11678
12246
|
] }),
|
|
11679
12247
|
mode === "days" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dp__grid", ref: gridRef, onKeyDown: onGridKeyDown, children: [
|
|
11680
12248
|
dows.map((d, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dp__dow", children: d }, i)),
|
|
@@ -11700,7 +12268,7 @@ function DatePicker({
|
|
|
11700
12268
|
i
|
|
11701
12269
|
);
|
|
11702
12270
|
})
|
|
11703
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dp__months", ref: gridRef, onKeyDown: onMonthsKeyDown, role: "grid", children: monthsShort.map((name, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12271
|
+
] }) : mode === "months" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dp__months", ref: gridRef, onKeyDown: onMonthsKeyDown, role: "grid", children: monthsShort.map((name, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
11704
12272
|
"button",
|
|
11705
12273
|
{
|
|
11706
12274
|
type: "button",
|
|
@@ -11716,7 +12284,30 @@ function DatePicker({
|
|
|
11716
12284
|
children: name
|
|
11717
12285
|
},
|
|
11718
12286
|
i
|
|
11719
|
-
)) })
|
|
12287
|
+
)) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dp__years", ref: gridRef, onKeyDown: onYearsKeyDown, role: "grid", children: yearCells.map((yr) => {
|
|
12288
|
+
const outside = yr < decadeStart || yr > decadeStart + 9;
|
|
12289
|
+
const disabled2 = min && yr < min.getFullYear() || max && yr > max.getFullYear();
|
|
12290
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12291
|
+
"button",
|
|
12292
|
+
{
|
|
12293
|
+
type: "button",
|
|
12294
|
+
className: "twc-dp__yr",
|
|
12295
|
+
role: "gridcell",
|
|
12296
|
+
"data-yr": yr,
|
|
12297
|
+
"data-outside": outside || void 0,
|
|
12298
|
+
disabled: disabled2,
|
|
12299
|
+
"data-selected": selected && selected.getFullYear() === yr || void 0,
|
|
12300
|
+
tabIndex: yr === (focusYear ?? y) ? 0 : -1,
|
|
12301
|
+
onClick: () => {
|
|
12302
|
+
setView(new Date(yr, m, 1));
|
|
12303
|
+
setFocusMonth(m);
|
|
12304
|
+
setMode("months");
|
|
12305
|
+
},
|
|
12306
|
+
children: yr
|
|
12307
|
+
},
|
|
12308
|
+
yr
|
|
12309
|
+
);
|
|
12310
|
+
}) })
|
|
11720
12311
|
]
|
|
11721
12312
|
}
|
|
11722
12313
|
),
|
|
@@ -11735,12 +12326,14 @@ var FIELD_CSS4 = `
|
|
|
11735
12326
|
var RANGE_CSS2 = `
|
|
11736
12327
|
.twc-drp { position: relative; font-family: var(--font-sans); display: flex; flex-direction: column; gap: var(--space-1-5); }
|
|
11737
12328
|
.twc-drp__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); }
|
|
11738
|
-
.twc-drp__control { display: flex; align-items: center; gap: var(--space-2);
|
|
12329
|
+
.twc-drp__control { display: flex; align-items: center; gap: var(--space-2); --_h: var(--control-h-md); height: var(--_h); padding: 0 var(--space-3);
|
|
11739
12330
|
background: var(--color-surface); border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md); cursor: pointer;
|
|
11740
12331
|
transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); }
|
|
11741
12332
|
.twc-drp__control:hover:not([data-open="true"]):not([data-disabled="true"]) { border-color: var(--color-border-strong); }
|
|
11742
12333
|
/* tone \u2192 focus/open accent (default primary; reproduces current look). */
|
|
11743
12334
|
.twc-drp__control { --_accent: var(--color-primary); --_ring: var(--ring); }
|
|
12335
|
+
.twc-drp__control[data-size="sm"] { --_h: var(--control-h-sm); }
|
|
12336
|
+
.twc-drp__control[data-size="lg"] { --_h: var(--control-h-lg); }
|
|
11744
12337
|
.twc-drp__control[data-tone="success"] { --_accent: var(--color-success); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-success) 32%, transparent); }
|
|
11745
12338
|
.twc-drp__control[data-tone="warning"] { --_accent: var(--color-warning); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-warning) 32%, transparent); }
|
|
11746
12339
|
.twc-drp__control[data-tone="danger"] { --_accent: var(--color-danger); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 32%, transparent); }
|
|
@@ -11754,6 +12347,9 @@ var RANGE_CSS2 = `
|
|
|
11754
12347
|
.twc-drp__ic svg { width: 17px; height: 17px; }
|
|
11755
12348
|
.twc-drp__text { flex: 1; font-size: var(--text-sm); color: var(--color-text); white-space: nowrap; }
|
|
11756
12349
|
.twc-drp__text[data-placeholder="true"] { color: var(--color-text-subtle); }
|
|
12350
|
+
.twc-drp__clear { flex: none; display: inline-grid; place-items: center; width: 20px; height: 20px; border: none; padding: 0; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-full); }
|
|
12351
|
+
.twc-drp__clear:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
12352
|
+
.twc-drp__clear svg { width: 14px; height: 14px; }
|
|
11757
12353
|
/* #105: editable (typed entry) variant. */
|
|
11758
12354
|
.twc-drp__control--editable { cursor: text; gap: 0; padding-inline-end: var(--space-1); }
|
|
11759
12355
|
.twc-drp__input { flex: 1; min-width: 0; height: 100%; border: none; background: transparent; outline: none; padding: 0;
|
|
@@ -11777,7 +12373,14 @@ var RANGE_CSS2 = `
|
|
|
11777
12373
|
.twc-drp__nav { display: inline-grid; place-items: center; width: 30px; height: 30px; border: none; background: transparent; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-md); }
|
|
11778
12374
|
.twc-drp__nav:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
11779
12375
|
.twc-drp__nav svg { width: 17px; height: 17px; }
|
|
11780
|
-
.twc-drp__title { font-size: var(--text-sm); font-weight: var(--font-bold); }
|
|
12376
|
+
.twc-drp__title { font-size: var(--text-sm); font-weight: var(--font-bold); color: var(--color-text); border: none; background: transparent; cursor: pointer; padding: 5px 10px; border-radius: var(--radius-md); }
|
|
12377
|
+
.twc-drp__title:hover { background: var(--color-surface-sunken); }
|
|
12378
|
+
.twc-drp__months, .twc-drp__years { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
|
|
12379
|
+
.twc-drp__mo, .twc-drp__yr { 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); }
|
|
12380
|
+
.twc-drp__mo:hover:not(:disabled), .twc-drp__yr:hover:not(:disabled) { background: var(--color-surface-sunken); }
|
|
12381
|
+
.twc-drp__yr[data-outside="true"] { color: var(--color-text-subtle); }
|
|
12382
|
+
.twc-drp__mo[data-selected="true"], .twc-drp__yr[data-selected="true"] { background: var(--color-primary); color: var(--color-primary-fg); font-weight: var(--font-bold); }
|
|
12383
|
+
.twc-drp__mo:disabled, .twc-drp__yr:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
11781
12384
|
.twc-drp__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
|
|
11782
12385
|
.twc-drp__dow { text-align: center; font-size: 11px; font-weight: var(--font-bold); color: var(--color-text-subtle); padding: 4px 0; }
|
|
11783
12386
|
.twc-drp__day { aspect-ratio: 1; border: none; background: transparent; cursor: pointer; font-family: inherit; font-size: var(--text-sm); color: var(--color-text); display: grid; place-items: center; position: relative; }
|
|
@@ -11803,6 +12406,18 @@ var weekdayNames2 = (locale, weekStartsOn) => {
|
|
|
11803
12406
|
};
|
|
11804
12407
|
var ymd = (d) => d ? new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime() : null;
|
|
11805
12408
|
var fmtD = (d, locale) => d ? d.toLocaleDateString(locale, { month: "short", day: "numeric", year: "numeric" }) : "";
|
|
12409
|
+
var rollingDays = (days) => {
|
|
12410
|
+
const end = /* @__PURE__ */ new Date();
|
|
12411
|
+
const start = /* @__PURE__ */ new Date();
|
|
12412
|
+
start.setDate(end.getDate() - days + 1);
|
|
12413
|
+
return { start, end };
|
|
12414
|
+
};
|
|
12415
|
+
var DEFAULT_PRESETS2 = [
|
|
12416
|
+
{ label: "Last 7 days", range: () => rollingDays(7) },
|
|
12417
|
+
{ label: "Last 14 days", range: () => rollingDays(14) },
|
|
12418
|
+
{ label: "Last 30 days", range: () => rollingDays(30) },
|
|
12419
|
+
{ label: "Last 90 days", range: () => rollingDays(90) }
|
|
12420
|
+
];
|
|
11806
12421
|
function DateRangePicker({
|
|
11807
12422
|
label,
|
|
11808
12423
|
hint,
|
|
@@ -11819,6 +12434,9 @@ function DateRangePicker({
|
|
|
11819
12434
|
disabledDate,
|
|
11820
12435
|
disabled = false,
|
|
11821
12436
|
tone = "primary",
|
|
12437
|
+
size = "md",
|
|
12438
|
+
clearable = true,
|
|
12439
|
+
format,
|
|
11822
12440
|
editable = false,
|
|
11823
12441
|
parse,
|
|
11824
12442
|
onChange,
|
|
@@ -11828,11 +12446,14 @@ function DateRangePicker({
|
|
|
11828
12446
|
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS4);
|
|
11829
12447
|
const __twcStyles1 = useScopedStyles("twc-drp-styles", RANGE_CSS2);
|
|
11830
12448
|
const [internal, setInternal] = React51__namespace.default.useState(defaultValue);
|
|
11831
|
-
const
|
|
12449
|
+
const range2 = value !== void 0 ? value : internal;
|
|
11832
12450
|
const [open, setOpen] = React51__namespace.default.useState(false);
|
|
11833
|
-
const [view, setView] = React51__namespace.default.useState(
|
|
12451
|
+
const [view, setView] = React51__namespace.default.useState(range2.start || /* @__PURE__ */ new Date());
|
|
11834
12452
|
const [hover, setHover] = React51__namespace.default.useState(null);
|
|
11835
12453
|
const [focusDate, setFocusDate] = React51__namespace.default.useState(null);
|
|
12454
|
+
const [mode, setMode] = React51__namespace.default.useState("days");
|
|
12455
|
+
const [focusMonth, setFocusMonth] = React51__namespace.default.useState(null);
|
|
12456
|
+
const [focusYear, setFocusYear] = React51__namespace.default.useState(null);
|
|
11836
12457
|
const [editText, setEditText] = React51__namespace.default.useState(null);
|
|
11837
12458
|
const [coords, setCoords] = React51__namespace.default.useState(null);
|
|
11838
12459
|
const wrapRef = React51__namespace.default.useRef(null);
|
|
@@ -11904,7 +12525,7 @@ function DateRangePicker({
|
|
|
11904
12525
|
const raw = editText.trim();
|
|
11905
12526
|
if (raw === "") {
|
|
11906
12527
|
setEditText(null);
|
|
11907
|
-
if (
|
|
12528
|
+
if (range2.start || range2.end) set({ start: null, end: null });
|
|
11908
12529
|
return;
|
|
11909
12530
|
}
|
|
11910
12531
|
const parts = raw.split(/\s*(?:–|—|\bto\b|\.\.+)\s*/i).map((p) => p.trim());
|
|
@@ -11936,8 +12557,15 @@ function DateRangePicker({
|
|
|
11936
12557
|
if (!open) {
|
|
11937
12558
|
setFocusDate(null);
|
|
11938
12559
|
setHover(null);
|
|
12560
|
+
setMode("days");
|
|
11939
12561
|
}
|
|
11940
12562
|
}, [open]);
|
|
12563
|
+
React51__namespace.default.useEffect(() => {
|
|
12564
|
+
if (open && mode === "months" && focusMonth != null) gridRef.current?.querySelector(`[data-mo="${focusMonth}"]`)?.focus();
|
|
12565
|
+
}, [focusMonth, open, mode]);
|
|
12566
|
+
React51__namespace.default.useEffect(() => {
|
|
12567
|
+
if (open && mode === "years" && focusYear != null) gridRef.current?.querySelector(`[data-yr="${focusYear}"]`)?.focus();
|
|
12568
|
+
}, [focusYear, open, mode]);
|
|
11941
12569
|
React51__namespace.default.useEffect(() => {
|
|
11942
12570
|
if (!open || !focusDate) return;
|
|
11943
12571
|
gridRef.current?.querySelector(`[data-key="${keyOf(focusDate)}"]`)?.focus();
|
|
@@ -11968,35 +12596,74 @@ function DateRangePicker({
|
|
|
11968
12596
|
setHover(next);
|
|
11969
12597
|
if (next.getFullYear() !== view.getFullYear() || next.getMonth() !== view.getMonth()) setView(new Date(next.getFullYear(), next.getMonth(), 1));
|
|
11970
12598
|
};
|
|
11971
|
-
const
|
|
12599
|
+
const onMonthsKeyDown = (e) => {
|
|
12600
|
+
const vy = view.getFullYear();
|
|
12601
|
+
const cur = focusMonth == null ? view.getMonth() : focusMonth;
|
|
12602
|
+
let next;
|
|
12603
|
+
if (e.key === "ArrowRight") next = cur + 1;
|
|
12604
|
+
else if (e.key === "ArrowLeft") next = cur - 1;
|
|
12605
|
+
else if (e.key === "ArrowDown") next = cur + 3;
|
|
12606
|
+
else if (e.key === "ArrowUp") next = cur - 3;
|
|
12607
|
+
else if (e.key === "Home") next = 0;
|
|
12608
|
+
else if (e.key === "End") next = 11;
|
|
12609
|
+
else return;
|
|
12610
|
+
e.preventDefault();
|
|
12611
|
+
if (next < 0) {
|
|
12612
|
+
setView(new Date(vy - 1, 0, 1));
|
|
12613
|
+
next += 12;
|
|
12614
|
+
} else if (next > 11) {
|
|
12615
|
+
setView(new Date(vy + 1, 0, 1));
|
|
12616
|
+
next -= 12;
|
|
12617
|
+
}
|
|
12618
|
+
setFocusMonth(next);
|
|
12619
|
+
};
|
|
12620
|
+
const onYearsKeyDown = (e) => {
|
|
12621
|
+
const vm = view.getMonth(), ds = Math.floor(view.getFullYear() / 10) * 10;
|
|
12622
|
+
const cur = focusYear == null ? view.getFullYear() : focusYear;
|
|
12623
|
+
let next;
|
|
12624
|
+
if (e.key === "ArrowRight") next = cur + 1;
|
|
12625
|
+
else if (e.key === "ArrowLeft") next = cur - 1;
|
|
12626
|
+
else if (e.key === "ArrowDown") next = cur + 3;
|
|
12627
|
+
else if (e.key === "ArrowUp") next = cur - 3;
|
|
12628
|
+
else if (e.key === "Home") next = ds;
|
|
12629
|
+
else if (e.key === "End") next = ds + 9;
|
|
12630
|
+
else return;
|
|
12631
|
+
e.preventDefault();
|
|
12632
|
+
setView(new Date(next, vm, 1));
|
|
12633
|
+
setFocusYear(next);
|
|
12634
|
+
};
|
|
12635
|
+
const tabbableDate = focusDate || range2.start || /* @__PURE__ */ new Date();
|
|
11972
12636
|
const clickDay = (d) => {
|
|
11973
12637
|
if (outOfRange(d)) return;
|
|
11974
|
-
if (!
|
|
12638
|
+
if (!range2.start || range2.start && range2.end) {
|
|
11975
12639
|
set({ start: d, end: null });
|
|
11976
12640
|
} else {
|
|
11977
|
-
const [start, end] = ymd(d) < ymd(
|
|
12641
|
+
const [start, end] = ymd(d) < ymd(range2.start) ? [d, range2.start] : [range2.start, d];
|
|
11978
12642
|
set({ start, end });
|
|
11979
12643
|
setOpen(false);
|
|
11980
12644
|
}
|
|
11981
12645
|
};
|
|
11982
|
-
const
|
|
11983
|
-
|
|
11984
|
-
const
|
|
11985
|
-
|
|
11986
|
-
set(
|
|
11987
|
-
setView(start);
|
|
12646
|
+
const presetItems = presets === true ? DEFAULT_PRESETS2 : Array.isArray(presets) ? presets : [];
|
|
12647
|
+
const applyPreset = (preset) => {
|
|
12648
|
+
const r2 = typeof preset.range === "function" ? preset.range() : preset.range;
|
|
12649
|
+
if (!r2) return;
|
|
12650
|
+
set(r2);
|
|
12651
|
+
if (r2.start) setView(r2.start);
|
|
11988
12652
|
setOpen(false);
|
|
11989
12653
|
};
|
|
11990
12654
|
const months = React51__namespace.default.useMemo(() => locale === void 0 ? MONTHS2 : monthNames2(locale), [locale]);
|
|
12655
|
+
const monthsShort = React51__namespace.default.useMemo(() => months.map((n) => n.slice(0, 3)), [months]);
|
|
11991
12656
|
const dows = React51__namespace.default.useMemo(
|
|
11992
12657
|
() => locale === void 0 ? Array.from({ length: 7 }, (_, i) => DOW2[(i + weekStartsOn) % 7]) : weekdayNames2(locale, weekStartsOn),
|
|
11993
12658
|
[locale, weekStartsOn]
|
|
11994
12659
|
);
|
|
11995
12660
|
const y = view.getFullYear(), m = view.getMonth();
|
|
12661
|
+
const decadeStart = Math.floor(y / 10) * 10;
|
|
12662
|
+
const yearCells = Array.from({ length: 12 }, (_, i) => decadeStart - 1 + i);
|
|
11996
12663
|
const startOffset = (new Date(y, m, 1).getDay() - weekStartsOn + 7) % 7;
|
|
11997
12664
|
const gridStart = new Date(y, m, 1 - startOffset);
|
|
11998
12665
|
const edgeOf = (t) => {
|
|
11999
|
-
const s = ymd(
|
|
12666
|
+
const s = ymd(range2.start), e = ymd(range2.end) || (range2.start && hover ? ymd(hover) : null);
|
|
12000
12667
|
const lo = s != null && e != null ? Math.min(s, e) : s, hi = s != null && e != null ? Math.max(s, e) : s;
|
|
12001
12668
|
if (s != null && hi === lo && t === s) return "both";
|
|
12002
12669
|
if (t === lo) return "start";
|
|
@@ -12004,13 +12671,13 @@ function DateRangePicker({
|
|
|
12004
12671
|
return null;
|
|
12005
12672
|
};
|
|
12006
12673
|
const inRange = (t) => {
|
|
12007
|
-
const s = ymd(
|
|
12008
|
-
let e = ymd(
|
|
12674
|
+
const s = ymd(range2.start);
|
|
12675
|
+
let e = ymd(range2.end);
|
|
12009
12676
|
if (s != null && e == null && hover) e = ymd(hover);
|
|
12010
12677
|
if (s == null || e == null) return false;
|
|
12011
12678
|
return t > Math.min(s, e) && t < Math.max(s, e);
|
|
12012
12679
|
};
|
|
12013
|
-
const text =
|
|
12680
|
+
const text = range2.start ? format ? format(range2) : `${fmtD(range2.start, locale)} \u2013 ${range2.end ? fmtD(range2.end, locale) : "\u2026"}` : "";
|
|
12014
12681
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-drp twc-field ${className}`, ref: wrapRef, ...rest, children: [
|
|
12015
12682
|
__twcStyles0,
|
|
12016
12683
|
__twcStyles1,
|
|
@@ -12020,7 +12687,7 @@ function DateRangePicker({
|
|
|
12020
12687
|
] }) : null,
|
|
12021
12688
|
editable ? (
|
|
12022
12689
|
// #105: typed entry — a text input accepting "start – end"; commits via `parse` on Enter/blur.
|
|
12023
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__control twc-drp__control--editable", "data-open": open || void 0, "data-disabled": disabled || void 0, "data-invalid": invalid || void 0, "data-tone": tone, children: [
|
|
12690
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__control twc-drp__control--editable", "data-open": open || void 0, "data-disabled": disabled || void 0, "data-invalid": invalid || void 0, "data-tone": tone, "data-size": size, children: [
|
|
12024
12691
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12025
12692
|
"input",
|
|
12026
12693
|
{
|
|
@@ -12052,12 +12719,24 @@ function DateRangePicker({
|
|
|
12052
12719
|
}
|
|
12053
12720
|
}
|
|
12054
12721
|
),
|
|
12055
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12722
|
+
clearable && (range2.start || range2.end) && !disabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12056
12723
|
"button",
|
|
12057
12724
|
{
|
|
12058
12725
|
type: "button",
|
|
12059
|
-
className: "twc-
|
|
12060
|
-
"aria-label": "
|
|
12726
|
+
className: "twc-drp__clear",
|
|
12727
|
+
"aria-label": "Clear",
|
|
12728
|
+
tabIndex: -1,
|
|
12729
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
12730
|
+
onClick: () => set({ start: null, end: null }),
|
|
12731
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
12732
|
+
}
|
|
12733
|
+
) : null,
|
|
12734
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12735
|
+
"button",
|
|
12736
|
+
{
|
|
12737
|
+
type: "button",
|
|
12738
|
+
className: "twc-drp__toggle",
|
|
12739
|
+
"aria-label": "Open calendar",
|
|
12061
12740
|
tabIndex: -1,
|
|
12062
12741
|
disabled,
|
|
12063
12742
|
onClick: () => !disabled && setOpen((o) => !o),
|
|
@@ -12077,6 +12756,7 @@ function DateRangePicker({
|
|
|
12077
12756
|
"data-disabled": disabled || void 0,
|
|
12078
12757
|
"data-invalid": invalid || void 0,
|
|
12079
12758
|
"data-tone": tone,
|
|
12759
|
+
"data-size": size,
|
|
12080
12760
|
role: "button",
|
|
12081
12761
|
tabIndex: disabled ? -1 : 0,
|
|
12082
12762
|
"aria-haspopup": "dialog",
|
|
@@ -12097,7 +12777,22 @@ function DateRangePicker({
|
|
|
12097
12777
|
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
|
|
12098
12778
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 2v4M8 2v4M3 10h18" })
|
|
12099
12779
|
] }) }),
|
|
12100
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-drp__text", "data-placeholder": !
|
|
12780
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-drp__text", "data-placeholder": !range2.start || void 0, children: range2.start ? text : placeholder }),
|
|
12781
|
+
clearable && (range2.start || range2.end) && !disabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12782
|
+
"button",
|
|
12783
|
+
{
|
|
12784
|
+
type: "button",
|
|
12785
|
+
className: "twc-drp__clear",
|
|
12786
|
+
"aria-label": "Clear",
|
|
12787
|
+
tabIndex: -1,
|
|
12788
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
12789
|
+
onClick: (e) => {
|
|
12790
|
+
e.stopPropagation();
|
|
12791
|
+
set({ start: null, end: null });
|
|
12792
|
+
},
|
|
12793
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
12794
|
+
}
|
|
12795
|
+
) : null
|
|
12101
12796
|
]
|
|
12102
12797
|
}
|
|
12103
12798
|
),
|
|
@@ -12112,23 +12807,23 @@ function DateRangePicker({
|
|
|
12112
12807
|
"aria-label": "Choose date range",
|
|
12113
12808
|
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
|
|
12114
12809
|
children: [
|
|
12115
|
-
|
|
12810
|
+
presetItems.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drp__presets", children: presetItems.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__preset", onClick: () => applyPreset(p), children: p.label }, i)) }) : null,
|
|
12116
12811
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__cal", children: [
|
|
12117
12812
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__head", children: [
|
|
12118
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__nav", "aria-label": "Previous month", onClick: () => setView(new Date(y, m - 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
12119
|
-
/* @__PURE__ */ jsxRuntime.
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
] }),
|
|
12129
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__nav", "aria-label": "Next month", onClick: () => setView(new Date(y, m + 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) }) })
|
|
12813
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__nav", "aria-label": mode === "years" ? "Previous decade" : mode === "months" ? "Previous year" : "Previous month", onClick: () => setView(mode === "years" ? new Date(y - 10, m, 1) : mode === "months" ? new Date(y - 1, m, 1) : new Date(y, m - 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
12814
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__title", "aria-label": "Switch calendar view", onClick: () => {
|
|
12815
|
+
if (mode === "days") {
|
|
12816
|
+
setFocusMonth(m);
|
|
12817
|
+
setMode("months");
|
|
12818
|
+
} else if (mode === "months") {
|
|
12819
|
+
setFocusYear(y);
|
|
12820
|
+
setMode("years");
|
|
12821
|
+
} else setMode("days");
|
|
12822
|
+
}, children: mode === "days" ? `${months[m]} ${y}` : mode === "months" ? y : `${decadeStart}\u2013${decadeStart + 9}` }),
|
|
12823
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-drp__sr", "aria-live": "polite", children: mode === "days" ? `${months[m]} ${y}` : mode === "months" ? y : `${decadeStart}\u2013${decadeStart + 9}` }),
|
|
12824
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__nav", "aria-label": mode === "years" ? "Next decade" : mode === "months" ? "Next year" : "Next month", onClick: () => setView(mode === "years" ? new Date(y + 10, m, 1) : mode === "months" ? new Date(y + 1, m, 1) : new Date(y, m + 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) }) })
|
|
12130
12825
|
] }),
|
|
12131
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__grid", ref: gridRef, onKeyDown: onGridKeyDown, role: "grid", children: [
|
|
12826
|
+
mode === "days" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__grid", ref: gridRef, onKeyDown: onGridKeyDown, role: "grid", children: [
|
|
12132
12827
|
dows.map((d, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drp__dow", children: d }, i)),
|
|
12133
12828
|
Array.from({ length: 42 }).map((_, i) => {
|
|
12134
12829
|
const d = new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i);
|
|
@@ -12153,7 +12848,53 @@ function DateRangePicker({
|
|
|
12153
12848
|
i
|
|
12154
12849
|
);
|
|
12155
12850
|
})
|
|
12156
|
-
] })
|
|
12851
|
+
] }) : mode === "months" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drp__months", ref: gridRef, onKeyDown: onMonthsKeyDown, role: "grid", children: monthsShort.map((mo, i) => {
|
|
12852
|
+
const disabled2 = min && ymd(new Date(y, i + 1, 0)) < ymd(min) || max && ymd(new Date(y, i, 1)) > ymd(max);
|
|
12853
|
+
const sel = range2.start && range2.start.getFullYear() === y && range2.start.getMonth() === i || range2.end && range2.end.getFullYear() === y && range2.end.getMonth() === i;
|
|
12854
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12855
|
+
"button",
|
|
12856
|
+
{
|
|
12857
|
+
type: "button",
|
|
12858
|
+
className: "twc-drp__mo",
|
|
12859
|
+
role: "gridcell",
|
|
12860
|
+
"data-mo": i,
|
|
12861
|
+
disabled: disabled2 || void 0,
|
|
12862
|
+
"data-selected": sel || void 0,
|
|
12863
|
+
tabIndex: i === (focusMonth ?? m) ? 0 : -1,
|
|
12864
|
+
onClick: () => {
|
|
12865
|
+
setView(new Date(y, i, 1));
|
|
12866
|
+
setFocusDate(null);
|
|
12867
|
+
setMode("days");
|
|
12868
|
+
},
|
|
12869
|
+
children: mo
|
|
12870
|
+
},
|
|
12871
|
+
i
|
|
12872
|
+
);
|
|
12873
|
+
}) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drp__years", ref: gridRef, onKeyDown: onYearsKeyDown, role: "grid", children: yearCells.map((yr) => {
|
|
12874
|
+
const outside = yr < decadeStart || yr > decadeStart + 9;
|
|
12875
|
+
const disabled2 = min && ymd(new Date(yr, 11, 31)) < ymd(min) || max && ymd(new Date(yr, 0, 1)) > ymd(max);
|
|
12876
|
+
const sel = range2.start && range2.start.getFullYear() === yr || range2.end && range2.end.getFullYear() === yr;
|
|
12877
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12878
|
+
"button",
|
|
12879
|
+
{
|
|
12880
|
+
type: "button",
|
|
12881
|
+
className: "twc-drp__yr",
|
|
12882
|
+
role: "gridcell",
|
|
12883
|
+
"data-yr": yr,
|
|
12884
|
+
"data-outside": outside || void 0,
|
|
12885
|
+
disabled: disabled2 || void 0,
|
|
12886
|
+
"data-selected": sel || void 0,
|
|
12887
|
+
tabIndex: yr === (focusYear ?? y) ? 0 : -1,
|
|
12888
|
+
onClick: () => {
|
|
12889
|
+
setView(new Date(yr, m, 1));
|
|
12890
|
+
setFocusMonth(m);
|
|
12891
|
+
setMode("months");
|
|
12892
|
+
},
|
|
12893
|
+
children: yr
|
|
12894
|
+
},
|
|
12895
|
+
yr
|
|
12896
|
+
);
|
|
12897
|
+
}) })
|
|
12157
12898
|
] })
|
|
12158
12899
|
]
|
|
12159
12900
|
}
|
|
@@ -12163,6 +12904,776 @@ function DateRangePicker({
|
|
|
12163
12904
|
error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
|
|
12164
12905
|
] });
|
|
12165
12906
|
}
|
|
12907
|
+
var FIELD_CSS5 = `
|
|
12908
|
+
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
12909
|
+
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
12910
|
+
.twc-field__req { color: var(--color-danger); }
|
|
12911
|
+
.twc-field__hint { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
12912
|
+
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
12913
|
+
`;
|
|
12914
|
+
var TIMEPICKER_CSS = `
|
|
12915
|
+
.twc-tp { position: relative; font-family: var(--font-sans); display: flex; flex-direction: column; gap: var(--space-1-5); }
|
|
12916
|
+
.twc-tp__control {
|
|
12917
|
+
display: flex; align-items: center; gap: var(--space-2); --_h: var(--control-h-md); height: var(--_h); padding: 0 var(--space-3);
|
|
12918
|
+
background: var(--color-surface); border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md);
|
|
12919
|
+
cursor: pointer; transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
|
|
12920
|
+
}
|
|
12921
|
+
.twc-tp__control:hover:not([data-open="true"]) { border-color: var(--color-border-strong); }
|
|
12922
|
+
.twc-tp__control { --_accent: var(--color-primary); --_ring: var(--ring); }
|
|
12923
|
+
.twc-tp__control[data-size="sm"] { --_h: var(--control-h-sm); }
|
|
12924
|
+
.twc-tp__control[data-size="lg"] { --_h: var(--control-h-lg); }
|
|
12925
|
+
.twc-tp__control[data-tone="success"] { --_accent: var(--color-success); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-success) 32%, transparent); }
|
|
12926
|
+
.twc-tp__control[data-tone="warning"] { --_accent: var(--color-warning); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-warning) 32%, transparent); }
|
|
12927
|
+
.twc-tp__control[data-tone="danger"] { --_accent: var(--color-danger); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 32%, transparent); }
|
|
12928
|
+
.twc-tp__control[data-tone="info"] { --_accent: var(--color-info); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-info) 32%, transparent); }
|
|
12929
|
+
.twc-tp__control[data-tone="neutral"] { --_accent: var(--color-border-strong); --_ring: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-text) 14%, transparent); }
|
|
12930
|
+
.twc-tp__control[data-open="true"] { border-color: var(--_accent); box-shadow: var(--_ring); }
|
|
12931
|
+
.twc-tp__control[data-invalid="true"] { border-color: var(--color-danger); }
|
|
12932
|
+
.twc-tp__control[data-invalid="true"][data-open="true"] { box-shadow: 0 0 0 var(--ring-width) color-mix(in srgb, var(--color-danger) 28%, transparent); }
|
|
12933
|
+
.twc-tp__control[data-disabled="true"] { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
12934
|
+
.twc-tp__field { position: relative; display: flex; flex-direction: column; }
|
|
12935
|
+
.twc-tp__control[data-has-clear="true"] { padding-inline-end: 34px; }
|
|
12936
|
+
.twc-tp__ic { flex: none; color: var(--color-text-subtle); display: inline-flex; }
|
|
12937
|
+
.twc-tp__ic svg { width: 17px; height: 17px; }
|
|
12938
|
+
.twc-tp__text { flex: 1; font-size: var(--text-sm); color: var(--color-text); font-variant-numeric: tabular-nums; }
|
|
12939
|
+
.twc-tp__text[data-placeholder="true"] { color: var(--color-text-subtle); font-variant-numeric: normal; }
|
|
12940
|
+
.twc-tp__clear { position: absolute; inset-inline-end: 10px; top: 50%; transform: translateY(-50%); display: inline-grid; place-items: center; width: 20px; height: 20px; border: none; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-full); }
|
|
12941
|
+
.twc-tp__clear:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
12942
|
+
.twc-tp__clear svg { width: 14px; height: 14px; }
|
|
12943
|
+
.twc-tp__control--editable { cursor: text; gap: 0; padding-inline-end: var(--space-1); }
|
|
12944
|
+
.twc-tp__input { flex: 1; min-width: 0; height: 100%; border: none; background: transparent; outline: none; padding: 0; font-family: inherit; font-size: var(--text-sm); color: var(--color-text); font-variant-numeric: tabular-nums; }
|
|
12945
|
+
.twc-tp__input::placeholder { color: var(--color-text-subtle); font-variant-numeric: normal; }
|
|
12946
|
+
.twc-tp__input:disabled { cursor: not-allowed; }
|
|
12947
|
+
.twc-tp__clear--inline { position: static; transform: none; flex: none; }
|
|
12948
|
+
.twc-tp__toggle { flex: none; display: inline-grid; place-items: center; width: 26px; height: 26px; border: none; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-md); transition: background-color var(--duration-fast), color var(--duration-fast); }
|
|
12949
|
+
.twc-tp__toggle:hover:not(:disabled) { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
12950
|
+
.twc-tp__toggle:disabled { cursor: not-allowed; }
|
|
12951
|
+
.twc-tp__toggle svg { width: 17px; height: 17px; }
|
|
12952
|
+
|
|
12953
|
+
.twc-tp__pop {
|
|
12954
|
+
position: fixed; z-index: var(--z-popover);
|
|
12955
|
+
background: var(--color-surface-raised); border: var(--border-thin) solid var(--color-border);
|
|
12956
|
+
border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--space-2);
|
|
12957
|
+
animation: twico-scale-in var(--duration-fast) var(--ease-spring); transform-origin: top;
|
|
12958
|
+
}
|
|
12959
|
+
.twc-tp__cols { display: flex; gap: var(--space-1); max-height: 232px; }
|
|
12960
|
+
.twc-tp__col { display: flex; flex-direction: column; gap: 2px; overflow-y: auto; scrollbar-width: thin; padding-inline: 2px; scroll-behavior: smooth; }
|
|
12961
|
+
.twc-tp__col::-webkit-scrollbar { width: 6px; }
|
|
12962
|
+
.twc-tp__col::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: var(--radius-full); }
|
|
12963
|
+
.twc-tp__col + .twc-tp__col { border-inline-start: var(--border-thin) solid var(--color-divider); }
|
|
12964
|
+
.twc-tp__colhead { text-align: center; font-size: 11px; font-weight: var(--font-bold); color: var(--color-text-subtle); text-transform: uppercase; padding: 2px 0 4px; position: sticky; top: 0; background: var(--color-surface-raised); }
|
|
12965
|
+
.twc-tp__opt { min-width: 46px; padding: 6px 10px; border: none; background: transparent; cursor: pointer; font-family: inherit; font-size: var(--text-sm); color: var(--color-text); border-radius: var(--radius-md); text-align: center; font-variant-numeric: tabular-nums; transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
|
|
12966
|
+
.twc-tp__opt:hover:not(:disabled):not([data-selected="true"]) { background: var(--color-surface-sunken); }
|
|
12967
|
+
.twc-tp__opt[data-selected="true"] { background: var(--color-primary); color: var(--color-primary-fg); font-weight: var(--font-bold); }
|
|
12968
|
+
.twc-tp__opt:disabled { opacity: 0.35; cursor: not-allowed; }
|
|
12969
|
+
.twc-tp__opt:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
12970
|
+
`;
|
|
12971
|
+
var pad = (n) => String(n).padStart(2, "0");
|
|
12972
|
+
var range = (start, end, step) => {
|
|
12973
|
+
const out = [];
|
|
12974
|
+
for (let i = start; i < end; i += step) out.push(i);
|
|
12975
|
+
return out;
|
|
12976
|
+
};
|
|
12977
|
+
var tod = (h, m, s) => h * 3600 + m * 60 + s;
|
|
12978
|
+
var to24 = (dh, mer) => mer === "PM" ? dh === 12 ? 12 : dh + 12 : dh === 12 ? 0 : dh;
|
|
12979
|
+
function TimePicker({
|
|
12980
|
+
label,
|
|
12981
|
+
hint,
|
|
12982
|
+
error,
|
|
12983
|
+
required = false,
|
|
12984
|
+
value,
|
|
12985
|
+
defaultValue = null,
|
|
12986
|
+
placeholder = "Select time",
|
|
12987
|
+
min,
|
|
12988
|
+
max,
|
|
12989
|
+
minuteStep = 5,
|
|
12990
|
+
secondStep = 5,
|
|
12991
|
+
granularity = "minute",
|
|
12992
|
+
// "hour" | "minute" | "second"
|
|
12993
|
+
hourCycle = 24,
|
|
12994
|
+
// 24 | 12
|
|
12995
|
+
referenceDate,
|
|
12996
|
+
disabled = false,
|
|
12997
|
+
tone = "primary",
|
|
12998
|
+
size = "md",
|
|
12999
|
+
clearable = true,
|
|
13000
|
+
editable = false,
|
|
13001
|
+
parse,
|
|
13002
|
+
format,
|
|
13003
|
+
locale,
|
|
13004
|
+
onChange,
|
|
13005
|
+
id,
|
|
13006
|
+
className = "",
|
|
13007
|
+
...rest
|
|
13008
|
+
}) {
|
|
13009
|
+
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS5);
|
|
13010
|
+
const __twcStyles1 = useScopedStyles("twc-timepicker-styles", TIMEPICKER_CSS);
|
|
13011
|
+
const autoId = React51__namespace.default.useId();
|
|
13012
|
+
const fieldId = id || autoId;
|
|
13013
|
+
const descId = `${fieldId}-desc`;
|
|
13014
|
+
const invalid = Boolean(error);
|
|
13015
|
+
const [internal, setInternal] = React51__namespace.default.useState(defaultValue);
|
|
13016
|
+
const selected = value !== void 0 ? value : internal;
|
|
13017
|
+
const [open, setOpen] = React51__namespace.default.useState(false);
|
|
13018
|
+
const [editText, setEditText] = React51__namespace.default.useState(null);
|
|
13019
|
+
const [coords, setCoords] = React51__namespace.default.useState(null);
|
|
13020
|
+
const wrapRef = React51__namespace.default.useRef(null);
|
|
13021
|
+
const triggerRef = React51__namespace.default.useRef(null);
|
|
13022
|
+
const popRef = React51__namespace.default.useRef(null);
|
|
13023
|
+
const place = React51__namespace.default.useCallback(() => {
|
|
13024
|
+
const el = triggerRef.current;
|
|
13025
|
+
if (!el) return;
|
|
13026
|
+
const r2 = el.getBoundingClientRect();
|
|
13027
|
+
const vh = window.innerHeight, POP_W = 220;
|
|
13028
|
+
const below = vh - r2.bottom;
|
|
13029
|
+
const flip = below < 300 && r2.top > below;
|
|
13030
|
+
let left = Math.min(r2.left, window.innerWidth - POP_W - 8);
|
|
13031
|
+
left = Math.max(8, left);
|
|
13032
|
+
setCoords({ left, top: flip ? void 0 : Math.round(r2.bottom + 6), bottom: flip ? Math.round(vh - r2.top + 6) : void 0 });
|
|
13033
|
+
}, []);
|
|
13034
|
+
React51__namespace.default.useEffect(() => {
|
|
13035
|
+
if (!open) return void 0;
|
|
13036
|
+
place();
|
|
13037
|
+
const onMove = () => place();
|
|
13038
|
+
window.addEventListener("scroll", onMove, true);
|
|
13039
|
+
window.addEventListener("resize", onMove);
|
|
13040
|
+
return () => {
|
|
13041
|
+
window.removeEventListener("scroll", onMove, true);
|
|
13042
|
+
window.removeEventListener("resize", onMove);
|
|
13043
|
+
};
|
|
13044
|
+
}, [open, place]);
|
|
13045
|
+
React51__namespace.default.useEffect(() => {
|
|
13046
|
+
if (!open) return void 0;
|
|
13047
|
+
const onDown = (e) => {
|
|
13048
|
+
if (wrapRef.current && wrapRef.current.contains(e.target)) return;
|
|
13049
|
+
if (popRef.current && popRef.current.contains(e.target)) return;
|
|
13050
|
+
setOpen(false);
|
|
13051
|
+
};
|
|
13052
|
+
const onKey = (e) => {
|
|
13053
|
+
if (e.key === "Escape") setOpen(false);
|
|
13054
|
+
};
|
|
13055
|
+
document.addEventListener("mousedown", onDown);
|
|
13056
|
+
document.addEventListener("keydown", onKey);
|
|
13057
|
+
return () => {
|
|
13058
|
+
document.removeEventListener("mousedown", onDown);
|
|
13059
|
+
document.removeEventListener("keydown", onKey);
|
|
13060
|
+
};
|
|
13061
|
+
}, [open]);
|
|
13062
|
+
useFocusTrap(popRef, open && !!coords, {
|
|
13063
|
+
initialFocus: () => popRef.current?.querySelector('.twc-tp__opt[data-selected="true"]') || popRef.current?.querySelector('.twc-tp__opt[tabindex="0"]')
|
|
13064
|
+
});
|
|
13065
|
+
React51__namespace.default.useEffect(() => {
|
|
13066
|
+
if (!open || !coords) return;
|
|
13067
|
+
popRef.current?.querySelectorAll('.twc-tp__opt[data-selected="true"]').forEach((el) => el.scrollIntoView({ block: "center" }));
|
|
13068
|
+
}, [open, coords]);
|
|
13069
|
+
const refBase = referenceDate || /* @__PURE__ */ new Date();
|
|
13070
|
+
const minTod = min ? tod(min.getHours(), min.getMinutes(), min.getSeconds()) : null;
|
|
13071
|
+
const maxTod = max ? tod(max.getHours(), max.getMinutes(), max.getSeconds()) : null;
|
|
13072
|
+
const outOfRange = (h, m, s) => minTod != null && tod(h, m, s) < minTod || maxTod != null && tod(h, m, s) > maxTod;
|
|
13073
|
+
const curH = selected ? selected.getHours() : null;
|
|
13074
|
+
const curM = selected ? selected.getMinutes() : null;
|
|
13075
|
+
const curS = selected ? selected.getSeconds() : null;
|
|
13076
|
+
const curMer = curH == null ? "AM" : curH < 12 ? "AM" : "PM";
|
|
13077
|
+
const fmt = (d) => {
|
|
13078
|
+
if (!d) return "";
|
|
13079
|
+
if (format) return format(d);
|
|
13080
|
+
const opts = { hour: hourCycle === 12 ? "numeric" : "2-digit", minute: "2-digit", hour12: hourCycle === 12 };
|
|
13081
|
+
if (granularity === "second") opts.second = "2-digit";
|
|
13082
|
+
if (granularity === "hour") delete opts.minute;
|
|
13083
|
+
return d.toLocaleTimeString(locale, opts);
|
|
13084
|
+
};
|
|
13085
|
+
const commit = (h, m, s) => {
|
|
13086
|
+
const b = selected || refBase;
|
|
13087
|
+
const d = new Date(b.getFullYear(), b.getMonth(), b.getDate(), h, m, s, 0);
|
|
13088
|
+
if (value === void 0) setInternal(d);
|
|
13089
|
+
onChange?.(d);
|
|
13090
|
+
setEditText(null);
|
|
13091
|
+
};
|
|
13092
|
+
const pickHour = (h) => commit(h, granularity === "hour" ? 0 : curM ?? 0, granularity === "second" ? curS ?? 0 : 0);
|
|
13093
|
+
const pickMinute = (m) => commit(curH ?? refBase.getHours(), m, granularity === "second" ? curS ?? 0 : 0);
|
|
13094
|
+
const pickSecond = (s) => commit(curH ?? refBase.getHours(), curM ?? 0, s);
|
|
13095
|
+
const pickMeridiem = (mer) => {
|
|
13096
|
+
const dh = curH == null ? 0 : curH % 12 === 0 ? 12 : curH % 12;
|
|
13097
|
+
commit(to24(dh, mer), curM ?? 0, granularity === "second" ? curS ?? 0 : 0);
|
|
13098
|
+
};
|
|
13099
|
+
const clear = () => {
|
|
13100
|
+
if (value === void 0) setInternal(null);
|
|
13101
|
+
onChange?.(null);
|
|
13102
|
+
setEditText(null);
|
|
13103
|
+
};
|
|
13104
|
+
const parseTyped = (str) => {
|
|
13105
|
+
const s = str.trim();
|
|
13106
|
+
if (s === "") return null;
|
|
13107
|
+
if (parse) {
|
|
13108
|
+
const d = parse(s);
|
|
13109
|
+
return d instanceof Date && !Number.isNaN(d.getTime()) ? d : void 0;
|
|
13110
|
+
}
|
|
13111
|
+
const mm = s.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s*([ap]m)?$/i);
|
|
13112
|
+
if (!mm) return void 0;
|
|
13113
|
+
let h = +mm[1];
|
|
13114
|
+
const mi = +mm[2];
|
|
13115
|
+
const se = mm[3] ? +mm[3] : 0;
|
|
13116
|
+
const mer = mm[4] && mm[4].toLowerCase();
|
|
13117
|
+
if (mer === "pm" && h < 12) h += 12;
|
|
13118
|
+
else if (mer === "am" && h === 12) h = 0;
|
|
13119
|
+
if (h > 23 || mi > 59 || se > 59) return void 0;
|
|
13120
|
+
const b = selected || refBase;
|
|
13121
|
+
return new Date(b.getFullYear(), b.getMonth(), b.getDate(), h, mi, se, 0);
|
|
13122
|
+
};
|
|
13123
|
+
const commitText = () => {
|
|
13124
|
+
if (editText == null) return;
|
|
13125
|
+
const parsed = parseTyped(editText);
|
|
13126
|
+
if (parsed === null) {
|
|
13127
|
+
setEditText(null);
|
|
13128
|
+
if (selected) clear();
|
|
13129
|
+
return;
|
|
13130
|
+
}
|
|
13131
|
+
if (parsed === void 0 || outOfRange(parsed.getHours(), parsed.getMinutes(), parsed.getSeconds())) {
|
|
13132
|
+
setEditText(null);
|
|
13133
|
+
return;
|
|
13134
|
+
}
|
|
13135
|
+
commit(parsed.getHours(), parsed.getMinutes(), parsed.getSeconds());
|
|
13136
|
+
setOpen(false);
|
|
13137
|
+
};
|
|
13138
|
+
const hourVals = hourCycle === 12 ? [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] : range(0, 24, 1);
|
|
13139
|
+
const columns = [
|
|
13140
|
+
{
|
|
13141
|
+
key: "h",
|
|
13142
|
+
head: "hr",
|
|
13143
|
+
aria: "Hour",
|
|
13144
|
+
items: hourVals.map((hv) => {
|
|
13145
|
+
const h24 = hourCycle === 12 ? to24(hv, curMer) : hv;
|
|
13146
|
+
return {
|
|
13147
|
+
val: hv,
|
|
13148
|
+
text: hourCycle === 12 ? String(hv) : pad(hv),
|
|
13149
|
+
selected: curH != null && h24 === curH,
|
|
13150
|
+
disabled: outOfRange(h24, 0, 0) && outOfRange(h24, 59, 59),
|
|
13151
|
+
onSelect: () => pickHour(h24)
|
|
13152
|
+
};
|
|
13153
|
+
})
|
|
13154
|
+
}
|
|
13155
|
+
];
|
|
13156
|
+
if (granularity !== "hour") {
|
|
13157
|
+
const h = curH ?? refBase.getHours();
|
|
13158
|
+
columns.push({ key: "m", head: "min", aria: "Minute", items: range(0, 60, minuteStep).map((mv) => ({
|
|
13159
|
+
val: mv,
|
|
13160
|
+
text: pad(mv),
|
|
13161
|
+
selected: curM != null && mv === curM,
|
|
13162
|
+
disabled: outOfRange(h, mv, 0) && outOfRange(h, mv, 59),
|
|
13163
|
+
onSelect: () => pickMinute(mv)
|
|
13164
|
+
})) });
|
|
13165
|
+
}
|
|
13166
|
+
if (granularity === "second") {
|
|
13167
|
+
const h = curH ?? refBase.getHours(), m = curM ?? 0;
|
|
13168
|
+
columns.push({ key: "s", head: "sec", aria: "Second", items: range(0, 60, secondStep).map((sv) => ({
|
|
13169
|
+
val: sv,
|
|
13170
|
+
text: pad(sv),
|
|
13171
|
+
selected: curS != null && sv === curS,
|
|
13172
|
+
disabled: outOfRange(h, m, sv),
|
|
13173
|
+
onSelect: () => pickSecond(sv)
|
|
13174
|
+
})) });
|
|
13175
|
+
}
|
|
13176
|
+
if (hourCycle === 12) {
|
|
13177
|
+
columns.push({ key: "mer", head: "", aria: "AM or PM", items: ["AM", "PM"].map((mer) => ({
|
|
13178
|
+
val: mer,
|
|
13179
|
+
text: mer,
|
|
13180
|
+
selected: curH != null && curMer === mer,
|
|
13181
|
+
disabled: [...Array(12)].every((_, i) => {
|
|
13182
|
+
const hh = mer === "AM" ? i : i + 12;
|
|
13183
|
+
return outOfRange(hh, 0, 0) && outOfRange(hh, 59, 59);
|
|
13184
|
+
}),
|
|
13185
|
+
onSelect: () => pickMeridiem(mer)
|
|
13186
|
+
})) });
|
|
13187
|
+
}
|
|
13188
|
+
const onOptKey = (e) => {
|
|
13189
|
+
const btn = e.target;
|
|
13190
|
+
const col = btn.closest("[data-col]");
|
|
13191
|
+
if (!col) return;
|
|
13192
|
+
const opts = Array.from(col.querySelectorAll(".twc-tp__opt:not(:disabled)"));
|
|
13193
|
+
const i = opts.indexOf(btn);
|
|
13194
|
+
let target;
|
|
13195
|
+
if (e.key === "ArrowDown") target = opts[Math.min(i + 1, opts.length - 1)];
|
|
13196
|
+
else if (e.key === "ArrowUp") target = opts[Math.max(i - 1, 0)];
|
|
13197
|
+
else if (e.key === "Home") target = opts[0];
|
|
13198
|
+
else if (e.key === "End") target = opts[opts.length - 1];
|
|
13199
|
+
else if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
|
|
13200
|
+
const cols = Array.from(popRef.current.querySelectorAll("[data-col]"));
|
|
13201
|
+
const nextCol = cols[cols.indexOf(col) + (e.key === "ArrowRight" ? 1 : -1)];
|
|
13202
|
+
if (nextCol) {
|
|
13203
|
+
const nopts = Array.from(nextCol.querySelectorAll(".twc-tp__opt:not(:disabled)"));
|
|
13204
|
+
target = nextCol.querySelector('.twc-tp__opt[data-selected="true"]') || nopts[Math.min(i, nopts.length - 1)] || nopts[0];
|
|
13205
|
+
}
|
|
13206
|
+
} else return;
|
|
13207
|
+
e.preventDefault();
|
|
13208
|
+
target?.focus();
|
|
13209
|
+
};
|
|
13210
|
+
const clockIcon = /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
13211
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
13212
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 7v5l3 2" })
|
|
13213
|
+
] });
|
|
13214
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-tp twc-field ${className}`, ref: wrapRef, ...rest, children: [
|
|
13215
|
+
__twcStyles0,
|
|
13216
|
+
__twcStyles1,
|
|
13217
|
+
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", id: `${fieldId}-label`, children: [
|
|
13218
|
+
label,
|
|
13219
|
+
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
13220
|
+
] }) : null,
|
|
13221
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-tp__field", children: editable ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13222
|
+
"div",
|
|
13223
|
+
{
|
|
13224
|
+
className: "twc-tp__control twc-tp__control--editable",
|
|
13225
|
+
"data-open": open || void 0,
|
|
13226
|
+
"data-disabled": disabled || void 0,
|
|
13227
|
+
"data-tone": tone,
|
|
13228
|
+
"data-invalid": invalid || void 0,
|
|
13229
|
+
"data-size": size,
|
|
13230
|
+
children: [
|
|
13231
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13232
|
+
"input",
|
|
13233
|
+
{
|
|
13234
|
+
ref: triggerRef,
|
|
13235
|
+
className: "twc-tp__input",
|
|
13236
|
+
id: fieldId,
|
|
13237
|
+
type: "text",
|
|
13238
|
+
inputMode: "numeric",
|
|
13239
|
+
autoComplete: "off",
|
|
13240
|
+
disabled,
|
|
13241
|
+
placeholder,
|
|
13242
|
+
value: editText != null ? editText : selected ? fmt(selected) : "",
|
|
13243
|
+
"aria-haspopup": "dialog",
|
|
13244
|
+
"aria-expanded": open,
|
|
13245
|
+
"aria-labelledby": label ? `${fieldId}-label` : void 0,
|
|
13246
|
+
"aria-invalid": invalid || void 0,
|
|
13247
|
+
"aria-describedby": error || hint ? descId : void 0,
|
|
13248
|
+
onChange: (e) => setEditText(e.target.value),
|
|
13249
|
+
onKeyDown: (e) => {
|
|
13250
|
+
if (e.key === "Enter") {
|
|
13251
|
+
e.preventDefault();
|
|
13252
|
+
commitText();
|
|
13253
|
+
} else if (e.key === "ArrowDown" && (e.altKey || !open)) {
|
|
13254
|
+
e.preventDefault();
|
|
13255
|
+
setOpen(true);
|
|
13256
|
+
} else if (e.key === "Escape" && open) setOpen(false);
|
|
13257
|
+
},
|
|
13258
|
+
onBlur: (e) => {
|
|
13259
|
+
if (popRef.current && popRef.current.contains(e.relatedTarget)) return;
|
|
13260
|
+
commitText();
|
|
13261
|
+
}
|
|
13262
|
+
}
|
|
13263
|
+
),
|
|
13264
|
+
clearable && selected && !disabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
13265
|
+
"button",
|
|
13266
|
+
{
|
|
13267
|
+
type: "button",
|
|
13268
|
+
className: "twc-tp__clear twc-tp__clear--inline",
|
|
13269
|
+
"aria-label": "Clear",
|
|
13270
|
+
tabIndex: -1,
|
|
13271
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
13272
|
+
onClick: clear,
|
|
13273
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
13274
|
+
}
|
|
13275
|
+
) : null,
|
|
13276
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13277
|
+
"button",
|
|
13278
|
+
{
|
|
13279
|
+
type: "button",
|
|
13280
|
+
className: "twc-tp__toggle",
|
|
13281
|
+
"aria-label": "Open time list",
|
|
13282
|
+
tabIndex: -1,
|
|
13283
|
+
disabled,
|
|
13284
|
+
onClick: () => !disabled && setOpen((o) => !o),
|
|
13285
|
+
children: clockIcon
|
|
13286
|
+
}
|
|
13287
|
+
)
|
|
13288
|
+
]
|
|
13289
|
+
}
|
|
13290
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
13291
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
13292
|
+
"div",
|
|
13293
|
+
{
|
|
13294
|
+
ref: triggerRef,
|
|
13295
|
+
className: "twc-tp__control",
|
|
13296
|
+
id: fieldId,
|
|
13297
|
+
"data-open": open || void 0,
|
|
13298
|
+
"data-disabled": disabled || void 0,
|
|
13299
|
+
"data-size": size,
|
|
13300
|
+
"data-tone": tone,
|
|
13301
|
+
"data-has-clear": clearable && selected && !disabled ? "true" : void 0,
|
|
13302
|
+
"data-invalid": invalid || void 0,
|
|
13303
|
+
role: "button",
|
|
13304
|
+
tabIndex: disabled ? -1 : 0,
|
|
13305
|
+
"aria-haspopup": "dialog",
|
|
13306
|
+
"aria-expanded": open,
|
|
13307
|
+
"aria-labelledby": label ? `${fieldId}-label` : void 0,
|
|
13308
|
+
"aria-invalid": invalid || void 0,
|
|
13309
|
+
"aria-describedby": error || hint ? descId : void 0,
|
|
13310
|
+
onClick: () => !disabled && setOpen((o) => !o),
|
|
13311
|
+
onKeyDown: (e) => {
|
|
13312
|
+
if ((e.key === "Enter" || e.key === " ") && !disabled) {
|
|
13313
|
+
e.preventDefault();
|
|
13314
|
+
setOpen((o) => !o);
|
|
13315
|
+
}
|
|
13316
|
+
},
|
|
13317
|
+
children: [
|
|
13318
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-tp__ic", "aria-hidden": "true", children: clockIcon }),
|
|
13319
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-tp__text", "data-placeholder": !selected || void 0, children: selected ? fmt(selected) : placeholder })
|
|
13320
|
+
]
|
|
13321
|
+
}
|
|
13322
|
+
),
|
|
13323
|
+
clearable && selected && !disabled ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-tp__clear", "aria-label": "Clear", onClick: (e) => {
|
|
13324
|
+
e.stopPropagation();
|
|
13325
|
+
clear();
|
|
13326
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
|
|
13327
|
+
] }) }),
|
|
13328
|
+
open && coords ? reactDom.createPortal(
|
|
13329
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13330
|
+
"div",
|
|
13331
|
+
{
|
|
13332
|
+
className: "twc-tp__pop",
|
|
13333
|
+
ref: popRef,
|
|
13334
|
+
role: "dialog",
|
|
13335
|
+
"aria-modal": "true",
|
|
13336
|
+
"aria-label": "Choose time",
|
|
13337
|
+
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
|
|
13338
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-tp__cols", children: columns.map((col) => {
|
|
13339
|
+
const firstTab = col.items.find((it) => it.selected) || col.items.find((it) => !it.disabled);
|
|
13340
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-tp__col", role: "listbox", "aria-label": col.aria, "data-col": col.key, children: [
|
|
13341
|
+
col.head ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-tp__colhead", "aria-hidden": "true", children: col.head }) : null,
|
|
13342
|
+
col.items.map((it) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
13343
|
+
"button",
|
|
13344
|
+
{
|
|
13345
|
+
type: "button",
|
|
13346
|
+
className: "twc-tp__opt",
|
|
13347
|
+
role: "option",
|
|
13348
|
+
"aria-selected": it.selected || false,
|
|
13349
|
+
"data-selected": it.selected || void 0,
|
|
13350
|
+
"data-val": it.val,
|
|
13351
|
+
disabled: it.disabled || void 0,
|
|
13352
|
+
tabIndex: it === firstTab ? 0 : -1,
|
|
13353
|
+
onClick: it.onSelect,
|
|
13354
|
+
onKeyDown: onOptKey,
|
|
13355
|
+
children: it.text
|
|
13356
|
+
},
|
|
13357
|
+
it.val
|
|
13358
|
+
))
|
|
13359
|
+
] }, col.key);
|
|
13360
|
+
}) })
|
|
13361
|
+
}
|
|
13362
|
+
),
|
|
13363
|
+
document.body
|
|
13364
|
+
) : null,
|
|
13365
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
|
|
13366
|
+
] });
|
|
13367
|
+
}
|
|
13368
|
+
var FIELD_CSS6 = `
|
|
13369
|
+
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
13370
|
+
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
13371
|
+
.twc-field__req { color: var(--color-danger); }
|
|
13372
|
+
.twc-field__hint { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
13373
|
+
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
13374
|
+
`;
|
|
13375
|
+
var DTP_CSS = `
|
|
13376
|
+
.twc-dtp { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
13377
|
+
.twc-dtp__row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: flex-start; }
|
|
13378
|
+
.twc-dtp__date { flex: 1 1 11rem; min-width: 9rem; }
|
|
13379
|
+
.twc-dtp__time { flex: 0 1 8rem; min-width: 7rem; }
|
|
13380
|
+
`;
|
|
13381
|
+
function DateTimePicker({
|
|
13382
|
+
label,
|
|
13383
|
+
hint,
|
|
13384
|
+
error,
|
|
13385
|
+
required = false,
|
|
13386
|
+
value,
|
|
13387
|
+
defaultValue = null,
|
|
13388
|
+
disabled = false,
|
|
13389
|
+
tone = "primary",
|
|
13390
|
+
size = "md",
|
|
13391
|
+
clearable = true,
|
|
13392
|
+
min,
|
|
13393
|
+
max,
|
|
13394
|
+
disabledDate,
|
|
13395
|
+
minuteStep = 5,
|
|
13396
|
+
secondStep = 5,
|
|
13397
|
+
granularity = "minute",
|
|
13398
|
+
hourCycle = 24,
|
|
13399
|
+
locale,
|
|
13400
|
+
weekStartsOn = 0,
|
|
13401
|
+
dateFormat,
|
|
13402
|
+
timeFormat,
|
|
13403
|
+
datePlaceholder = "Select date",
|
|
13404
|
+
timePlaceholder = "Time",
|
|
13405
|
+
onChange,
|
|
13406
|
+
id,
|
|
13407
|
+
className = "",
|
|
13408
|
+
...rest
|
|
13409
|
+
}) {
|
|
13410
|
+
const __twcStyles0 = useScopedStyles("twc-field-styles", FIELD_CSS6);
|
|
13411
|
+
const __twcStyles1 = useScopedStyles("twc-datetimepicker-styles", DTP_CSS);
|
|
13412
|
+
const autoId = React51__namespace.default.useId();
|
|
13413
|
+
const fieldId = id || autoId;
|
|
13414
|
+
const descId = `${fieldId}-desc`;
|
|
13415
|
+
const [internal, setInternal] = React51__namespace.default.useState(defaultValue);
|
|
13416
|
+
const selected = value !== void 0 ? value : internal;
|
|
13417
|
+
const commitVal = (d) => {
|
|
13418
|
+
if (value === void 0) setInternal(d);
|
|
13419
|
+
onChange?.(d);
|
|
13420
|
+
};
|
|
13421
|
+
const onDateChange = (d) => {
|
|
13422
|
+
if (!d) return commitVal(null);
|
|
13423
|
+
const b = selected;
|
|
13424
|
+
commitVal(new Date(d.getFullYear(), d.getMonth(), d.getDate(), b ? b.getHours() : 0, b ? b.getMinutes() : 0, b ? b.getSeconds() : 0, 0));
|
|
13425
|
+
};
|
|
13426
|
+
const onTimeChange = (t) => {
|
|
13427
|
+
if (!t) return;
|
|
13428
|
+
const b = selected;
|
|
13429
|
+
commitVal(new Date(b ? b.getFullYear() : t.getFullYear(), b ? b.getMonth() : t.getMonth(), b ? b.getDate() : t.getDate(), t.getHours(), t.getMinutes(), t.getSeconds(), 0));
|
|
13430
|
+
};
|
|
13431
|
+
const childTone = error ? "danger" : tone;
|
|
13432
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-dtp twc-field ${className}`, id: fieldId, ...rest, children: [
|
|
13433
|
+
__twcStyles0,
|
|
13434
|
+
__twcStyles1,
|
|
13435
|
+
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", id: `${fieldId}-label`, children: [
|
|
13436
|
+
label,
|
|
13437
|
+
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
13438
|
+
] }) : null,
|
|
13439
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dtp__row", role: "group", "aria-labelledby": label ? `${fieldId}-label` : void 0, "aria-describedby": error || hint ? descId : void 0, children: [
|
|
13440
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dtp__date", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13441
|
+
DatePicker,
|
|
13442
|
+
{
|
|
13443
|
+
value: selected,
|
|
13444
|
+
onChange: onDateChange,
|
|
13445
|
+
disabled,
|
|
13446
|
+
tone: childTone,
|
|
13447
|
+
size,
|
|
13448
|
+
clearable,
|
|
13449
|
+
min,
|
|
13450
|
+
max,
|
|
13451
|
+
disabledDate,
|
|
13452
|
+
locale,
|
|
13453
|
+
weekStartsOn,
|
|
13454
|
+
format: dateFormat,
|
|
13455
|
+
placeholder: datePlaceholder,
|
|
13456
|
+
"aria-label": "Date"
|
|
13457
|
+
}
|
|
13458
|
+
) }),
|
|
13459
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dtp__time", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13460
|
+
TimePicker,
|
|
13461
|
+
{
|
|
13462
|
+
value: selected,
|
|
13463
|
+
onChange: onTimeChange,
|
|
13464
|
+
disabled,
|
|
13465
|
+
tone: childTone,
|
|
13466
|
+
size,
|
|
13467
|
+
clearable: false,
|
|
13468
|
+
minuteStep,
|
|
13469
|
+
secondStep,
|
|
13470
|
+
granularity,
|
|
13471
|
+
hourCycle,
|
|
13472
|
+
locale,
|
|
13473
|
+
referenceDate: selected || void 0,
|
|
13474
|
+
format: timeFormat,
|
|
13475
|
+
placeholder: timePlaceholder,
|
|
13476
|
+
"aria-label": "Time"
|
|
13477
|
+
}
|
|
13478
|
+
) })
|
|
13479
|
+
] }),
|
|
13480
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null
|
|
13481
|
+
] });
|
|
13482
|
+
}
|
|
13483
|
+
var FILTERBAR_CSS = `
|
|
13484
|
+
.twc-fbar { font-family: var(--font-sans); display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); }
|
|
13485
|
+
.twc-fbar__field { display: flex; flex-direction: column; min-width: 170px; }
|
|
13486
|
+
.twc-fbar__field[data-type="search"], .twc-fbar__field[data-type="text"] { flex: 1 1 200px; }
|
|
13487
|
+
.twc-fbar__field[data-type="daterange"] { min-width: 220px; }
|
|
13488
|
+
.twc-fbar__field[data-type="boolean"], .twc-fbar__field[data-type="number"] { min-width: 130px; }
|
|
13489
|
+
.twc-fbar__labelrow { display: flex; align-items: center; gap: 6px; min-height: 18px; margin-bottom: var(--space-1); }
|
|
13490
|
+
.twc-fbar__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); }
|
|
13491
|
+
.twc-fbar__clearone { display: inline-grid; place-items: center; width: 16px; height: 16px; border: none; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-full); padding: 0; }
|
|
13492
|
+
.twc-fbar__clearone:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
13493
|
+
.twc-fbar__clearone svg { width: 11px; height: 11px; }
|
|
13494
|
+
.twc-fbar__actions { display: flex; align-items: center; gap: var(--space-2); }
|
|
13495
|
+
.twc-fbar__clearall { display: inline-flex; align-items: center; gap: 6px; height: var(--control-h-md); padding: 0 var(--space-3); border: var(--border-thin) solid var(--color-border); background: var(--color-surface); color: var(--color-text-muted); border-radius: var(--radius-md); cursor: pointer; font-family: inherit; font-size: var(--text-sm); font-weight: var(--font-medium); transition: background-color var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast); }
|
|
13496
|
+
.twc-fbar__clearall:hover:not(:disabled) { background: var(--color-surface-sunken); color: var(--color-text); border-color: var(--color-border-strong); }
|
|
13497
|
+
.twc-fbar__clearall:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
13498
|
+
.twc-fbar__clearall svg { width: 15px; height: 15px; }
|
|
13499
|
+
`;
|
|
13500
|
+
var isEmpty = (f, v) => {
|
|
13501
|
+
if (v == null) return true;
|
|
13502
|
+
if (f.type === "multiselect" || f.type === "select-multiple") return !Array.isArray(v) || v.length === 0;
|
|
13503
|
+
if (f.type === "daterange") return v.start == null && v.end == null;
|
|
13504
|
+
return v === "";
|
|
13505
|
+
};
|
|
13506
|
+
var emptyFor = (f) => f.type === "multiselect" ? [] : f.type === "daterange" ? { start: null, end: null } : void 0;
|
|
13507
|
+
function valuesToClauses(fields, values) {
|
|
13508
|
+
const out = [];
|
|
13509
|
+
for (const f of fields) {
|
|
13510
|
+
const v = values[f.field];
|
|
13511
|
+
if (isEmpty(f, v)) continue;
|
|
13512
|
+
if (f.type === "multiselect") out.push({ field: f.field, op: "isAnyOf", value: v });
|
|
13513
|
+
else if (f.type === "daterange") {
|
|
13514
|
+
if (v.start != null) out.push({ field: f.field, op: ">=", value: v.start });
|
|
13515
|
+
if (v.end != null) out.push({ field: f.field, op: "<", value: v.end });
|
|
13516
|
+
} else if (f.type === "search" || f.type === "text") out.push({ field: f.field, op: f.op || "contains", value: v });
|
|
13517
|
+
else if (f.type === "number") out.push({ field: f.field, op: f.op || "=", value: v });
|
|
13518
|
+
else if (f.type === "boolean") out.push({ field: f.field, op: "=", value: v });
|
|
13519
|
+
else out.push({ field: f.field, op: f.op || "=", value: v });
|
|
13520
|
+
}
|
|
13521
|
+
return out;
|
|
13522
|
+
}
|
|
13523
|
+
function clausesToValues(fields, clauses) {
|
|
13524
|
+
const v = {};
|
|
13525
|
+
for (const f of fields) v[f.field] = emptyFor(f);
|
|
13526
|
+
for (const c of clauses || []) {
|
|
13527
|
+
const f = fields.find((x) => x.field === c.field);
|
|
13528
|
+
if (!f) continue;
|
|
13529
|
+
if (f.type === "daterange") {
|
|
13530
|
+
v[f.field] = { ...v[f.field] || { start: null, end: null } };
|
|
13531
|
+
if (c.op === ">=" || c.op === ">") v[f.field].start = c.value;
|
|
13532
|
+
else if (c.op === "<" || c.op === "<=") v[f.field].end = c.value;
|
|
13533
|
+
} else if (f.type === "multiselect") {
|
|
13534
|
+
v[f.field] = Array.isArray(c.value) ? c.value : [];
|
|
13535
|
+
} else {
|
|
13536
|
+
v[f.field] = c.value;
|
|
13537
|
+
}
|
|
13538
|
+
}
|
|
13539
|
+
return v;
|
|
13540
|
+
}
|
|
13541
|
+
var xIcon = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) });
|
|
13542
|
+
function FilterBar({
|
|
13543
|
+
fields = [],
|
|
13544
|
+
value,
|
|
13545
|
+
defaultValue = [],
|
|
13546
|
+
onChange,
|
|
13547
|
+
onValuesChange,
|
|
13548
|
+
showClearAll = false,
|
|
13549
|
+
clearAllLabel = "Clear all",
|
|
13550
|
+
showFieldClear = true,
|
|
13551
|
+
size = "md",
|
|
13552
|
+
tone = "primary",
|
|
13553
|
+
disabled = false,
|
|
13554
|
+
id,
|
|
13555
|
+
className = "",
|
|
13556
|
+
...rest
|
|
13557
|
+
}) {
|
|
13558
|
+
const styles = useScopedStyles("twc-filterbar-styles", FILTERBAR_CSS);
|
|
13559
|
+
const autoId = React51__namespace.default.useId();
|
|
13560
|
+
const fieldId = id || autoId;
|
|
13561
|
+
const [internal, setInternal] = React51__namespace.default.useState(defaultValue);
|
|
13562
|
+
const clauses = value !== void 0 ? value : internal;
|
|
13563
|
+
const values = React51__namespace.default.useMemo(() => clausesToValues(fields, clauses), [fields, clauses]);
|
|
13564
|
+
const emit = (nextValues) => {
|
|
13565
|
+
const next = valuesToClauses(fields, nextValues);
|
|
13566
|
+
if (value === void 0) setInternal(next);
|
|
13567
|
+
onChange?.(next);
|
|
13568
|
+
onValuesChange?.(nextValues);
|
|
13569
|
+
};
|
|
13570
|
+
const setField = (f, v) => emit({ ...values, [f.field]: v });
|
|
13571
|
+
const clearField = (f) => setField(f, emptyFor(f));
|
|
13572
|
+
const clearAll = () => {
|
|
13573
|
+
const cleared = {};
|
|
13574
|
+
for (const f of fields) cleared[f.field] = emptyFor(f);
|
|
13575
|
+
emit(cleared);
|
|
13576
|
+
};
|
|
13577
|
+
const activeCount = fields.reduce((n, f) => n + (isEmpty(f, values[f.field]) ? 0 : 1), 0);
|
|
13578
|
+
const control = (f) => {
|
|
13579
|
+
const v = values[f.field];
|
|
13580
|
+
const name = f.label || f.field;
|
|
13581
|
+
const opts = typeof f.options === "function" ? f.options(values) : f.options;
|
|
13582
|
+
const common = { size, disabled: disabled || f.disabled, "aria-label": name };
|
|
13583
|
+
if (f.type === "multiselect") {
|
|
13584
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13585
|
+
MultiSelect,
|
|
13586
|
+
{
|
|
13587
|
+
...common,
|
|
13588
|
+
options: opts || [],
|
|
13589
|
+
value: v || [],
|
|
13590
|
+
placeholder: f.placeholder || "Any",
|
|
13591
|
+
clearable: true,
|
|
13592
|
+
onChange: (next) => setField(f, next)
|
|
13593
|
+
}
|
|
13594
|
+
);
|
|
13595
|
+
}
|
|
13596
|
+
if (f.type === "daterange") {
|
|
13597
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13598
|
+
DateRangePicker,
|
|
13599
|
+
{
|
|
13600
|
+
...common,
|
|
13601
|
+
tone,
|
|
13602
|
+
value: v || { start: null, end: null },
|
|
13603
|
+
clearable: true,
|
|
13604
|
+
onChange: (range2) => setField(f, range2)
|
|
13605
|
+
}
|
|
13606
|
+
);
|
|
13607
|
+
}
|
|
13608
|
+
if (f.type === "boolean") {
|
|
13609
|
+
const boolOpts = [{ value: "", label: f.anyLabel || "Any" }, { value: "true", label: f.trueLabel || "Yes" }, { value: "false", label: f.falseLabel || "No" }];
|
|
13610
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13611
|
+
Select,
|
|
13612
|
+
{
|
|
13613
|
+
...common,
|
|
13614
|
+
searchable: false,
|
|
13615
|
+
options: boolOpts,
|
|
13616
|
+
value: v == null ? "" : String(v),
|
|
13617
|
+
onChange: (next) => setField(f, next === "" ? void 0 : next === "true")
|
|
13618
|
+
}
|
|
13619
|
+
);
|
|
13620
|
+
}
|
|
13621
|
+
if (f.type === "select") {
|
|
13622
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13623
|
+
Select,
|
|
13624
|
+
{
|
|
13625
|
+
...common,
|
|
13626
|
+
searchable: f.searchable,
|
|
13627
|
+
options: opts || [],
|
|
13628
|
+
value: v ?? "",
|
|
13629
|
+
placeholder: f.placeholder || "Any",
|
|
13630
|
+
portal: f.portal,
|
|
13631
|
+
onChange: (next) => setField(f, next === "" ? void 0 : next)
|
|
13632
|
+
}
|
|
13633
|
+
);
|
|
13634
|
+
}
|
|
13635
|
+
if (f.type === "number") {
|
|
13636
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13637
|
+
Input,
|
|
13638
|
+
{
|
|
13639
|
+
...common,
|
|
13640
|
+
type: "number",
|
|
13641
|
+
value: v ?? "",
|
|
13642
|
+
placeholder: f.placeholder,
|
|
13643
|
+
onChange: (e) => setField(f, e.target.value === "" ? void 0 : Number(e.target.value))
|
|
13644
|
+
}
|
|
13645
|
+
);
|
|
13646
|
+
}
|
|
13647
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13648
|
+
Input,
|
|
13649
|
+
{
|
|
13650
|
+
...common,
|
|
13651
|
+
type: f.type === "search" ? "search" : "text",
|
|
13652
|
+
value: v ?? "",
|
|
13653
|
+
placeholder: f.placeholder || (f.type === "search" ? "Search\u2026" : ""),
|
|
13654
|
+
onChange: (e) => setField(f, e.target.value)
|
|
13655
|
+
}
|
|
13656
|
+
);
|
|
13657
|
+
};
|
|
13658
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-fbar ${className}`, id: fieldId, role: "group", "aria-label": "Filters", ...rest, children: [
|
|
13659
|
+
styles,
|
|
13660
|
+
fields.map((f) => {
|
|
13661
|
+
const active = !isEmpty(f, values[f.field]);
|
|
13662
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-fbar__field", "data-type": f.type, children: [
|
|
13663
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-fbar__labelrow", children: [
|
|
13664
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-fbar__label", children: f.label || f.field }),
|
|
13665
|
+
showFieldClear && active && !disabled ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-fbar__clearone", "aria-label": `Clear ${f.label || f.field}`, onClick: () => clearField(f), children: xIcon }) : null
|
|
13666
|
+
] }),
|
|
13667
|
+
control(f)
|
|
13668
|
+
] }, f.field);
|
|
13669
|
+
}),
|
|
13670
|
+
showClearAll ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-fbar__actions", children: /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-fbar__clearall", onClick: clearAll, disabled: disabled || activeCount === 0, children: [
|
|
13671
|
+
xIcon,
|
|
13672
|
+
clearAllLabel,
|
|
13673
|
+
activeCount > 0 ? ` (${activeCount})` : ""
|
|
13674
|
+
] }) }) : null
|
|
13675
|
+
] });
|
|
13676
|
+
}
|
|
12166
13677
|
var DIALOG_CSS = `
|
|
12167
13678
|
.twc-dialog__overlay {
|
|
12168
13679
|
position: fixed; inset: 0; z-index: var(--z-modal);
|
|
@@ -12480,7 +13991,7 @@ function EmptyState({
|
|
|
12480
13991
|
actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-empty__actions", children: actions }) : null
|
|
12481
13992
|
] });
|
|
12482
13993
|
}
|
|
12483
|
-
var
|
|
13994
|
+
var FIELD_CSS7 = `
|
|
12484
13995
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
12485
13996
|
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
12486
13997
|
.twc-field__req { color: var(--color-danger); }
|
|
@@ -12499,7 +14010,7 @@ function Field({
|
|
|
12499
14010
|
children,
|
|
12500
14011
|
...rest
|
|
12501
14012
|
}) {
|
|
12502
|
-
const __twcStyles = useScopedStyles("twc-field-styles",
|
|
14013
|
+
const __twcStyles = useScopedStyles("twc-field-styles", FIELD_CSS7);
|
|
12503
14014
|
const autoId = React51__namespace.default.useId();
|
|
12504
14015
|
const fieldId = id || autoId;
|
|
12505
14016
|
const descId = `${fieldId}-desc`;
|
|
@@ -12520,6 +14031,8 @@ function Field({
|
|
|
12520
14031
|
}
|
|
12521
14032
|
var UPLOAD_CSS = `
|
|
12522
14033
|
.twc-upload { font-family: var(--font-sans); display: flex; flex-direction: column; gap: var(--space-3); }
|
|
14034
|
+
.twc-upload[data-size="sm"] { --_pad-y: var(--space-5); --_pad-x: var(--space-4); }
|
|
14035
|
+
.twc-upload[data-size="lg"] { --_pad-y: var(--space-10); --_pad-x: var(--space-8); }
|
|
12523
14036
|
.twc-field__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); display: flex; gap: 4px; align-items: center; }
|
|
12524
14037
|
.twc-field__req { color: var(--color-danger); }
|
|
12525
14038
|
.twc-field__hint { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
@@ -12527,7 +14040,7 @@ var UPLOAD_CSS = `
|
|
|
12527
14040
|
.twc-upload__zone[data-invalid="true"] { border-color: var(--color-danger); }
|
|
12528
14041
|
.twc-upload__zone {
|
|
12529
14042
|
display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
|
|
12530
|
-
gap: 6px; padding: var(--space-8) var(--space-6); cursor: pointer;
|
|
14043
|
+
gap: 6px; padding: var(--_pad-y, var(--space-8)) var(--_pad-x, var(--space-6)); cursor: pointer;
|
|
12531
14044
|
border: var(--border-medium) dashed var(--color-border-strong); border-radius: var(--radius-xl);
|
|
12532
14045
|
background: var(--color-surface); color: var(--color-text-muted);
|
|
12533
14046
|
transition: border-color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard);
|
|
@@ -12580,6 +14093,7 @@ function FileUpload({
|
|
|
12580
14093
|
accept,
|
|
12581
14094
|
multiple = false,
|
|
12582
14095
|
disabled = false,
|
|
14096
|
+
size = "md",
|
|
12583
14097
|
tone = "primary",
|
|
12584
14098
|
label,
|
|
12585
14099
|
hint,
|
|
@@ -12635,7 +14149,7 @@ function FileUpload({
|
|
|
12635
14149
|
function remove(i) {
|
|
12636
14150
|
set(files.filter((_, idx) => idx !== i));
|
|
12637
14151
|
}
|
|
12638
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-upload ${className}`, ...rest, children: [
|
|
14152
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-upload ${className}`, "data-size": size, ...rest, children: [
|
|
12639
14153
|
__twcStyles,
|
|
12640
14154
|
label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-field__label", htmlFor: fieldId, children: [
|
|
12641
14155
|
label,
|
|
@@ -13048,7 +14562,7 @@ button.twc-navbar__brand, a.twc-navbar__brand { cursor: pointer; }
|
|
|
13048
14562
|
.twc-navbar__menu-btn { display: inline-grid; }
|
|
13049
14563
|
}
|
|
13050
14564
|
`;
|
|
13051
|
-
function
|
|
14565
|
+
function safeHref6(url) {
|
|
13052
14566
|
if (url == null) return void 0;
|
|
13053
14567
|
const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
|
|
13054
14568
|
return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
|
|
@@ -13071,9 +14585,9 @@ function Navbar({
|
|
|
13071
14585
|
return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: `twc-navbar ${className}`, "data-sticky": sticky || void 0, ...rest, children: [
|
|
13072
14586
|
__twcStyles,
|
|
13073
14587
|
onMenuClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-navbar__menu-btn", "aria-expanded": menuOpen, "aria-controls": menuControls, "aria-label": menuOpen ? "Close menu" : "Open menu", onClick: onMenuClick, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 6h16M4 12h16M4 18h16" }) }) }) : null,
|
|
13074
|
-
brand ? brandHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "twc-navbar__brand", href:
|
|
14588
|
+
brand ? brandHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "twc-navbar__brand", href: safeHref6(brandHref), children: brand }) : onBrandClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-navbar__brand", onClick: onBrandClick, children: brand }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-navbar__brand", children: brand }) : null,
|
|
13075
14589
|
/* @__PURE__ */ jsxRuntime.jsx("nav", { className: "twc-navbar__links", "aria-label": navLabel, children: links.map((l, i) => {
|
|
13076
|
-
const href =
|
|
14590
|
+
const href = safeHref6(l.href);
|
|
13077
14591
|
const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
13078
14592
|
l.icon,
|
|
13079
14593
|
l.label
|
|
@@ -13433,6 +14947,7 @@ function Radio({
|
|
|
13433
14947
|
.twc-radio[data-invalid="true"] .twc-radio__dot { border-color: var(--color-danger); }
|
|
13434
14948
|
.twc-radio__text { display: flex; flex-direction: column; gap: 2px; }
|
|
13435
14949
|
.twc-radio__label { font-size: var(--text-sm); font-weight: var(--font-medium); color: var(--color-text); line-height: 1.3; }
|
|
14950
|
+
.twc-field__req { color: var(--color-danger); }
|
|
13436
14951
|
.twc-radio__desc { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
13437
14952
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
13438
14953
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
@@ -13468,7 +14983,10 @@ function Radio({
|
|
|
13468
14983
|
),
|
|
13469
14984
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-radio__dot", "aria-hidden": "true" }),
|
|
13470
14985
|
label || description ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-radio__text", children: [
|
|
13471
|
-
label ? /* @__PURE__ */ jsxRuntime.
|
|
14986
|
+
label ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-radio__label", children: [
|
|
14987
|
+
label,
|
|
14988
|
+
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
14989
|
+
] }) : null,
|
|
13472
14990
|
description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-radio__desc", children: description }) : null
|
|
13473
14991
|
] }) : null
|
|
13474
14992
|
] });
|
|
@@ -13998,20 +15516,23 @@ var SLIDER_CSS = `
|
|
|
13998
15516
|
.twc-slider__msgs { display: flex; flex-direction: column; gap: var(--space-1-5); margin-top: var(--space-2); }
|
|
13999
15517
|
.twc-field__hint { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
14000
15518
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
15519
|
+
.twc-slider { --_track-h: 22px; --_thumb: 18px; --_rail: 6px; }
|
|
15520
|
+
.twc-slider[data-size="sm"] { --_track-h: 18px; --_thumb: 14px; --_rail: 4px; }
|
|
15521
|
+
.twc-slider[data-size="lg"] { --_track-h: 28px; --_thumb: 22px; --_rail: 8px; }
|
|
14001
15522
|
.twc-slider__head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: var(--space-2); }
|
|
14002
15523
|
.twc-slider__label { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-text); }
|
|
14003
15524
|
.twc-slider__value { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--_accent); font-variant-numeric: tabular-nums; }
|
|
14004
15525
|
.twc-slider__track {
|
|
14005
|
-
position: relative; height:
|
|
15526
|
+
position: relative; height: var(--_track-h); display: flex; align-items: center; cursor: pointer; touch-action: none;
|
|
14006
15527
|
}
|
|
14007
15528
|
.twc-slider[data-disabled="true"] { opacity: 0.55; }
|
|
14008
15529
|
.twc-slider[data-disabled="true"] .twc-slider__track { cursor: not-allowed; }
|
|
14009
|
-
.twc-slider__rail { position: absolute; left: 0; right: 0; height:
|
|
14010
|
-
.twc-slider__fill { position: absolute; height:
|
|
15530
|
+
.twc-slider__rail { position: absolute; left: 0; right: 0; height: var(--_rail); border-radius: var(--radius-full); background: var(--color-surface-sunken); box-shadow: inset 0 0 0 1px var(--color-border); }
|
|
15531
|
+
.twc-slider__fill { position: absolute; height: var(--_rail); border-radius: var(--radius-full); background: var(--_accent); }
|
|
14011
15532
|
.twc-slider__thumb {
|
|
14012
|
-
position: absolute; width:
|
|
15533
|
+
position: absolute; width: var(--_thumb); height: var(--_thumb); border-radius: var(--radius-full);
|
|
14013
15534
|
background: var(--color-surface); border: var(--border-thick) solid var(--_accent);
|
|
14014
|
-
box-shadow: var(--shadow-sm); transform: translateX(-50%); top: 50%; margin-top: -
|
|
15535
|
+
box-shadow: var(--shadow-sm); transform: translateX(-50%); top: 50%; margin-top: calc(var(--_thumb) / -2);
|
|
14015
15536
|
transition: box-shadow var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-spring);
|
|
14016
15537
|
}
|
|
14017
15538
|
.twc-slider__thumb:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
@@ -14039,7 +15560,8 @@ function Slider({
|
|
|
14039
15560
|
precision,
|
|
14040
15561
|
tone = "primary",
|
|
14041
15562
|
disabled = false,
|
|
14042
|
-
|
|
15563
|
+
size = "md",
|
|
15564
|
+
range: range2 = false,
|
|
14043
15565
|
showValue = true,
|
|
14044
15566
|
showTicks = false,
|
|
14045
15567
|
formatValue,
|
|
@@ -14067,7 +15589,7 @@ function Slider({
|
|
|
14067
15589
|
const __twcStyles = useScopedStyles("twc-slider-styles", SLIDER_CSS);
|
|
14068
15590
|
const autoId = React51__namespace.default.useId();
|
|
14069
15591
|
const fieldId = id || autoId;
|
|
14070
|
-
const isRange =
|
|
15592
|
+
const isRange = range2 || Array.isArray(value) || Array.isArray(defaultValue);
|
|
14071
15593
|
const [internal, setInternal] = React51__namespace.default.useState(() => {
|
|
14072
15594
|
if (isRange) {
|
|
14073
15595
|
const dv = Array.isArray(defaultValue) ? defaultValue : [min, max];
|
|
@@ -14155,7 +15677,7 @@ function Slider({
|
|
|
14155
15677
|
const fillLo = (Math.min(...clampedVals) - min) / (max - min) * 100;
|
|
14156
15678
|
const fillHi = (Math.max(...clampedVals) - min) / (max - min) * 100;
|
|
14157
15679
|
const fillStyle = isRange ? { left: `${fillLo}%`, width: `${fillHi - fillLo}%` } : { width: `${fillHi}%` };
|
|
14158
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-slider ${className}`, "data-tone": tone, "data-disabled": disabled || void 0, ...rest, children: [
|
|
15680
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-slider ${className}`, "data-tone": tone, "data-size": size, "data-disabled": disabled || void 0, ...rest, children: [
|
|
14159
15681
|
__twcStyles,
|
|
14160
15682
|
name ? clampedVals.map((v, i) => /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: v, disabled: disabled || void 0 }, i)) : null,
|
|
14161
15683
|
label || showValue ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-slider__head", children: [
|
|
@@ -14207,10 +15729,10 @@ function Spinner({
|
|
|
14207
15729
|
className = "",
|
|
14208
15730
|
...rest
|
|
14209
15731
|
}) {
|
|
14210
|
-
if (process.env.NODE_ENV !== "production" &&
|
|
14211
|
-
warnOnce("Spinner.
|
|
15732
|
+
if (process.env.NODE_ENV !== "production" && color !== void 0 && tone === void 0) {
|
|
15733
|
+
warnOnce("Spinner.color", "Spinner: `color` is deprecated and will be removed in 2.0 \u2014 use `tone` (matches every other tone-driven component).");
|
|
14212
15734
|
}
|
|
14213
|
-
const
|
|
15735
|
+
const resolvedTone = tone ?? color ?? "current";
|
|
14214
15736
|
const __twcStyles = useScopedStyles("twc-spinner-styles", `
|
|
14215
15737
|
.twc-spinner {
|
|
14216
15738
|
--_sz: 24px; --_bw: 2.5px;
|
|
@@ -14236,7 +15758,7 @@ function Spinner({
|
|
|
14236
15758
|
.twc-spinner { animation-duration: 0.65s !important; animation-iteration-count: infinite !important; }
|
|
14237
15759
|
}
|
|
14238
15760
|
`);
|
|
14239
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: `twc-spinner ${className}`, "data-size": size, "data-tone":
|
|
15761
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: `twc-spinner ${className}`, "data-size": size, "data-tone": resolvedTone, role: "status", "aria-label": label, ...rest, children: __twcStyles });
|
|
14240
15762
|
}
|
|
14241
15763
|
var STAT_CSS = `
|
|
14242
15764
|
.twc-stat { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-sans);
|
|
@@ -14470,6 +15992,7 @@ function Switch({
|
|
|
14470
15992
|
.twc-switch[data-invalid="true"] .twc-switch__track { box-shadow: inset 0 0 0 var(--border-medium) var(--color-danger); }
|
|
14471
15993
|
.twc-switch__text { display: flex; flex-direction: column; gap: 2px; }
|
|
14472
15994
|
.twc-switch__label { font-size: var(--text-sm); font-weight: var(--font-medium); color: var(--color-text); line-height: 1.3; }
|
|
15995
|
+
.twc-field__req { color: var(--color-danger); }
|
|
14473
15996
|
.twc-switch__desc { font-size: var(--text-xs); color: var(--color-text-muted); }
|
|
14474
15997
|
.twc-field { display: flex; flex-direction: column; gap: var(--space-1-5); font-family: var(--font-sans); }
|
|
14475
15998
|
.twc-field__error { font-size: var(--text-xs); color: var(--color-danger-subtle-fg); font-weight: var(--font-medium); }
|
|
@@ -14504,7 +16027,10 @@ function Switch({
|
|
|
14504
16027
|
),
|
|
14505
16028
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-switch__track", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-switch__thumb" }) }),
|
|
14506
16029
|
label || description ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-switch__text", children: [
|
|
14507
|
-
label ? /* @__PURE__ */ jsxRuntime.
|
|
16030
|
+
label ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-switch__label", children: [
|
|
16031
|
+
label,
|
|
16032
|
+
required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
16033
|
+
] }) : null,
|
|
14508
16034
|
description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-switch__desc", children: description }) : null
|
|
14509
16035
|
] }) : null
|
|
14510
16036
|
] });
|
|
@@ -14717,6 +16243,11 @@ var TABS_CSS = `
|
|
|
14717
16243
|
top: auto; inset-inline-end: 4px; inset-inline-start: 4px; width: auto;
|
|
14718
16244
|
}
|
|
14719
16245
|
.twc-tabs[data-orientation="vertical"] .twc-tabs__panel { padding-top: 0; flex: 1; min-width: 0; }
|
|
16246
|
+
/* WCAG 2.3.3: the active-tab indicator jumps instead of sliding under reduced motion (both
|
|
16247
|
+
the horizontal left/width and vertical top/height variants). */
|
|
16248
|
+
@media (prefers-reduced-motion: reduce) {
|
|
16249
|
+
.twc-tabs__indicator, .twc-tabs[data-orientation="vertical"] .twc-tabs__indicator { transition: none; }
|
|
16250
|
+
}
|
|
14720
16251
|
`;
|
|
14721
16252
|
function Tabs({
|
|
14722
16253
|
items,
|
|
@@ -15095,6 +16626,12 @@ var TOAST_CSS = `
|
|
|
15095
16626
|
from { opacity: 0; transform: translateX(-24px); }
|
|
15096
16627
|
to { opacity: 1; transform: translateX(0); }
|
|
15097
16628
|
}
|
|
16629
|
+
/* WCAG 2.3.3: appear without the slide under reduced motion (covers the RTL variant too). */
|
|
16630
|
+
@media (prefers-reduced-motion: reduce) {
|
|
16631
|
+
.twc-toast, [dir="rtl"] .twc-toast { animation: none; }
|
|
16632
|
+
}
|
|
16633
|
+
/* #209: visually-hidden persistent live-region announcers (rendered by ToastProvider). */
|
|
16634
|
+
.twc-toast-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
|
|
15098
16635
|
.twc-toast::before { content: ""; position: absolute; inset-inline-start: 0; top: 0; bottom: 0; width: 4px; background: var(--_accent, var(--color-primary)); }
|
|
15099
16636
|
.twc-toast[data-tone="success"] { --_accent: var(--color-success); }
|
|
15100
16637
|
.twc-toast[data-tone="warning"] { --_accent: var(--color-warning); }
|
|
@@ -15211,6 +16748,8 @@ function useToast() {
|
|
|
15211
16748
|
}
|
|
15212
16749
|
function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps }) {
|
|
15213
16750
|
const [toasts, setToasts] = React51__namespace.default.useState([]);
|
|
16751
|
+
const [politeMsg, setPoliteMsg] = React51__namespace.default.useState("");
|
|
16752
|
+
const [assertiveMsg, setAssertiveMsg] = React51__namespace.default.useState("");
|
|
15214
16753
|
const idRef = React51__namespace.default.useRef(0);
|
|
15215
16754
|
const limitRef = React51__namespace.default.useRef(limit);
|
|
15216
16755
|
React51__namespace.default.useEffect(() => {
|
|
@@ -15229,6 +16768,12 @@ function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps
|
|
|
15229
16768
|
const n = limitRef.current;
|
|
15230
16769
|
return n && n > 0 ? arr.slice(-n) : arr;
|
|
15231
16770
|
});
|
|
16771
|
+
const parts = [next.title, next.description != null ? next.description : next.children].filter((p) => typeof p === "string" || typeof p === "number").map(String);
|
|
16772
|
+
const msg = parts.join(". ").trim();
|
|
16773
|
+
if (msg) {
|
|
16774
|
+
const setter = next.tone === "danger" || next.tone === "warning" ? setAssertiveMsg : setPoliteMsg;
|
|
16775
|
+
setter((prev) => prev === msg ? msg + "\u200B" : msg);
|
|
16776
|
+
}
|
|
15232
16777
|
return id;
|
|
15233
16778
|
};
|
|
15234
16779
|
const withTone = (tone) => (title, options) => push(typeof title === "object" && title !== null ? { tone, ...title } : { tone, title, ...options });
|
|
@@ -15244,12 +16789,15 @@ function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps
|
|
|
15244
16789
|
const value = React51__namespace.default.useMemo(() => ({ ...api, toasts }), [api, toasts]);
|
|
15245
16790
|
return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value, children: [
|
|
15246
16791
|
children,
|
|
16792
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-toast-sr", "aria-live": "polite", "aria-atomic": "true", children: politeMsg }),
|
|
16793
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-toast-sr", "aria-live": "assertive", "aria-atomic": "true", children: assertiveMsg }),
|
|
15247
16794
|
/* @__PURE__ */ jsxRuntime.jsx(ToastViewport, { limit, ...viewportProps, children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
15248
16795
|
Toast,
|
|
15249
16796
|
{
|
|
15250
16797
|
tone: t.tone,
|
|
15251
16798
|
title: t.title,
|
|
15252
16799
|
icon: t.icon,
|
|
16800
|
+
role: "group",
|
|
15253
16801
|
duration: t.duration != null ? t.duration : duration,
|
|
15254
16802
|
onClose: () => dismiss(t.id),
|
|
15255
16803
|
children: t.description != null ? t.description : t.children
|
|
@@ -15523,7 +17071,7 @@ function bgValue(bg) {
|
|
|
15523
17071
|
if (BG[bg]) return `var(${BG[bg]})`;
|
|
15524
17072
|
return String(bg).startsWith("--") ? `var(${bg})` : bg;
|
|
15525
17073
|
}
|
|
15526
|
-
function
|
|
17074
|
+
function safeHref7(url) {
|
|
15527
17075
|
if (url == null) return void 0;
|
|
15528
17076
|
const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
|
|
15529
17077
|
return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
|
|
@@ -15571,7 +17119,7 @@ var Box = React51__namespace.default.forwardRef(function Box2({
|
|
|
15571
17119
|
...style,
|
|
15572
17120
|
...flatStyle
|
|
15573
17121
|
};
|
|
15574
|
-
if (Tag2 === "a" && rest.href != null) rest.href =
|
|
17122
|
+
if (Tag2 === "a" && rest.href != null) rest.href = safeHref7(rest.href);
|
|
15575
17123
|
return /* @__PURE__ */ jsxRuntime.jsxs(Tag2, { ref, className: `twc-box ${className}`.trim(), style: s, "data-twc-sx": sxAttr, ...rest, children: [
|
|
15576
17124
|
styleNode,
|
|
15577
17125
|
children
|
|
@@ -15579,7 +17127,7 @@ var Box = React51__namespace.default.forwardRef(function Box2({
|
|
|
15579
17127
|
});
|
|
15580
17128
|
Box.displayName = "Box";
|
|
15581
17129
|
var SIZES = { sm: 640, md: 768, lg: 1024, xl: 1280, full: "100%" };
|
|
15582
|
-
function
|
|
17130
|
+
function safeHref8(url) {
|
|
15583
17131
|
if (url == null) return void 0;
|
|
15584
17132
|
const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
|
|
15585
17133
|
return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
|
|
@@ -15596,7 +17144,7 @@ var Container = React51__namespace.default.forwardRef(function Container2({
|
|
|
15596
17144
|
}, ref) {
|
|
15597
17145
|
const { flatStyle, styleNode, sxAttr } = useSx(sx);
|
|
15598
17146
|
const max = SIZES[size] ?? size;
|
|
15599
|
-
if (Tag2 === "a" && rest.href != null) rest.href =
|
|
17147
|
+
if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
|
|
15600
17148
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15601
17149
|
Tag2,
|
|
15602
17150
|
{
|
|
@@ -15622,83 +17170,6 @@ var Container = React51__namespace.default.forwardRef(function Container2({
|
|
|
15622
17170
|
);
|
|
15623
17171
|
});
|
|
15624
17172
|
Container.displayName = "Container";
|
|
15625
|
-
function space(v) {
|
|
15626
|
-
if (v == null) return void 0;
|
|
15627
|
-
if (typeof v === "number") return `var(--space-${String(v).replace(".", "-")})`;
|
|
15628
|
-
return v;
|
|
15629
|
-
}
|
|
15630
|
-
function len(v) {
|
|
15631
|
-
return typeof v === "number" ? `${v}px` : v;
|
|
15632
|
-
}
|
|
15633
|
-
var BP = { sm: 640, md: 768, lg: 1024, xl: 1280 };
|
|
15634
|
-
function safeHref8(url) {
|
|
15635
|
-
if (url == null) return void 0;
|
|
15636
|
-
const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
|
|
15637
|
-
return s.startsWith("javascript:") || s.startsWith("data:") || s.startsWith("vbscript:") ? void 0 : url;
|
|
15638
|
-
}
|
|
15639
|
-
var Grid = React51__namespace.default.forwardRef(function Grid2({
|
|
15640
|
-
as: Tag2 = "div",
|
|
15641
|
-
columns,
|
|
15642
|
-
minChildWidth,
|
|
15643
|
-
gap = 4,
|
|
15644
|
-
rowGap,
|
|
15645
|
-
columnGap,
|
|
15646
|
-
align,
|
|
15647
|
-
justify,
|
|
15648
|
-
alignContent,
|
|
15649
|
-
justifyContent,
|
|
15650
|
-
sx,
|
|
15651
|
-
className = "",
|
|
15652
|
-
style,
|
|
15653
|
-
children,
|
|
15654
|
-
...rest
|
|
15655
|
-
}, ref) {
|
|
15656
|
-
const { flatStyle, styleNode, sxAttr } = useSx(sx);
|
|
15657
|
-
const responsive = columns != null && typeof columns === "object";
|
|
15658
|
-
const uid = React51__namespace.default.useId();
|
|
15659
|
-
const gridId = responsive ? `g${uid.replace(/[^a-zA-Z0-9]/g, "")}` : null;
|
|
15660
|
-
let css = "";
|
|
15661
|
-
if (responsive) {
|
|
15662
|
-
const base = columns.base ?? 1;
|
|
15663
|
-
const sel = `[data-twc-grid-id="${gridId}"]`;
|
|
15664
|
-
css = `${sel} { --twc-grid-cols: ${base}; }`;
|
|
15665
|
-
for (const bp of ["sm", "md", "lg", "xl"]) {
|
|
15666
|
-
if (columns[bp] != null) css += `
|
|
15667
|
-
@media (min-width: ${BP[bp]}px) { ${sel} { --twc-grid-cols: ${columns[bp]}; } }`;
|
|
15668
|
-
}
|
|
15669
|
-
}
|
|
15670
|
-
const __twcStyles = useScopedStyles(gridId ? `twc-grid-${gridId}` : "twc-grid", css);
|
|
15671
|
-
const templateColumns = minChildWidth ? `repeat(auto-fill, minmax(min(${len(minChildWidth)}, 100%), 1fr))` : responsive ? `repeat(var(--twc-grid-cols, ${columns.base ?? 1}), minmax(0, 1fr))` : `repeat(${columns || 1}, minmax(0, 1fr))`;
|
|
15672
|
-
if (Tag2 === "a" && rest.href != null) rest.href = safeHref8(rest.href);
|
|
15673
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15674
|
-
Tag2,
|
|
15675
|
-
{
|
|
15676
|
-
ref,
|
|
15677
|
-
className: `twc-grid ${className}`.trim(),
|
|
15678
|
-
"data-twc-grid-id": gridId || void 0,
|
|
15679
|
-
"data-twc-sx": sxAttr,
|
|
15680
|
-
style: {
|
|
15681
|
-
display: "grid",
|
|
15682
|
-
gridTemplateColumns: templateColumns,
|
|
15683
|
-
rowGap: space(rowGap ?? gap),
|
|
15684
|
-
columnGap: space(columnGap ?? gap),
|
|
15685
|
-
alignItems: align,
|
|
15686
|
-
justifyItems: justify,
|
|
15687
|
-
alignContent,
|
|
15688
|
-
justifyContent,
|
|
15689
|
-
...style,
|
|
15690
|
-
...flatStyle
|
|
15691
|
-
},
|
|
15692
|
-
...rest,
|
|
15693
|
-
children: [
|
|
15694
|
-
responsive ? __twcStyles : null,
|
|
15695
|
-
styleNode,
|
|
15696
|
-
children
|
|
15697
|
-
]
|
|
15698
|
-
}
|
|
15699
|
-
);
|
|
15700
|
-
});
|
|
15701
|
-
Grid.displayName = "Grid";
|
|
15702
17173
|
function space2(v) {
|
|
15703
17174
|
if (v == null) return void 0;
|
|
15704
17175
|
if (typeof v === "number") return `var(--space-${String(v).replace(".", "-")})`;
|
|
@@ -16302,6 +17773,7 @@ exports.BubbleChart = BubbleChart;
|
|
|
16302
17773
|
exports.Button = Button;
|
|
16303
17774
|
exports.Candlestick = Candlestick;
|
|
16304
17775
|
exports.Card = Card;
|
|
17776
|
+
exports.CardGrid = CardGrid;
|
|
16305
17777
|
exports.Carousel = Carousel;
|
|
16306
17778
|
exports.Chart = Chart;
|
|
16307
17779
|
exports.Checkbox = Checkbox;
|
|
@@ -16316,13 +17788,16 @@ exports.CurrencyField = CurrencyField;
|
|
|
16316
17788
|
exports.Datatable = Datatable;
|
|
16317
17789
|
exports.DatePicker = DatePicker;
|
|
16318
17790
|
exports.DateRangePicker = DateRangePicker;
|
|
17791
|
+
exports.DateTimePicker = DateTimePicker;
|
|
16319
17792
|
exports.Dialog = Dialog;
|
|
17793
|
+
exports.DiffTable = DiffTable;
|
|
16320
17794
|
exports.Divider = Divider;
|
|
16321
17795
|
exports.DonutChart = DonutChart;
|
|
16322
17796
|
exports.Drawer = Drawer;
|
|
16323
17797
|
exports.EmptyState = EmptyState;
|
|
16324
17798
|
exports.Field = Field;
|
|
16325
17799
|
exports.FileUpload = FileUpload;
|
|
17800
|
+
exports.FilterBar = FilterBar;
|
|
16326
17801
|
exports.Form = Form;
|
|
16327
17802
|
exports.FunnelChart = FunnelChart;
|
|
16328
17803
|
exports.Gauge = Gauge;
|
|
@@ -16368,6 +17843,7 @@ exports.Tag = Tag;
|
|
|
16368
17843
|
exports.Text = Text;
|
|
16369
17844
|
exports.Textarea = Textarea;
|
|
16370
17845
|
exports.ThemeProvider = ThemeProvider;
|
|
17846
|
+
exports.TimePicker = TimePicker;
|
|
16371
17847
|
exports.Timeline = Timeline;
|
|
16372
17848
|
exports.Toast = Toast;
|
|
16373
17849
|
exports.ToastProvider = ToastProvider;
|