twico-ui 1.18.1 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -7896,11 +7896,15 @@ function Tooltip({
7896
7896
  placement = "top",
7897
7897
  delay = 120,
7898
7898
  className = "",
7899
+ open: openProp,
7900
+ anchor,
7899
7901
  ...rest
7900
7902
  }) {
7901
7903
  const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
7904
+ const anchored = anchor !== void 0;
7902
7905
  const id = React51__namespace.default.useId();
7903
- const [show, setShow] = React51__namespace.default.useState(false);
7906
+ const [showU, setShowU] = React51__namespace.default.useState(false);
7907
+ const show = anchored ? !!openProp : showU;
7904
7908
  const [coords, setCoords] = React51__namespace.default.useState(null);
7905
7909
  const timer = React51__namespace.default.useRef(null);
7906
7910
  const closeTimer = React51__namespace.default.useRef(null);
@@ -7909,12 +7913,12 @@ function Tooltip({
7909
7913
  const open = () => {
7910
7914
  clearTimeout(closeTimer.current);
7911
7915
  clearTimeout(timer.current);
7912
- timer.current = setTimeout(() => setShow(true), delay);
7916
+ timer.current = setTimeout(() => setShowU(true), delay);
7913
7917
  };
7914
7918
  const close = () => {
7915
7919
  clearTimeout(timer.current);
7916
7920
  clearTimeout(closeTimer.current);
7917
- closeTimer.current = setTimeout(() => setShow(false), 120);
7921
+ closeTimer.current = setTimeout(() => setShowU(false), 120);
7918
7922
  };
7919
7923
  const cancelClose = () => {
7920
7924
  clearTimeout(closeTimer.current);
@@ -7924,8 +7928,8 @@ function Tooltip({
7924
7928
  clearTimeout(closeTimer.current);
7925
7929
  }, []);
7926
7930
  const place = React51__namespace.default.useCallback(() => {
7927
- const el = wrapRef.current;
7928
- if (!el) return;
7931
+ const el = anchored ? anchor : wrapRef.current;
7932
+ if (!el || !el.getBoundingClientRect) return;
7929
7933
  const r2 = el.getBoundingClientRect();
7930
7934
  const cx = Math.round(r2.left + r2.width / 2), cy = Math.round(r2.top + r2.height / 2);
7931
7935
  const vw = window.innerWidth, vh = window.innerHeight, gap = 8, margin = 8;
@@ -7957,7 +7961,7 @@ function Tooltip({
7957
7961
  const c = clampX(cx);
7958
7962
  setCoords({ ...base, left: c, bottom: Math.round(vh - r2.top + gap), arrowX: arrowX(c) });
7959
7963
  }
7960
- }, [placement]);
7964
+ }, [placement, anchored, anchor]);
7961
7965
  React51__namespace.default.useEffect(() => {
7962
7966
  place();
7963
7967
  }, [place]);
@@ -7973,16 +7977,50 @@ function Tooltip({
7973
7977
  };
7974
7978
  }, [show, place]);
7975
7979
  React51__namespace.default.useEffect(() => {
7976
- if (!show) return;
7980
+ if (!show || anchored) return;
7977
7981
  const onKeyDown = (e) => {
7978
7982
  if (e.key === "Escape") {
7979
7983
  clearTimeout(timer.current);
7980
- setShow(false);
7984
+ setShowU(false);
7981
7985
  }
7982
7986
  };
7983
7987
  document.addEventListener("keydown", onKeyDown);
7984
7988
  return () => document.removeEventListener("keydown", onKeyDown);
7985
- }, [show]);
7989
+ }, [show, anchored]);
7990
+ const bubble = coords && (!anchored || anchor) ? reactDom.createPortal(
7991
+ /* @__PURE__ */ jsxRuntime.jsxs(
7992
+ "span",
7993
+ {
7994
+ ref: tipRef,
7995
+ id,
7996
+ className: "twc-tooltip",
7997
+ "data-place": coords.place || placement,
7998
+ "data-show": show || void 0,
7999
+ role: "tooltip",
8000
+ "aria-hidden": show ? void 0 : "true",
8001
+ onMouseEnter: anchored ? void 0 : cancelClose,
8002
+ onMouseLeave: anchored ? void 0 : close,
8003
+ style: {
8004
+ position: "fixed",
8005
+ left: coords.left,
8006
+ right: coords.right,
8007
+ top: coords.top,
8008
+ bottom: coords.bottom,
8009
+ "--_tw-arrow-x": coords.arrowX != null ? `${coords.arrowX}px` : void 0,
8010
+ "--_tw-arrow-y": coords.arrowY != null ? `${coords.arrowY}px` : void 0
8011
+ },
8012
+ children: [
8013
+ label,
8014
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
8015
+ ]
8016
+ }
8017
+ ),
8018
+ document.body
8019
+ ) : null;
8020
+ if (anchored) return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8021
+ __twcStyles,
8022
+ bubble
8023
+ ] });
7986
8024
  const describedBy = show ? id : void 0;
7987
8025
  const trigger = React51__namespace.default.isValidElement(children) && children.type !== React51__namespace.default.Fragment ? React51__namespace.default.cloneElement(children, {
7988
8026
  "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
@@ -8000,36 +8038,7 @@ function Tooltip({
8000
8038
  children: [
8001
8039
  __twcStyles,
8002
8040
  trigger,
8003
- coords ? reactDom.createPortal(
8004
- /* @__PURE__ */ jsxRuntime.jsxs(
8005
- "span",
8006
- {
8007
- ref: tipRef,
8008
- id,
8009
- className: "twc-tooltip",
8010
- "data-place": coords.place || placement,
8011
- "data-show": show || void 0,
8012
- role: "tooltip",
8013
- "aria-hidden": show ? void 0 : "true",
8014
- onMouseEnter: cancelClose,
8015
- onMouseLeave: close,
8016
- style: {
8017
- position: "fixed",
8018
- left: coords.left,
8019
- right: coords.right,
8020
- top: coords.top,
8021
- bottom: coords.bottom,
8022
- "--_tw-arrow-x": coords.arrowX != null ? `${coords.arrowX}px` : void 0,
8023
- "--_tw-arrow-y": coords.arrowY != null ? `${coords.arrowY}px` : void 0
8024
- },
8025
- children: [
8026
- label,
8027
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
8028
- ]
8029
- }
8030
- ),
8031
- document.body
8032
- ) : null
8041
+ bubble
8033
8042
  ]
8034
8043
  }
8035
8044
  );
@@ -8346,8 +8355,8 @@ var DT_CSS = `
8346
8355
  .twc-dt__row[data-pinned-row="top"] > .twc-dt__td { border-bottom: var(--border-medium) solid var(--color-primary-border); box-shadow: 0 1px 0 var(--color-primary-border); }
8347
8356
  .twc-dt__row[data-pinned-row="bottom"] > .twc-dt__td { border-top: var(--border-medium) solid var(--color-primary-border); }
8348
8357
 
8349
- /* Row reordering */
8350
- .twc-dt__row[data-reorderable] { cursor: grab; }
8358
+ /* Row reordering \u2014 the grab affordance lives on the drag handle only (#263), not the whole row, so
8359
+ hovering a normal data cell isn't presented as draggable (the row stays a drag source for the mouse). */
8351
8360
  .twc-dt__row[data-row-dragging] { opacity: 0.4; }
8352
8361
  /* #239 diff mode: row op tint + before\u2192after cells (single-line, clipped by the td's own overflow). */
8353
8362
  .twc-dt__row[data-op="added"] > .twc-dt__td { background: color-mix(in srgb, var(--color-success) 7%, transparent); }
@@ -8378,6 +8387,7 @@ var DT_CSS = `
8378
8387
  .twc-dt__row:hover .twc-dt__row-handle, .twc-dt__row-handle:focus-visible { opacity: 0.7; }
8379
8388
  .twc-dt__row-handle:focus-visible { outline: none; box-shadow: var(--ring); color: var(--color-primary); }
8380
8389
  .twc-dt__row-handle[data-grabbed="true"] { opacity: 1; color: var(--color-primary); }
8390
+ .twc-dt__row-handle:active, .twc-dt__row-handle[data-grabbed="true"] { cursor: grabbing; }
8381
8391
  .twc-dt__row-handle svg { width: 14px; height: 14px; }
8382
8392
  /* Visually-hidden aria-live region for reorder announcements */
8383
8393
  .twc-dt__sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@@ -9263,6 +9273,40 @@ function Datatable({
9263
9273
  const scrollRef = React51__namespace.default.useRef(null);
9264
9274
  const [scrollTop, setScrollTop] = React51__namespace.default.useState(0);
9265
9275
  const [viewportH, setViewportH] = React51__namespace.default.useState(0);
9276
+ const [ovTip, setOvTip] = React51__namespace.default.useState(null);
9277
+ const ovTimer = React51__namespace.default.useRef(null);
9278
+ const hideOverflowTip = () => {
9279
+ clearTimeout(ovTimer.current);
9280
+ setOvTip((t) => t ? null : t);
9281
+ };
9282
+ const onOverflowOver = (e) => {
9283
+ const el = e.target.closest?.("[data-ovtext]");
9284
+ if (!el) return;
9285
+ if (ovTip && ovTip.anchor === el) return;
9286
+ clearTimeout(ovTimer.current);
9287
+ if (el.scrollWidth > el.clientWidth + 1) {
9288
+ const text = el.getAttribute("data-ovtext");
9289
+ ovTimer.current = setTimeout(() => setOvTip({ anchor: el, text }), 120);
9290
+ } else if (ovTip) setOvTip(null);
9291
+ };
9292
+ const onOverflowOut = (e) => {
9293
+ const el = e.target.closest?.("[data-ovtext]");
9294
+ if (el && !el.contains(e.relatedTarget)) hideOverflowTip();
9295
+ };
9296
+ const onOverflowFocus = (e) => {
9297
+ const el = e.target.closest?.("[data-ovtext]");
9298
+ if (el && el.scrollWidth > el.clientWidth + 1) setOvTip({ anchor: el, text: el.getAttribute("data-ovtext") });
9299
+ else hideOverflowTip();
9300
+ };
9301
+ React51__namespace.default.useEffect(() => () => clearTimeout(ovTimer.current), []);
9302
+ React51__namespace.default.useEffect(() => {
9303
+ if (!ovTip) return void 0;
9304
+ const onKey = (e) => {
9305
+ if (e.key === "Escape") setOvTip(null);
9306
+ };
9307
+ document.addEventListener("keydown", onKey);
9308
+ return () => document.removeEventListener("keydown", onKey);
9309
+ }, [ovTip]);
9266
9310
  const [pivotOn, setPivotOn] = React51__namespace.default.useState(pivotMode);
9267
9311
  const [aggConfig, setAggConfig] = React51__namespace.default.useState(() => {
9268
9312
  const m = {};
@@ -10428,7 +10472,7 @@ function Datatable({
10428
10472
  "data-pin": st.pin,
10429
10473
  "data-pin-edge": st.edge,
10430
10474
  style: { width: widthOf(c), ...st.style },
10431
- title: cellTitle,
10475
+ "data-ovtext": cellTitle,
10432
10476
  onClick: selectionMode === "cell" ? (e) => handleCellClick(e, k, row, c) : void 0,
10433
10477
  onFocus: () => setFocus((f) => f.r === ri && f.c === ci ? f : { r: ri, c: ci }),
10434
10478
  onDoubleClick: editable ? () => beginEdit(k, c, row) : void 0,
@@ -10769,233 +10813,247 @@ function Datatable({
10769
10813
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dt__groupbar-clear", onClick: () => setGroupBy([]), children: "Clear all" })
10770
10814
  ] }) : null,
10771
10815
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__sr", role: "status", "aria-live": "polite", children: reorderMsg }),
10772
- pivotActive ? renderPivot() : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__scroll", style: { maxHeight: height }, ref: scrollRef, onScroll: virtualizing ? onScrollVirtual : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
10773
- "table",
10816
+ pivotActive ? renderPivot() : /* @__PURE__ */ jsxRuntime.jsx(
10817
+ "div",
10774
10818
  {
10775
- className: "twc-dt__table",
10776
- style: { width: tableMinWidth, minWidth: "100%" },
10777
- ref: gridRef,
10778
- role: "grid",
10779
- "aria-label": ariaLabelAttr || ariaLabel,
10780
- "aria-rowcount": totalRows + 1,
10781
- "aria-colcount": ordered.length + (checkboxSelection ? 1 : 0),
10782
- "aria-busy": loading || void 0,
10783
- onKeyDown: onGridKeyDown,
10784
- children: [
10785
- /* @__PURE__ */ jsxRuntime.jsx("thead", { ref: theadRef, children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", "aria-rowindex": 1, children: [
10786
- checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("th", { className: "twc-dt__th", role: "columnheader", "aria-label": "Select", "data-pin": "left", "data-pin-edge": pins.left.length || showRowNum ? void 0 : "left", style: { insetInlineStart: 0, 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(
10787
- "span",
10788
- {
10789
- className: "twc-dt__check",
10790
- "data-checked": allSel || void 0,
10791
- "data-indeterminate": !allSel && someSel || void 0,
10792
- onClick: toggleAll,
10793
- role: "checkbox",
10794
- "aria-checked": allSel ? true : someSel ? "mixed" : false,
10795
- "aria-label": "Select all rows",
10796
- tabIndex: 0,
10797
- onKeyDown: (e) => {
10798
- if (e.key === " " || e.key === "Enter") {
10799
- e.preventDefault();
10800
- toggleAll();
10819
+ className: "twc-dt__scroll",
10820
+ style: { maxHeight: height },
10821
+ ref: scrollRef,
10822
+ onScroll: virtualizing ? onScrollVirtual : void 0,
10823
+ onMouseOver: onOverflowOver,
10824
+ onMouseOut: onOverflowOut,
10825
+ onFocus: onOverflowFocus,
10826
+ onBlur: hideOverflowTip,
10827
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
10828
+ "table",
10829
+ {
10830
+ className: "twc-dt__table",
10831
+ style: { width: tableMinWidth, minWidth: "100%" },
10832
+ ref: gridRef,
10833
+ role: "grid",
10834
+ "aria-label": ariaLabelAttr || ariaLabel,
10835
+ "aria-rowcount": totalRows + 1,
10836
+ "aria-colcount": ordered.length + (checkboxSelection ? 1 : 0),
10837
+ "aria-busy": loading || void 0,
10838
+ onKeyDown: onGridKeyDown,
10839
+ children: [
10840
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { ref: theadRef, children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", "aria-rowindex": 1, children: [
10841
+ checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("th", { className: "twc-dt__th", role: "columnheader", "aria-label": "Select", "data-pin": "left", "data-pin-edge": pins.left.length || showRowNum ? void 0 : "left", style: { insetInlineStart: 0, 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(
10842
+ "span",
10843
+ {
10844
+ className: "twc-dt__check",
10845
+ "data-checked": allSel || void 0,
10846
+ "data-indeterminate": !allSel && someSel || void 0,
10847
+ onClick: toggleAll,
10848
+ role: "checkbox",
10849
+ "aria-checked": allSel ? true : someSel ? "mixed" : false,
10850
+ "aria-label": "Select all rows",
10851
+ tabIndex: 0,
10852
+ onKeyDown: (e) => {
10853
+ if (e.key === " " || e.key === "Enter") {
10854
+ e.preventDefault();
10855
+ toggleAll();
10856
+ }
10857
+ },
10858
+ children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: allSel ? I.check : I.minus })
10801
10859
  }
10802
- },
10803
- children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: allSel ? I.check : I.minus })
10804
- }
10805
- ) }) }) : null,
10806
- showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("th", { className: "twc-dt__th twc-dt__rownum", role: "columnheader", "aria-label": "Row number", "data-pin": "left", "data-pin-edge": pins.left.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W, minWidth: NUM_W }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__th-inner", children: [
10807
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__th-label", style: { flex: "none", cursor: "default" }, children: "#" }),
10808
- /* @__PURE__ */ jsxRuntime.jsx(
10809
- "button",
10810
- {
10811
- type: "button",
10812
- className: "twc-dt__menu-btn",
10813
- "aria-label": "Row number column menu",
10814
- "aria-haspopup": "menu",
10815
- "aria-expanded": colMenu?.field === "__rownum__" || void 0,
10816
- onClick: (e) => {
10817
- e.stopPropagation();
10818
- menuTriggerRef.current = e.currentTarget;
10819
- setPanel(null);
10820
- closePanel();
10821
- setRowMenu(null);
10822
- closeRowMenu();
10823
- setExportOpen(false);
10824
- closeExport();
10825
- setColMenu({ field: "__rownum__" });
10826
- openMenu(e.currentTarget, "right", 180);
10827
- },
10828
- children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.more })
10829
- }
10830
- )
10831
- ] }) }) : null,
10832
- ordered.map((c) => {
10833
- const st = stickyOf(c.field);
10834
- const sorted = sort && sort.field === c.field ? sort.dir : void 0;
10835
- const w = widthOf(c);
10836
- const reorderable = !disableColumnReorder && st.pin == null && c.type !== "actions" && c.reorderable !== false;
10837
- const resizable = !disableColumnResize && c.resizable !== false;
10838
- const hasMenu = !c.disableColumnMenu && (c.sortable || c.filterable || c.pinnable || c.hideable);
10839
- return /* @__PURE__ */ jsxRuntime.jsxs(
10840
- "th",
10841
- {
10842
- className: "twc-dt__th",
10843
- role: "columnheader",
10844
- scope: "col",
10845
- "aria-sort": sorted ? sorted === "asc" ? "ascending" : "descending" : c.sortable ? "none" : void 0,
10846
- "data-num": c.type === "number" || void 0,
10847
- "data-actions-col": c.type === "actions" || void 0,
10848
- "data-sorted": sorted,
10849
- "data-pin": st.pin,
10850
- "data-pin-edge": st.edge,
10851
- "data-dragging": drag.from === c.field || void 0,
10852
- "data-dropbefore": drag.over === c.field && !drag.after || void 0,
10853
- "data-dropafter": drag.over === c.field && drag.after || void 0,
10854
- style: { width: w, minWidth: w, ...st.style },
10855
- onDragOver: reorderable && drag.from ? (e) => {
10856
- e.preventDefault();
10857
- const r2 = e.currentTarget.getBoundingClientRect();
10858
- const after = e.clientX > r2.left + r2.width / 2;
10859
- setDrag((d) => d.over === c.field && d.after === after ? d : { ...d, over: c.field, after });
10860
- } : void 0,
10861
- onDrop: reorderable && drag.from ? (e) => {
10862
- e.preventDefault();
10863
- onColDrop(c.field);
10864
- } : void 0,
10865
- children: [
10866
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__th-inner", children: [
10867
- /* @__PURE__ */ jsxRuntime.jsxs(
10868
- "span",
10869
- {
10870
- className: "twc-dt__th-label",
10871
- role: c.sortable ? "button" : void 0,
10872
- tabIndex: c.sortable ? 0 : void 0,
10873
- title: typeof c.headerName === "string" ? c.headerName : void 0,
10874
- "aria-label": c.sortable ? `${c.headerName}, sort` : void 0,
10875
- draggable: reorderable || void 0,
10876
- onDragStart: reorderable ? (e) => {
10877
- setDrag({ from: c.field, over: null, after: false });
10878
- e.dataTransfer.effectAllowed = "move";
10879
- e.dataTransfer.setData("text/plain", c.field);
10880
- } : void 0,
10881
- onDragEnd: reorderable ? () => setDrag({ from: null, over: null, after: false }) : void 0,
10882
- onClick: () => c.sortable && cycleSort(c.field),
10883
- onKeyDown: c.sortable ? (e) => {
10884
- if (e.key === "Enter" || e.key === " ") {
10885
- e.preventDefault();
10886
- cycleSort(c.field);
10860
+ ) }) }) : null,
10861
+ showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("th", { className: "twc-dt__th twc-dt__rownum", role: "columnheader", "aria-label": "Row number", "data-pin": "left", "data-pin-edge": pins.left.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W, minWidth: NUM_W }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__th-inner", children: [
10862
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__th-label", style: { flex: "none", cursor: "default" }, children: "#" }),
10863
+ /* @__PURE__ */ jsxRuntime.jsx(
10864
+ "button",
10865
+ {
10866
+ type: "button",
10867
+ className: "twc-dt__menu-btn",
10868
+ "aria-label": "Row number column menu",
10869
+ "aria-haspopup": "menu",
10870
+ "aria-expanded": colMenu?.field === "__rownum__" || void 0,
10871
+ onClick: (e) => {
10872
+ e.stopPropagation();
10873
+ menuTriggerRef.current = e.currentTarget;
10874
+ setPanel(null);
10875
+ closePanel();
10876
+ setRowMenu(null);
10877
+ closeRowMenu();
10878
+ setExportOpen(false);
10879
+ closeExport();
10880
+ setColMenu({ field: "__rownum__" });
10881
+ openMenu(e.currentTarget, "right", 180);
10882
+ },
10883
+ children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.more })
10884
+ }
10885
+ )
10886
+ ] }) }) : null,
10887
+ ordered.map((c) => {
10888
+ const st = stickyOf(c.field);
10889
+ const sorted = sort && sort.field === c.field ? sort.dir : void 0;
10890
+ const w = widthOf(c);
10891
+ const reorderable = !disableColumnReorder && st.pin == null && c.type !== "actions" && c.reorderable !== false;
10892
+ const resizable = !disableColumnResize && c.resizable !== false;
10893
+ const hasMenu = !c.disableColumnMenu && (c.sortable || c.filterable || c.pinnable || c.hideable);
10894
+ return /* @__PURE__ */ jsxRuntime.jsxs(
10895
+ "th",
10896
+ {
10897
+ className: "twc-dt__th",
10898
+ role: "columnheader",
10899
+ scope: "col",
10900
+ "aria-sort": sorted ? sorted === "asc" ? "ascending" : "descending" : c.sortable ? "none" : void 0,
10901
+ "data-num": c.type === "number" || void 0,
10902
+ "data-actions-col": c.type === "actions" || void 0,
10903
+ "data-sorted": sorted,
10904
+ "data-pin": st.pin,
10905
+ "data-pin-edge": st.edge,
10906
+ "data-dragging": drag.from === c.field || void 0,
10907
+ "data-dropbefore": drag.over === c.field && !drag.after || void 0,
10908
+ "data-dropafter": drag.over === c.field && drag.after || void 0,
10909
+ style: { width: w, minWidth: w, ...st.style },
10910
+ onDragOver: reorderable && drag.from ? (e) => {
10911
+ e.preventDefault();
10912
+ const r2 = e.currentTarget.getBoundingClientRect();
10913
+ const after = e.clientX > r2.left + r2.width / 2;
10914
+ setDrag((d) => d.over === c.field && d.after === after ? d : { ...d, over: c.field, after });
10915
+ } : void 0,
10916
+ onDrop: reorderable && drag.from ? (e) => {
10917
+ e.preventDefault();
10918
+ onColDrop(c.field);
10919
+ } : void 0,
10920
+ children: [
10921
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__th-inner", children: [
10922
+ /* @__PURE__ */ jsxRuntime.jsxs(
10923
+ "span",
10924
+ {
10925
+ className: "twc-dt__th-label",
10926
+ role: c.sortable ? "button" : void 0,
10927
+ tabIndex: c.sortable ? 0 : void 0,
10928
+ "data-ovtext": typeof c.headerName === "string" ? c.headerName : void 0,
10929
+ "aria-label": c.sortable ? `${c.headerName}, sort` : void 0,
10930
+ draggable: reorderable || void 0,
10931
+ onDragStart: reorderable ? (e) => {
10932
+ setDrag({ from: c.field, over: null, after: false });
10933
+ e.dataTransfer.effectAllowed = "move";
10934
+ e.dataTransfer.setData("text/plain", c.field);
10935
+ } : void 0,
10936
+ onDragEnd: reorderable ? () => setDrag({ from: null, over: null, after: false }) : void 0,
10937
+ onClick: () => c.sortable && cycleSort(c.field),
10938
+ onKeyDown: c.sortable ? (e) => {
10939
+ if (e.key === "Enter" || e.key === " ") {
10940
+ e.preventDefault();
10941
+ cycleSort(c.field);
10942
+ }
10943
+ } : void 0,
10944
+ children: [
10945
+ reorderable ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__grip", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.grip }) }) : null,
10946
+ filteredFields.has(c.field) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__filterdot" }) : null,
10947
+ c.headerName,
10948
+ c.sortable ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sort", children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.arrow }) }) : null
10949
+ ]
10887
10950
  }
10888
- } : void 0,
10889
- children: [
10890
- reorderable ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__grip", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.grip }) }) : null,
10891
- filteredFields.has(c.field) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__filterdot" }) : null,
10892
- c.headerName,
10893
- c.sortable ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sort", children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.arrow }) }) : null
10894
- ]
10895
- }
10896
- ),
10897
- hasMenu ? /* @__PURE__ */ jsxRuntime.jsx(
10898
- "button",
10899
- {
10900
- type: "button",
10901
- className: "twc-dt__menu-btn",
10902
- "aria-label": "Column menu",
10903
- "aria-haspopup": "menu",
10904
- "aria-expanded": colMenu?.field === c.field || void 0,
10905
- onClick: (e) => {
10906
- e.stopPropagation();
10907
- menuTriggerRef.current = e.currentTarget;
10908
- setPanel(null);
10909
- closePanel();
10910
- setRowMenu(null);
10911
- closeRowMenu();
10912
- setExportOpen(false);
10913
- closeExport();
10914
- setColMenu({ field: c.field });
10915
- openMenu(e.currentTarget, "right", 230);
10916
- },
10917
- children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.more })
10918
- }
10919
- ) : null
10920
- ] }),
10921
- resizable ? /* @__PURE__ */ jsxRuntime.jsx(
10922
- "span",
10923
- {
10924
- className: "twc-dt__resizer",
10925
- "data-active": resizing || void 0,
10926
- role: "separator",
10927
- "aria-orientation": "vertical",
10928
- "aria-label": `Resize ${c.headerName} column (double-click to fit content)`,
10929
- "aria-valuenow": w,
10930
- "aria-valuemin": 72,
10931
- tabIndex: 0,
10932
- onPointerDown: (e) => startResize(e, c.field),
10933
- onClick: (e) => e.stopPropagation(),
10934
- onDoubleClick: (e) => {
10935
- e.preventDefault();
10936
- e.stopPropagation();
10937
- autoFitColumn(c.field, e.currentTarget.closest("th"));
10938
- },
10939
- onKeyDown: (e) => {
10940
- if (e.key === "Enter" || e.key === " ") {
10941
- e.preventDefault();
10942
- e.stopPropagation();
10943
- autoFitColumn(c.field, e.currentTarget.closest("th"));
10944
- return;
10951
+ ),
10952
+ hasMenu ? /* @__PURE__ */ jsxRuntime.jsx(
10953
+ "button",
10954
+ {
10955
+ type: "button",
10956
+ className: "twc-dt__menu-btn",
10957
+ "aria-label": "Column menu",
10958
+ "aria-haspopup": "menu",
10959
+ "aria-expanded": colMenu?.field === c.field || void 0,
10960
+ onClick: (e) => {
10961
+ e.stopPropagation();
10962
+ menuTriggerRef.current = e.currentTarget;
10963
+ setPanel(null);
10964
+ closePanel();
10965
+ setRowMenu(null);
10966
+ closeRowMenu();
10967
+ setExportOpen(false);
10968
+ closeExport();
10969
+ setColMenu({ field: c.field });
10970
+ openMenu(e.currentTarget, "right", 230);
10971
+ },
10972
+ children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.more })
10973
+ }
10974
+ ) : null
10975
+ ] }),
10976
+ resizable ? /* @__PURE__ */ jsxRuntime.jsx(
10977
+ "span",
10978
+ {
10979
+ className: "twc-dt__resizer",
10980
+ "data-active": resizing || void 0,
10981
+ role: "separator",
10982
+ "aria-orientation": "vertical",
10983
+ "aria-label": `Resize ${c.headerName} column (double-click to fit content)`,
10984
+ "aria-valuenow": w,
10985
+ "aria-valuemin": 72,
10986
+ tabIndex: 0,
10987
+ onPointerDown: (e) => startResize(e, c.field),
10988
+ onClick: (e) => e.stopPropagation(),
10989
+ onDoubleClick: (e) => {
10990
+ e.preventDefault();
10991
+ e.stopPropagation();
10992
+ autoFitColumn(c.field, e.currentTarget.closest("th"));
10993
+ },
10994
+ onKeyDown: (e) => {
10995
+ if (e.key === "Enter" || e.key === " ") {
10996
+ e.preventDefault();
10997
+ e.stopPropagation();
10998
+ autoFitColumn(c.field, e.currentTarget.closest("th"));
10999
+ return;
11000
+ }
11001
+ if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
11002
+ e.preventDefault();
11003
+ e.stopPropagation();
11004
+ const delta = e.key === "ArrowRight" ? 10 : -10;
11005
+ setWidths((m) => ({ ...m, [c.field]: Math.max(72, (m[c.field] ?? intrinsicWidth(c)) + delta) }));
11006
+ },
11007
+ title: "Drag to resize \xB7 double-click to fit content"
10945
11008
  }
10946
- if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
10947
- e.preventDefault();
10948
- e.stopPropagation();
10949
- const delta = e.key === "ArrowRight" ? 10 : -10;
10950
- setWidths((m) => ({ ...m, [c.field]: Math.max(72, (m[c.field] ?? intrinsicWidth(c)) + delta) }));
10951
- },
10952
- title: "Drag to resize \xB7 double-click to fit content"
10953
- }
10954
- ) : null
10955
- ]
10956
- },
10957
- c.field
10958
- );
10959
- })
10960
- ] }) }),
10961
- /* @__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: [
10962
- checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", "data-pin": "left", style: { insetInlineStart: 0, width: CHK_W }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "18px", height: 18, borderRadius: 4 } }) }) : null,
10963
- 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,
10964
- ordered.map((c, ci) => {
10965
- const st = stickyOf(c.field);
10966
- return /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", "data-num": c.type === "number" || void 0, "data-pin": st.pin, "data-pin-edge": st.edge, style: { width: widthOf(c), ...st.style }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": `${45 + (ri * 13 + ci * 29) % 45}%` } }) }, c.field);
10967
- })
10968
- ] }, ri)) : (displayItems ? displayItems.length === 0 : paged.length === 0) ? (
10969
- // #121: customizable, filter-aware empty state. #122: grid roles on the empty row.
10970
- /* @__PURE__ */ jsxRuntime.jsx("tr", { role: "row", "aria-rowindex": 2, children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", colSpan: totalCols, style: { maxWidth: "none" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__empty", children: renderEmpty ? renderEmpty() : emptyMessage ?? (filters.length > 0 || quick.trim() !== "" ? "No rows match your filters" : "No rows") }) }) })
10971
- ) : displayItems ? (() => {
10972
- let li = -1;
10973
- return displayItems.map((item) => item.kind === "group" ? renderGroupRow(item) : renderLeaf(item.row, ++li));
10974
- })() : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10975
- pinnedTopRows.map((row) => renderLeaf(row, keyIndex.get(keyOf(row)), "top")),
10976
- vWindow ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10977
- vWindow.padTop > 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": "true", className: "twc-dt__vspacer", children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalCols, style: { height: vWindow.padTop, padding: 0, border: "none", maxWidth: "none" } }) }) : null,
10978
- middleRows.slice(vWindow.start, vWindow.end).map((row, i) => renderLeaf(row, keyIndex.get(keyOf(row)), void 0, vWindow.start + i)),
10979
- vWindow.padBottom > 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": "true", className: "twc-dt__vspacer", children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalCols, style: { height: vWindow.padBottom, padding: 0, border: "none", maxWidth: "none" } }) }) : null
10980
- ] }) : middleRows.map((row, i) => renderLeaf(row, keyIndex.get(keyOf(row)), void 0, i)),
10981
- pinnedBottomRows.map((row) => renderLeaf(row, keyIndex.get(keyOf(row)), "bottom"))
10982
- ] }) }),
10983
- hasAggregation && aggOn && !loading && paged.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("tfoot", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", children: [
10984
- checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { role: "gridcell", "data-pin": "left", "data-pin-edge": pins.left.length || showRowNum ? void 0 : "left", style: { insetInlineStart: 0, width: CHK_W } }) : null,
10985
- showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", "data-pin-edge": pins.left.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W } }) : null,
10986
- ordered.map((c) => {
10987
- const st = stickyOf(c.field);
10988
- const v = aggregate(c);
10989
- const display = v == null ? null : c.aggregationFormatter ? c.aggregationFormatter(v) : c.valueFormatter ? c.valueFormatter(v, null) : typeof v === "number" ? v.toLocaleString() : v;
10990
- return /* @__PURE__ */ jsxRuntime.jsx("td", { role: "gridcell", "data-num": c.type === "number" || void 0, "data-pin": st.pin, "data-pin-edge": st.edge, style: { width: widthOf(c), ...st.style }, children: v == null ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10991
- typeof aggOf(c) === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__agg-label", children: aggLabels[aggOf(c)] }) : null,
10992
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__agg-val", children: display })
10993
- ] }) }, c.field);
10994
- })
10995
- ] }) }) : null
10996
- ]
11009
+ ) : null
11010
+ ]
11011
+ },
11012
+ c.field
11013
+ );
11014
+ })
11015
+ ] }) }),
11016
+ /* @__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: [
11017
+ checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", "data-pin": "left", style: { insetInlineStart: 0, width: CHK_W }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": "18px", height: 18, borderRadius: 4 } }) }) : null,
11018
+ 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,
11019
+ ordered.map((c, ci) => {
11020
+ const st = stickyOf(c.field);
11021
+ return /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", "data-num": c.type === "number" || void 0, "data-pin": st.pin, "data-pin-edge": st.edge, style: { width: widthOf(c), ...st.style }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__sk", "aria-hidden": "true", style: { "--_w": `${45 + (ri * 13 + ci * 29) % 45}%` } }) }, c.field);
11022
+ })
11023
+ ] }, ri)) : (displayItems ? displayItems.length === 0 : paged.length === 0) ? (
11024
+ // #121: customizable, filter-aware empty state. #122: grid roles on the empty row.
11025
+ /* @__PURE__ */ jsxRuntime.jsx("tr", { role: "row", "aria-rowindex": 2, children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__td", role: "gridcell", colSpan: totalCols, style: { maxWidth: "none" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__empty", children: renderEmpty ? renderEmpty() : emptyMessage ?? (filters.length > 0 || quick.trim() !== "" ? "No rows match your filters" : "No rows") }) }) })
11026
+ ) : displayItems ? (() => {
11027
+ let li = -1;
11028
+ return displayItems.map((item) => item.kind === "group" ? renderGroupRow(item) : renderLeaf(item.row, ++li));
11029
+ })() : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11030
+ pinnedTopRows.map((row) => renderLeaf(row, keyIndex.get(keyOf(row)), "top")),
11031
+ vWindow ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11032
+ vWindow.padTop > 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": "true", className: "twc-dt__vspacer", children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalCols, style: { height: vWindow.padTop, padding: 0, border: "none", maxWidth: "none" } }) }) : null,
11033
+ middleRows.slice(vWindow.start, vWindow.end).map((row, i) => renderLeaf(row, keyIndex.get(keyOf(row)), void 0, vWindow.start + i)),
11034
+ vWindow.padBottom > 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": "true", className: "twc-dt__vspacer", children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalCols, style: { height: vWindow.padBottom, padding: 0, border: "none", maxWidth: "none" } }) }) : null
11035
+ ] }) : middleRows.map((row, i) => renderLeaf(row, keyIndex.get(keyOf(row)), void 0, i)),
11036
+ pinnedBottomRows.map((row) => renderLeaf(row, keyIndex.get(keyOf(row)), "bottom"))
11037
+ ] }) }),
11038
+ hasAggregation && aggOn && !loading && paged.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("tfoot", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", children: [
11039
+ checkboxSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { role: "gridcell", "data-pin": "left", "data-pin-edge": pins.left.length || showRowNum ? void 0 : "left", style: { insetInlineStart: 0, width: CHK_W } }) : null,
11040
+ showRowNum ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-dt__rownum", role: "gridcell", "aria-hidden": "true", "data-pin": "left", "data-pin-edge": pins.left.length ? void 0 : "left", style: { insetInlineStart: numLeft, width: NUM_W } }) : null,
11041
+ ordered.map((c) => {
11042
+ const st = stickyOf(c.field);
11043
+ const v = aggregate(c);
11044
+ const display = v == null ? null : c.aggregationFormatter ? c.aggregationFormatter(v) : c.valueFormatter ? c.valueFormatter(v, null) : typeof v === "number" ? v.toLocaleString() : v;
11045
+ return /* @__PURE__ */ jsxRuntime.jsx("td", { role: "gridcell", "data-num": c.type === "number" || void 0, "data-pin": st.pin, "data-pin-edge": st.edge, style: { width: widthOf(c), ...st.style }, children: v == null ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11046
+ typeof aggOf(c) === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__agg-label", children: aggLabels[aggOf(c)] }) : null,
11047
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__agg-val", children: display })
11048
+ ] }) }, c.field);
11049
+ })
11050
+ ] }) }) : null
11051
+ ]
11052
+ }
11053
+ )
10997
11054
  }
10998
- ) }),
11055
+ ),
11056
+ /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { anchor: ovTip ? ovTip.anchor : null, open: !!ovTip, label: ovTip ? ovTip.text : null, placement: "top" }),
10999
11057
  !pivotActive ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__footer", children: [
11000
11058
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__footer-row", "data-bottom": "true", children: [
11001
11059
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__status", children: loading ? "Loading\u2026" : (() => {