@sia.soul/sia-react-ui 0.1.52 → 0.1.53

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.css CHANGED
@@ -2190,14 +2190,24 @@ fieldset:disabled .sia-input-number__floating-placeholder {
2190
2190
  overflow: var(--sia-scroll-overflow, auto);
2191
2191
  padding: 10vh 16px 32px;
2192
2192
  color: var(--sia-color-text);
2193
+ isolation: isolate;
2194
+ }
2195
+ .sia-modal-root::before {
2196
+ content: "";
2197
+ position: fixed;
2198
+ inset: 0;
2199
+ z-index: 0;
2193
2200
  background: rgb(0 0 0 / 45%);
2194
- animation: sia-modal-mask-in 200ms ease both;
2201
+ animation: sia-modal-mask-in 220ms ease both;
2202
+ will-change: opacity;
2195
2203
  }
2196
2204
  .sia-modal-root--centered {
2197
2205
  align-items: center;
2198
2206
  padding-block: 24px;
2199
2207
  }
2200
2208
  .sia-modal {
2209
+ position: relative;
2210
+ z-index: 1;
2201
2211
  width: min(var(--sia-modal-width), calc(100vw - 32px));
2202
2212
  overflow: hidden;
2203
2213
  background: var(--sia-color-surface);
@@ -2210,6 +2220,8 @@ fieldset:disabled .sia-input-number__floating-placeholder {
2210
2220
  }
2211
2221
  .sia-modal-root[data-state=closing] {
2212
2222
  pointer-events: none;
2223
+ }
2224
+ .sia-modal-root[data-state=closing]::before {
2213
2225
  animation: sia-modal-mask-out 220ms ease both;
2214
2226
  }
2215
2227
  .sia-modal-root[data-state=closing] .sia-modal {
@@ -4401,12 +4413,18 @@ fieldset:disabled .sia-input-number__floating-placeholder {
4401
4413
  }
4402
4414
  @keyframes sia-modal-mask-in {
4403
4415
  from {
4404
- background-color: rgb(0 0 0 / 0%);
4416
+ opacity: 0;
4417
+ }
4418
+ to {
4419
+ opacity: 1;
4405
4420
  }
4406
4421
  }
4407
4422
  @keyframes sia-modal-mask-out {
4423
+ from {
4424
+ opacity: 1;
4425
+ }
4408
4426
  to {
4409
- background-color: rgb(0 0 0 / 0%);
4427
+ opacity: 0;
4410
4428
  }
4411
4429
  }
4412
4430
  @keyframes sia-modal-slide-in {
@@ -4554,7 +4572,7 @@ fieldset:disabled .sia-input-number__floating-placeholder {
4554
4572
  .sia-button::after,
4555
4573
  .sia-icon--spin,
4556
4574
  .sia-icon--pulse,
4557
- .sia-modal-root,
4575
+ .sia-modal-root::before,
4558
4576
  .sia-modal,
4559
4577
  .sia-drawer,
4560
4578
  .sia-drawer__mask,
package/dist/index.d.cts CHANGED
@@ -2109,6 +2109,19 @@ interface TableProps<T extends Record<string, unknown> = Record<string, unknown>
2109
2109
  emptyText?: ReactNode;
2110
2110
  /** 高度;数值按像素处理,字符串可使用 CSS 尺寸。 */
2111
2111
  height?: number | string;
2112
+ /**
2113
+ * 自动填充从表格顶部到可视区域底部的剩余高度,包含工具栏和分页;true 使用当前窗口视口。
2114
+ * 查询区尺寸、祖先布局、窗口尺寸及隐藏页签显示后自动重测。height / tableHeight 显式设置时优先。
2115
+ * 默认关闭;不要同时使用依赖表格自身高度的容器或垂直居中布局。
2116
+ */
2117
+ fillRemaining?: boolean | {
2118
+ /** 返回具有独立确定高度的容器,按其内边距内侧底边计算;默认使用窗口视口,返回 null 时等待容器就绪。 */
2119
+ container?: () => HTMLElement | null;
2120
+ /** 从可用高度中额外扣除的底部留白,单位 px,默认 0;不自动预留表格之后的兄弟内容。 */
2121
+ bottomOffset?: number;
2122
+ /** 最小总高度,单位 px,默认 0;超过可用空间时允许溢出,以保证最低可操作区域。 */
2123
+ minHeight?: number;
2124
+ };
2112
2125
  /** 表格滚动区域的高度。 */
2113
2126
  tableHeight?: number | string;
2114
2127
  /**
package/dist/index.d.ts CHANGED
@@ -2109,6 +2109,19 @@ interface TableProps<T extends Record<string, unknown> = Record<string, unknown>
2109
2109
  emptyText?: ReactNode;
2110
2110
  /** 高度;数值按像素处理,字符串可使用 CSS 尺寸。 */
2111
2111
  height?: number | string;
2112
+ /**
2113
+ * 自动填充从表格顶部到可视区域底部的剩余高度,包含工具栏和分页;true 使用当前窗口视口。
2114
+ * 查询区尺寸、祖先布局、窗口尺寸及隐藏页签显示后自动重测。height / tableHeight 显式设置时优先。
2115
+ * 默认关闭;不要同时使用依赖表格自身高度的容器或垂直居中布局。
2116
+ */
2117
+ fillRemaining?: boolean | {
2118
+ /** 返回具有独立确定高度的容器,按其内边距内侧底边计算;默认使用窗口视口,返回 null 时等待容器就绪。 */
2119
+ container?: () => HTMLElement | null;
2120
+ /** 从可用高度中额外扣除的底部留白,单位 px,默认 0;不自动预留表格之后的兄弟内容。 */
2121
+ bottomOffset?: number;
2122
+ /** 最小总高度,单位 px,默认 0;超过可用空间时允许溢出,以保证最低可操作区域。 */
2123
+ minHeight?: number;
2124
+ };
2112
2125
  /** 表格滚动区域的高度。 */
2113
2126
  tableHeight?: number | string;
2114
2127
  /**
package/dist/index.js CHANGED
@@ -4751,8 +4751,86 @@ function TableCellContent({ children, ellipsis, title }) {
4751
4751
  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 });
4752
4752
  }
4753
4753
 
4754
+ // src/components/Table/useRemainingHeight.ts
4755
+ import { useLayoutEffect as useLayoutEffect4, useState as useState17 } from "react";
4756
+ function useRemainingHeight(rootRef, options) {
4757
+ const [height, setHeight] = useState17();
4758
+ const enabled = !!options;
4759
+ const container = typeof options === "object" ? options.container : void 0;
4760
+ const bottomOffset = typeof options === "object" ? options.bottomOffset ?? 0 : 0;
4761
+ const minHeight = typeof options === "object" ? options.minHeight ?? 0 : 0;
4762
+ useLayoutEffect4(() => {
4763
+ const root = rootRef.current;
4764
+ if (!enabled || !root) return;
4765
+ const win = root.ownerDocument.defaultView;
4766
+ if (!win) return;
4767
+ let frame = 0;
4768
+ let disposed = false;
4769
+ const observed = /* @__PURE__ */ new Set();
4770
+ const observe = (element) => {
4771
+ if (observed.has(element)) return;
4772
+ observed.add(element);
4773
+ resize?.observe(element);
4774
+ };
4775
+ const measure = () => {
4776
+ frame = 0;
4777
+ if (disposed || !root.isConnected || !root.getClientRects().length) return;
4778
+ const target = container?.();
4779
+ if (container && (!target || !target.getClientRects().length)) return;
4780
+ let branch = root;
4781
+ while (branch.parentElement) {
4782
+ const parent = branch.parentElement;
4783
+ observe(parent);
4784
+ for (const sibling of parent.children) if (sibling !== branch) observe(sibling);
4785
+ branch = parent;
4786
+ }
4787
+ if (target) observe(target);
4788
+ const viewport = win.visualViewport;
4789
+ const bottom = target ? target.getBoundingClientRect().top + target.clientTop + target.clientHeight - (parseFloat(win.getComputedStyle(target).paddingBottom) || 0) : viewport ? viewport.offsetTop + viewport.height : win.innerHeight;
4790
+ const next = Math.max(0, minHeight, Math.floor(bottom - root.getBoundingClientRect().top - bottomOffset));
4791
+ setHeight((previous) => previous === next ? previous : next);
4792
+ };
4793
+ const schedule = () => {
4794
+ if (!disposed && !frame) frame = win.requestAnimationFrame(measure);
4795
+ };
4796
+ const onScroll = (event) => {
4797
+ if (event.target instanceof Node && root.contains(event.target)) return;
4798
+ schedule();
4799
+ };
4800
+ const onMotionEnd = (event) => {
4801
+ if (event.target instanceof Element && event.target.contains(root)) schedule();
4802
+ };
4803
+ const resize = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(schedule);
4804
+ const mutation = new MutationObserver(schedule);
4805
+ for (let node = root.parentElement; node; node = node.parentElement) {
4806
+ mutation.observe(node, { attributes: true, attributeFilter: ["style", "class", "hidden"], childList: true });
4807
+ }
4808
+ measure();
4809
+ schedule();
4810
+ win.addEventListener("resize", schedule);
4811
+ win.addEventListener("scroll", onScroll, true);
4812
+ win.addEventListener("transitionend", onMotionEnd, true);
4813
+ win.addEventListener("animationend", onMotionEnd, true);
4814
+ win.visualViewport?.addEventListener("resize", schedule);
4815
+ win.visualViewport?.addEventListener("scroll", schedule);
4816
+ return () => {
4817
+ disposed = true;
4818
+ win.cancelAnimationFrame(frame);
4819
+ resize?.disconnect();
4820
+ mutation.disconnect();
4821
+ win.removeEventListener("resize", schedule);
4822
+ win.removeEventListener("scroll", onScroll, true);
4823
+ win.removeEventListener("transitionend", onMotionEnd, true);
4824
+ win.removeEventListener("animationend", onMotionEnd, true);
4825
+ win.visualViewport?.removeEventListener("resize", schedule);
4826
+ win.visualViewport?.removeEventListener("scroll", schedule);
4827
+ };
4828
+ }, [rootRef, enabled, container, bottomOffset, minHeight]);
4829
+ return enabled ? height : void 0;
4830
+ }
4831
+
4754
4832
  // src/components/Table/TableCanvasLayer.tsx
4755
- import { useLayoutEffect as useLayoutEffect4, useRef as useRef14 } from "react";
4833
+ import { useLayoutEffect as useLayoutEffect5, useRef as useRef14 } from "react";
4756
4834
 
4757
4835
  // src/components/Table/utils.ts
4758
4836
  var AUTO_WIDTH_COLUMN_KEYS = /* @__PURE__ */ new Set(["action", "actions", "operation", "operations"]);
@@ -4808,7 +4886,7 @@ function toTablePageParams(current, pageSize) {
4808
4886
  import { jsx as jsx21 } from "react/jsx-runtime";
4809
4887
  function TableCanvasLayer({ viewport, rows, columns, widths, rowHeight, headerHeight }) {
4810
4888
  const canvasRef = useRef14(null);
4811
- useLayoutEffect4(() => {
4889
+ useLayoutEffect5(() => {
4812
4890
  const canvas = canvasRef.current;
4813
4891
  const scroller = viewport.current;
4814
4892
  if (!canvas || !scroller) return;
@@ -4935,10 +5013,10 @@ function TableCanvasLayer({ viewport, rows, columns, widths, rowHeight, headerHe
4935
5013
  }
4936
5014
 
4937
5015
  // src/components/Table/Table.tsx
4938
- import { Fragment as Fragment8, forwardRef as forwardRef5, isValidElement as isValidElement4, memo, useCallback as useCallback2, useEffect as useEffect12, useImperativeHandle, useMemo as useMemo9, useRef as useRef16, useState as useState18 } from "react";
5016
+ import { Fragment as Fragment8, forwardRef as forwardRef5, isValidElement as isValidElement4, memo, useCallback as useCallback2, useEffect as useEffect12, useImperativeHandle, useMemo as useMemo9, useRef as useRef16, useState as useState19 } from "react";
4939
5017
 
4940
5018
  // src/components/Table/plugins.tsx
4941
- import { isValidElement as isValidElement3, useEffect as useEffect11, useRef as useRef15, useState as useState17 } from "react";
5019
+ import { isValidElement as isValidElement3, useEffect as useEffect11, useRef as useRef15, useState as useState18 } from "react";
4942
5020
  import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4943
5021
  function TableCheckbox({
4944
5022
  checked,
@@ -5565,7 +5643,7 @@ function TableSelectedItemsPanel({
5565
5643
  onRemove,
5566
5644
  onClear
5567
5645
  }) {
5568
- const [showAll, setShowAll] = useState17(false);
5646
+ const [showAll, setShowAll] = useState18(false);
5569
5647
  const visibleEntries = showAll ? entries : entries.slice(0, maxCount);
5570
5648
  const hiddenCount = Math.max(0, entries.length - visibleEntries.length);
5571
5649
  const baseColumnMap = new Map(
@@ -5964,8 +6042,8 @@ function TableFilterControl({
5964
6042
  placeholder,
5965
6043
  onApply
5966
6044
  }) {
5967
- const [open, setOpen] = useState17(false);
5968
- const [draft, setDraft] = useState17(value);
6045
+ const [open, setOpen] = useState18(false);
6046
+ const [draft, setDraft] = useState18(value);
5969
6047
  const label = getColumnLabel(column);
5970
6048
  useEffect11(() => {
5971
6049
  if (open) setDraft(value);
@@ -6392,8 +6470,8 @@ function EditableTableCell({
6392
6470
  trigger
6393
6471
  }) {
6394
6472
  const config = typeof editable === "object" ? editable : { type: "input" };
6395
- const [editValue, setEditValue] = useState17(value);
6396
- const [saving, setSaving] = useState17(false);
6473
+ const [editValue, setEditValue] = useState18(value);
6474
+ const [saving, setSaving] = useState18(false);
6397
6475
  const inputRef = useRef15(null);
6398
6476
  const editorRef = useRef15(null);
6399
6477
  const editValueRef = useRef15(value);
@@ -6738,10 +6816,10 @@ function ColumnSettingPanel({
6738
6816
  onClose,
6739
6817
  onApply
6740
6818
  }) {
6741
- const [draft, setDraft] = useState17(items);
6819
+ const [draft, setDraft] = useState18(items);
6742
6820
  const listRef = useRef15(null);
6743
6821
  const cancelDrag = useRef15(null);
6744
- const [preview, setPreview] = useState17(null);
6822
+ const [preview, setPreview] = useState18(null);
6745
6823
  useEffect11(() => {
6746
6824
  cancelDrag.current?.();
6747
6825
  if (open) setDraft(orderColumnSettings(items));
@@ -7541,6 +7619,7 @@ function TableInner(props, ref) {
7541
7619
  emptyText = "\u6682\u65E0\u6570\u636E",
7542
7620
  height,
7543
7621
  tableHeight,
7622
+ fillRemaining,
7544
7623
  size = "medium",
7545
7624
  bordered = true,
7546
7625
  rowBordered = true,
@@ -7566,16 +7645,17 @@ function TableInner(props, ref) {
7566
7645
  ...htmlProps
7567
7646
  } = props;
7568
7647
  const rootRef = useRef16(null);
7648
+ const remainingHeight = useRemainingHeight(rootRef, height == null && tableHeight == null ? fillRemaining : false);
7569
7649
  const scrollRef = useRef16(null);
7570
7650
  const tableRef = useRef16(null);
7571
7651
  useScrollbarProximity();
7572
7652
  const scrollbarDragRef = useRef16(null);
7573
- const [internalLoading, setInternalLoading] = useState18(false);
7574
- const [scrollTop, setScrollTop] = useState18(0);
7575
- const [scrollLeft, setScrollLeft] = useState18(0);
7576
- const [viewportHeight, setViewportHeight] = useState18(420);
7577
- const [viewportWidth, setViewportWidth] = useState18(0);
7578
- const [autoColumnWidths, setAutoColumnWidths] = useState18({});
7653
+ const [internalLoading, setInternalLoading] = useState19(false);
7654
+ const [scrollTop, setScrollTop] = useState19(0);
7655
+ const [scrollLeft, setScrollLeft] = useState19(0);
7656
+ const [viewportHeight, setViewportHeight] = useState19(420);
7657
+ const [viewportWidth, setViewportWidth] = useState19(0);
7658
+ const [autoColumnWidths, setAutoColumnWidths] = useState19({});
7579
7659
  const getRowKey = useCallback2((record, index) => typeof rowKey === "function" ? rowKey(record, index) : record[String(rowKey)] ?? index, [rowKey]);
7580
7660
  const builtInResizePlugin = useMemo9(() => createResizePlugin(), []);
7581
7661
  const builtInHighlightPlugin = useMemo9(() => createHighlightPlugin(), []);
@@ -7592,7 +7672,7 @@ function TableInner(props, ref) {
7592
7672
  const sortedPlugins = useMemo9(() => [...activePlugins].sort((a, b) => (a.order ?? 100) - (b.order ?? 100)), [activePlugins]);
7593
7673
  const pluginsByIdRef = useRef16(/* @__PURE__ */ new Map());
7594
7674
  pluginsByIdRef.current = new Map(sortedPlugins.map((plugin) => [plugin.id, plugin]));
7595
- const [pluginStates, setPluginStates] = useState18(() => Object.fromEntries(
7675
+ const [pluginStates, setPluginStates] = useState19(() => Object.fromEntries(
7596
7676
  sortedPlugins.map((plugin) => [plugin.id, resolveInitialState(plugin)])
7597
7677
  ));
7598
7678
  const pluginApisRef = useRef16({});
@@ -7854,7 +7934,7 @@ function TableInner(props, ref) {
7854
7934
  return content ? /* @__PURE__ */ jsx23(Fragment8, { children: content }, `overlay-${plugin.id}`) : null;
7855
7935
  }).filter(Boolean);
7856
7936
  const hasToolbar = toolbarStart.length > 0 || toolbarEnd.length > 0;
7857
- const effectiveHeight = height ?? tableHeight ?? (shouldVirtualize ? 420 : void 0);
7937
+ const effectiveHeight = height ?? tableHeight ?? remainingHeight ?? (shouldVirtualize ? 420 : void 0);
7858
7938
  const rootStyle = {
7859
7939
  ...style,
7860
7940
  height: effectiveHeight,
@@ -8266,7 +8346,7 @@ function applySiaTheme(mode, target = document.documentElement) {
8266
8346
  }
8267
8347
 
8268
8348
  // src/components/InputSelect.tsx
8269
- import { forwardRef as forwardRef7, useEffect as useEffect13, useRef as useRef17, useState as useState19 } from "react";
8349
+ import { forwardRef as forwardRef7, useEffect as useEffect13, useRef as useRef17, useState as useState20 } from "react";
8270
8350
  import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
8271
8351
  var InputSelect = forwardRef7(function InputSelect2({
8272
8352
  options,
@@ -8294,19 +8374,19 @@ var InputSelect = forwardRef7(function InputSelect2({
8294
8374
  ...inputProps
8295
8375
  }, forwardedRef) {
8296
8376
  const size = useControlSize(sizeProp);
8297
- const [internal, setInternal] = useState19(defaultValue);
8377
+ const [internal, setInternal] = useState20(defaultValue);
8298
8378
  const current = value !== void 0 ? value : internal;
8299
8379
  const values = current == null ? [] : Array.isArray(current) ? current : [current];
8300
8380
  const text = values.map((item) => displayField === "label" ? String(options.find((option) => option.optionType !== "divider" && option.value === item)?.label ?? item) : String(item)).join(",");
8301
- const [draft, setDraft] = useState19(text);
8381
+ const [draft, setDraft] = useState20(text);
8302
8382
  useEffect13(() => {
8303
8383
  setDraft(text);
8304
8384
  }, [text, current]);
8305
- const [open, setOpen] = useState19(false);
8306
- const [search, setSearch] = useState19("");
8307
- const [modalOpen, setModalOpen] = useState19(false);
8308
- const [modalValues, setModalValues] = useState19([]);
8309
- const [selectedOnly, setSelectedOnly] = useState19(false);
8385
+ const [open, setOpen] = useState20(false);
8386
+ const [search, setSearch] = useState20("");
8387
+ const [modalOpen, setModalOpen] = useState20(false);
8388
+ const [modalValues, setModalValues] = useState20([]);
8389
+ const [selectedOnly, setSelectedOnly] = useState20(false);
8310
8390
  const rootRef = useRef17(null);
8311
8391
  const popupRef = useRef17(null);
8312
8392
  const inputRef = useRef17(null);
@@ -8470,7 +8550,7 @@ var InputSelect = forwardRef7(function InputSelect2({
8470
8550
  });
8471
8551
 
8472
8552
  // src/components/QueryForm.tsx
8473
- import { Children as Children4, useLayoutEffect as useLayoutEffect5, useRef as useRef18, useState as useState20 } from "react";
8553
+ import { Children as Children4, useLayoutEffect as useLayoutEffect6, useRef as useRef18, useState as useState21 } from "react";
8474
8554
  import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
8475
8555
  function QueryForm({
8476
8556
  fields,
@@ -8504,17 +8584,17 @@ function QueryForm({
8504
8584
  ...formProps
8505
8585
  }) {
8506
8586
  const [form] = useForm(providedForm);
8507
- const [internalCollapsed, setInternalCollapsed] = useState20(defaultCollapsed);
8508
- const [needsCollapse, setNeedsCollapse] = useState20(false);
8587
+ const [internalCollapsed, setInternalCollapsed] = useState21(defaultCollapsed);
8588
+ const [needsCollapse, setNeedsCollapse] = useState21(false);
8509
8589
  const collapsed = collapsible && needsCollapse && (controlledCollapsed ?? internalCollapsed);
8510
- const [searching, setSearching] = useState20(false);
8511
- const [saving, setSaving] = useState20(false);
8512
- const [removing, setRemoving] = useState20(false);
8513
- const [saveOpen, setSaveOpen] = useState20(false);
8514
- const [saveName, setSaveName] = useState20("");
8515
- const [saveError, setSaveError] = useState20("");
8516
- const [error, setError] = useState20("");
8517
- const [activeShortcut, setActiveShortcut] = useState20("");
8590
+ const [searching, setSearching] = useState21(false);
8591
+ const [saving, setSaving] = useState21(false);
8592
+ const [removing, setRemoving] = useState21(false);
8593
+ const [saveOpen, setSaveOpen] = useState21(false);
8594
+ const [saveName, setSaveName] = useState21("");
8595
+ const [saveError, setSaveError] = useState21("");
8596
+ const [error, setError] = useState21("");
8597
+ const [activeShortcut, setActiveShortcut] = useState21("");
8518
8598
  const source = useRef18({ source: "submit" });
8519
8599
  const searchLock = useRef18(false);
8520
8600
  const saveLock = useRef18(false);
@@ -8527,8 +8607,8 @@ function QueryForm({
8527
8607
  const rowRef = useRef18(null);
8528
8608
  const actionsRef = useRef18(null);
8529
8609
  const toggleRef = useRef18(null);
8530
- const [fittingCount, setFittingCount] = useState20(limit);
8531
- useLayoutEffect5(() => {
8610
+ const [fittingCount, setFittingCount] = useState21(limit);
8611
+ useLayoutEffect6(() => {
8532
8612
  const row = rowRef.current;
8533
8613
  const actions = actionsRef.current;
8534
8614
  if (!row || !actions) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sia.soul/sia-react-ui",
3
- "version": "0.1.52",
3
+ "version": "0.1.53",
4
4
  "description": "Sia Design components and tokens for React",
5
5
  "publishConfig": {
6
6
  "access": "public",