@sia.soul/sia-react-ui 0.1.48 → 0.1.51

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.
@@ -467,7 +467,7 @@ type MenuItem = {
467
467
  icon?: ReactNode;
468
468
  /** 主体之外的补充内容或操作区。 */
469
469
  extra?: ReactNode;
470
- /** 标题内容,可传入文本或 React 节点。 */
470
+ /** 菜单项的悬停提示文字,停留 600ms 后显示,禁用项同样支持;收起的图标菜单未设置时使用纯文本 label。 */
471
471
  title?: string;
472
472
  /** 是否禁用交互。 */
473
473
  disabled?: boolean;
@@ -467,7 +467,7 @@ type MenuItem = {
467
467
  icon?: ReactNode;
468
468
  /** 主体之外的补充内容或操作区。 */
469
469
  extra?: ReactNode;
470
- /** 标题内容,可传入文本或 React 节点。 */
470
+ /** 菜单项的悬停提示文字,停留 600ms 后显示,禁用项同样支持;收起的图标菜单未设置时使用纯文本 label。 */
471
471
  title?: string;
472
472
  /** 是否禁用交互。 */
473
473
  disabled?: boolean;
package/dist/core.css CHANGED
@@ -7458,11 +7458,15 @@ fieldset:disabled .sia-input-number__floating-placeholder {
7458
7458
  }
7459
7459
  .sia-form-item {
7460
7460
  display: grid;
7461
- grid-template-columns: minmax(90px, 140px) minmax(0, 1fr);
7461
+ grid-template-columns: var(--sia-form-label-width, var(--sia-form-auto-label-width, 0px)) minmax(0, 1fr);
7462
7462
  gap: 8px 14px;
7463
7463
  margin-bottom: 6px;
7464
7464
  color: var(--sia-color-text);
7465
7465
  }
7466
+ .sia-form-item__label-content {
7467
+ display: inline-block;
7468
+ width: max-content;
7469
+ }
7466
7470
  .sia-form-item__label {
7467
7471
  padding-top: 8px;
7468
7472
  text-align: right;
@@ -7554,6 +7558,7 @@ fieldset:disabled .sia-input-number__floating-placeholder {
7554
7558
  gap: 8px;
7555
7559
  }
7556
7560
  .sia-form--inline .sia-form-item__label {
7561
+ flex: 0 0 var(--sia-form-label-width, var(--sia-form-auto-label-width, 0px));
7557
7562
  text-align: left;
7558
7563
  }
7559
7564
  .sia-form-error-list {
package/dist/core.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { d as Breadcrumb, e as BreadcrumbItem, f as BreadcrumbProps, h as Card, i as CardAccent, j as CardProps, n as Collapse, o as CollapseItem, p as CollapseKey, q as CollapseProps, x as FilledIconName, y as FloatButton, z as FloatButtonBackTopProps, A as FloatButtonGroupProps, E as FloatButtonProps, G as FloatButtonShape, K as Icon, L as IconName, M as IconProps, N as IconVariant, U as Input, V as InputProps, a0 as MessageConfig, a1 as MessageHandle, a2 as MessageKey, a3 as MessageType, ab as Progress, ac as ProgressProps, ad as ProgressStatus, ag as Segmented, ah as SegmentedOption, ai as SegmentedProps, aj as SegmentedValue, aq as TabItem, ar as Tabs, at as TabsOrientation, au as TabsPosition, av as TabsProps, aw as TabsType, ax as Tag, ay as TagProps, az as TagSize, T as TagStatus, aA as TagVariant, aE as Toolbar, aF as ToolbarItem, aG as ToolbarProps, aR as Typography, aS as TypographyLinkProps, aT as TypographyProps, aU as TypographyTitleProps, aV as TypographyType, aW as Upload, aX as UploadChangeInfo, aY as UploadDraggerProps, aZ as UploadFile, a_ as UploadFileStatus, b1 as UploadProps, b5 as UploadRequestOptions, b9 as message } from './core-D2IjiQhj.cjs';
1
+ export { d as Breadcrumb, e as BreadcrumbItem, f as BreadcrumbProps, h as Card, i as CardAccent, j as CardProps, n as Collapse, o as CollapseItem, p as CollapseKey, q as CollapseProps, x as FilledIconName, y as FloatButton, z as FloatButtonBackTopProps, A as FloatButtonGroupProps, E as FloatButtonProps, G as FloatButtonShape, K as Icon, L as IconName, M as IconProps, N as IconVariant, U as Input, V as InputProps, a0 as MessageConfig, a1 as MessageHandle, a2 as MessageKey, a3 as MessageType, ab as Progress, ac as ProgressProps, ad as ProgressStatus, ag as Segmented, ah as SegmentedOption, ai as SegmentedProps, aj as SegmentedValue, aq as TabItem, ar as Tabs, at as TabsOrientation, au as TabsPosition, av as TabsProps, aw as TabsType, ax as Tag, ay as TagProps, az as TagSize, T as TagStatus, aA as TagVariant, aE as Toolbar, aF as ToolbarItem, aG as ToolbarProps, aR as Typography, aS as TypographyLinkProps, aT as TypographyProps, aU as TypographyTitleProps, aV as TypographyType, aW as Upload, aX as UploadChangeInfo, aY as UploadDraggerProps, aZ as UploadFile, a_ as UploadFileStatus, b1 as UploadProps, b5 as UploadRequestOptions, b9 as message } from './core-KIaXZ4_O.cjs';
2
2
  export { f as Button, B as ButtonProps, e as ButtonSize, g as ButtonVariant, h as Modal, d as ModalActionResult, M as ModalOpenConfig, i as ModalProps, j as ModalType, a as OverlayApiHandle, k as Select, S as SelectOption, c as SelectProps, m as SelectValue } from './Select-YJbT-MF1.cjs';
3
3
  import 'react';
4
4
  import './shared-Bx4B28Wh.cjs';
package/dist/core.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { d as Breadcrumb, e as BreadcrumbItem, f as BreadcrumbProps, h as Card, i as CardAccent, j as CardProps, n as Collapse, o as CollapseItem, p as CollapseKey, q as CollapseProps, x as FilledIconName, y as FloatButton, z as FloatButtonBackTopProps, A as FloatButtonGroupProps, E as FloatButtonProps, G as FloatButtonShape, K as Icon, L as IconName, M as IconProps, N as IconVariant, U as Input, V as InputProps, a0 as MessageConfig, a1 as MessageHandle, a2 as MessageKey, a3 as MessageType, ab as Progress, ac as ProgressProps, ad as ProgressStatus, ag as Segmented, ah as SegmentedOption, ai as SegmentedProps, aj as SegmentedValue, aq as TabItem, ar as Tabs, at as TabsOrientation, au as TabsPosition, av as TabsProps, aw as TabsType, ax as Tag, ay as TagProps, az as TagSize, T as TagStatus, aA as TagVariant, aE as Toolbar, aF as ToolbarItem, aG as ToolbarProps, aR as Typography, aS as TypographyLinkProps, aT as TypographyProps, aU as TypographyTitleProps, aV as TypographyType, aW as Upload, aX as UploadChangeInfo, aY as UploadDraggerProps, aZ as UploadFile, a_ as UploadFileStatus, b1 as UploadProps, b5 as UploadRequestOptions, b9 as message } from './core-Bb0160em.js';
1
+ export { d as Breadcrumb, e as BreadcrumbItem, f as BreadcrumbProps, h as Card, i as CardAccent, j as CardProps, n as Collapse, o as CollapseItem, p as CollapseKey, q as CollapseProps, x as FilledIconName, y as FloatButton, z as FloatButtonBackTopProps, A as FloatButtonGroupProps, E as FloatButtonProps, G as FloatButtonShape, K as Icon, L as IconName, M as IconProps, N as IconVariant, U as Input, V as InputProps, a0 as MessageConfig, a1 as MessageHandle, a2 as MessageKey, a3 as MessageType, ab as Progress, ac as ProgressProps, ad as ProgressStatus, ag as Segmented, ah as SegmentedOption, ai as SegmentedProps, aj as SegmentedValue, aq as TabItem, ar as Tabs, at as TabsOrientation, au as TabsPosition, av as TabsProps, aw as TabsType, ax as Tag, ay as TagProps, az as TagSize, T as TagStatus, aA as TagVariant, aE as Toolbar, aF as ToolbarItem, aG as ToolbarProps, aR as Typography, aS as TypographyLinkProps, aT as TypographyProps, aU as TypographyTitleProps, aV as TypographyType, aW as Upload, aX as UploadChangeInfo, aY as UploadDraggerProps, aZ as UploadFile, a_ as UploadFileStatus, b1 as UploadProps, b5 as UploadRequestOptions, b9 as message } from './core-murmERqF.js';
2
2
  export { f as Button, B as ButtonProps, e as ButtonSize, g as ButtonVariant, h as Modal, d as ModalActionResult, M as ModalOpenConfig, i as ModalProps, j as ModalType, a as OverlayApiHandle, k as Select, S as SelectOption, c as SelectProps, m as SelectValue } from './Select-CCrPqULn.js';
3
3
  import 'react';
4
4
  import './shared-Bx4B28Wh.js';
package/dist/index.cjs CHANGED
@@ -6352,9 +6352,51 @@ function FormRoot({
6352
6352
  const instance = internalForm;
6353
6353
  instance.configure(initialValues, { onFinish, onFinishFailed, onValuesChange });
6354
6354
  const context = (0, import_react29.useMemo)(() => instance, [instance]);
6355
+ const formRef = (0, import_react29.useRef)(null);
6356
+ (0, import_react29.useLayoutEffect)(() => {
6357
+ const root = formRef.current;
6358
+ if (!root) return;
6359
+ let frame = 0;
6360
+ const observed = /* @__PURE__ */ new Set();
6361
+ const measure = () => {
6362
+ frame = 0;
6363
+ const labels = [...root.querySelectorAll(".sia-form-item__label-content")].filter((label) => label.closest(".sia-form") === root);
6364
+ const next = new Set(labels);
6365
+ observed.forEach((label) => {
6366
+ if (!next.has(label)) {
6367
+ resizeObserver.unobserve(label);
6368
+ observed.delete(label);
6369
+ }
6370
+ });
6371
+ let width = 0;
6372
+ labels.forEach((label) => {
6373
+ if (!observed.has(label)) {
6374
+ resizeObserver.observe(label);
6375
+ observed.add(label);
6376
+ }
6377
+ if (label.getClientRects().length) width = Math.max(width, label.offsetWidth);
6378
+ });
6379
+ const value = `${Math.ceil(width)}px`;
6380
+ if (root.style.getPropertyValue("--sia-form-auto-label-width") !== value) root.style.setProperty("--sia-form-auto-label-width", value);
6381
+ };
6382
+ const schedule = () => {
6383
+ if (!frame) frame = requestAnimationFrame(measure);
6384
+ };
6385
+ const resizeObserver = new ResizeObserver(schedule);
6386
+ resizeObserver.observe(root);
6387
+ const mutations = new MutationObserver(schedule);
6388
+ mutations.observe(root, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ["class", "style", "hidden"] });
6389
+ measure();
6390
+ return () => {
6391
+ resizeObserver.disconnect();
6392
+ mutations.disconnect();
6393
+ if (frame) cancelAnimationFrame(frame);
6394
+ };
6395
+ }, []);
6355
6396
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(FormContext.Provider, { value: context, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(PlaceholderModeContext.Provider, { value: resolvedPlaceholderMode, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ControlSizeContext.Provider, { value: size, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6356
6397
  "form",
6357
6398
  {
6399
+ ref: formRef,
6358
6400
  ...withTitleTooltip(props),
6359
6401
  className: `sia-form sia-form--${layout} sia-form--${size}${disabled ? " is-disabled" : ""} ${className}`.trim(),
6360
6402
  "data-required-mark": requiredMark,
@@ -6447,10 +6489,10 @@ function FormItem({
6447
6489
  const inputWrap = /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "sia-form-item__input-wrap", children: content });
6448
6490
  const hasError = status === "error" && Boolean(helpContent);
6449
6491
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { ref: itemRef, className: `sia-form-item${status ? ` sia-form-item--${status}` : ""} ${className}`.trim(), "data-sia-form-field": key || void 0, children: [
6450
- label ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { id: labelId, className: "sia-form-item__label", children: [
6492
+ label ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { id: labelId, className: "sia-form-item__label", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "sia-form-item__label-content", children: [
6451
6493
  ruleRequired ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "sia-form-item__required-mark", "aria-hidden": "true", children: "*" }) : null,
6452
6494
  label
6453
- ] }) : null,
6495
+ ] }) }) : null,
6454
6496
  /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "sia-form-item__control", children: [
6455
6497
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6456
6498
  Tooltip,
@@ -14344,6 +14386,8 @@ function createColumnSettingPlugin(options = {}) {
14344
14386
  ...customItems.map((item) => ({
14345
14387
  key: "custom:" + item.key,
14346
14388
  label: item.label,
14389
+ // 设置菜单复用菜单项提示,禁用操作也需说明不可用原因。
14390
+ title: item.title,
14347
14391
  icon: item.icon,
14348
14392
  danger: item.danger,
14349
14393
  disabled: item.disabled === true || typeof item.disabled === "function" && item.disabled(context)
@@ -14439,6 +14483,7 @@ function ToolbarItems({
14439
14483
  {
14440
14484
  size: "small",
14441
14485
  danger: item.danger,
14486
+ title: item.title,
14442
14487
  icon: item.icon,
14443
14488
  disabled,
14444
14489
  onClick: () => void item.onClick?.(context),
@@ -23291,7 +23336,8 @@ function QueryForm({
23291
23336
  }) {
23292
23337
  const [form] = useForm(providedForm);
23293
23338
  const [internalCollapsed, setInternalCollapsed] = (0, import_react93.useState)(defaultCollapsed);
23294
- const collapsed = collapsible && (controlledCollapsed ?? internalCollapsed);
23339
+ const [needsCollapse, setNeedsCollapse] = (0, import_react93.useState)(false);
23340
+ const collapsed = collapsible && needsCollapse && (controlledCollapsed ?? internalCollapsed);
23295
23341
  const [searching, setSearching] = (0, import_react93.useState)(false);
23296
23342
  const [saving, setSaving] = (0, import_react93.useState)(false);
23297
23343
  const [removing, setRemoving] = (0, import_react93.useState)(false);
@@ -23311,15 +23357,33 @@ function QueryForm({
23311
23357
  const limit = Math.max(1, Math.floor(collapsedCount));
23312
23358
  const rowRef = (0, import_react93.useRef)(null);
23313
23359
  const actionsRef = (0, import_react93.useRef)(null);
23360
+ const toggleRef = (0, import_react93.useRef)(null);
23314
23361
  const [fittingCount, setFittingCount] = (0, import_react93.useState)(limit);
23315
23362
  (0, import_react93.useLayoutEffect)(() => {
23316
- if (!collapsed) return;
23317
23363
  const row = rowRef.current;
23318
23364
  const actions = actionsRef.current;
23319
23365
  if (!row || !actions) return;
23320
23366
  function measure() {
23321
23367
  if (!row || !actions) return;
23322
23368
  const gap = parseFloat(getComputedStyle(row).columnGap) || 0;
23369
+ const allFields = Array.from(row.querySelectorAll(":scope > .sia-query-form__field"));
23370
+ const hiddenFields = allFields.filter((field) => field.hidden);
23371
+ const wasCollapsed = row.classList.contains("is-collapsed");
23372
+ const toggle = toggleRef.current;
23373
+ const toggleHidden = toggle?.hidden;
23374
+ row.classList.remove("is-collapsed");
23375
+ hiddenFields.forEach((field) => {
23376
+ field.hidden = false;
23377
+ });
23378
+ if (toggle) toggle.hidden = true;
23379
+ const requiredWidth = allFields.reduce((total, field) => total + field.getBoundingClientRect().width + gap, actions.getBoundingClientRect().width);
23380
+ setNeedsCollapse(allFields.length > 0 && requiredWidth > row.clientWidth + 0.5);
23381
+ if (toggle) toggle.hidden = Boolean(toggleHidden);
23382
+ hiddenFields.forEach((field) => {
23383
+ field.hidden = true;
23384
+ });
23385
+ row.classList.toggle("is-collapsed", wasCollapsed);
23386
+ if (!collapsed) return;
23323
23387
  let remaining = row.clientWidth - actions.getBoundingClientRect().width;
23324
23388
  let count = 0;
23325
23389
  for (const field of Array.from(row.querySelectorAll(":scope > .sia-query-form__field")).slice(0, limit)) {
@@ -23336,7 +23400,7 @@ function QueryForm({
23336
23400
  observer.observe(actions);
23337
23401
  row.querySelectorAll(":scope > .sia-query-form__field").forEach((field) => observer.observe(field));
23338
23402
  return () => observer.disconnect();
23339
- }, [collapsed, limit, fieldWidth, fields, children]);
23403
+ }, [collapsed, needsCollapse, collapsible, limit, fieldWidth, fields, children, actionsExtra, onSaveQuery, searchText, resetText, saveText]);
23340
23404
  async function search(values) {
23341
23405
  const info = source.current;
23342
23406
  source.current = { source: "submit" };
@@ -23467,7 +23531,7 @@ function QueryForm({
23467
23531
  setSaveOpen(true);
23468
23532
  }, children: saveText }) : null
23469
23533
  ] }),
23470
- collapsible && entries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
23534
+ collapsible && entries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { ref: toggleRef, hidden: !needsCollapse, children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
23471
23535
  Button,
23472
23536
  {
23473
23537
  variant: "link",
@@ -23480,7 +23544,7 @@ function QueryForm({
23480
23544
  },
23481
23545
  children: collapsed ? "\u5C55\u5F00" : "\u6536\u8D77"
23482
23546
  }
23483
- ) : null,
23547
+ ) }) : null,
23484
23548
  actionsExtra
23485
23549
  ] })
23486
23550
  ] }),
package/dist/index.css CHANGED
@@ -7458,11 +7458,15 @@ fieldset:disabled .sia-input-number__floating-placeholder {
7458
7458
  }
7459
7459
  .sia-form-item {
7460
7460
  display: grid;
7461
- grid-template-columns: minmax(90px, 140px) minmax(0, 1fr);
7461
+ grid-template-columns: var(--sia-form-label-width, var(--sia-form-auto-label-width, 0px)) minmax(0, 1fr);
7462
7462
  gap: 8px 14px;
7463
7463
  margin-bottom: 6px;
7464
7464
  color: var(--sia-color-text);
7465
7465
  }
7466
+ .sia-form-item__label-content {
7467
+ display: inline-block;
7468
+ width: max-content;
7469
+ }
7466
7470
  .sia-form-item__label {
7467
7471
  padding-top: 8px;
7468
7472
  text-align: right;
@@ -7554,6 +7558,7 @@ fieldset:disabled .sia-input-number__floating-placeholder {
7554
7558
  gap: 8px;
7555
7559
  }
7556
7560
  .sia-form--inline .sia-form-item__label {
7561
+ flex: 0 0 var(--sia-form-label-width, var(--sia-form-auto-label-width, 0px));
7557
7562
  text-align: left;
7558
7563
  }
7559
7564
  .sia-form-error-list {
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TagStatus, B as BadgeProps } from './core-D2IjiQhj.cjs';
2
- export { a as Badge, b as BadgeRibbonProps, c as BadgeStatus, d as Breadcrumb, e as BreadcrumbItem, f as BreadcrumbProps, C as Calendar, g as CalendarProps, h as Card, i as CardAccent, j as CardProps, k as Carousel, l as CarouselProps, m as CarouselRef, n as Collapse, o as CollapseItem, p as CollapseKey, q as CollapseProps, D as Dropdown, r as DropdownButtonProps, s as DropdownMenuProps, t as DropdownOpenSource, u as DropdownPlacement, v as DropdownProps, w as DropdownTrigger, F as FILLED_ICON_NAMES, x as FilledIconName, y as FloatButton, z as FloatButtonBackTopProps, A as FloatButtonGroupProps, E as FloatButtonProps, G as FloatButtonShape, H as FloatingPlacement, I as FloatingTrigger, J as ICON_NAMES, K as Icon, L as IconName, M as IconProps, N as IconVariant, O as Image, P as ImagePreview, Q as ImagePreviewConfig, R as ImagePreviewProps, S as ImageProps, U as Input, V as InputProps, W as Menu, X as MenuClickInfo, Y as MenuItem, Z as MenuMode, _ as MenuProps, $ as MenuTheme, a0 as MessageConfig, a1 as MessageHandle, a2 as MessageKey, a3 as MessageType, a4 as NotificationConfig, a5 as NotificationPlacement, a6 as NotificationType, a7 as Popconfirm, a8 as PopconfirmProps, a9 as Popover, aa as PopoverProps, ab as Progress, ac as ProgressProps, ad as ProgressStatus, ae as Rate, af as RateProps, ag as Segmented, ah as SegmentedOption, ai as SegmentedProps, aj as SegmentedValue, ak as Spin, al as SpinProps, am as StepItem, an as StepStatus, ao as Steps, ap as StepsProps, aq as TabItem, ar as Tabs, as as TabsContextMenuClickInfo, at as TabsOrientation, au as TabsPosition, av as TabsProps, aw as TabsType, ax as Tag, ay as TagProps, az as TagSize, aA as TagVariant, aB as Timeline, aC as TimelineItem, aD as TimelineProps, aE as Toolbar, aF as ToolbarItem, aG as ToolbarProps, aH as Tooltip, aI as TooltipProps, aJ as Tour, aK as TourProps, aL as TourStep, aM as Tree, aN as TreeDropPosition, aO as TreeKey, aP as TreeNode, aQ as TreeProps, aR as Typography, aS as TypographyLinkProps, aT as TypographyProps, aU as TypographyTitleProps, aV as TypographyType, aW as Upload, aX as UploadChangeInfo, aY as UploadDraggerProps, aZ as UploadFile, a_ as UploadFileStatus, a$ as UploadHttpRequest, b0 as UploadItemActions, b1 as UploadProps, b2 as UploadRef, b3 as UploadRejectInfo, b4 as UploadRequestHandle, b5 as UploadRequestOptions, b6 as Watermark, b7 as WatermarkFont, b8 as WatermarkProps, b9 as message, ba as notification } from './core-D2IjiQhj.cjs';
1
+ import { T as TagStatus, B as BadgeProps } from './core-KIaXZ4_O.cjs';
2
+ export { a as Badge, b as BadgeRibbonProps, c as BadgeStatus, d as Breadcrumb, e as BreadcrumbItem, f as BreadcrumbProps, C as Calendar, g as CalendarProps, h as Card, i as CardAccent, j as CardProps, k as Carousel, l as CarouselProps, m as CarouselRef, n as Collapse, o as CollapseItem, p as CollapseKey, q as CollapseProps, D as Dropdown, r as DropdownButtonProps, s as DropdownMenuProps, t as DropdownOpenSource, u as DropdownPlacement, v as DropdownProps, w as DropdownTrigger, F as FILLED_ICON_NAMES, x as FilledIconName, y as FloatButton, z as FloatButtonBackTopProps, A as FloatButtonGroupProps, E as FloatButtonProps, G as FloatButtonShape, H as FloatingPlacement, I as FloatingTrigger, J as ICON_NAMES, K as Icon, L as IconName, M as IconProps, N as IconVariant, O as Image, P as ImagePreview, Q as ImagePreviewConfig, R as ImagePreviewProps, S as ImageProps, U as Input, V as InputProps, W as Menu, X as MenuClickInfo, Y as MenuItem, Z as MenuMode, _ as MenuProps, $ as MenuTheme, a0 as MessageConfig, a1 as MessageHandle, a2 as MessageKey, a3 as MessageType, a4 as NotificationConfig, a5 as NotificationPlacement, a6 as NotificationType, a7 as Popconfirm, a8 as PopconfirmProps, a9 as Popover, aa as PopoverProps, ab as Progress, ac as ProgressProps, ad as ProgressStatus, ae as Rate, af as RateProps, ag as Segmented, ah as SegmentedOption, ai as SegmentedProps, aj as SegmentedValue, ak as Spin, al as SpinProps, am as StepItem, an as StepStatus, ao as Steps, ap as StepsProps, aq as TabItem, ar as Tabs, as as TabsContextMenuClickInfo, at as TabsOrientation, au as TabsPosition, av as TabsProps, aw as TabsType, ax as Tag, ay as TagProps, az as TagSize, aA as TagVariant, aB as Timeline, aC as TimelineItem, aD as TimelineProps, aE as Toolbar, aF as ToolbarItem, aG as ToolbarProps, aH as Tooltip, aI as TooltipProps, aJ as Tour, aK as TourProps, aL as TourStep, aM as Tree, aN as TreeDropPosition, aO as TreeKey, aP as TreeNode, aQ as TreeProps, aR as Typography, aS as TypographyLinkProps, aT as TypographyProps, aU as TypographyTitleProps, aV as TypographyType, aW as Upload, aX as UploadChangeInfo, aY as UploadDraggerProps, aZ as UploadFile, a_ as UploadFileStatus, a$ as UploadHttpRequest, b0 as UploadItemActions, b1 as UploadProps, b2 as UploadRef, b3 as UploadRejectInfo, b4 as UploadRequestHandle, b5 as UploadRequestOptions, b6 as Watermark, b7 as WatermarkFont, b8 as WatermarkProps, b9 as message, ba as notification } from './core-KIaXZ4_O.cjs';
3
3
  import * as react from 'react';
4
4
  import { HTMLAttributes, ReactNode, CSSProperties, ElementType, FormHTMLAttributes, InputHTMLAttributes, ChangeEvent, TextareaHTMLAttributes, MouseEvent, Key, PointerEvent, Ref, ReactElement, ButtonHTMLAttributes, RefObject } from 'react';
5
5
  import { C as ControlSize, I as InputPlaceholderMode, a as ControlStatus } from './shared-Bx4B28Wh.cjs';
@@ -736,7 +736,7 @@ interface FormProps extends Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"
736
736
  /** 表单初始值 */
737
737
  initialValues?: FormValues;
738
738
  /**
739
- * 布局方式。
739
+ * 布局方式;horizontal 与 inline 默认按当前表单内最宽标签对齐,vertical 保持标签在控件上方。
740
740
  * @defaultValue "horizontal"
741
741
  */
742
742
  layout?: "horizontal" | "vertical" | "inline";
@@ -769,7 +769,7 @@ declare function FormRoot({ form, initialValues, layout, size: sizeProp, placeho
769
769
  interface FormItemProps {
770
770
  /** 绑定到表单值的字段名或嵌套路径,例如 ["user", "name"]。 */
771
771
  name?: NamePath;
772
- /** 字段标签,支持文本或 React 节点。 */
772
+ /** 字段标签,支持文本或 React 节点;横向及行内布局未指定标签列宽时,与同一 Form 内最宽的可见标签对齐,测量包含必填标记。 */
773
773
  label?: ReactNode;
774
774
  /**
775
775
  * 字段的校验规则,按配置执行。
@@ -2733,6 +2733,8 @@ interface TableToolbarItem<T> {
2733
2733
  key: string;
2734
2734
  /** 展示给用户的名称,可传入文本或 React 节点。 */
2735
2735
  label: ReactNode;
2736
+ /** 操作的悬停提示文字;普通工具栏按钮和设置菜单项均支持,禁用时仍可显示,停留 600ms 后出现。 */
2737
+ title?: string;
2736
2738
  /** 显示在内容旁的图标节点,建议使用 Icon 组件。 */
2737
2739
  icon?: ReactNode;
2738
2740
  /** 显示位置或定位配置。 */
@@ -3099,11 +3101,11 @@ interface QueryFormProps<T extends FormValues = FormValues> extends Omit<FormPro
3099
3101
  */
3100
3102
  fieldWidth?: number | string;
3101
3103
  /**
3102
- 是否显示展开和收起入口;false 时始终展示全部字段。
3104
+ * 是否允许展开和收起;仅全部字段与操作区无法在一行内显示时提供入口,false 时始终展示全部字段。
3103
3105
  * @defaultValue true
3104
3106
  */
3105
3107
  collapsible?: boolean;
3106
- /** 受控收起状态,需在 onCollapsedChange 中更新。收起时保留字段挂载和值,只隐藏放不下的字段和底部快捷标签。 */
3108
+ /** 受控收起状态,需在 onCollapsedChange 中更新;全部字段能单行显示时不执行收起。收起时保留字段挂载和值,只隐藏放不下的字段和底部快捷标签。 */
3107
3109
  collapsed?: boolean;
3108
3110
  /**
3109
3111
  * 非受控模式的初始收起状态。
@@ -3111,7 +3113,7 @@ interface QueryFormProps<T extends FormValues = FormValues> extends Omit<FormPro
3111
3113
  */
3112
3114
  defaultCollapsed?: boolean;
3113
3115
  /**
3114
- * 收起时最多保留的字段数;实际数量会根据可用宽度减少,以保持单行。
3116
+ * 需要折叠时最多保留的字段数;实际数量会根据可用宽度减少,以保持单行。全部字段能单行显示时不限制字段数。
3115
3117
  * @defaultValue 3
3116
3118
  */
3117
3119
  collapsedCount?: number;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TagStatus, B as BadgeProps } from './core-Bb0160em.js';
2
- export { a as Badge, b as BadgeRibbonProps, c as BadgeStatus, d as Breadcrumb, e as BreadcrumbItem, f as BreadcrumbProps, C as Calendar, g as CalendarProps, h as Card, i as CardAccent, j as CardProps, k as Carousel, l as CarouselProps, m as CarouselRef, n as Collapse, o as CollapseItem, p as CollapseKey, q as CollapseProps, D as Dropdown, r as DropdownButtonProps, s as DropdownMenuProps, t as DropdownOpenSource, u as DropdownPlacement, v as DropdownProps, w as DropdownTrigger, F as FILLED_ICON_NAMES, x as FilledIconName, y as FloatButton, z as FloatButtonBackTopProps, A as FloatButtonGroupProps, E as FloatButtonProps, G as FloatButtonShape, H as FloatingPlacement, I as FloatingTrigger, J as ICON_NAMES, K as Icon, L as IconName, M as IconProps, N as IconVariant, O as Image, P as ImagePreview, Q as ImagePreviewConfig, R as ImagePreviewProps, S as ImageProps, U as Input, V as InputProps, W as Menu, X as MenuClickInfo, Y as MenuItem, Z as MenuMode, _ as MenuProps, $ as MenuTheme, a0 as MessageConfig, a1 as MessageHandle, a2 as MessageKey, a3 as MessageType, a4 as NotificationConfig, a5 as NotificationPlacement, a6 as NotificationType, a7 as Popconfirm, a8 as PopconfirmProps, a9 as Popover, aa as PopoverProps, ab as Progress, ac as ProgressProps, ad as ProgressStatus, ae as Rate, af as RateProps, ag as Segmented, ah as SegmentedOption, ai as SegmentedProps, aj as SegmentedValue, ak as Spin, al as SpinProps, am as StepItem, an as StepStatus, ao as Steps, ap as StepsProps, aq as TabItem, ar as Tabs, as as TabsContextMenuClickInfo, at as TabsOrientation, au as TabsPosition, av as TabsProps, aw as TabsType, ax as Tag, ay as TagProps, az as TagSize, aA as TagVariant, aB as Timeline, aC as TimelineItem, aD as TimelineProps, aE as Toolbar, aF as ToolbarItem, aG as ToolbarProps, aH as Tooltip, aI as TooltipProps, aJ as Tour, aK as TourProps, aL as TourStep, aM as Tree, aN as TreeDropPosition, aO as TreeKey, aP as TreeNode, aQ as TreeProps, aR as Typography, aS as TypographyLinkProps, aT as TypographyProps, aU as TypographyTitleProps, aV as TypographyType, aW as Upload, aX as UploadChangeInfo, aY as UploadDraggerProps, aZ as UploadFile, a_ as UploadFileStatus, a$ as UploadHttpRequest, b0 as UploadItemActions, b1 as UploadProps, b2 as UploadRef, b3 as UploadRejectInfo, b4 as UploadRequestHandle, b5 as UploadRequestOptions, b6 as Watermark, b7 as WatermarkFont, b8 as WatermarkProps, b9 as message, ba as notification } from './core-Bb0160em.js';
1
+ import { T as TagStatus, B as BadgeProps } from './core-murmERqF.js';
2
+ export { a as Badge, b as BadgeRibbonProps, c as BadgeStatus, d as Breadcrumb, e as BreadcrumbItem, f as BreadcrumbProps, C as Calendar, g as CalendarProps, h as Card, i as CardAccent, j as CardProps, k as Carousel, l as CarouselProps, m as CarouselRef, n as Collapse, o as CollapseItem, p as CollapseKey, q as CollapseProps, D as Dropdown, r as DropdownButtonProps, s as DropdownMenuProps, t as DropdownOpenSource, u as DropdownPlacement, v as DropdownProps, w as DropdownTrigger, F as FILLED_ICON_NAMES, x as FilledIconName, y as FloatButton, z as FloatButtonBackTopProps, A as FloatButtonGroupProps, E as FloatButtonProps, G as FloatButtonShape, H as FloatingPlacement, I as FloatingTrigger, J as ICON_NAMES, K as Icon, L as IconName, M as IconProps, N as IconVariant, O as Image, P as ImagePreview, Q as ImagePreviewConfig, R as ImagePreviewProps, S as ImageProps, U as Input, V as InputProps, W as Menu, X as MenuClickInfo, Y as MenuItem, Z as MenuMode, _ as MenuProps, $ as MenuTheme, a0 as MessageConfig, a1 as MessageHandle, a2 as MessageKey, a3 as MessageType, a4 as NotificationConfig, a5 as NotificationPlacement, a6 as NotificationType, a7 as Popconfirm, a8 as PopconfirmProps, a9 as Popover, aa as PopoverProps, ab as Progress, ac as ProgressProps, ad as ProgressStatus, ae as Rate, af as RateProps, ag as Segmented, ah as SegmentedOption, ai as SegmentedProps, aj as SegmentedValue, ak as Spin, al as SpinProps, am as StepItem, an as StepStatus, ao as Steps, ap as StepsProps, aq as TabItem, ar as Tabs, as as TabsContextMenuClickInfo, at as TabsOrientation, au as TabsPosition, av as TabsProps, aw as TabsType, ax as Tag, ay as TagProps, az as TagSize, aA as TagVariant, aB as Timeline, aC as TimelineItem, aD as TimelineProps, aE as Toolbar, aF as ToolbarItem, aG as ToolbarProps, aH as Tooltip, aI as TooltipProps, aJ as Tour, aK as TourProps, aL as TourStep, aM as Tree, aN as TreeDropPosition, aO as TreeKey, aP as TreeNode, aQ as TreeProps, aR as Typography, aS as TypographyLinkProps, aT as TypographyProps, aU as TypographyTitleProps, aV as TypographyType, aW as Upload, aX as UploadChangeInfo, aY as UploadDraggerProps, aZ as UploadFile, a_ as UploadFileStatus, a$ as UploadHttpRequest, b0 as UploadItemActions, b1 as UploadProps, b2 as UploadRef, b3 as UploadRejectInfo, b4 as UploadRequestHandle, b5 as UploadRequestOptions, b6 as Watermark, b7 as WatermarkFont, b8 as WatermarkProps, b9 as message, ba as notification } from './core-murmERqF.js';
3
3
  import * as react from 'react';
4
4
  import { HTMLAttributes, ReactNode, CSSProperties, ElementType, FormHTMLAttributes, InputHTMLAttributes, ChangeEvent, TextareaHTMLAttributes, MouseEvent, Key, PointerEvent, Ref, ReactElement, ButtonHTMLAttributes, RefObject } from 'react';
5
5
  import { C as ControlSize, I as InputPlaceholderMode, a as ControlStatus } from './shared-Bx4B28Wh.js';
@@ -736,7 +736,7 @@ interface FormProps extends Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"
736
736
  /** 表单初始值 */
737
737
  initialValues?: FormValues;
738
738
  /**
739
- * 布局方式。
739
+ * 布局方式;horizontal 与 inline 默认按当前表单内最宽标签对齐,vertical 保持标签在控件上方。
740
740
  * @defaultValue "horizontal"
741
741
  */
742
742
  layout?: "horizontal" | "vertical" | "inline";
@@ -769,7 +769,7 @@ declare function FormRoot({ form, initialValues, layout, size: sizeProp, placeho
769
769
  interface FormItemProps {
770
770
  /** 绑定到表单值的字段名或嵌套路径,例如 ["user", "name"]。 */
771
771
  name?: NamePath;
772
- /** 字段标签,支持文本或 React 节点。 */
772
+ /** 字段标签,支持文本或 React 节点;横向及行内布局未指定标签列宽时,与同一 Form 内最宽的可见标签对齐,测量包含必填标记。 */
773
773
  label?: ReactNode;
774
774
  /**
775
775
  * 字段的校验规则,按配置执行。
@@ -2733,6 +2733,8 @@ interface TableToolbarItem<T> {
2733
2733
  key: string;
2734
2734
  /** 展示给用户的名称,可传入文本或 React 节点。 */
2735
2735
  label: ReactNode;
2736
+ /** 操作的悬停提示文字;普通工具栏按钮和设置菜单项均支持,禁用时仍可显示,停留 600ms 后出现。 */
2737
+ title?: string;
2736
2738
  /** 显示在内容旁的图标节点,建议使用 Icon 组件。 */
2737
2739
  icon?: ReactNode;
2738
2740
  /** 显示位置或定位配置。 */
@@ -3099,11 +3101,11 @@ interface QueryFormProps<T extends FormValues = FormValues> extends Omit<FormPro
3099
3101
  */
3100
3102
  fieldWidth?: number | string;
3101
3103
  /**
3102
- 是否显示展开和收起入口;false 时始终展示全部字段。
3104
+ * 是否允许展开和收起;仅全部字段与操作区无法在一行内显示时提供入口,false 时始终展示全部字段。
3103
3105
  * @defaultValue true
3104
3106
  */
3105
3107
  collapsible?: boolean;
3106
- /** 受控收起状态,需在 onCollapsedChange 中更新。收起时保留字段挂载和值,只隐藏放不下的字段和底部快捷标签。 */
3108
+ /** 受控收起状态,需在 onCollapsedChange 中更新;全部字段能单行显示时不执行收起。收起时保留字段挂载和值,只隐藏放不下的字段和底部快捷标签。 */
3107
3109
  collapsed?: boolean;
3108
3110
  /**
3109
3111
  * 非受控模式的初始收起状态。
@@ -3111,7 +3113,7 @@ interface QueryFormProps<T extends FormValues = FormValues> extends Omit<FormPro
3111
3113
  */
3112
3114
  defaultCollapsed?: boolean;
3113
3115
  /**
3114
- * 收起时最多保留的字段数;实际数量会根据可用宽度减少,以保持单行。
3116
+ * 需要折叠时最多保留的字段数;实际数量会根据可用宽度减少,以保持单行。全部字段能单行显示时不限制字段数。
3115
3117
  * @defaultValue 3
3116
3118
  */
3117
3119
  collapsedCount?: number;
package/dist/index.js CHANGED
@@ -1413,7 +1413,7 @@ var Drawer2 = Object.assign(DrawerRoot, {
1413
1413
  });
1414
1414
 
1415
1415
  // src/components/Form.tsx
1416
- import { Children as Children3, cloneElement as cloneElement2, createContext as createContext2, forwardRef as forwardRef2, isValidElement as isValidElement2, useContext as useContext2, useEffect as useEffect3, useId as useId3, useMemo as useMemo4, useRef as useRef5, useSyncExternalStore } from "react";
1416
+ import { Children as Children3, cloneElement as cloneElement2, createContext as createContext2, forwardRef as forwardRef2, isValidElement as isValidElement2, useContext as useContext2, useEffect as useEffect3, useId as useId3, useLayoutEffect as useLayoutEffect2, useMemo as useMemo4, useRef as useRef5, useSyncExternalStore } from "react";
1417
1417
  import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1418
1418
  var Switch = forwardRef2(function Switch2({
1419
1419
  label,
@@ -1660,9 +1660,51 @@ function FormRoot({
1660
1660
  const instance = internalForm;
1661
1661
  instance.configure(initialValues, { onFinish, onFinishFailed, onValuesChange });
1662
1662
  const context = useMemo4(() => instance, [instance]);
1663
+ const formRef = useRef5(null);
1664
+ useLayoutEffect2(() => {
1665
+ const root = formRef.current;
1666
+ if (!root) return;
1667
+ let frame = 0;
1668
+ const observed = /* @__PURE__ */ new Set();
1669
+ const measure = () => {
1670
+ frame = 0;
1671
+ const labels = [...root.querySelectorAll(".sia-form-item__label-content")].filter((label) => label.closest(".sia-form") === root);
1672
+ const next = new Set(labels);
1673
+ observed.forEach((label) => {
1674
+ if (!next.has(label)) {
1675
+ resizeObserver.unobserve(label);
1676
+ observed.delete(label);
1677
+ }
1678
+ });
1679
+ let width = 0;
1680
+ labels.forEach((label) => {
1681
+ if (!observed.has(label)) {
1682
+ resizeObserver.observe(label);
1683
+ observed.add(label);
1684
+ }
1685
+ if (label.getClientRects().length) width = Math.max(width, label.offsetWidth);
1686
+ });
1687
+ const value = `${Math.ceil(width)}px`;
1688
+ if (root.style.getPropertyValue("--sia-form-auto-label-width") !== value) root.style.setProperty("--sia-form-auto-label-width", value);
1689
+ };
1690
+ const schedule = () => {
1691
+ if (!frame) frame = requestAnimationFrame(measure);
1692
+ };
1693
+ const resizeObserver = new ResizeObserver(schedule);
1694
+ resizeObserver.observe(root);
1695
+ const mutations = new MutationObserver(schedule);
1696
+ mutations.observe(root, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ["class", "style", "hidden"] });
1697
+ measure();
1698
+ return () => {
1699
+ resizeObserver.disconnect();
1700
+ mutations.disconnect();
1701
+ if (frame) cancelAnimationFrame(frame);
1702
+ };
1703
+ }, []);
1663
1704
  return /* @__PURE__ */ jsx9(FormContext.Provider, { value: context, children: /* @__PURE__ */ jsx9(PlaceholderModeContext.Provider, { value: resolvedPlaceholderMode, children: /* @__PURE__ */ jsx9(ControlSizeContext.Provider, { value: size, children: /* @__PURE__ */ jsx9(
1664
1705
  "form",
1665
1706
  {
1707
+ ref: formRef,
1666
1708
  ...withTitleTooltip(props),
1667
1709
  className: `sia-form sia-form--${layout} sia-form--${size}${disabled ? " is-disabled" : ""} ${className}`.trim(),
1668
1710
  "data-required-mark": requiredMark,
@@ -1755,10 +1797,10 @@ function FormItem({
1755
1797
  const inputWrap = /* @__PURE__ */ jsx9("div", { className: "sia-form-item__input-wrap", children: content });
1756
1798
  const hasError = status === "error" && Boolean(helpContent);
1757
1799
  return /* @__PURE__ */ jsxs9("div", { ref: itemRef, className: `sia-form-item${status ? ` sia-form-item--${status}` : ""} ${className}`.trim(), "data-sia-form-field": key || void 0, children: [
1758
- label ? /* @__PURE__ */ jsxs9("div", { id: labelId, className: "sia-form-item__label", children: [
1800
+ label ? /* @__PURE__ */ jsx9("div", { id: labelId, className: "sia-form-item__label", children: /* @__PURE__ */ jsxs9("span", { className: "sia-form-item__label-content", children: [
1759
1801
  ruleRequired ? /* @__PURE__ */ jsx9("span", { className: "sia-form-item__required-mark", "aria-hidden": "true", children: "*" }) : null,
1760
1802
  label
1761
- ] }) : null,
1803
+ ] }) }) : null,
1762
1804
  /* @__PURE__ */ jsxs9("div", { className: "sia-form-item__control", children: [
1763
1805
  /* @__PURE__ */ jsx9(
1764
1806
  Tooltip,
@@ -4652,7 +4694,7 @@ function Treemap({
4652
4694
  }
4653
4695
 
4654
4696
  // src/components/Table/TableCellContent.tsx
4655
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef13, useState as useState16 } from "react";
4697
+ import { useLayoutEffect as useLayoutEffect3, useRef as useRef13, useState as useState16 } from "react";
4656
4698
  import { jsx as jsx20 } from "react/jsx-runtime";
4657
4699
  var pendingLayouts = /* @__PURE__ */ new Map();
4658
4700
  var layoutFrame;
@@ -4674,7 +4716,7 @@ function TableCellContent({ children, ellipsis, title }) {
4674
4716
  const ref = useRef13(null);
4675
4717
  const [overflowing, setOverflowing] = useState16(false);
4676
4718
  const customContent = typeof children !== "string" && typeof children !== "number" && children != null;
4677
- useLayoutEffect2(() => {
4719
+ useLayoutEffect3(() => {
4678
4720
  const element = ref.current;
4679
4721
  if (!element || !ellipsis || !customContent) return;
4680
4722
  const normalizeLayouts = (parent, layouts) => {
@@ -4710,7 +4752,7 @@ function TableCellContent({ children, ellipsis, title }) {
4710
4752
  }
4711
4753
 
4712
4754
  // src/components/Table/TableCanvasLayer.tsx
4713
- import { useLayoutEffect as useLayoutEffect3, useRef as useRef14 } from "react";
4755
+ import { useLayoutEffect as useLayoutEffect4, useRef as useRef14 } from "react";
4714
4756
 
4715
4757
  // src/components/Table/utils.ts
4716
4758
  var AUTO_WIDTH_COLUMN_KEYS = /* @__PURE__ */ new Set(["action", "actions", "operation", "operations"]);
@@ -4766,7 +4808,7 @@ function toTablePageParams(current, pageSize) {
4766
4808
  import { jsx as jsx21 } from "react/jsx-runtime";
4767
4809
  function TableCanvasLayer({ viewport, rows, columns, widths, rowHeight, headerHeight }) {
4768
4810
  const canvasRef = useRef14(null);
4769
- useLayoutEffect3(() => {
4811
+ useLayoutEffect4(() => {
4770
4812
  const canvas = canvasRef.current;
4771
4813
  const scroller = viewport.current;
4772
4814
  if (!canvas || !scroller) return;
@@ -7094,6 +7136,8 @@ function createColumnSettingPlugin(options = {}) {
7094
7136
  ...customItems.map((item) => ({
7095
7137
  key: "custom:" + item.key,
7096
7138
  label: item.label,
7139
+ // 设置菜单复用菜单项提示,禁用操作也需说明不可用原因。
7140
+ title: item.title,
7097
7141
  icon: item.icon,
7098
7142
  danger: item.danger,
7099
7143
  disabled: item.disabled === true || typeof item.disabled === "function" && item.disabled(context)
@@ -7189,6 +7233,7 @@ function ToolbarItems({
7189
7233
  {
7190
7234
  size: "small",
7191
7235
  danger: item.danger,
7236
+ title: item.title,
7192
7237
  icon: item.icon,
7193
7238
  disabled,
7194
7239
  onClick: () => void item.onClick?.(context),
@@ -8425,7 +8470,7 @@ var InputSelect = forwardRef7(function InputSelect2({
8425
8470
  });
8426
8471
 
8427
8472
  // src/components/QueryForm.tsx
8428
- import { Children as Children4, useLayoutEffect as useLayoutEffect4, useRef as useRef18, useState as useState20 } from "react";
8473
+ import { Children as Children4, useLayoutEffect as useLayoutEffect5, useRef as useRef18, useState as useState20 } from "react";
8429
8474
  import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
8430
8475
  function QueryForm({
8431
8476
  fields,
@@ -8460,7 +8505,8 @@ function QueryForm({
8460
8505
  }) {
8461
8506
  const [form] = useForm(providedForm);
8462
8507
  const [internalCollapsed, setInternalCollapsed] = useState20(defaultCollapsed);
8463
- const collapsed = collapsible && (controlledCollapsed ?? internalCollapsed);
8508
+ const [needsCollapse, setNeedsCollapse] = useState20(false);
8509
+ const collapsed = collapsible && needsCollapse && (controlledCollapsed ?? internalCollapsed);
8464
8510
  const [searching, setSearching] = useState20(false);
8465
8511
  const [saving, setSaving] = useState20(false);
8466
8512
  const [removing, setRemoving] = useState20(false);
@@ -8480,15 +8526,33 @@ function QueryForm({
8480
8526
  const limit = Math.max(1, Math.floor(collapsedCount));
8481
8527
  const rowRef = useRef18(null);
8482
8528
  const actionsRef = useRef18(null);
8529
+ const toggleRef = useRef18(null);
8483
8530
  const [fittingCount, setFittingCount] = useState20(limit);
8484
- useLayoutEffect4(() => {
8485
- if (!collapsed) return;
8531
+ useLayoutEffect5(() => {
8486
8532
  const row = rowRef.current;
8487
8533
  const actions = actionsRef.current;
8488
8534
  if (!row || !actions) return;
8489
8535
  function measure() {
8490
8536
  if (!row || !actions) return;
8491
8537
  const gap = parseFloat(getComputedStyle(row).columnGap) || 0;
8538
+ const allFields = Array.from(row.querySelectorAll(":scope > .sia-query-form__field"));
8539
+ const hiddenFields = allFields.filter((field) => field.hidden);
8540
+ const wasCollapsed = row.classList.contains("is-collapsed");
8541
+ const toggle = toggleRef.current;
8542
+ const toggleHidden = toggle?.hidden;
8543
+ row.classList.remove("is-collapsed");
8544
+ hiddenFields.forEach((field) => {
8545
+ field.hidden = false;
8546
+ });
8547
+ if (toggle) toggle.hidden = true;
8548
+ const requiredWidth = allFields.reduce((total, field) => total + field.getBoundingClientRect().width + gap, actions.getBoundingClientRect().width);
8549
+ setNeedsCollapse(allFields.length > 0 && requiredWidth > row.clientWidth + 0.5);
8550
+ if (toggle) toggle.hidden = Boolean(toggleHidden);
8551
+ hiddenFields.forEach((field) => {
8552
+ field.hidden = true;
8553
+ });
8554
+ row.classList.toggle("is-collapsed", wasCollapsed);
8555
+ if (!collapsed) return;
8492
8556
  let remaining = row.clientWidth - actions.getBoundingClientRect().width;
8493
8557
  let count = 0;
8494
8558
  for (const field of Array.from(row.querySelectorAll(":scope > .sia-query-form__field")).slice(0, limit)) {
@@ -8505,7 +8569,7 @@ function QueryForm({
8505
8569
  observer.observe(actions);
8506
8570
  row.querySelectorAll(":scope > .sia-query-form__field").forEach((field) => observer.observe(field));
8507
8571
  return () => observer.disconnect();
8508
- }, [collapsed, limit, fieldWidth, fields, children]);
8572
+ }, [collapsed, needsCollapse, collapsible, limit, fieldWidth, fields, children, actionsExtra, onSaveQuery, searchText, resetText, saveText]);
8509
8573
  async function search(values) {
8510
8574
  const info = source.current;
8511
8575
  source.current = { source: "submit" };
@@ -8636,7 +8700,7 @@ function QueryForm({
8636
8700
  setSaveOpen(true);
8637
8701
  }, children: saveText }) : null
8638
8702
  ] }),
8639
- collapsible && entries.length > 0 ? /* @__PURE__ */ jsx26(
8703
+ collapsible && entries.length > 0 ? /* @__PURE__ */ jsx26("span", { ref: toggleRef, hidden: !needsCollapse, children: /* @__PURE__ */ jsx26(
8640
8704
  Button,
8641
8705
  {
8642
8706
  variant: "link",
@@ -8649,7 +8713,7 @@ function QueryForm({
8649
8713
  },
8650
8714
  children: collapsed ? "\u5C55\u5F00" : "\u6536\u8D77"
8651
8715
  }
8652
- ) : null,
8716
+ ) }) : null,
8653
8717
  actionsExtra
8654
8718
  ] })
8655
8719
  ] }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sia.soul/sia-react-ui",
3
- "version": "0.1.48",
3
+ "version": "0.1.51",
4
4
  "description": "Sia Design components and tokens for React",
5
5
  "publishConfig": {
6
6
  "access": "public",