@sia.soul/sia-react-ui 0.1.4 → 0.1.6

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
@@ -1259,7 +1259,7 @@ function openDrawer(config) {
1259
1259
  let currentOpen = true;
1260
1260
  let destroyed = false;
1261
1261
  let cleanupTimer;
1262
- function cleanup() {
1262
+ function cleanup2() {
1263
1263
  if (destroyed) return;
1264
1264
  destroyed = true;
1265
1265
  if (cleanupTimer !== void 0) window.clearTimeout(cleanupTimer);
@@ -1271,7 +1271,7 @@ function openDrawer(config) {
1271
1271
  if (destroyed || !currentOpen) return;
1272
1272
  currentOpen = false;
1273
1273
  render();
1274
- cleanupTimer = window.setTimeout(cleanup, DRAWER_MOTION_DURATION + 100);
1274
+ cleanupTimer = window.setTimeout(cleanup2, DRAWER_MOTION_DURATION + 100);
1275
1275
  }
1276
1276
  function render() {
1277
1277
  root.render(/* @__PURE__ */ jsx8(
@@ -1286,7 +1286,7 @@ function openDrawer(config) {
1286
1286
  afterOpen: () => currentConfig.afterOpen?.(),
1287
1287
  afterClose: () => {
1288
1288
  currentConfig.afterClose?.();
1289
- cleanup();
1289
+ cleanup2();
1290
1290
  }
1291
1291
  }
1292
1292
  ));
@@ -3806,7 +3806,7 @@ function Markdown({ content, emptyText = "\u6682\u65E0 Markdown \u5185\u5BB9", r
3806
3806
  });
3807
3807
  return () => {
3808
3808
  cancelled = true;
3809
- cleanups.forEach((cleanup) => cleanup());
3809
+ cleanups.forEach((cleanup2) => cleanup2());
3810
3810
  };
3811
3811
  }, [html, imagePreview, resolveImageSrc]);
3812
3812
  function openImagePreview(target) {
@@ -4398,6 +4398,68 @@ function Treemap({
4398
4398
  );
4399
4399
  }
4400
4400
 
4401
+ // src/components/useScrollbarProximity.ts
4402
+ import { useEffect as useEffect11 } from "react";
4403
+ var users = 0;
4404
+ var cleanup;
4405
+ function useScrollbarProximity() {
4406
+ useEffect11(() => {
4407
+ if (users++ === 0) {
4408
+ let frame = 0;
4409
+ let x = -Infinity;
4410
+ let y = -Infinity;
4411
+ const nearby = /* @__PURE__ */ new Set();
4412
+ const clear = () => {
4413
+ nearby.forEach((track) => track.removeAttribute("data-scrollbar-near"));
4414
+ nearby.clear();
4415
+ };
4416
+ const update = () => {
4417
+ frame = 0;
4418
+ const next = /* @__PURE__ */ new Set();
4419
+ document.querySelectorAll(".sia-scrollbar-track").forEach((track) => {
4420
+ const rect = track.getBoundingClientRect();
4421
+ const proximity = Number.parseFloat(getComputedStyle(track).getPropertyValue("--sia-scrollbar-proximity")) || 16;
4422
+ if (rect.width && rect.height && x >= rect.left - proximity && x <= rect.right + proximity && y >= rect.top - proximity && y <= rect.bottom + proximity) {
4423
+ next.add(track);
4424
+ if (!nearby.has(track)) track.setAttribute("data-scrollbar-near", "true");
4425
+ }
4426
+ });
4427
+ nearby.forEach((track) => {
4428
+ if (!next.has(track)) track.removeAttribute("data-scrollbar-near");
4429
+ });
4430
+ nearby.clear();
4431
+ next.forEach((track) => nearby.add(track));
4432
+ };
4433
+ const move = (event) => {
4434
+ if (event.pointerType === "touch") return;
4435
+ x = event.clientX;
4436
+ y = event.clientY;
4437
+ if (!frame) frame = requestAnimationFrame(update);
4438
+ };
4439
+ const leave = () => {
4440
+ x = y = -Infinity;
4441
+ clear();
4442
+ };
4443
+ document.addEventListener("pointermove", move, { passive: true });
4444
+ document.documentElement.addEventListener("pointerleave", leave);
4445
+ window.addEventListener("blur", leave);
4446
+ cleanup = () => {
4447
+ if (frame) cancelAnimationFrame(frame);
4448
+ document.removeEventListener("pointermove", move);
4449
+ document.documentElement.removeEventListener("pointerleave", leave);
4450
+ window.removeEventListener("blur", leave);
4451
+ clear();
4452
+ };
4453
+ }
4454
+ return () => {
4455
+ if (--users === 0) {
4456
+ cleanup?.();
4457
+ cleanup = void 0;
4458
+ }
4459
+ };
4460
+ }, []);
4461
+ }
4462
+
4401
4463
  // src/components/Table/TableCellContent.tsx
4402
4464
  import { useLayoutEffect, useRef as useRef12, useState as useState15 } from "react";
4403
4465
  import { jsx as jsx19 } from "react/jsx-runtime";
@@ -4408,21 +4470,39 @@ function TableCellContent({ children, ellipsis, title }) {
4408
4470
  useLayoutEffect(() => {
4409
4471
  const element = ref.current;
4410
4472
  if (!element || !ellipsis || !customContent) return;
4411
- const update = () => setOverflowing(element.scrollWidth > element.clientWidth + 1);
4473
+ const layouts = [];
4474
+ const normalizeLayouts = (parent) => {
4475
+ for (const child of parent.children) {
4476
+ if (!(child instanceof HTMLElement)) continue;
4477
+ const component = [...child.classList].some((name) => name.startsWith("sia-") && !name.startsWith("sia-space") && name !== "sia-flex");
4478
+ if (component || child.matches("button, input, textarea, select, [contenteditable]")) continue;
4479
+ const display = getComputedStyle(child).display;
4480
+ if (["flex", "inline-flex", "grid", "inline-grid"].includes(display)) {
4481
+ child.setAttribute("data-table-inline-layout", "");
4482
+ layouts.push(child);
4483
+ }
4484
+ normalizeLayouts(child);
4485
+ }
4486
+ };
4487
+ normalizeLayouts(element);
4488
+ const update = () => setOverflowing(element.scrollWidth > element.clientWidth + 1 || element.scrollHeight > element.clientHeight + 1);
4412
4489
  update();
4413
4490
  const observer = new ResizeObserver(update);
4414
4491
  observer.observe(element);
4415
4492
  for (const child of element.children) observer.observe(child);
4416
- return () => observer.disconnect();
4493
+ return () => {
4494
+ observer.disconnect();
4495
+ layouts.forEach((layout) => layout.removeAttribute("data-table-inline-layout"));
4496
+ };
4417
4497
  }, [children, ellipsis, customContent]);
4418
- return /* @__PURE__ */ jsx19("div", { ref, className: "sia-table__cell-content", title, "data-content-overflow": ellipsis && customContent && overflowing || void 0, children });
4498
+ return /* @__PURE__ */ jsx19("div", { ref, className: "sia-table__cell-content", title, "data-custom-content": customContent || void 0, "data-content-overflow": ellipsis && customContent && overflowing || void 0, children });
4419
4499
  }
4420
4500
 
4421
4501
  // src/components/Table/Table.tsx
4422
- import { Fragment as Fragment7, forwardRef as forwardRef5, memo, useCallback as useCallback2, useEffect as useEffect12, useImperativeHandle, useMemo as useMemo9, useRef as useRef14, useState as useState17 } from "react";
4502
+ import { Fragment as Fragment7, forwardRef as forwardRef5, memo, useCallback as useCallback2, useEffect as useEffect13, useImperativeHandle, useMemo as useMemo9, useRef as useRef14, useState as useState17 } from "react";
4423
4503
 
4424
4504
  // src/components/Table/plugins.tsx
4425
- import { isValidElement as isValidElement3, useEffect as useEffect11, useRef as useRef13, useState as useState16 } from "react";
4505
+ import { isValidElement as isValidElement3, useEffect as useEffect12, useRef as useRef13, useState as useState16 } from "react";
4426
4506
 
4427
4507
  // src/components/Table/utils.ts
4428
4508
  var AUTO_WIDTH_COLUMN_KEYS = /* @__PURE__ */ new Set(["action", "actions", "operation", "operations"]);
@@ -5172,7 +5252,7 @@ function TableFilterControl({
5172
5252
  const [open, setOpen] = useState16(false);
5173
5253
  const [draft, setDraft] = useState16(value);
5174
5254
  const label = getColumnLabel(column);
5175
- useEffect11(() => {
5255
+ useEffect12(() => {
5176
5256
  if (open) setDraft(value);
5177
5257
  }, [open, value]);
5178
5258
  const apply = (nextValue) => {
@@ -5445,7 +5525,7 @@ function EditableTableCell({
5445
5525
  const savingRef = useRef13(false);
5446
5526
  const saveRef = useRef13(async () => {
5447
5527
  });
5448
- useEffect11(() => {
5528
+ useEffect12(() => {
5449
5529
  if (!active) return;
5450
5530
  editValueRef.current = value;
5451
5531
  setEditValue(value);
@@ -5476,7 +5556,7 @@ function EditableTableCell({
5476
5556
  }
5477
5557
  }
5478
5558
  saveRef.current = save;
5479
- useEffect11(() => {
5559
+ useEffect12(() => {
5480
5560
  if (!active || config.type === "select" || config.type === "custom") return;
5481
5561
  const handleOutsidePointerDown = (event) => {
5482
5562
  const target = event.target;
@@ -5637,7 +5717,7 @@ function applyColumnSettingsToTree(columns, items) {
5637
5717
  function ColumnSettingPanel({ open, items, columns, onClose, onApply }) {
5638
5718
  const [draft, setDraft] = useState16(items);
5639
5719
  const dragIndex = useRef13(null);
5640
- useEffect11(() => {
5720
+ useEffect12(() => {
5641
5721
  if (open) setDraft(items);
5642
5722
  }, [items, open]);
5643
5723
  const labels = new Map(flattenTableColumns(columns).map((column) => [column.key, getColumnLabel(column)]));
@@ -5732,7 +5812,30 @@ function createColumnSettingPlugin(options = {}) {
5732
5812
  void save({ columns: currentItems(context), pageSize, version: 1 });
5733
5813
  }
5734
5814
  },
5735
- renderToolbarEnd: options.showButton === false ? void 0 : (context) => /* @__PURE__ */ jsx20(Button, { size: "small", variant: "text", className: "sia-table__toolbar-icon", icon: /* @__PURE__ */ jsx20(Icon, { name: "settings", size: 16 }), "aria-label": "\u6253\u5F00\u5217\u8BBE\u7F6E", title: "\u5217\u8BBE\u7F6E", onClick: () => context.setState((state) => ({ ...state, open: true })) }),
5815
+ renderToolbarEnd: options.showButton === false ? void 0 : (context) => {
5816
+ const exportApi = () => context.getPluginApi("export") ?? createExportPlugin().getApi({ ...context, state: void 0, setState: () => {
5817
+ } });
5818
+ const customItems = (options.menuItems ?? []).filter((item) => !(item.hidden === true || typeof item.hidden === "function" && item.hidden(context)));
5819
+ const items = [
5820
+ ...options.showExport === false ? [] : [
5821
+ { key: "builtin:export", label: "\u8868\u683C\u5BFC\u51FA", icon: /* @__PURE__ */ jsx20(Icon, { name: "download", size: 18 }), disabled: exportApi().getRows().length === 0 },
5822
+ { key: "builtin:divider", type: "divider" }
5823
+ ],
5824
+ { key: "builtin:columns", label: "\u5217\u8BBE\u7F6E", icon: /* @__PURE__ */ jsx20(Icon, { name: "settings", size: 18 }) },
5825
+ ...customItems.map((item) => ({
5826
+ key: "custom:" + item.key,
5827
+ label: item.label,
5828
+ icon: item.icon,
5829
+ danger: item.danger,
5830
+ disabled: item.disabled === true || typeof item.disabled === "function" && item.disabled(context)
5831
+ }))
5832
+ ];
5833
+ return /* @__PURE__ */ jsx20(Dropdown, { trigger: ["hover", "click"], placement: "bottomRight", popupClassName: "sia-table__settings-dropdown", menu: { items, onClick: ({ key }) => {
5834
+ if (key === "builtin:export") void exportApi().download();
5835
+ else if (key === "builtin:columns") context.setState((state) => ({ ...state, open: true }));
5836
+ else void customItems.find((item) => "custom:" + item.key === key)?.onClick?.(context);
5837
+ } }, children: /* @__PURE__ */ jsx20(Button, { size: "small", variant: "text", className: "sia-table__toolbar-icon", icon: /* @__PURE__ */ jsx20(Icon, { name: "settings", size: 16 }), "aria-label": "\u8868\u683C\u8BBE\u7F6E" }) });
5838
+ },
5736
5839
  renderOverlay: (context) => /* @__PURE__ */ jsx20(ColumnSettingPanel, { open: context.state.open, items: currentItems(context), columns: context.baseColumns, onClose: () => context.setState((state) => ({ ...state, open: false })), onApply: (items) => apply(items, context) }),
5737
5840
  getApi: (context) => ({ open: () => context.setState((state) => ({ ...state, open: true })), close: () => context.setState((state) => ({ ...state, open: false })), getSettings: () => currentItems(context), apply: (items) => apply(items, context) })
5738
5841
  };
@@ -6017,6 +6120,7 @@ function TableInner(props, ref) {
6017
6120
  tableHeight,
6018
6121
  size = "medium",
6019
6122
  bordered = true,
6123
+ toolbarBordered = false,
6020
6124
  striped = true,
6021
6125
  virtual,
6022
6126
  virtualThreshold = 100,
@@ -6036,6 +6140,7 @@ function TableInner(props, ref) {
6036
6140
  const rootRef = useRef14(null);
6037
6141
  const scrollRef = useRef14(null);
6038
6142
  const tableRef = useRef14(null);
6143
+ useScrollbarProximity();
6039
6144
  const scrollbarDragRef = useRef14(null);
6040
6145
  const [internalLoading, setInternalLoading] = useState17(false);
6041
6146
  const [scrollTop, setScrollTop] = useState17(0);
@@ -6116,7 +6221,7 @@ function TableInner(props, ref) {
6116
6221
  });
6117
6222
  pluginApisRef.current = nextApis;
6118
6223
  contextsRef.current = contexts;
6119
- useEffect12(() => {
6224
+ useEffect13(() => {
6120
6225
  const activePlugins2 = new Map(sortedPlugins.map((plugin) => [plugin.id, plugin]));
6121
6226
  for (const [pluginId, mounted] of mountedPluginsRef.current) {
6122
6227
  if (activePlugins2.get(pluginId) === mounted.plugin) continue;
@@ -6128,7 +6233,7 @@ function TableInner(props, ref) {
6128
6233
  mountedPluginsRef.current.set(plugin.id, { plugin, cleanup: plugin.onMount(contextsRef.current.get(plugin.id)) });
6129
6234
  }
6130
6235
  }, [sortedPlugins]);
6131
- useEffect12(() => () => {
6236
+ useEffect13(() => () => {
6132
6237
  for (const mounted of mountedPluginsRef.current.values()) mounted.cleanup?.();
6133
6238
  mountedPluginsRef.current.clear();
6134
6239
  }, []);
@@ -6140,8 +6245,10 @@ function TableInner(props, ref) {
6140
6245
  if (element.scrollLeft > maxLeft) element.scrollLeft = maxLeft > 1 ? maxLeft : 0;
6141
6246
  const logicalScrollLeft = Math.min(element.scrollLeft, maxLeft);
6142
6247
  const maxTop = Math.max(0, element.scrollHeight - element.clientHeight);
6143
- const horizontalTrack = Math.max(0, element.clientWidth - 8);
6144
- const verticalTrack = Math.max(0, element.clientHeight - 8);
6248
+ root.dataset.overflowX = String(maxLeft > 1);
6249
+ root.dataset.overflowY = String(maxTop > 1);
6250
+ const horizontalTrack = root.querySelector(".sia-table__scrollbar--horizontal")?.clientWidth ?? 0;
6251
+ const verticalTrack = root.querySelector(".sia-table__scrollbar--vertical")?.clientHeight ?? 0;
6145
6252
  const horizontalThumb = maxLeft > 1 ? Math.min(horizontalTrack, Math.max(36, horizontalTrack * element.clientWidth / horizontalContentWidth)) : 0;
6146
6253
  const verticalThumb = maxTop > 1 ? Math.min(verticalTrack, Math.max(36, verticalTrack * element.clientHeight / element.scrollHeight)) : 0;
6147
6254
  const horizontalPosition = maxLeft > 0 ? logicalScrollLeft / maxLeft * Math.max(0, horizontalTrack - horizontalThumb) : 0;
@@ -6166,7 +6273,7 @@ function TableInner(props, ref) {
6166
6273
  root.style.setProperty("--sia-table-scrollbar-y-size", `${verticalThumb}px`);
6167
6274
  root.style.setProperty("--sia-table-scrollbar-y-position", `${verticalPosition}px`);
6168
6275
  }, []);
6169
- useEffect12(() => {
6276
+ useEffect13(() => {
6170
6277
  const element = scrollRef.current;
6171
6278
  if (!element || typeof ResizeObserver === "undefined") return;
6172
6279
  const observer = new ResizeObserver(() => {
@@ -6179,13 +6286,13 @@ function TableInner(props, ref) {
6179
6286
  updateScrollMetrics();
6180
6287
  return () => observer.disconnect();
6181
6288
  }, [updateScrollMetrics]);
6182
- useEffect12(() => {
6289
+ useEffect13(() => {
6183
6290
  updateScrollMetrics();
6184
6291
  });
6185
6292
  const orderedColumns = useMemo9(() => sortTableColumnsByFixed(pipeline.columns), [pipeline.columns]);
6186
6293
  const leafColumns = useMemo9(() => flattenTableColumns(orderedColumns), [orderedColumns]);
6187
6294
  const headerRows = useMemo9(() => buildHeaderRows(orderedColumns), [orderedColumns]);
6188
- useEffect12(() => {
6295
+ useEffect13(() => {
6189
6296
  const autoWidthColumns = leafColumns.filter((column) => column.autoWidth && resizedWidths[column.key] === void 0);
6190
6297
  const root = rootRef.current;
6191
6298
  if (!root || autoWidthColumns.length === 0) return;
@@ -6282,16 +6389,26 @@ function TableInner(props, ref) {
6282
6389
  if (shouldVirtualize) setScrollTop(element.scrollTop);
6283
6390
  updateScrollMetrics();
6284
6391
  }, [shouldVirtualize, updateScrollMetrics]);
6285
- const handleScrollbarPointerDown = useCallback2((axis, event) => {
6392
+ const handleScrollbarPointerDown = useCallback2((axis, event, track = event.currentTarget) => {
6286
6393
  const element = scrollRef.current;
6287
- const track = event.currentTarget.parentElement;
6288
- if (!element || !track) return;
6394
+ const thumb = track.firstElementChild;
6395
+ if (!element || !thumb || event.button !== 0) return;
6289
6396
  event.preventDefault();
6290
6397
  event.stopPropagation();
6291
- event.currentTarget.setPointerCapture(event.pointerId);
6398
+ track.setPointerCapture(event.pointerId);
6292
6399
  const trackLength = axis === "x" ? track.clientWidth : track.clientHeight;
6293
- const thumbLength = axis === "x" ? event.currentTarget.offsetWidth : event.currentTarget.offsetHeight;
6400
+ const thumbLength = axis === "x" ? thumb.offsetWidth : thumb.offsetHeight;
6294
6401
  const maxScroll = axis === "x" ? getTableHorizontalMetrics(element, tableRef.current).maxLeft : element.scrollHeight - element.clientHeight;
6402
+ const thumbRect = thumb.getBoundingClientRect();
6403
+ const coordinate = axis === "x" ? event.clientX : event.clientY;
6404
+ const thumbStart = axis === "x" ? thumbRect.left : thumbRect.top;
6405
+ if (coordinate < thumbStart || coordinate > thumbStart + thumbLength) {
6406
+ const trackRect = track.getBoundingClientRect();
6407
+ const trackStart = axis === "x" ? trackRect.left : trackRect.top;
6408
+ const ratio = Math.max(0, Math.min(1, (coordinate - trackStart - thumbLength / 2) / Math.max(1, trackLength - thumbLength)));
6409
+ if (axis === "x") element.scrollLeft = ratio * maxScroll;
6410
+ else element.scrollTop = ratio * maxScroll;
6411
+ }
6295
6412
  scrollbarDragRef.current = {
6296
6413
  axis,
6297
6414
  pointerId: event.pointerId,
@@ -6384,6 +6501,16 @@ function TableInner(props, ref) {
6384
6501
  };
6385
6502
  }, {});
6386
6503
  }
6504
+ function scrollbarAtPoint(event) {
6505
+ const tracks = rootRef.current?.querySelectorAll(".sia-table__scrollbar");
6506
+ for (const track of tracks ?? []) {
6507
+ if (track.closest(".sia-table") !== rootRef.current) continue;
6508
+ const rect = track.getBoundingClientRect();
6509
+ if (rect.width > 0 && rect.height > 0 && event.clientX >= rect.left && event.clientX < rect.right && event.clientY >= rect.top && event.clientY < rect.bottom) {
6510
+ return { track, axis: track.classList.contains("sia-table__scrollbar--vertical") ? "y" : "x" };
6511
+ }
6512
+ }
6513
+ }
6387
6514
  function renderSummaryRow(summary) {
6388
6515
  let labelRendered = false;
6389
6516
  return /* @__PURE__ */ jsx21("tr", { className: `sia-table__summary-row ${summary.className ?? ""}`.trim(), children: leafColumns.map((column) => {
@@ -6399,13 +6526,51 @@ function TableInner(props, ref) {
6399
6526
  "div",
6400
6527
  {
6401
6528
  ref: rootRef,
6402
- className: `sia-table sia-table--${size}${bordered ? " sia-table--bordered" : ""} ${className}`.trim(),
6529
+ className: `sia-table sia-table--${size}${bordered ? " sia-table--bordered" : ""}${hasToolbar && !toolbarBordered ? " sia-table--borderless-toolbar" : ""} ${className}`.trim(),
6403
6530
  style: rootStyle,
6404
6531
  "data-has-fixed-left": left > 0,
6405
6532
  "data-has-fixed-right": right > 0,
6406
6533
  "data-scrolled-left": "false",
6407
6534
  "data-scrolled-right": "true",
6408
6535
  ...htmlProps,
6536
+ onPointerDownCapture: (event) => {
6537
+ htmlProps.onPointerDownCapture?.(event);
6538
+ if (event.defaultPrevented || loading || internalLoading) return;
6539
+ const hit = scrollbarAtPoint(event);
6540
+ if (hit) handleScrollbarPointerDown(hit.axis, event, hit.track);
6541
+ },
6542
+ onPointerMoveCapture: (event) => {
6543
+ htmlProps.onPointerMoveCapture?.(event);
6544
+ const hit = scrollbarAtPoint(event);
6545
+ rootRef.current?.querySelectorAll(".sia-table__scrollbar").forEach((track) => {
6546
+ const hovered = track === hit?.track;
6547
+ if (hovered !== track.hasAttribute("data-pointer-hover")) track.toggleAttribute("data-pointer-hover", hovered);
6548
+ });
6549
+ if (hit || scrollbarDragRef.current) {
6550
+ handleScrollbarPointerMove(event);
6551
+ event.stopPropagation();
6552
+ }
6553
+ },
6554
+ onPointerLeave: (event) => {
6555
+ htmlProps.onPointerLeave?.(event);
6556
+ rootRef.current?.querySelectorAll("[data-pointer-hover]").forEach((track) => track.removeAttribute("data-pointer-hover"));
6557
+ },
6558
+ onClickCapture: (event) => {
6559
+ if (scrollbarAtPoint(event)) {
6560
+ event.preventDefault();
6561
+ event.stopPropagation();
6562
+ return;
6563
+ }
6564
+ htmlProps.onClickCapture?.(event);
6565
+ },
6566
+ onDoubleClickCapture: (event) => {
6567
+ if (scrollbarAtPoint(event)) {
6568
+ event.preventDefault();
6569
+ event.stopPropagation();
6570
+ return;
6571
+ }
6572
+ htmlProps.onDoubleClickCapture?.(event);
6573
+ },
6409
6574
  children: [
6410
6575
  hasToolbar ? /* @__PURE__ */ jsxs20("div", { className: "sia-table__toolbar", children: [
6411
6576
  /* @__PURE__ */ jsx21("div", { children: toolbarStart }),
@@ -6498,26 +6663,34 @@ function TableInner(props, ref) {
6498
6663
  summaries.length > 0 ? /* @__PURE__ */ jsx21("tfoot", { className: "sia-table__summary", children: summaries.map(renderSummaryRow) }) : null
6499
6664
  ] }) }),
6500
6665
  pipeline.rows.length === 0 ? /* @__PURE__ */ jsx21("div", { className: "sia-table__empty", role: "status", children: emptyText }) : null,
6501
- /* @__PURE__ */ jsx21("div", { className: "sia-scrollbar-track sia-table__scrollbar sia-table__scrollbar--horizontal", "aria-hidden": "true", children: /* @__PURE__ */ jsx21(
6666
+ /* @__PURE__ */ jsx21(
6502
6667
  "div",
6503
6668
  {
6504
- className: "sia-table__scrollbar-thumb",
6669
+ className: "sia-scrollbar-track sia-table__scrollbar sia-table__scrollbar--horizontal",
6670
+ "aria-hidden": "true",
6505
6671
  onPointerDown: (event) => handleScrollbarPointerDown("x", event),
6672
+ onClick: (event) => event.stopPropagation(),
6673
+ onDoubleClick: (event) => event.stopPropagation(),
6506
6674
  onPointerMove: handleScrollbarPointerMove,
6507
6675
  onPointerUp: handleScrollbarPointerEnd,
6508
- onPointerCancel: handleScrollbarPointerEnd
6676
+ onPointerCancel: handleScrollbarPointerEnd,
6677
+ children: /* @__PURE__ */ jsx21("div", { className: "sia-table__scrollbar-thumb" })
6509
6678
  }
6510
- ) }),
6511
- /* @__PURE__ */ jsx21("div", { className: "sia-scrollbar-track sia-table__scrollbar sia-table__scrollbar--vertical", "aria-hidden": "true", children: /* @__PURE__ */ jsx21(
6679
+ ),
6680
+ /* @__PURE__ */ jsx21(
6512
6681
  "div",
6513
6682
  {
6514
- className: "sia-table__scrollbar-thumb",
6683
+ className: "sia-scrollbar-track sia-table__scrollbar sia-table__scrollbar--vertical",
6684
+ "aria-hidden": "true",
6515
6685
  onPointerDown: (event) => handleScrollbarPointerDown("y", event),
6686
+ onClick: (event) => event.stopPropagation(),
6687
+ onDoubleClick: (event) => event.stopPropagation(),
6516
6688
  onPointerMove: handleScrollbarPointerMove,
6517
6689
  onPointerUp: handleScrollbarPointerEnd,
6518
- onPointerCancel: handleScrollbarPointerEnd
6690
+ onPointerCancel: handleScrollbarPointerEnd,
6691
+ children: /* @__PURE__ */ jsx21("div", { className: "sia-table__scrollbar-thumb" })
6519
6692
  }
6520
- ) })
6693
+ )
6521
6694
  ] }),
6522
6695
  footers.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "sia-table__footer", children: footers }) : null,
6523
6696
  loading || internalLoading ? /* @__PURE__ */ jsxs20("div", { className: "sia-table__loading", role: "status", children: [
@@ -6571,7 +6744,7 @@ var ThemeSwitch = forwardRef6(function ThemeSwitch2({
6571
6744
  });
6572
6745
 
6573
6746
  // src/components/FloatingScrollbarProvider.tsx
6574
- import { useEffect as useEffect13 } from "react";
6747
+ import { useEffect as useEffect14 } from "react";
6575
6748
  var scrollableOverflow = /* @__PURE__ */ new Set(["auto", "scroll", "overlay"]);
6576
6749
  var clippingOverflow = /* @__PURE__ */ new Set(["auto", "scroll", "overlay", "hidden", "clip"]);
6577
6750
  function isRootScroller(target) {
@@ -6634,7 +6807,8 @@ function createTrack(axis) {
6634
6807
  return { track, thumb };
6635
6808
  }
6636
6809
  function FloatingScrollbarProvider({ disabled = false }) {
6637
- useEffect13(() => {
6810
+ useScrollbarProximity();
6811
+ useEffect14(() => {
6638
6812
  if (disabled) return;
6639
6813
  const layer = document.createElement("div");
6640
6814
  layer.className = "sia-floating-scrollbar-layer";
@@ -6664,7 +6838,7 @@ function FloatingScrollbarProvider({ disabled = false }) {
6664
6838
  const hasHorizontal = canScroll(target, "horizontal");
6665
6839
  const hasVertical = canScroll(target, "vertical");
6666
6840
  const rect = visibleRect(target);
6667
- const thickness = 8;
6841
+ const thickness = 10;
6668
6842
  horizontalTrack.hidden = !hasHorizontal || rect.width <= thickness || rect.height <= 0;
6669
6843
  verticalTrack.hidden = !hasVertical || rect.height <= thickness || rect.width <= 0;
6670
6844
  if (!horizontalTrack.hidden) {
@@ -6903,7 +7077,7 @@ function applySiaTheme(mode, target = document.documentElement) {
6903
7077
  }
6904
7078
 
6905
7079
  // src/components/SelectionPanel.tsx
6906
- import { useEffect as useEffect14, useId as useId7, useMemo as useMemo10, useRef as useRef15, useState as useState18 } from "react";
7080
+ import { useEffect as useEffect15, useId as useId7, useMemo as useMemo10, useRef as useRef15, useState as useState18 } from "react";
6907
7081
  import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
6908
7082
  function SelectionPanel({
6909
7083
  options,
@@ -6964,7 +7138,7 @@ function SelectionPanel({
6964
7138
  const virtual = filtered.length > 100;
6965
7139
  const renderedRows = virtual ? rows.filter((row) => row.top + row.height >= scrollTop - 100 && row.top <= scrollTop + maxHeight + 100) : rows;
6966
7140
  const enabled = filtered.filter((option) => !option.disabled && option.optionType !== "divider");
6967
- useEffect14(() => {
7141
+ useEffect15(() => {
6968
7142
  setScrollTop(0);
6969
7143
  if (listRef.current) listRef.current.scrollTop = 0;
6970
7144
  setActive(void 0);
@@ -7074,7 +7248,7 @@ function SelectionPanel({
7074
7248
  }
7075
7249
 
7076
7250
  // src/components/InputSelect.tsx
7077
- import { forwardRef as forwardRef7, useEffect as useEffect15, useRef as useRef16, useState as useState19 } from "react";
7251
+ import { forwardRef as forwardRef7, useEffect as useEffect16, useRef as useRef16, useState as useState19 } from "react";
7078
7252
  import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
7079
7253
  var InputSelect = forwardRef7(function InputSelect2({
7080
7254
  options,
@@ -7106,7 +7280,7 @@ var InputSelect = forwardRef7(function InputSelect2({
7106
7280
  const values = current == null ? [] : Array.isArray(current) ? current : [current];
7107
7281
  const text = values.map((item) => displayField === "label" ? String(options.find((option) => option.optionType !== "divider" && option.value === item)?.label ?? item) : String(item)).join(",");
7108
7282
  const [draft, setDraft] = useState19(text);
7109
- useEffect15(() => {
7283
+ useEffect16(() => {
7110
7284
  setDraft(text);
7111
7285
  }, [text, current]);
7112
7286
  const [open, setOpen] = useState19(false);
@@ -7136,7 +7310,7 @@ var InputSelect = forwardRef7(function InputSelect2({
7136
7310
  inputRef.current?.focus();
7137
7311
  }
7138
7312
  }
7139
- useEffect15(() => {
7313
+ useEffect16(() => {
7140
7314
  if (!open) return;
7141
7315
  const outside = (event) => {
7142
7316
  if (!rootRef.current?.contains(event.target) && !popupRef.current?.contains(event.target)) changeOpen(false);
@@ -7144,7 +7318,7 @@ var InputSelect = forwardRef7(function InputSelect2({
7144
7318
  document.addEventListener("pointerdown", outside);
7145
7319
  return () => document.removeEventListener("pointerdown", outside);
7146
7320
  }, [open, onOpenChange]);
7147
- useEffect15(() => {
7321
+ useEffect16(() => {
7148
7322
  if (disabled || loading) {
7149
7323
  changeOpen(false);
7150
7324
  setModalOpen(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sia.soul/sia-react-ui",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Sia Design components and tokens for React",
5
5
  "publishConfig": {
6
6
  "access": "public",