@sia.soul/sia-react-ui 0.1.42 → 0.1.44

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.js CHANGED
@@ -80,7 +80,7 @@ import {
80
80
  Watermark,
81
81
  message,
82
82
  notification
83
- } from "./chunk-IPDCEXQO.js";
83
+ } from "./chunk-KXPNW4E6.js";
84
84
  import {
85
85
  TextArea
86
86
  } from "./chunk-SMCYEPBL.js";
@@ -95,7 +95,7 @@ import {
95
95
  DatePicker,
96
96
  SelectDateRange,
97
97
  TimePanel
98
- } from "./chunk-LWVZEUGJ.js";
98
+ } from "./chunk-QIXU7N4X.js";
99
99
  import {
100
100
  Checkbox,
101
101
  FloatingScrollbarProvider,
@@ -110,7 +110,7 @@ import {
110
110
  Tree,
111
111
  useOverlayLifecycle,
112
112
  useScrollbarProximity
113
- } from "./chunk-3Q3S6CDZ.js";
113
+ } from "./chunk-NYJSSPIX.js";
114
114
  import {
115
115
  Dropdown,
116
116
  FILLED_ICON_NAMES,
@@ -4652,6 +4652,22 @@ function Treemap({
4652
4652
  // src/components/Table/TableCellContent.tsx
4653
4653
  import { useLayoutEffect as useLayoutEffect2, useRef as useRef13, useState as useState16 } from "react";
4654
4654
  import { jsx as jsx20 } from "react/jsx-runtime";
4655
+ var pendingLayouts = /* @__PURE__ */ new Map();
4656
+ var layoutFrame;
4657
+ function scheduleLayout(element, task) {
4658
+ pendingLayouts.set(element, task);
4659
+ if (layoutFrame !== void 0) return;
4660
+ layoutFrame = requestAnimationFrame(() => {
4661
+ layoutFrame = void 0;
4662
+ const tasks = [...pendingLayouts.values()];
4663
+ pendingLayouts.clear();
4664
+ const layouts = tasks.flatMap((task2) => task2.layouts());
4665
+ layouts.forEach((layout) => {
4666
+ if (!layout.hasAttribute("data-table-inline-layout")) layout.setAttribute("data-table-inline-layout", "");
4667
+ });
4668
+ tasks.forEach((task2) => task2.measure());
4669
+ });
4670
+ }
4655
4671
  function TableCellContent({ children, ellipsis, title }) {
4656
4672
  const ref = useRef13(null);
4657
4673
  const [overflowing, setOverflowing] = useState16(false);
@@ -4659,29 +4675,33 @@ function TableCellContent({ children, ellipsis, title }) {
4659
4675
  useLayoutEffect2(() => {
4660
4676
  const element = ref.current;
4661
4677
  if (!element || !ellipsis || !customContent) return;
4662
- const layouts = [];
4663
- const normalizeLayouts = (parent) => {
4678
+ const normalizeLayouts = (parent, layouts) => {
4664
4679
  for (const child of parent.children) {
4665
4680
  if (!(child instanceof HTMLElement)) continue;
4666
4681
  const component = [...child.classList].some((name) => name.startsWith("sia-") && !name.startsWith("sia-space") && name !== "sia-flex");
4667
4682
  if (component || child.matches("button, input, textarea, select, [contenteditable]")) continue;
4668
4683
  const display = getComputedStyle(child).display;
4669
4684
  if (["flex", "inline-flex", "grid", "inline-grid"].includes(display)) {
4670
- child.setAttribute("data-table-inline-layout", "");
4671
4685
  layouts.push(child);
4672
4686
  }
4673
- normalizeLayouts(child);
4687
+ normalizeLayouts(child, layouts);
4674
4688
  }
4675
4689
  };
4676
- normalizeLayouts(element);
4677
4690
  const update = () => setOverflowing(element.scrollWidth > element.clientWidth + 1 || element.scrollHeight > element.clientHeight + 1);
4678
- update();
4691
+ scheduleLayout(element, {
4692
+ layouts: () => {
4693
+ const layouts = [];
4694
+ normalizeLayouts(element, layouts);
4695
+ return layouts;
4696
+ },
4697
+ measure: update
4698
+ });
4679
4699
  const observer = new ResizeObserver(update);
4680
4700
  observer.observe(element);
4681
4701
  for (const child of element.children) observer.observe(child);
4682
4702
  return () => {
4683
4703
  observer.disconnect();
4684
- layouts.forEach((layout) => layout.removeAttribute("data-table-inline-layout"));
4704
+ pendingLayouts.delete(element);
4685
4705
  };
4686
4706
  }, [children, ellipsis, customContent]);
4687
4707
  return /* @__PURE__ */ jsx20("div", { ref, className: "sia-table__cell-content", "data-custom-content": customContent || void 0, "data-content-overflow": ellipsis && customContent && overflowing || void 0, children: title ? /* @__PURE__ */ jsx20(Tooltip, { title, className: "sia-table__cell-tooltip", children: /* @__PURE__ */ jsx20("span", { children }) }) : children });
@@ -6484,8 +6504,11 @@ function createResizePlugin(options = {}) {
6484
6504
  })
6485
6505
  };
6486
6506
  }
6507
+ function isTableAuxiliaryColumn(column) {
6508
+ return column.meta?.plugin === "index" || column.meta?.plugin === "selection" || column.key === "__index__" || column.key === "__selection__";
6509
+ }
6487
6510
  function createColumnSettingItems(columns, visibleKeys) {
6488
- return flattenTableColumns(columns).map((column, order) => ({
6511
+ return flattenTableColumns(columns).filter((column) => !isTableAuxiliaryColumn(column)).map((column, order) => ({
6489
6512
  key: column.key,
6490
6513
  width: column.width,
6491
6514
  fixed: normalizeFixed(column.fixed),
@@ -6496,6 +6519,7 @@ function createColumnSettingItems(columns, visibleKeys) {
6496
6519
  function applyColumnSettingsToTree(columns, items) {
6497
6520
  const itemMap = new Map(items.map((item) => [item.key, item]));
6498
6521
  const walk = (source) => source.flatMap((column, sourceOrder) => {
6522
+ if (isTableAuxiliaryColumn(column)) return [{ column, order: column.meta?.plugin === "selection" || column.key === "__selection__" ? -2 : -1 }];
6499
6523
  if (column.children?.length) {
6500
6524
  const children = walk(column.children);
6501
6525
  if (children.length === 0) return [];
@@ -6805,11 +6829,15 @@ function ColumnSettingPanel({
6805
6829
  var columnSettingLoadTokens = /* @__PURE__ */ new WeakMap();
6806
6830
  function createColumnSettingPlugin(options = {}) {
6807
6831
  const baseItems = (context) => createColumnSettingItems(context.baseColumns, options.defaultVisibleKeys);
6808
- const currentItems = (context) => context.state.items?.length ? context.state.items : baseItems(context);
6832
+ const editableItems = (items, context) => {
6833
+ const keys = new Set(baseItems(context).map((item) => item.key));
6834
+ return items.filter((item) => keys.has(item.key));
6835
+ };
6836
+ const currentItems = (context) => context.state.items?.length ? editableItems(context.state.items, context) : baseItems(context);
6809
6837
  const save = (snapshot) => options.adapter && options.scope ? options.adapter.save(options.scope, snapshot).catch(() => void 0) : Promise.resolve();
6810
6838
  function apply(items, context, persist = true) {
6811
6839
  const normalized = orderColumnSettings(
6812
- [...items].sort((a, b) => a.order - b.order)
6840
+ editableItems(items, context).sort((a, b) => a.order - b.order)
6813
6841
  );
6814
6842
  context.setState((state) => ({ ...state, items: normalized, open: false }));
6815
6843
  const columnMap = new Map(
@@ -7216,10 +7244,9 @@ function buildHeaderRows(columns) {
7216
7244
  function resolveInitialState(plugin) {
7217
7245
  return typeof plugin.initialState === "function" ? plugin.initialState() : plugin.initialState;
7218
7246
  }
7219
- function measureTableCellContentWidth(cell) {
7247
+ function prepareTableCellMeasurement(cell) {
7220
7248
  const content = cell.querySelector(":scope > .sia-table__cell-content");
7221
7249
  const target = cell.classList.contains("sia-table__header-cell") ? cell.querySelector(".sia-table__resizable-header > span:first-child, .sia-table__header-label-content") : content;
7222
- let contentWidth = cell.scrollWidth;
7223
7250
  if (target) {
7224
7251
  const measurement = target.cloneNode(true);
7225
7252
  Object.assign(measurement.style, {
@@ -7237,11 +7264,8 @@ function measureTableCellContentWidth(cell) {
7237
7264
  });
7238
7265
  measurement.setAttribute("aria-hidden", "true");
7239
7266
  cell.appendChild(measurement);
7240
- contentWidth = Math.max(measurement.scrollWidth, measurement.getBoundingClientRect().width);
7241
- measurement.remove();
7267
+ return measurement;
7242
7268
  }
7243
- const style = window.getComputedStyle(cell);
7244
- return contentWidth + (Number.parseFloat(style.paddingLeft) || 0) + (Number.parseFloat(style.paddingRight) || 0) + (Number.parseFloat(style.borderLeftWidth) || 0) + (Number.parseFloat(style.borderRightWidth) || 0);
7245
7269
  }
7246
7270
  function getTableHorizontalMetrics(viewport, table) {
7247
7271
  const contentWidth = Math.max(viewport.clientWidth, table?.getBoundingClientRect().width ?? viewport.clientWidth);
@@ -7462,18 +7486,22 @@ function TableInner(props, ref) {
7462
7486
  if (element.scrollLeft > maxLeft) element.scrollLeft = maxLeft > 1 ? maxLeft : 0;
7463
7487
  const logicalScrollLeft = Math.min(element.scrollLeft, maxLeft);
7464
7488
  const maxTop = Math.max(0, element.scrollHeight - element.clientHeight);
7465
- root.dataset.overflowX = String(maxLeft > 1);
7466
- root.dataset.overflowY = String(maxTop > 1);
7467
- const horizontalTrack = root.querySelector(".sia-table__scrollbar--horizontal")?.clientWidth ?? 0;
7468
- const verticalTrack = root.querySelector(".sia-table__scrollbar--vertical")?.clientHeight ?? 0;
7489
+ const setFlag = (key, value) => {
7490
+ const next = String(value);
7491
+ if (root.dataset[key] !== next) root.dataset[key] = next;
7492
+ };
7493
+ setFlag("overflowX", maxLeft > 1);
7494
+ setFlag("overflowY", maxTop > 1);
7495
+ const horizontalTrackElement = root.querySelector(".sia-table__scrollbar--horizontal");
7496
+ const verticalTrackElement = root.querySelector(".sia-table__scrollbar--vertical");
7497
+ const horizontalTrack = horizontalTrackElement?.clientWidth ?? 0;
7498
+ const verticalTrack = verticalTrackElement?.clientHeight ?? 0;
7469
7499
  const horizontalThumb = maxLeft > 1 ? Math.min(horizontalTrack, Math.max(36, horizontalTrack * element.clientWidth / horizontalContentWidth)) : 0;
7470
7500
  const verticalThumb = maxTop > 1 ? Math.min(verticalTrack, Math.max(36, verticalTrack * element.clientHeight / element.scrollHeight)) : 0;
7471
7501
  const horizontalPosition = maxLeft > 0 ? logicalScrollLeft / maxLeft * Math.max(0, horizontalTrack - horizontalThumb) : 0;
7472
7502
  const verticalPosition = maxTop > 0 ? element.scrollTop / maxTop * Math.max(0, verticalTrack - verticalThumb) : 0;
7473
- root.dataset.scrolledLeft = String(logicalScrollLeft > 1);
7474
- root.dataset.scrolledRight = String(maxLeft > 1 && logicalScrollLeft < maxLeft - 1);
7475
- root.dataset.overflowX = String(maxLeft > 1);
7476
- root.dataset.overflowY = String(maxTop > 1);
7503
+ setFlag("scrolledLeft", logicalScrollLeft > 1);
7504
+ setFlag("scrolledRight", maxLeft > 1 && logicalScrollLeft < maxLeft - 1);
7477
7505
  const viewportRect = element.getBoundingClientRect();
7478
7506
  const leftEdge = root.querySelector(".sia-table__header-cell.sia-table__cell--fixed-left-edge");
7479
7507
  const rightEdge = root.querySelector(".sia-table__header-cell.sia-table__cell--fixed-right-edge");
@@ -7485,10 +7513,10 @@ function TableInner(props, ref) {
7485
7513
  const rightEdgeRect = rightEdge.getBoundingClientRect();
7486
7514
  root.style.setProperty("--sia-table-fixed-right-width", `${Math.max(0, viewportRect.right - rightEdgeRect.left)}px`);
7487
7515
  }
7488
- root.style.setProperty("--sia-table-scrollbar-x-size", `${horizontalThumb}px`);
7489
- root.style.setProperty("--sia-table-scrollbar-x-position", `${horizontalPosition}px`);
7490
- root.style.setProperty("--sia-table-scrollbar-y-size", `${verticalThumb}px`);
7491
- root.style.setProperty("--sia-table-scrollbar-y-position", `${verticalPosition}px`);
7516
+ horizontalTrackElement?.style.setProperty("--sia-table-scrollbar-x-size", `${horizontalThumb}px`);
7517
+ horizontalTrackElement?.style.setProperty("--sia-table-scrollbar-x-position", `${horizontalPosition}px`);
7518
+ verticalTrackElement?.style.setProperty("--sia-table-scrollbar-y-size", `${verticalThumb}px`);
7519
+ verticalTrackElement?.style.setProperty("--sia-table-scrollbar-y-position", `${verticalPosition}px`);
7492
7520
  }, []);
7493
7521
  useEffect12(() => {
7494
7522
  const element = scrollRef.current;
@@ -7509,19 +7537,33 @@ function TableInner(props, ref) {
7509
7537
  const orderedColumns = useMemo9(() => sortTableColumnsByFixed(pipeline.columns), [pipeline.columns]);
7510
7538
  const leafColumns = useMemo9(() => flattenTableColumns(orderedColumns), [orderedColumns]);
7511
7539
  const headerRows = useMemo9(() => buildHeaderRows(orderedColumns), [orderedColumns]);
7540
+ const measuredCells = useRef15(/* @__PURE__ */ new WeakSet());
7541
+ const autoWidthSignature = leafColumns.map((column) => `${column.key}:${column.autoWidth}:${resizedWidths[column.key] ?? ""}`).join("|");
7542
+ useEffect12(() => {
7543
+ measuredCells.current = /* @__PURE__ */ new WeakSet();
7544
+ setAutoColumnWidths({});
7545
+ }, [dataSource, baseColumns, size, autoWidthSignature]);
7512
7546
  useEffect12(() => {
7513
7547
  const autoWidthColumns = leafColumns.filter((column) => column.autoWidth && resizedWidths[column.key] === void 0);
7514
7548
  const root = rootRef.current;
7515
7549
  if (!root || autoWidthColumns.length === 0) return;
7516
7550
  const frame = window.requestAnimationFrame(() => {
7517
7551
  const measurements = {};
7518
- const cells = root.querySelectorAll("[data-column-key]");
7552
+ const columnsByKey = new Map(autoWidthColumns.map((column) => [column.key, column]));
7553
+ const cells = [...root.querySelectorAll("th[data-column-key], td[data-column-key]")].filter((cell) => columnsByKey.has(cell.dataset.columnKey) && !measuredCells.current.has(cell));
7554
+ if (cells.length === 0) return;
7555
+ const prepared = cells.map((cell) => ({ cell, node: prepareTableCellMeasurement(cell) }));
7556
+ for (const { cell, node } of prepared) {
7557
+ const key = cell.dataset.columnKey;
7558
+ const style2 = window.getComputedStyle(cell);
7559
+ const padding = (Number.parseFloat(style2.paddingLeft) || 0) + (Number.parseFloat(style2.paddingRight) || 0) + (Number.parseFloat(style2.borderLeftWidth) || 0) + (Number.parseFloat(style2.borderRightWidth) || 0);
7560
+ measurements[key] = Math.max(measurements[key] ?? 0, node ? Math.max(node.scrollWidth, node.getBoundingClientRect().width) + padding : cell.scrollWidth);
7561
+ measuredCells.current.add(cell);
7562
+ }
7563
+ prepared.forEach(({ node }) => node?.remove());
7519
7564
  for (const column of autoWidthColumns) {
7520
- let width = column.minWidth ?? 56;
7521
- for (const cell of cells) {
7522
- if (cell.dataset.columnKey !== column.key) continue;
7523
- width = Math.max(width, measureTableCellContentWidth(cell));
7524
- }
7565
+ if (measurements[column.key] === void 0) continue;
7566
+ const width = Math.max(column.minWidth ?? 56, autoColumnWidths[column.key] ?? 0, measurements[column.key]);
7525
7567
  measurements[column.key] = Math.ceil(Math.min(column.maxWidth ?? Number.POSITIVE_INFINITY, width));
7526
7568
  }
7527
7569
  setAutoColumnWidths((previous) => {
@@ -7577,6 +7619,21 @@ function TableInner(props, ref) {
7577
7619
  const renderedRows = pipeline.rows.slice(startIndex, endIndex);
7578
7620
  const topSpacer = shouldVirtualize ? startIndex * rowHeight : 0;
7579
7621
  const bottomSpacer = shouldVirtualize ? Math.max(0, (pipeline.rows.length - endIndex) * rowHeight) : 0;
7622
+ const rowElements = useMemo9(() => /* @__PURE__ */ new Map(), [
7623
+ dataSource,
7624
+ baseColumns,
7625
+ sortedPlugins,
7626
+ pluginStates,
7627
+ autoColumnWidths,
7628
+ viewportWidth,
7629
+ rowHeight,
7630
+ striped,
7631
+ rowClassName,
7632
+ getRowKey,
7633
+ onRowClick,
7634
+ onRowDoubleClick,
7635
+ onCellContextMenu
7636
+ ]);
7580
7637
  const toolbarStart = sortedPlugins.map((plugin) => {
7581
7638
  const content = plugin.renderToolbarStart?.(getContext(plugin));
7582
7639
  return content ? /* @__PURE__ */ jsx22(Fragment8, { children: content }, `toolbar-start-${plugin.id}`) : null;
@@ -7603,9 +7660,9 @@ function TableInner(props, ref) {
7603
7660
  };
7604
7661
  const handleScroll = useCallback2((event) => {
7605
7662
  const element = event.currentTarget;
7606
- if (shouldVirtualize) setScrollTop(element.scrollTop);
7663
+ if (shouldVirtualize) setScrollTop((previous) => Math.floor(previous / rowHeight) === Math.floor(element.scrollTop / rowHeight) ? previous : element.scrollTop);
7607
7664
  updateScrollMetrics();
7608
- }, [shouldVirtualize, updateScrollMetrics]);
7665
+ }, [shouldVirtualize, rowHeight, updateScrollMetrics]);
7609
7666
  const handleScrollbarPointerDown = useCallback2((axis, event, track = event.currentTarget) => {
7610
7667
  const element = scrollRef.current;
7611
7668
  const thumb = track.firstElementChild;
@@ -7826,10 +7883,12 @@ function TableInner(props, ref) {
7826
7883
  /* @__PURE__ */ jsxs21("tbody", { children: [
7827
7884
  topSpacer > 0 ? /* @__PURE__ */ jsx22("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx22("td", { colSpan: leafColumns.length, style: { height: topSpacer, padding: 0, border: 0 } }) }) : null,
7828
7885
  renderedRows.map((row, offset) => {
7886
+ const cached = rowElements.get(row.key);
7887
+ if (cached) return cached;
7829
7888
  const rowIndex = startIndex + offset;
7830
7889
  const pluginClasses = sortedPlugins.map((plugin) => plugin.getRowClassName?.(row, getContext(plugin))).filter(Boolean).join(" ");
7831
7890
  const customClass = typeof rowClassName === "function" ? rowClassName(row.record, row.sourceIndex) : rowClassName ?? "";
7832
- return /* @__PURE__ */ jsx22(
7891
+ const element = /* @__PURE__ */ jsx22(
7833
7892
  TableBodyRow,
7834
7893
  {
7835
7894
  row,
@@ -7875,6 +7934,8 @@ function TableInner(props, ref) {
7875
7934
  },
7876
7935
  row.key
7877
7936
  );
7937
+ rowElements.set(row.key, element);
7938
+ return element;
7878
7939
  }),
7879
7940
  bottomSpacer > 0 ? /* @__PURE__ */ jsx22("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx22("td", { colSpan: leafColumns.length, style: { height: bottomSpacer, padding: 0, border: 0 } }) }) : null
7880
7941
  ] }),
@@ -1474,7 +1474,17 @@ function FloatingScrollbarProvider({ disabled = false, targetRef }) {
1474
1474
  };
1475
1475
  const scanTargets = () => {
1476
1476
  scanFrame = 0;
1477
- const candidates = (targetRef ? [targetRef.current] : [document.scrollingElement, ...document.querySelectorAll("*")]).filter((target) => target instanceof HTMLElement);
1477
+ const managedSelector = ".sia-table__viewport, [data-sia-native-scrollbar], .sia-scrollbar-track, .sia-floating-scrollbar-layer";
1478
+ const discovered = [];
1479
+ if (!targetRef) {
1480
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
1481
+ acceptNode: (node) => node.matches(managedSelector) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT
1482
+ });
1483
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
1484
+ if (node instanceof HTMLElement) discovered.push(node);
1485
+ }
1486
+ }
1487
+ const candidates = (targetRef ? [targetRef.current] : [document.scrollingElement, ...discovered]).filter((target) => target instanceof HTMLElement);
1478
1488
  const nextTargets = /* @__PURE__ */ new Set();
1479
1489
  candidates.forEach((target) => {
1480
1490
  if (canScroll(target, "horizontal") || canScroll(target, "vertical")) {
@@ -1492,9 +1502,12 @@ function FloatingScrollbarProvider({ disabled = false, targetRef }) {
1492
1502
  scanFrame = window.requestAnimationFrame(scanTargets);
1493
1503
  };
1494
1504
  const mutationObserver = new MutationObserver((mutations) => {
1495
- if (mutations.some((mutation) => !layer.contains(mutation.target))) scheduleScan();
1505
+ if (mutations.some((mutation) => {
1506
+ const target = mutation.target instanceof Element ? mutation.target : mutation.target.parentElement;
1507
+ return target && !layer.contains(target) && !target.closest(".sia-table__viewport, [data-sia-native-scrollbar], .sia-scrollbar-track");
1508
+ })) scheduleScan();
1496
1509
  });
1497
- mutationObserver.observe(document.documentElement, { subtree: true, childList: true, attributes: true });
1510
+ mutationObserver.observe(document.documentElement, { subtree: true, childList: true, attributes: true, attributeFilter: ["class", "style", "hidden"] });
1498
1511
  window.addEventListener("resize", scheduleScan);
1499
1512
  window.addEventListener("scroll", scheduleUpdateAll, true);
1500
1513
  scheduleScan();
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SelectDateRange
3
- } from "./chunk-LWVZEUGJ.js";
4
- import "./chunk-3Q3S6CDZ.js";
3
+ } from "./chunk-QIXU7N4X.js";
4
+ import "./chunk-NYJSSPIX.js";
5
5
  import "./chunk-XCVAVCIO.js";
6
6
  import "./chunk-IKAMZNCK.js";
7
7
  import "./chunk-H7IAG72O.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sia.soul/sia-react-ui",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "Sia Design components and tokens for React",
5
5
  "publishConfig": {
6
6
  "access": "public",