twico-ui 1.33.0 → 1.34.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 +20 -0
- package/dist/index.cjs +270 -164
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.mjs +270 -164
- package/dist/index.mjs.map +1 -1
- package/llms.txt +4 -0
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -7963,6 +7963,9 @@ var TOOLTIP_CSS = `
|
|
|
7963
7963
|
.twc-tooltip-wrap { display: inline-flex; }
|
|
7964
7964
|
.twc-tooltip {
|
|
7965
7965
|
position: fixed; z-index: var(--z-tooltip);
|
|
7966
|
+
/* #348: purely presentational \u2014 the bubble must NEVER intercept the pointer, so neither a hidden
|
|
7967
|
+
(opacity:0) nor a shown bubble can block neighbouring cells/buttons (matches MUI/Radix tooltips). */
|
|
7968
|
+
pointer-events: none;
|
|
7966
7969
|
padding: 6px 10px; border-radius: var(--radius-md);
|
|
7967
7970
|
background: var(--color-text); color: var(--color-surface);
|
|
7968
7971
|
font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--font-medium);
|
|
@@ -7974,7 +7977,6 @@ var TOOLTIP_CSS = `
|
|
|
7974
7977
|
width: max-content; max-width: var(--_tw-maxw, 320px); box-shadow: var(--shadow-md);
|
|
7975
7978
|
opacity: 0; transform: scale(0.9); transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-spring);
|
|
7976
7979
|
}
|
|
7977
|
-
.twc-tooltip[data-show="true"] { pointer-events: auto; }
|
|
7978
7980
|
.twc-tooltip[data-show="true"] { opacity: 1; transform: scale(1); }
|
|
7979
7981
|
.twc-tooltip[data-place="top"] { transform-origin: bottom center; translate: -50% 0; }
|
|
7980
7982
|
.twc-tooltip[data-place="bottom"] { transform-origin: top center; translate: -50% 0; }
|
|
@@ -8021,9 +8023,6 @@ function Tooltip({
|
|
|
8021
8023
|
clearTimeout(closeTimer.current);
|
|
8022
8024
|
closeTimer.current = setTimeout(() => setShowU(false), 120);
|
|
8023
8025
|
};
|
|
8024
|
-
const cancelClose = () => {
|
|
8025
|
-
clearTimeout(closeTimer.current);
|
|
8026
|
-
};
|
|
8027
8026
|
React51__namespace.default.useEffect(() => () => {
|
|
8028
8027
|
clearTimeout(timer.current);
|
|
8029
8028
|
clearTimeout(closeTimer.current);
|
|
@@ -8099,8 +8098,6 @@ function Tooltip({
|
|
|
8099
8098
|
"data-show": show || void 0,
|
|
8100
8099
|
role: "tooltip",
|
|
8101
8100
|
"aria-hidden": show ? void 0 : "true",
|
|
8102
|
-
onMouseEnter: anchored ? void 0 : cancelClose,
|
|
8103
|
-
onMouseLeave: anchored ? void 0 : close,
|
|
8104
8101
|
style: {
|
|
8105
8102
|
position: "fixed",
|
|
8106
8103
|
left: coords.left,
|
|
@@ -8386,6 +8383,16 @@ var DT_CSS = `
|
|
|
8386
8383
|
.twc-dt__group-sub span { font-variant-numeric: tabular-nums; }
|
|
8387
8384
|
.twc-dt__group-sub span b { color: var(--color-text); }
|
|
8388
8385
|
|
|
8386
|
+
/* #350: expandable row detail (renderRowDetail) \u2014 leading chevron column + full-width detail row */
|
|
8387
|
+
.twc-dt__expand-cell { text-align: center; padding-inline: 0; }
|
|
8388
|
+
.twc-dt__expand-btn { display: inline-grid; place-items: center; width: 24px; height: 24px; border: none; padding: 0; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-sm); }
|
|
8389
|
+
.twc-dt__expand-btn:hover { color: var(--color-text); background: color-mix(in srgb, currentColor 12%, transparent); }
|
|
8390
|
+
.twc-dt__expand-btn:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
8391
|
+
.twc-dt__expand-chev { display: inline-flex; transform: rotate(-90deg); transition: transform var(--duration-base) var(--ease-spring); }
|
|
8392
|
+
.twc-dt__expand-chev[data-open] { transform: rotate(0deg); color: var(--color-primary); }
|
|
8393
|
+
.twc-dt__expand-chev svg { width: 16px; height: 16px; }
|
|
8394
|
+
.twc-dt__detail-cell { box-sizing: border-box; background: var(--color-surface-sunken); border-bottom: var(--border-thin) solid var(--color-divider); padding: 12px 16px; }
|
|
8395
|
+
|
|
8389
8396
|
/* Pivot view */
|
|
8390
8397
|
.twc-dt__pivot { table-layout: auto; width: 100%; }
|
|
8391
8398
|
.twc-dt__pivot th, .twc-dt__pivot td { white-space: nowrap; }
|
|
@@ -9333,6 +9340,13 @@ function Datatable({
|
|
|
9333
9340
|
virtualized = false,
|
|
9334
9341
|
overscan = 8,
|
|
9335
9342
|
rowHeight,
|
|
9343
|
+
// #350 (first pass): expandable/collapsible rows. `renderRowDetail(row)` returns the detail panel for a
|
|
9344
|
+
// row (return null/undefined ⇒ that row isn't expandable). Presence of the fn enables a leading chevron
|
|
9345
|
+
// column + a full-width detail <tr> under each expanded row. Expansion is uncontrolled unless
|
|
9346
|
+
// `expandedRowIds` is supplied; `onExpandedRowsChange` fires the next expanded-key array on every toggle.
|
|
9347
|
+
renderRowDetail,
|
|
9348
|
+
expandedRowIds,
|
|
9349
|
+
onExpandedRowsChange,
|
|
9336
9350
|
className = "",
|
|
9337
9351
|
...rest
|
|
9338
9352
|
}) {
|
|
@@ -9539,6 +9553,12 @@ function Datatable({
|
|
|
9539
9553
|
const gridRef = React51__namespace.default.useRef(null);
|
|
9540
9554
|
const [groupBy, setGroupBy] = React51__namespace.default.useState(rowGrouping || []);
|
|
9541
9555
|
const [collapsed, setCollapsed] = React51__namespace.default.useState(() => /* @__PURE__ */ new Set());
|
|
9556
|
+
const [internalExpanded, setInternalExpanded] = React51__namespace.default.useState(() => /* @__PURE__ */ new Set());
|
|
9557
|
+
const expandControlled = expandedRowIds !== void 0;
|
|
9558
|
+
const expandedSet = React51__namespace.default.useMemo(
|
|
9559
|
+
() => new Set(expandControlled ? expandedRowIds : internalExpanded),
|
|
9560
|
+
[expandControlled, expandedRowIds, internalExpanded]
|
|
9561
|
+
);
|
|
9542
9562
|
const [pinnedRows, setPinnedRows] = React51__namespace.default.useState({ top: [], bottom: [] });
|
|
9543
9563
|
const [headH, setHeadH] = React51__namespace.default.useState(41);
|
|
9544
9564
|
const theadRef = React51__namespace.default.useRef(null);
|
|
@@ -9940,7 +9960,9 @@ function Datatable({
|
|
|
9940
9960
|
}, [pins, effectiveHidden, visibleCols, colByField, order]);
|
|
9941
9961
|
const NUM_W = 56;
|
|
9942
9962
|
const CHK_W = checkboxSelection ? rowReorder ? 68 : 44 : 0;
|
|
9943
|
-
const
|
|
9963
|
+
const hasRowDetail = typeof renderRowDetail === "function";
|
|
9964
|
+
const EXP_W = hasRowDetail ? 44 : 0;
|
|
9965
|
+
const numLeft = EXP_W + CHK_W;
|
|
9944
9966
|
const leadW = numLeft + (showRowNum ? NUM_W : 0);
|
|
9945
9967
|
const visLeft = React51__namespace.default.useMemo(() => pins.left.filter((f) => colByField[f] && !effectiveHidden.has(f)), [pins.left, colByField, effectiveHidden]);
|
|
9946
9968
|
const visRight = React51__namespace.default.useMemo(() => pins.right.filter((f) => colByField[f] && !effectiveHidden.has(f)), [pins.right, colByField, effectiveHidden]);
|
|
@@ -10535,6 +10557,12 @@ function Datatable({
|
|
|
10535
10557
|
return n;
|
|
10536
10558
|
});
|
|
10537
10559
|
}
|
|
10560
|
+
function toggleRowDetail(k) {
|
|
10561
|
+
const n = new Set(expandedSet);
|
|
10562
|
+
n.has(k) ? n.delete(k) : n.add(k);
|
|
10563
|
+
onExpandedRowsChange?.([...n]);
|
|
10564
|
+
if (!expandControlled) setInternalExpanded(n);
|
|
10565
|
+
}
|
|
10538
10566
|
function handleRowClick(e, k, row) {
|
|
10539
10567
|
if (selectionMode === "none") return;
|
|
10540
10568
|
if (e.target.closest("button, a, input, select, .twc-dt__check, .twc-dt__editor-wrap")) return;
|
|
@@ -11381,7 +11409,7 @@ function Datatable({
|
|
|
11381
11409
|
const manageableCols = cols.filter((c) => c.field !== "__pinactions__");
|
|
11382
11410
|
const visibleColCount = manageableCols.filter((c) => !effectiveHidden.has(c.field)).length;
|
|
11383
11411
|
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) }));
|
|
11384
|
-
const totalCols = ordered.length + (checkboxSelection ? 1 : 0) + (showRowNum ? 1 : 0);
|
|
11412
|
+
const totalCols = ordered.length + (checkboxSelection ? 1 : 0) + (showRowNum ? 1 : 0) + (hasRowDetail ? 1 : 0);
|
|
11385
11413
|
function renderGroupRow(item) {
|
|
11386
11414
|
const subs = aggOn ? subtotalText(item.rows) : [];
|
|
11387
11415
|
return /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "twc-dt__group-row", role: "row", children: /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "twc-dt__group-cell", role: "gridcell", colSpan: totalCols, style: { maxWidth: "none" }, children: [
|
|
@@ -11435,6 +11463,9 @@ function Datatable({
|
|
|
11435
11463
|
function renderLeaf(row, ri, pinSide, midIdx) {
|
|
11436
11464
|
const k = keyOf(row, ri);
|
|
11437
11465
|
const sel = selected.has(k);
|
|
11466
|
+
const detail = hasRowDetail && !pinSide ? renderRowDetail(row) : null;
|
|
11467
|
+
const expandable = detail != null;
|
|
11468
|
+
const open = expandable && expandedSet.has(k);
|
|
11438
11469
|
const rowActive = selectionMode === "row" && activeRowVal === k;
|
|
11439
11470
|
const stickyStyle = pinSide === "top" ? { position: "sticky", top: headH, zIndex: 5 } : pinSide === "bottom" ? { position: "sticky", bottom: 0, zIndex: 5 } : void 0;
|
|
11440
11471
|
const h = rowHeights[k];
|
|
@@ -11442,159 +11473,165 @@ function Datatable({
|
|
|
11442
11473
|
const reorderable = canReorderRows && !pinSide;
|
|
11443
11474
|
const grabbed = rowGrab && rowGrab.key === k;
|
|
11444
11475
|
const grabTarget = rowGrab && !grabbed && midIdx != null && rowGrab.index === midIdx ? rowGrab.index >= keyIndexMid.get(rowGrab.key) ? "after" : "before" : void 0;
|
|
11445
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11446
|
-
|
|
11447
|
-
|
|
11448
|
-
|
|
11449
|
-
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11485
|
-
/* @__PURE__ */ jsxRuntime.
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11476
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React51__namespace.default.Fragment, { children: [
|
|
11477
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11478
|
+
"tr",
|
|
11479
|
+
{
|
|
11480
|
+
className: "twc-dt__row",
|
|
11481
|
+
role: "row",
|
|
11482
|
+
"aria-rowindex": (paginated && !serverMode ? pageVal * sizeVal : 0) + ri + 2,
|
|
11483
|
+
"aria-selected": (checkboxSelection ? sel : rowActive) || void 0,
|
|
11484
|
+
"data-op": row.__diffop || void 0,
|
|
11485
|
+
"data-selected": sel || void 0,
|
|
11486
|
+
"data-active": rowActive || void 0,
|
|
11487
|
+
"data-pinned-row": pinSide || void 0,
|
|
11488
|
+
"data-reorderable": reorderable || void 0,
|
|
11489
|
+
"data-row-dragging": rowDrag.from === k || void 0,
|
|
11490
|
+
"data-row-grabbed": grabbed || void 0,
|
|
11491
|
+
"data-row-grabtarget": grabTarget,
|
|
11492
|
+
"data-row-dropbefore": reorderable && rowDrag.over === k && !rowDrag.after || void 0,
|
|
11493
|
+
"data-row-dropafter": reorderable && rowDrag.over === k && rowDrag.after || void 0,
|
|
11494
|
+
"data-vrow": virtualizing && midIdx != null ? String(k) : void 0,
|
|
11495
|
+
"data-selectable": selectionMode !== "none" || void 0,
|
|
11496
|
+
style: Object.keys(rowStyle).length ? rowStyle : void 0,
|
|
11497
|
+
draggable: reorderable || void 0,
|
|
11498
|
+
onDragStart: reorderable ? (e) => {
|
|
11499
|
+
setRowDrag({ from: k, over: null, after: false });
|
|
11500
|
+
e.dataTransfer.effectAllowed = "move";
|
|
11501
|
+
e.dataTransfer.setData("text/plain", String(k));
|
|
11502
|
+
} : void 0,
|
|
11503
|
+
onDragOver: reorderable && rowDrag.from != null ? (e) => {
|
|
11504
|
+
e.preventDefault();
|
|
11505
|
+
const r2 = e.currentTarget.getBoundingClientRect();
|
|
11506
|
+
const after = e.clientY > r2.top + r2.height / 2;
|
|
11507
|
+
setRowDrag((d) => d.over === k && d.after === after ? d : { ...d, over: k, after });
|
|
11508
|
+
} : void 0,
|
|
11509
|
+
onDrop: reorderable && rowDrag.from != null ? (e) => {
|
|
11510
|
+
e.preventDefault();
|
|
11511
|
+
onRowDrop(k);
|
|
11512
|
+
} : void 0,
|
|
11513
|
+
onDragEnd: reorderable ? () => setRowDrag({ from: null, over: null, after: false }) : void 0,
|
|
11514
|
+
onClick: (e) => handleRowClick(e, k, row),
|
|
11515
|
+
children: [
|
|
11516
|
+
hasRowDetail ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__expand-cell", role: "gridcell", "data-pin": "left", "data-pin-edge": checkboxSelection || showRowNum || visLeft.length ? void 0 : "left", style: { insetInlineStart: 0, width: EXP_W }, children: expandable ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dt__expand-btn", "aria-expanded": open, "aria-controls": open ? `${gridId}-detail-${ri}` : void 0, "aria-label": open ? "Collapse row" : "Expand row", onClick: (e) => {
|
|
11517
|
+
e.stopPropagation();
|
|
11518
|
+
toggleRowDetail(k);
|
|
11519
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__expand-chev", "data-open": open || void 0, children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.chevDown }) }) }) : null }) : null,
|
|
11520
|
+
checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "twc-dt__td", role: "gridcell", "data-pin": "left", "data-pin-edge": visLeft.length || showRowNum ? void 0 : "left", style: { insetInlineStart: EXP_W, width: CHK_W }, children: [
|
|
11521
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
|
|
11522
|
+
reorderable ? rowHandle(k, midIdx, row) : null,
|
|
11523
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11524
|
+
"span",
|
|
11525
|
+
{
|
|
11526
|
+
className: "twc-dt__check",
|
|
11527
|
+
"data-checked": sel || void 0,
|
|
11528
|
+
onClick: () => toggleRow(k),
|
|
11529
|
+
role: "checkbox",
|
|
11530
|
+
"aria-checked": sel,
|
|
11531
|
+
"aria-label": "Select row",
|
|
11532
|
+
tabIndex: 0,
|
|
11533
|
+
onKeyDown: (e) => {
|
|
11534
|
+
if (e.key === " " || e.key === "Enter") {
|
|
11535
|
+
e.preventDefault();
|
|
11536
|
+
toggleRow(k);
|
|
11537
|
+
}
|
|
11538
|
+
},
|
|
11539
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.check })
|
|
11540
|
+
}
|
|
11541
|
+
)
|
|
11542
|
+
] }),
|
|
11543
|
+
rowResize && !pinSide ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__row-resizer", title: "Drag to resize row", onPointerDown: (e) => startRowResize(e, k, e.currentTarget.closest("tr")), onClick: (e) => e.stopPropagation() }) : null
|
|
11544
|
+
] }) : null,
|
|
11545
|
+
showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", "data-pin-edge": visLeft.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W }, children: typeof ri === "number" ? (paginated || serverMode ? pageVal * sizeVal : 0) + ri + 1 : "" }) : null,
|
|
11546
|
+
ordered.map((c, ci) => {
|
|
11547
|
+
const st = stickyOf(c.field);
|
|
11548
|
+
const val = getColVal(c, row);
|
|
11549
|
+
const isActions = c.type === "actions";
|
|
11550
|
+
const editable = isColEditable(c);
|
|
11551
|
+
const isEditing = editing && editing.key === k && editing.field === c.field;
|
|
11552
|
+
const cellActive = selectionMode === "cell" && activeCell && activeCell.key === k && activeCell.field === c.field;
|
|
11553
|
+
const cellSelected = selectionMode === "cell" && cellRect && ri >= cellRect.r0 && ri <= cellRect.r1 && ci >= cellRect.c0 && ci <= cellRect.c1;
|
|
11554
|
+
const cellFlash = clipFx && clipFx.rect && ri >= clipFx.rect.r0 && ri <= clipFx.rect.r1 && ci >= clipFx.rect.c0 && ci <= clipFx.rect.c1;
|
|
11555
|
+
const cellId = selectionMode === "cell" ? `${gridId}-${ri}-${ci}` : void 0;
|
|
11556
|
+
const display = c.valueFormatter ? c.valueFormatter(val, row) : val;
|
|
11557
|
+
const cellTitle = !isActions && !c.renderCell && !isEditing && (typeof display === "string" || typeof display === "number") ? String(display) : void 0;
|
|
11558
|
+
const cellClass = c.cellClassName ? c.cellClassName(val, row) : void 0;
|
|
11559
|
+
const cellSty = c.cellStyle ? c.cellStyle(val, row) : void 0;
|
|
11560
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11561
|
+
"td",
|
|
11489
11562
|
{
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
"
|
|
11495
|
-
"aria-
|
|
11496
|
-
tabIndex: 0,
|
|
11497
|
-
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
|
|
11516
|
-
|
|
11517
|
-
|
|
11518
|
-
|
|
11519
|
-
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11530
|
-
|
|
11531
|
-
|
|
11532
|
-
|
|
11533
|
-
|
|
11534
|
-
|
|
11535
|
-
|
|
11536
|
-
|
|
11537
|
-
|
|
11538
|
-
|
|
11539
|
-
|
|
11540
|
-
"data-cell-selected": cellSelected || void 0,
|
|
11541
|
-
"data-copied": cellFlash || void 0,
|
|
11542
|
-
"data-wrap": effectiveWrapped.has(c.field) || void 0,
|
|
11543
|
-
"data-pin": st.pin,
|
|
11544
|
-
"data-pin-edge": st.edge,
|
|
11545
|
-
style: { width: widthOf(c), ...cellSty, ...st.style, ...st.pin ? { position: "sticky", zIndex: 2 } : null },
|
|
11546
|
-
"data-ovtext": cellTitle,
|
|
11547
|
-
onClick: selectionMode === "cell" ? (e) => handleCellClick(e, k, row, c) : void 0,
|
|
11548
|
-
onFocus: () => setFocus((f) => f.r === ri && f.c === ci ? f : { r: ri, c: ci }),
|
|
11549
|
-
onDoubleClick: editable ? () => beginEdit(k, c, row) : void 0,
|
|
11550
|
-
children: [
|
|
11551
|
-
!checkboxSelection && reorderable && ci === 0 && !isEditing ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, maxWidth: "100%" }, children: [
|
|
11552
|
-
rowHandle(k, midIdx, row),
|
|
11553
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: isActions ? renderActions(c, row) : c.renderCell ? c.renderCell(val, row) : display })
|
|
11554
|
-
] }) : isEditing ? c.renderEditCell ? (
|
|
11555
|
-
// #236: full escape hatch — the host drops in its own editor (searchable/creatable/
|
|
11556
|
-
// async Combobox, …) and drives the lifecycle via commit/cancel. Wrapped in
|
|
11557
|
-
// .twc-dt__editor-wrap so inline clicks (and any .twc-pop portal dropdown) don't
|
|
11558
|
-
// trip the outside-click auto-cancel.
|
|
11559
|
-
// #273: the wrapper handles Escape → cancel so it works for every custom editor without
|
|
11560
|
-
// each having to wire a keydown (they only get commit/cancel). A custom control that
|
|
11561
|
-
// wants Escape itself (e.g. to close its own open dropdown) stops propagation first.
|
|
11562
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11563
|
-
"div",
|
|
11563
|
+
id: cellId,
|
|
11564
|
+
className: cellClass ? `twc-dt__td ${cellClass}` : "twc-dt__td",
|
|
11565
|
+
role: "gridcell",
|
|
11566
|
+
"data-r": ri,
|
|
11567
|
+
"data-c": ci,
|
|
11568
|
+
"aria-colindex": ci + 1 + (checkboxSelection ? 1 : 0) + (hasRowDetail ? 1 : 0),
|
|
11569
|
+
tabIndex: focus.r === ri && focus.c === ci ? 0 : -1,
|
|
11570
|
+
"aria-selected": cellSelected || void 0,
|
|
11571
|
+
"data-num": c.type === "number" || void 0,
|
|
11572
|
+
"data-actions": isActions || void 0,
|
|
11573
|
+
"data-editable": editable && !isEditing || void 0,
|
|
11574
|
+
"data-editing": isEditing || void 0,
|
|
11575
|
+
"data-cell-active": cellActive || void 0,
|
|
11576
|
+
"data-cell-selected": cellSelected || void 0,
|
|
11577
|
+
"data-copied": cellFlash || void 0,
|
|
11578
|
+
"data-wrap": effectiveWrapped.has(c.field) || void 0,
|
|
11579
|
+
"data-pin": st.pin,
|
|
11580
|
+
"data-pin-edge": st.edge,
|
|
11581
|
+
style: { width: widthOf(c), ...cellSty, ...st.style, ...st.pin ? { position: "sticky", zIndex: 2 } : null },
|
|
11582
|
+
"data-ovtext": cellTitle,
|
|
11583
|
+
onClick: selectionMode === "cell" ? (e) => handleCellClick(e, k, row, c) : void 0,
|
|
11584
|
+
onFocus: () => setFocus((f) => f.r === ri && f.c === ci ? f : { r: ri, c: ci }),
|
|
11585
|
+
onDoubleClick: editable ? () => beginEdit(k, c, row) : void 0,
|
|
11586
|
+
children: [
|
|
11587
|
+
!checkboxSelection && reorderable && ci === 0 && !isEditing ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, maxWidth: "100%" }, children: [
|
|
11588
|
+
rowHandle(k, midIdx, row),
|
|
11589
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: isActions ? renderActions(c, row) : c.renderCell ? c.renderCell(val, row) : display })
|
|
11590
|
+
] }) : isEditing ? c.renderEditCell ? (
|
|
11591
|
+
// #236: full escape hatch — the host drops in its own editor (searchable/creatable/
|
|
11592
|
+
// async Combobox, …) and drives the lifecycle via commit/cancel. Wrapped in
|
|
11593
|
+
// .twc-dt__editor-wrap so inline clicks (and any .twc-pop portal dropdown) don't
|
|
11594
|
+
// trip the outside-click auto-cancel.
|
|
11595
|
+
// #273: the wrapper handles Escape → cancel so it works for every custom editor without
|
|
11596
|
+
// each having to wire a keydown (they only get commit/cancel). A custom control that
|
|
11597
|
+
// wants Escape itself (e.g. to close its own open dropdown) stops propagation first.
|
|
11598
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11599
|
+
"div",
|
|
11600
|
+
{
|
|
11601
|
+
className: "twc-dt__editor-wrap",
|
|
11602
|
+
onKeyDown: (e) => {
|
|
11603
|
+
if (e.key === "Escape") {
|
|
11604
|
+
e.stopPropagation();
|
|
11605
|
+
cancelEdit();
|
|
11606
|
+
}
|
|
11607
|
+
},
|
|
11608
|
+
children: c.renderEditCell({ value: editing.value, row, field: c.field, commit: (v) => commitEdit(v), cancel: cancelEdit })
|
|
11609
|
+
}
|
|
11610
|
+
)
|
|
11611
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
11612
|
+
EditCell,
|
|
11564
11613
|
{
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
|
|
11568
|
-
|
|
11569
|
-
|
|
11570
|
-
|
|
11571
|
-
|
|
11572
|
-
|
|
11614
|
+
col: c,
|
|
11615
|
+
value: editing.value,
|
|
11616
|
+
options: c.valueOptions ? optionsForField(c.field) : null,
|
|
11617
|
+
onChange: (v) => setEditing((e) => ({ ...e, value: v })),
|
|
11618
|
+
onCommit: () => commitEdit(),
|
|
11619
|
+
onCommitValue: (v) => commitEdit(v),
|
|
11620
|
+
onCancel: cancelEdit,
|
|
11621
|
+
onKeyDown: onEditKey
|
|
11573
11622
|
}
|
|
11574
|
-
)
|
|
11575
|
-
|
|
11576
|
-
|
|
11577
|
-
|
|
11578
|
-
|
|
11579
|
-
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
}
|
|
11587
|
-
) : isActions ? renderActions(c, row) : c.renderCell ? c.renderCell(val, row) : display,
|
|
11588
|
-
editable && !isEditing ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__edit-hint", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.pencil }) }) : null
|
|
11589
|
-
]
|
|
11590
|
-
},
|
|
11591
|
-
c.field
|
|
11592
|
-
);
|
|
11593
|
-
})
|
|
11594
|
-
]
|
|
11595
|
-
},
|
|
11596
|
-
(pinSide ? "p-" : "") + k
|
|
11597
|
-
);
|
|
11623
|
+
) : isActions ? renderActions(c, row) : c.renderCell ? c.renderCell(val, row) : display,
|
|
11624
|
+
editable && !isEditing ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__edit-hint", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.pencil }) }) : null
|
|
11625
|
+
]
|
|
11626
|
+
},
|
|
11627
|
+
c.field
|
|
11628
|
+
);
|
|
11629
|
+
})
|
|
11630
|
+
]
|
|
11631
|
+
}
|
|
11632
|
+
),
|
|
11633
|
+
open ? /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "twc-dt__detail-row", role: "row", children: /* @__PURE__ */ jsxRuntime.jsx("td", { id: `${gridId}-detail-${ri}`, className: "twc-dt__detail-cell", role: "gridcell", colSpan: totalCols, style: { maxWidth: "none" }, children: detail }) }) : null
|
|
11634
|
+
] }, (pinSide ? "p-" : "") + k);
|
|
11598
11635
|
}
|
|
11599
11636
|
function renderPivot() {
|
|
11600
11637
|
const rFields = pivotConfig.rows, cFields = pivotConfig.columns || [], values = pivotConfig.values;
|
|
@@ -11931,14 +11968,15 @@ function Datatable({
|
|
|
11931
11968
|
role: "grid",
|
|
11932
11969
|
"aria-label": ariaLabelAttr || ariaLabel,
|
|
11933
11970
|
"aria-rowcount": totalRows + 1,
|
|
11934
|
-
"aria-colcount": ordered.length + (checkboxSelection ? 1 : 0),
|
|
11971
|
+
"aria-colcount": ordered.length + (checkboxSelection ? 1 : 0) + (hasRowDetail ? 1 : 0),
|
|
11935
11972
|
"aria-multiselectable": selectionMode === "cell" || void 0,
|
|
11936
11973
|
"aria-activedescendant": activeCellId,
|
|
11937
11974
|
"aria-busy": loading || void 0,
|
|
11938
11975
|
onKeyDown: onGridKeyDown,
|
|
11939
11976
|
children: [
|
|
11940
11977
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { ref: theadRef, children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", "aria-rowindex": 1, children: [
|
|
11941
|
-
|
|
11978
|
+
hasRowDetail ? /* @__PURE__ */ jsxRuntime.jsx("th", { className: "twc-dt__th twc-dt__expand-cell", role: "columnheader", "aria-label": "Expand", "data-pin": "left", "data-pin-edge": checkboxSelection || showRowNum || visLeft.length ? void 0 : "left", style: { insetInlineStart: 0, width: EXP_W, minWidth: EXP_W } }) : null,
|
|
11979
|
+
checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("th", { className: "twc-dt__th", role: "columnheader", "aria-label": "Select", "data-pin": "left", "data-pin-edge": visLeft.length || showRowNum ? void 0 : "left", style: { insetInlineStart: EXP_W, width: CHK_W, minWidth: CHK_W }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__th-inner", style: { justifyContent: "center", padding: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11942
11980
|
"span",
|
|
11943
11981
|
{
|
|
11944
11982
|
className: "twc-dt__check",
|
|
@@ -12114,7 +12152,8 @@ function Datatable({
|
|
|
12114
12152
|
})
|
|
12115
12153
|
] }) }),
|
|
12116
12154
|
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? Array.from({ length: paginated ? Math.min(sizeVal, 8) : 8 }).map((_, ri) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "twc-dt__row", role: "row", children: [
|
|
12117
|
-
|
|
12155
|
+
hasRowDetail ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__expand-cell", role: "gridcell", "data-pin": "left", style: { insetInlineStart: 0, width: EXP_W } }) : null,
|
|
12156
|
+
checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", "data-pin": "left", style: { insetInlineStart: EXP_W, width: CHK_W }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "18px", height: 18, borderRadius: 4 } }) }) : null,
|
|
12118
12157
|
showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", style: { insetInlineStart: numLeft, width: NUM_W }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "16px", height: 14, borderRadius: 4 } }) }) : null,
|
|
12119
12158
|
ordered.map((c, ci) => {
|
|
12120
12159
|
const st = stickyOf(c.field);
|
|
@@ -12136,7 +12175,8 @@ function Datatable({
|
|
|
12136
12175
|
pinnedBottomRows.map((row) => renderLeaf(row, keyIndex.get(keyOf(row)), "bottom"))
|
|
12137
12176
|
] }) }),
|
|
12138
12177
|
hasAggregation && aggOn && !loading && paged.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("tfoot", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", children: [
|
|
12139
|
-
|
|
12178
|
+
hasRowDetail ? /* @__PURE__ */ jsxRuntime.jsx("td", { role: "gridcell", "data-pin": "left", "data-pin-edge": checkboxSelection || showRowNum || visLeft.length ? void 0 : "left", style: { insetInlineStart: 0, width: EXP_W } }) : null,
|
|
12179
|
+
checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { role: "gridcell", "data-pin": "left", "data-pin-edge": visLeft.length || showRowNum ? void 0 : "left", style: { insetInlineStart: EXP_W, width: CHK_W } }) : null,
|
|
12140
12180
|
showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", "data-pin-edge": visLeft.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W } }) : null,
|
|
12141
12181
|
ordered.map((c) => {
|
|
12142
12182
|
const st = stickyOf(c.field);
|
|
@@ -17171,6 +17211,18 @@ var SLIDER_CSS = `
|
|
|
17171
17211
|
transition: opacity var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-spring);
|
|
17172
17212
|
}
|
|
17173
17213
|
.twc-slider__track[data-show-bubble="true"] .twc-slider__bubble { opacity: 1; transform: translateX(-50%) scale(1); }
|
|
17214
|
+
/* #351: editable numeric inputs (manual entry, synced with the thumbs) */
|
|
17215
|
+
.twc-slider__inputs { display: inline-flex; align-items: center; gap: var(--space-1-5); }
|
|
17216
|
+
.twc-slider__input-sep { color: var(--color-text-muted); font-weight: var(--font-semibold); }
|
|
17217
|
+
.twc-slider__input {
|
|
17218
|
+
min-width: 0; text-align: end; font-family: inherit; font-size: var(--text-sm); font-weight: var(--font-semibold);
|
|
17219
|
+
color: var(--_accent); font-variant-numeric: tabular-nums;
|
|
17220
|
+
padding: 2px 6px; border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface);
|
|
17221
|
+
transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
|
|
17222
|
+
}
|
|
17223
|
+
.twc-slider__input:hover:not(:disabled) { border-color: var(--color-border-strong); }
|
|
17224
|
+
.twc-slider__input:focus-visible { outline: none; border-color: var(--_accent); box-shadow: var(--ring); }
|
|
17225
|
+
.twc-slider[data-disabled="true"] .twc-slider__input { cursor: not-allowed; }
|
|
17174
17226
|
`;
|
|
17175
17227
|
function Slider({
|
|
17176
17228
|
label,
|
|
@@ -17189,6 +17241,7 @@ function Slider({
|
|
|
17189
17241
|
range: range2 = false,
|
|
17190
17242
|
showValue = true,
|
|
17191
17243
|
showTicks = false,
|
|
17244
|
+
editable = false,
|
|
17192
17245
|
formatValue,
|
|
17193
17246
|
getAriaValueText,
|
|
17194
17247
|
name,
|
|
@@ -17227,6 +17280,7 @@ function Slider({
|
|
|
17227
17280
|
const indices = isRange ? [0, 1] : [0];
|
|
17228
17281
|
const trackRef = React51__namespace.default.useRef(null);
|
|
17229
17282
|
const [dragging, setDragging] = React51__namespace.default.useState(false);
|
|
17283
|
+
const [typed, setTyped] = React51__namespace.default.useState({});
|
|
17230
17284
|
const fmt = (v) => formatValue ? formatValue(v) : v.toFixed(decimals);
|
|
17231
17285
|
const valueTextFor = (v) => {
|
|
17232
17286
|
if (getAriaValueText) return getAriaValueText(v);
|
|
@@ -17250,6 +17304,27 @@ function Slider({
|
|
|
17250
17304
|
}
|
|
17251
17305
|
commit(next);
|
|
17252
17306
|
};
|
|
17307
|
+
const commitInput = (i) => {
|
|
17308
|
+
const s = typed[i];
|
|
17309
|
+
setTyped((t) => {
|
|
17310
|
+
const n = { ...t };
|
|
17311
|
+
delete n[i];
|
|
17312
|
+
return n;
|
|
17313
|
+
});
|
|
17314
|
+
if (s == null || String(s).trim() === "") return;
|
|
17315
|
+
const num = parseFloat(s);
|
|
17316
|
+
if (Number.isFinite(num)) setThumb(i, num);
|
|
17317
|
+
};
|
|
17318
|
+
const stepInput = (i, dir) => {
|
|
17319
|
+
const base = typed[i] != null && Number.isFinite(parseFloat(typed[i])) ? parseFloat(typed[i]) : clampedVals[i];
|
|
17320
|
+
setTyped((t) => {
|
|
17321
|
+
const n = { ...t };
|
|
17322
|
+
delete n[i];
|
|
17323
|
+
return n;
|
|
17324
|
+
});
|
|
17325
|
+
setThumb(i, base + dir * step);
|
|
17326
|
+
};
|
|
17327
|
+
const inputSize = Math.max(String(min).length, String(max).length, decimals > 0 ? decimals + 2 : 1) + 1;
|
|
17253
17328
|
const fromClientX = (clientX) => {
|
|
17254
17329
|
const node = trackRef.current;
|
|
17255
17330
|
if (!node) return clampedVals[0];
|
|
@@ -17305,9 +17380,40 @@ function Slider({
|
|
|
17305
17380
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-slider ${className}`, "data-tone": tone, "data-size": size, "data-disabled": disabled || void 0, ...rest, children: [
|
|
17306
17381
|
__twcStyles,
|
|
17307
17382
|
name ? clampedVals.map((v, i) => /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: v, disabled: disabled || void 0 }, i)) : null,
|
|
17308
|
-
label || showValue ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-slider__head", children: [
|
|
17383
|
+
label || showValue || editable ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-slider__head", children: [
|
|
17309
17384
|
label ? /* @__PURE__ */ jsxRuntime.jsx("label", { className: "twc-slider__label", id: labelId, children: label }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
|
|
17310
|
-
|
|
17385
|
+
editable ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-slider__inputs", children: indices.map((i) => /* @__PURE__ */ jsxRuntime.jsxs(React51__namespace.default.Fragment, { children: [
|
|
17386
|
+
i > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-slider__input-sep", "aria-hidden": "true", children: "\u2013" }) : null,
|
|
17387
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17388
|
+
"input",
|
|
17389
|
+
{
|
|
17390
|
+
className: "twc-slider__input",
|
|
17391
|
+
type: "text",
|
|
17392
|
+
inputMode: min < 0 ? "text" : "decimal",
|
|
17393
|
+
size: inputSize,
|
|
17394
|
+
value: typed[i] != null ? typed[i] : String(clampedVals[i]),
|
|
17395
|
+
disabled: disabled || void 0,
|
|
17396
|
+
"aria-labelledby": isRange ? void 0 : labelId,
|
|
17397
|
+
"aria-label": isRange ? i === 0 ? "Minimum value" : "Maximum value" : labelId ? void 0 : "Value",
|
|
17398
|
+
onChange: (e) => setTyped((t) => ({ ...t, [i]: e.target.value })),
|
|
17399
|
+
onBlur: () => commitInput(i),
|
|
17400
|
+
onKeyDown: (e) => {
|
|
17401
|
+
if (e.key === "Enter") {
|
|
17402
|
+
if (typed[i] != null) {
|
|
17403
|
+
e.preventDefault();
|
|
17404
|
+
commitInput(i);
|
|
17405
|
+
}
|
|
17406
|
+
} else if (e.key === "ArrowUp") {
|
|
17407
|
+
e.preventDefault();
|
|
17408
|
+
stepInput(i, 1);
|
|
17409
|
+
} else if (e.key === "ArrowDown") {
|
|
17410
|
+
e.preventDefault();
|
|
17411
|
+
stepInput(i, -1);
|
|
17412
|
+
}
|
|
17413
|
+
}
|
|
17414
|
+
}
|
|
17415
|
+
)
|
|
17416
|
+
] }, i)) }) : showValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-slider__value", children: headValue }) : null
|
|
17311
17417
|
] }) : null,
|
|
17312
17418
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-slider__track", ref: trackRef, "data-show-bubble": dragging || void 0, onPointerDown, children: [
|
|
17313
17419
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-slider__rail" }),
|