@sia.soul/sia-react-ui 0.1.82 → 0.1.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -80,19 +80,19 @@ import {
80
80
  Watermark,
81
81
  message,
82
82
  notification
83
- } from "./chunk-BCOFQJ76.js";
83
+ } from "./chunk-2ETLCXNS.js";
84
84
  import {
85
85
  MarkdownEditor
86
86
  } from "./chunk-TUXNOSCT.js";
87
87
  import {
88
88
  RichTextContent,
89
89
  RichTextEditor
90
- } from "./chunk-SBNHEETW.js";
90
+ } from "./chunk-N4P3QKCY.js";
91
91
  import {
92
92
  DatePicker,
93
93
  SelectDateRange,
94
94
  TimePanel
95
- } from "./chunk-N6DVNCZT.js";
95
+ } from "./chunk-36FXHK4W.js";
96
96
  import {
97
97
  Checkbox,
98
98
  FloatingScrollbarProvider,
@@ -104,7 +104,7 @@ import {
104
104
  Tooltip,
105
105
  Tree,
106
106
  useScrollbarProximity
107
- } from "./chunk-V4GGPMKS.js";
107
+ } from "./chunk-W3EKQOPR.js";
108
108
  import {
109
109
  Dropdown,
110
110
  FILLED_ICON_NAMES,
@@ -117,7 +117,7 @@ import {
117
117
  Segmented,
118
118
  Steps,
119
119
  useOverlayLifecycle
120
- } from "./chunk-CLBWJEID.js";
120
+ } from "./chunk-VNVDG4AC.js";
121
121
  import {
122
122
  Button,
123
123
  TextArea
@@ -5097,6 +5097,22 @@ function TableCanvasLayer({ viewport, rows, columns, widths, rowHeight, headerHe
5097
5097
  return /* @__PURE__ */ jsx21("canvas", { ref: canvasRef, "aria-hidden": "true", className: "sia-table__canvas-layer" });
5098
5098
  }
5099
5099
 
5100
+ // src/components/Table/rowIdentity.ts
5101
+ function createRowIdentity() {
5102
+ const keys = /* @__PURE__ */ new WeakMap();
5103
+ let sequence = 0;
5104
+ return (record, index, rowKey) => {
5105
+ const explicit = typeof rowKey === "function" ? rowKey(record, index) : rowKey == null ? void 0 : record[rowKey];
5106
+ if (typeof explicit === "string" || typeof explicit === "bigint" || typeof explicit === "number" && Number.isFinite(explicit)) return explicit;
5107
+ let key = keys.get(record);
5108
+ if (key === void 0) {
5109
+ key = `__sia_internal_row_${++sequence}`;
5110
+ keys.set(record, key);
5111
+ }
5112
+ return key;
5113
+ };
5114
+ }
5115
+
5100
5116
  // src/components/Table/Table.tsx
5101
5117
  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";
5102
5118
 
@@ -5164,6 +5180,29 @@ function mergeColumnSettings(columns, saved, active) {
5164
5180
  return [...merged.values()].sort((left, right) => left.order - right.order);
5165
5181
  }
5166
5182
 
5183
+ // src/components/settingsPersistence.ts
5184
+ var queues = /* @__PURE__ */ new WeakMap();
5185
+ function saveSettingsPatch(adapter, scope, patch) {
5186
+ let scoped = queues.get(adapter);
5187
+ if (!scoped) {
5188
+ scoped = /* @__PURE__ */ new Map();
5189
+ queues.set(adapter, scoped);
5190
+ }
5191
+ const key = JSON.stringify([scope.moduleName, scope.businessKey]);
5192
+ const previous = scoped.get(key) ?? Promise.resolve();
5193
+ const task = previous.catch(() => void 0).then(async () => {
5194
+ const current = await adapter.load(scope);
5195
+ const defined = Object.fromEntries(Object.entries(patch).filter(([, value]) => value !== void 0));
5196
+ await adapter.save(scope, { ...current, ...defined });
5197
+ });
5198
+ scoped.set(key, task);
5199
+ const cleanup = () => {
5200
+ if (scoped.get(key) === task) scoped.delete(key);
5201
+ };
5202
+ void task.then(cleanup, cleanup);
5203
+ return task;
5204
+ }
5205
+
5167
5206
  // src/components/Table/plugins.tsx
5168
5207
  import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
5169
5208
  function TableCheckbox({
@@ -7256,7 +7295,7 @@ function createColumnSettingPlugin(options = {}) {
7256
7295
  return items.filter((item) => keys.has(item.key));
7257
7296
  };
7258
7297
  const currentItems = (context) => reconcileColumnSettings(context.baseColumns, baseItems(context), context.state.items ?? []);
7259
- const save = (snapshot) => options.adapter && options.scope ? options.adapter.save(options.scope, snapshot).catch(() => void 0) : Promise.resolve();
7298
+ const save = (snapshot) => options.adapter && options.scope ? saveSettingsPatch(options.adapter, options.scope, snapshot).catch(() => void 0) : Promise.resolve();
7260
7299
  function apply(items, context, persist = true) {
7261
7300
  const normalized = orderColumnSettings(
7262
7301
  editableItems(items, context).sort((a, b) => a.order - b.order)
@@ -7783,7 +7822,7 @@ function TableInner(props, ref) {
7783
7822
  const {
7784
7823
  dataSource = EMPTY_DATA,
7785
7824
  columns: baseColumns = EMPTY_COLUMNS,
7786
- rowKey = "id",
7825
+ rowKey,
7787
7826
  plugins: providedPlugins = EMPTY_PLUGINS,
7788
7827
  loading = false,
7789
7828
  emptyText = "\u6682\u65E0\u6570\u636E",
@@ -7826,7 +7865,8 @@ function TableInner(props, ref) {
7826
7865
  const [viewportHeight, setViewportHeight] = useState19(420);
7827
7866
  const [viewportWidth, setViewportWidth] = useState19(0);
7828
7867
  const [autoColumnWidths, setAutoColumnWidths] = useState19({});
7829
- const getRowKey = useCallback2((record, index) => typeof rowKey === "function" ? rowKey(record, index) : record[String(rowKey)] ?? index, [rowKey]);
7868
+ const [resolveRowIdentity] = useState19(createRowIdentity);
7869
+ const getRowKey = useCallback2((record, index) => resolveRowIdentity(record, index, typeof rowKey === "function" ? rowKey : rowKey == null ? void 0 : String(rowKey)), [rowKey, resolveRowIdentity]);
7830
7870
  const builtInResizePlugin = useMemo9(() => createResizePlugin(), []);
7831
7871
  const builtInHighlightPlugin = useMemo9(() => createHighlightPlugin(), []);
7832
7872
  const builtInCellSelectionPlugin = useMemo9(() => createCellSelectionPlugin(), []);
@@ -8720,10 +8760,318 @@ var InputSelect = forwardRef7(function InputSelect2({
8720
8760
  });
8721
8761
 
8722
8762
  // src/components/QueryForm.tsx
8723
- import { Children as Children4, useLayoutEffect as useLayoutEffect6, useRef as useRef18, useState as useState21 } from "react";
8724
- import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
8763
+ import { Children as Children4, isValidElement as isValidElement5, useLayoutEffect as useLayoutEffect6, useRef as useRef20, useState as useState23 } from "react";
8764
+
8765
+ // src/components/QueryFormSettings.tsx
8766
+ import { useEffect as useEffect15, useRef as useRef19, useState as useState22 } from "react";
8767
+
8768
+ // src/components/useQueryFieldSort.ts
8769
+ import { useEffect as useEffect14, useRef as useRef18, useState as useState21 } from "react";
8770
+ function getQuerySortPreview(keys, rects, from, dy, gap) {
8771
+ const center = rects[from].top + rects[from].height / 2 + dy;
8772
+ const rest = keys.map((_, index) => index).filter((index) => index !== from);
8773
+ const to = rest.filter((index) => center > rects[index].top + rects[index].height / 2).length;
8774
+ const ordered = [...keys];
8775
+ ordered.splice(to, 0, ordered.splice(from, 1)[0]);
8776
+ const offsets = {};
8777
+ const last = rects[rects.length - 1];
8778
+ const boundedDy = Math.max(rects[0].top - rects[from].top, Math.min(dy, last.top + last.height - rects[from].height - rects[from].top));
8779
+ let top = rects[0].top;
8780
+ for (const key of ordered) {
8781
+ const index = keys.indexOf(key);
8782
+ offsets[key] = index === from ? boundedDy : top - rects[index].top;
8783
+ top += rects[index].height + gap;
8784
+ }
8785
+ return { ordered, offsets };
8786
+ }
8787
+ function useQueryFieldSort(keys, enabled, onCommit) {
8788
+ const listRef = useRef18(null);
8789
+ const cancelRef = useRef18();
8790
+ const commitRef = useRef18(onCommit);
8791
+ commitRef.current = onCommit;
8792
+ const [preview, setPreview] = useState21();
8793
+ const signature = JSON.stringify(keys);
8794
+ useEffect14(() => {
8795
+ cancelRef.current?.();
8796
+ return () => cancelRef.current?.();
8797
+ }, [enabled, signature]);
8798
+ function start(event, key) {
8799
+ if (!enabled || event.button !== 0 || event.target.closest("button, input, label")) return;
8800
+ const list = listRef.current;
8801
+ const from = keys.indexOf(key);
8802
+ if (!list || from < 0) return;
8803
+ cancelRef.current?.();
8804
+ const elements = [...list.querySelectorAll(".sia-query-settings__item")];
8805
+ if (elements.length !== keys.length) return;
8806
+ const rects = elements.map((element) => element.getBoundingClientRect());
8807
+ const gap = parseFloat(getComputedStyle(list).rowGap) || 0;
8808
+ const original = [...keys];
8809
+ const target = event.currentTarget;
8810
+ const pointerId = event.pointerId;
8811
+ const startY = event.clientY;
8812
+ const initialScroll = list.scrollTop;
8813
+ const maxScroll = Math.max(0, list.scrollHeight - list.clientHeight);
8814
+ const originalUserSelect = document.body.style.userSelect;
8815
+ let lastY = startY;
8816
+ let moved = false;
8817
+ let ended = false;
8818
+ let ordered = original;
8819
+ let frame = 0;
8820
+ target.setPointerCapture(pointerId);
8821
+ const update = () => {
8822
+ const dy = lastY - startY + list.scrollTop - initialScroll;
8823
+ if (!moved && Math.abs(dy) < 4) return;
8824
+ moved = true;
8825
+ document.body.style.userSelect = "none";
8826
+ const next = getQuerySortPreview(original, rects, from, dy, gap);
8827
+ ordered = next.ordered;
8828
+ setPreview({ key, offsets: next.offsets });
8829
+ };
8830
+ const tick = () => {
8831
+ if (moved) {
8832
+ const bounds = list.getBoundingClientRect();
8833
+ const delta = lastY < bounds.top + 32 ? -10 : lastY > bounds.bottom - 32 ? 10 : 0;
8834
+ const nextScroll = Math.max(0, Math.min(maxScroll, list.scrollTop + delta));
8835
+ if (delta && nextScroll !== list.scrollTop) {
8836
+ list.scrollTop = nextScroll;
8837
+ update();
8838
+ }
8839
+ }
8840
+ frame = requestAnimationFrame(tick);
8841
+ };
8842
+ const move = (next) => {
8843
+ if (next.pointerId === pointerId) {
8844
+ lastY = next.clientY;
8845
+ update();
8846
+ }
8847
+ };
8848
+ const finish = (commit) => {
8849
+ if (ended) return;
8850
+ ended = true;
8851
+ document.removeEventListener("pointermove", move);
8852
+ document.removeEventListener("pointerup", up);
8853
+ document.removeEventListener("pointercancel", cancelPointer);
8854
+ target.removeEventListener("lostpointercapture", cancel);
8855
+ window.removeEventListener("blur", cancel);
8856
+ window.removeEventListener("keydown", escape, true);
8857
+ cancelAnimationFrame(frame);
8858
+ if (target.hasPointerCapture(pointerId)) target.releasePointerCapture(pointerId);
8859
+ document.body.style.userSelect = originalUserSelect;
8860
+ cancelRef.current = void 0;
8861
+ setPreview(void 0);
8862
+ if (commit && moved) commitRef.current(ordered);
8863
+ };
8864
+ const up = (next) => {
8865
+ if (next.pointerId === pointerId) {
8866
+ lastY = next.clientY;
8867
+ update();
8868
+ finish(true);
8869
+ }
8870
+ };
8871
+ const cancel = () => finish(false);
8872
+ const cancelPointer = (next) => {
8873
+ if (next.pointerId === pointerId) cancel();
8874
+ };
8875
+ const escape = (next) => {
8876
+ if (next.key === "Escape") {
8877
+ next.preventDefault();
8878
+ next.stopImmediatePropagation();
8879
+ cancel();
8880
+ }
8881
+ };
8882
+ cancelRef.current = cancel;
8883
+ document.addEventListener("pointermove", move);
8884
+ document.addEventListener("pointerup", up);
8885
+ document.addEventListener("pointercancel", cancelPointer);
8886
+ target.addEventListener("lostpointercapture", cancel);
8887
+ window.addEventListener("blur", cancel);
8888
+ window.addEventListener("keydown", escape, true);
8889
+ frame = requestAnimationFrame(tick);
8890
+ }
8891
+ return { listRef, preview, start };
8892
+ }
8893
+
8894
+ // src/components/queryFormSettingsUtils.ts
8895
+ function reconcileQueryFields(keys, saved = []) {
8896
+ const stored = new Map(saved.map((item) => [item.key, item]));
8897
+ return keys.map((key, index) => ({
8898
+ key,
8899
+ visible: stored.get(key)?.visible !== false,
8900
+ order: Number.isFinite(stored.get(key)?.order) ? stored.get(key).order : Infinity,
8901
+ index
8902
+ })).sort((a, b) => a.order - b.order || a.index - b.index).map(({ key, visible }, order) => ({ key, visible, order }));
8903
+ }
8904
+ function mergeQueryFields(saved, active) {
8905
+ const current = new Set(active.map((item) => item.key));
8906
+ return [...active, ...saved.filter((item) => !current.has(item.key))];
8907
+ }
8908
+
8909
+ // src/components/QueryFormSettings.tsx
8910
+ import { Fragment as Fragment9, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
8911
+ function useQueryFormSettings(config, fields, defaultCollapsed, applyCollapsed, disabled) {
8912
+ const [snapshot, setSnapshot] = useState22();
8913
+ const [draft, setDraft] = useState22({ fields: [], defaultCollapsed });
8914
+ const [open, setOpen] = useState22(false);
8915
+ const [loading, setLoading] = useState22(false);
8916
+ const [saving, setSaving] = useState22(false);
8917
+ const [error, setError] = useState22("");
8918
+ const [loadFailed, setLoadFailed] = useState22(false);
8919
+ const token = useRef19(0);
8920
+ const saveLock = useRef19(false);
8921
+ const latest = useRef19({ config, fields, defaultCollapsed, applyCollapsed });
8922
+ latest.current = { config, fields, defaultCollapsed, applyCollapsed };
8923
+ const moduleName = config?.scope.moduleName;
8924
+ const businessKey = config?.scope.businessKey;
8925
+ const adapter = config?.adapter;
8926
+ async function load(edit) {
8927
+ const current = latest.current;
8928
+ if (!current.config) return;
8929
+ const request = ++token.current;
8930
+ setLoading(true);
8931
+ setError("");
8932
+ setLoadFailed(false);
8933
+ try {
8934
+ const stored = (await current.config.adapter.load(current.config.scope))?.queryForm;
8935
+ if (request !== token.current) return;
8936
+ const next = stored ?? { fields: [], defaultCollapsed: current.defaultCollapsed };
8937
+ setSnapshot(next);
8938
+ setDraft({ ...next, fields: reconcileQueryFields(latest.current.fields.map((field) => field.key), next.fields) });
8939
+ if (!edit) latest.current.applyCollapsed(next.defaultCollapsed);
8940
+ } catch (reason) {
8941
+ if (request !== token.current) return;
8942
+ setLoadFailed(true);
8943
+ setError(reason instanceof Error ? reason.message : "\u8BFB\u53D6\u67E5\u8BE2\u8BBE\u7F6E\u5931\u8D25");
8944
+ current.config.onError?.(reason, "load");
8945
+ } finally {
8946
+ if (request === token.current) setLoading(false);
8947
+ }
8948
+ }
8949
+ useEffect15(() => {
8950
+ setSnapshot(void 0);
8951
+ setOpen(false);
8952
+ setError("");
8953
+ setLoadFailed(false);
8954
+ setLoading(false);
8955
+ setSaving(false);
8956
+ saveLock.current = false;
8957
+ latest.current.applyCollapsed(latest.current.defaultCollapsed);
8958
+ if (adapter) void load(false);
8959
+ return () => {
8960
+ token.current++;
8961
+ };
8962
+ }, [adapter, moduleName, businessKey]);
8963
+ async function save() {
8964
+ const current = latest.current;
8965
+ if (!current.config || loading || loadFailed || disabled || saveLock.current) return false;
8966
+ saveLock.current = true;
8967
+ setSaving(true);
8968
+ setError("");
8969
+ const request = token.current;
8970
+ const active = reconcileQueryFields(current.fields.map((field) => field.key), draft.fields);
8971
+ const next = { ...draft, fields: mergeQueryFields(snapshot?.fields ?? [], active) };
8972
+ try {
8973
+ await saveSettingsPatch(current.config.adapter, current.config.scope, { queryForm: next });
8974
+ if (request !== token.current) return false;
8975
+ setSnapshot(next);
8976
+ current.applyCollapsed(next.defaultCollapsed);
8977
+ setOpen(false);
8978
+ return true;
8979
+ } catch (reason) {
8980
+ if (request !== token.current) return false;
8981
+ setError(reason instanceof Error ? reason.message : "\u4FDD\u5B58\u67E5\u8BE2\u8BBE\u7F6E\u5931\u8D25");
8982
+ current.config.onError?.(reason, "save");
8983
+ return false;
8984
+ } finally {
8985
+ if (request === token.current) {
8986
+ saveLock.current = false;
8987
+ setSaving(false);
8988
+ }
8989
+ }
8990
+ }
8991
+ const visibleDraft = reconcileQueryFields(fields.map((field) => field.key), draft.fields);
8992
+ const labels = new Map(fields.map((field) => [field.key, field.label]));
8993
+ const locked = loading || saving || loadFailed || disabled;
8994
+ const move = (from, to) => {
8995
+ if (locked || from === to || to < 0 || to >= visibleDraft.length) return;
8996
+ const next = [...visibleDraft];
8997
+ next.splice(to, 0, next.splice(from, 1)[0]);
8998
+ setDraft((current) => ({ ...current, fields: next.map((item, order) => ({ ...item, order })) }));
8999
+ };
9000
+ const sort = useQueryFieldSort(visibleDraft.map((item) => item.key), open && !locked, (keys) => {
9001
+ const items = new Map(visibleDraft.map((item) => [item.key, item]));
9002
+ setDraft((current) => ({ ...current, fields: keys.map((key, order) => ({ ...items.get(key), order })) }));
9003
+ });
9004
+ const control = config ? /* @__PURE__ */ jsx26(
9005
+ Button,
9006
+ {
9007
+ type: "button",
9008
+ className: "sia-query-settings__trigger",
9009
+ title: "\u67E5\u8BE2\u8BBE\u7F6E",
9010
+ "aria-label": "\u67E5\u8BE2\u8BBE\u7F6E",
9011
+ disabled: disabled || saving,
9012
+ loading: loading && !open,
9013
+ icon: /* @__PURE__ */ jsx26(Icon, { name: "more-vertical" }),
9014
+ onClick: () => {
9015
+ setOpen(true);
9016
+ void load(true);
9017
+ }
9018
+ }
9019
+ ) : null;
9020
+ const panel = config ? /* @__PURE__ */ jsxs24(Fragment9, { children: [
9021
+ !open && error ? /* @__PURE__ */ jsx26("span", { className: "sia-query-form__error", role: "alert", children: "\u67E5\u8BE2\u8BBE\u7F6E\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u6253\u5F00\u8BBE\u7F6E\u91CD\u8BD5" }) : null,
9022
+ /* @__PURE__ */ jsx26(
9023
+ Modal,
9024
+ {
9025
+ title: "\u67E5\u8BE2\u8BBE\u7F6E",
9026
+ open,
9027
+ width: 520,
9028
+ okText: "\u4FDD\u5B58",
9029
+ confirmLoading: saving,
9030
+ okButtonProps: { disabled: locked },
9031
+ onOk: save,
9032
+ onOpenChange: (next) => {
9033
+ if (!saveLock.current) setOpen(next);
9034
+ },
9035
+ children: /* @__PURE__ */ jsxs24("div", { className: "sia-query-settings", children: [
9036
+ loading ? /* @__PURE__ */ jsx26("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u67E5\u8BE2\u8BBE\u7F6E\u2026" }) : null,
9037
+ error ? /* @__PURE__ */ jsxs24("div", { role: "alert", className: "sia-query-form__error", children: [
9038
+ error,
9039
+ loadFailed ? /* @__PURE__ */ jsx26(Button, { type: "button", variant: "link", onClick: () => void load(true), children: "\u91CD\u8BD5" }) : null
9040
+ ] }) : null,
9041
+ /* @__PURE__ */ jsx26(Checkbox, { checked: draft.defaultCollapsed, disabled: locked, onChange: (checked) => setDraft((current) => ({ ...current, defaultCollapsed: checked })), children: "\u9ED8\u8BA4\u6536\u8D77\u67E5\u8BE2\u6761\u4EF6" }),
9042
+ /* @__PURE__ */ jsx26("p", { className: "sia-query-settings__hint", children: "\u52FE\u9009\u9700\u8981\u663E\u793A\u7684\u6761\u4EF6\uFF0C\u62D6\u52A8\u6216\u4F7F\u7528\u4E0A\u4E0B\u6309\u94AE\u8C03\u6574\u987A\u5E8F\u3002" }),
9043
+ /* @__PURE__ */ jsx26("div", { ref: sort.listRef, className: `sia-query-settings__list${sort.preview ? " is-sorting" : ""}`, children: visibleDraft.map((item, index) => /* @__PURE__ */ jsxs24(
9044
+ "div",
9045
+ {
9046
+ "data-query-field-key": item.key,
9047
+ className: `sia-query-settings__item${sort.preview?.key === item.key ? " is-dragging" : ""}${locked ? " is-disabled" : ""}`,
9048
+ style: sort.preview ? { transform: `translateY(${sort.preview.offsets[item.key] ?? 0}px)` } : void 0,
9049
+ onPointerDown: (event) => sort.start(event, item.key),
9050
+ children: [
9051
+ /* @__PURE__ */ jsx26(Icon, { name: "menu", size: 15 }),
9052
+ /* @__PURE__ */ jsx26(Checkbox, { "aria-label": `\u663E\u793A ${item.key}`, checked: item.visible, disabled: locked, onChange: (checked) => setDraft((current) => ({ ...current, fields: visibleDraft.map((field) => field.key === item.key ? { ...field, visible: checked } : field) })) }),
9053
+ /* @__PURE__ */ jsx26("span", { className: "sia-query-settings__name", children: labels.get(item.key) ?? item.key }),
9054
+ /* @__PURE__ */ jsxs24("div", { className: "sia-query-settings__order", children: [
9055
+ /* @__PURE__ */ jsx26(Button, { type: "button", size: "small", variant: "text", "aria-label": `\u4E0A\u79FB ${item.key}`, disabled: locked || index === 0, icon: /* @__PURE__ */ jsx26(Icon, { name: "chevron-up" }), onClick: () => move(index, index - 1) }),
9056
+ /* @__PURE__ */ jsx26(Button, { type: "button", size: "small", variant: "text", "aria-label": `\u4E0B\u79FB ${item.key}`, disabled: locked || index === visibleDraft.length - 1, icon: /* @__PURE__ */ jsx26(Icon, { name: "chevron-down" }), onClick: () => move(index, index + 1) })
9057
+ ] })
9058
+ ]
9059
+ },
9060
+ item.key
9061
+ )) }),
9062
+ /* @__PURE__ */ jsx26(Button, { type: "button", disabled: locked, onClick: () => setDraft({ fields: reconcileQueryFields(fields.map((field) => field.key)), defaultCollapsed }), children: "\u6062\u590D\u9ED8\u8BA4" })
9063
+ ] })
9064
+ }
9065
+ )
9066
+ ] }) : null;
9067
+ return { snapshot, control, panel };
9068
+ }
9069
+
9070
+ // src/components/QueryForm.tsx
9071
+ import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
8725
9072
  function QueryForm({
8726
9073
  fields,
9074
+ settings,
8727
9075
  children,
8728
9076
  form: providedForm,
8729
9077
  onSearch,
@@ -8754,38 +9102,50 @@ function QueryForm({
8754
9102
  ...formProps
8755
9103
  }) {
8756
9104
  const [form] = useForm(providedForm);
8757
- const [internalCollapsed, setInternalCollapsed] = useState21(defaultCollapsed);
8758
- const [needsCollapse, setNeedsCollapse] = useState21(false);
9105
+ const [internalCollapsed, setInternalCollapsed] = useState23(defaultCollapsed);
9106
+ const [needsCollapse, setNeedsCollapse] = useState23(false);
8759
9107
  const collapsed = collapsible && needsCollapse && (controlledCollapsed ?? internalCollapsed);
8760
- const [searching, setSearching] = useState21(false);
8761
- const [saving, setSaving] = useState21(false);
8762
- const [removing, setRemoving] = useState21(false);
8763
- const [saveOpen, setSaveOpen] = useState21(false);
8764
- const [saveName, setSaveName] = useState21("");
8765
- const [saveError, setSaveError] = useState21("");
8766
- const [error, setError] = useState21("");
8767
- const [activeShortcut, setActiveShortcut] = useState21("");
8768
- const source = useRef18({ source: "submit" });
8769
- const searchLock = useRef18(false);
8770
- const saveLock = useRef18(false);
8771
- const removeLock = useRef18(false);
8772
- const snapshot = useRef18();
9108
+ const [searching, setSearching] = useState23(false);
9109
+ const [saving, setSaving] = useState23(false);
9110
+ const [removing, setRemoving] = useState23(false);
9111
+ const [saveOpen, setSaveOpen] = useState23(false);
9112
+ const [saveName, setSaveName] = useState23("");
9113
+ const [saveError, setSaveError] = useState23("");
9114
+ const [error, setError] = useState23("");
9115
+ const [activeShortcut, setActiveShortcut] = useState23("");
9116
+ const source = useRef20({ source: "submit" });
9117
+ const searchLock = useRef20(false);
9118
+ const saveLock = useRef20(false);
9119
+ const removeLock = useRef20(false);
9120
+ const snapshot = useRef20();
8773
9121
  const busy = disabled || loading || searching;
8774
9122
  const shortcutBusy = busy || shortcutsLoading || saving || removing;
8775
- const entries = fields ? fields.map(({ key, width, ...item }) => ({
9123
+ const fieldLabel = (content) => {
9124
+ if (!isValidElement5(content)) return void 0;
9125
+ return content.props.label ?? content.props.placeholder ?? fieldLabel(content.props.children);
9126
+ };
9127
+ const sourceEntries = fields ? fields.map(({ key, width, settingsLabel, ...item }) => ({
8776
9128
  key,
8777
9129
  width,
8778
- content: /* @__PURE__ */ jsx26(Form.Item, { noStyle: true, ...item })
9130
+ label: settingsLabel ?? item.label ?? (typeof item.children === "function" ? void 0 : fieldLabel(item.children)) ?? key,
9131
+ content: /* @__PURE__ */ jsx27(Form.Item, { noStyle: true, ...item })
8779
9132
  })) : Children4.toArray(children).map((content, index) => ({
8780
- key: String(index),
9133
+ key: isValidElement5(content) && content.key != null ? String(content.key) : String(index),
8781
9134
  width: void 0,
9135
+ label: fieldLabel(content) ?? `\u6761\u4EF6 ${index + 1}`,
8782
9136
  content
8783
9137
  }));
9138
+ const cloudSettings = useQueryFormSettings(settings, sourceEntries, defaultCollapsed, setInternalCollapsed, disabled);
9139
+ const configured = reconcileQueryFields(sourceEntries.map((entry) => entry.key), cloudSettings.snapshot?.fields);
9140
+ const entriesByKey = new Map(sourceEntries.map((entry) => [entry.key, entry]));
9141
+ let visibleIndex = 0;
9142
+ const entries = configured.map((item) => ({ ...entriesByKey.get(item.key), visible: item.visible, visibleIndex: item.visible ? visibleIndex++ : -1 }));
9143
+ const layoutKey = JSON.stringify(configured);
8784
9144
  const limit = Math.max(1, Math.floor(collapsedCount));
8785
- const rowRef = useRef18(null);
8786
- const actionsRef = useRef18(null);
8787
- const toggleRef = useRef18(null);
8788
- const [fittingCount, setFittingCount] = useState21(limit);
9145
+ const rowRef = useRef20(null);
9146
+ const actionsRef = useRef20(null);
9147
+ const toggleRef = useRef20(null);
9148
+ const [fittingCount, setFittingCount] = useState23(limit);
8789
9149
  useLayoutEffect6(() => {
8790
9150
  const row = rowRef.current;
8791
9151
  const actions = actionsRef.current;
@@ -8794,7 +9154,7 @@ function QueryForm({
8794
9154
  if (!row || !actions) return;
8795
9155
  const gap = parseFloat(getComputedStyle(row).columnGap) || 0;
8796
9156
  const allFields = Array.from(
8797
- row.querySelectorAll(":scope > .sia-query-form__field")
9157
+ row.querySelectorAll(":scope > .sia-query-form__field:not([data-settings-hidden])")
8798
9158
  );
8799
9159
  const hiddenFields = allFields.filter((field) => field.hidden);
8800
9160
  const wasCollapsed = row.classList.contains("is-collapsed");
@@ -8836,6 +9196,7 @@ function QueryForm({
8836
9196
  return () => observer.disconnect();
8837
9197
  }, [
8838
9198
  collapsed,
9199
+ layoutKey,
8839
9200
  needsCollapse,
8840
9201
  collapsible,
8841
9202
  limit,
@@ -8924,8 +9285,8 @@ function QueryForm({
8924
9285
  setRemoving(false);
8925
9286
  }
8926
9287
  }
8927
- return /* @__PURE__ */ jsxs24("div", { className: `sia-query-form ${className}`.trim(), children: [
8928
- /* @__PURE__ */ jsxs24(
9288
+ return /* @__PURE__ */ jsxs25("div", { className: `sia-query-form ${className}`.trim(), children: [
9289
+ /* @__PURE__ */ jsxs25(
8929
9290
  Form,
8930
9291
  {
8931
9292
  ...formProps,
@@ -8944,8 +9305,8 @@ function QueryForm({
8944
9305
  onValuesChange?.(changed, values);
8945
9306
  },
8946
9307
  children: [
8947
- quickQueries.length ? /* @__PURE__ */ jsxs24("div", { className: "sia-query-form__quick", "aria-label": "\u9884\u8BBE\u5FEB\u6377\u67E5\u8BE2", children: [
8948
- quickQueries.map((query) => /* @__PURE__ */ jsx26(
9308
+ quickQueries.length ? /* @__PURE__ */ jsxs25("div", { className: "sia-query-form__quick", "aria-label": "\u9884\u8BBE\u5FEB\u6377\u67E5\u8BE2", children: [
9309
+ quickQueries.map((query) => /* @__PURE__ */ jsx27(
8949
9310
  Badge,
8950
9311
  {
8951
9312
  className: "sia-query-form__quick-badge",
@@ -8954,7 +9315,7 @@ function QueryForm({
8954
9315
  title: query.count === void 0 ? void 0 : `\u5171 ${query.count} \u6761`,
8955
9316
  ...query.badgeProps,
8956
9317
  count: query.count,
8957
- children: /* @__PURE__ */ jsx26(
9318
+ children: /* @__PURE__ */ jsx27(
8958
9319
  Button,
8959
9320
  {
8960
9321
  size: query.size ?? quickQuerySize,
@@ -8970,7 +9331,7 @@ function QueryForm({
8970
9331
  )),
8971
9332
  " "
8972
9333
  ] }) : null,
8973
- /* @__PURE__ */ jsxs24(
9334
+ /* @__PURE__ */ jsxs25(
8974
9335
  "div",
8975
9336
  {
8976
9337
  ref: rowRef,
@@ -8979,11 +9340,12 @@ function QueryForm({
8979
9340
  "--sia-query-field-width": typeof fieldWidth === "number" ? `${fieldWidth}px` : fieldWidth
8980
9341
  },
8981
9342
  children: [
8982
- entries.map((entry, index) => /* @__PURE__ */ jsx26(
9343
+ entries.map((entry) => /* @__PURE__ */ jsx27(
8983
9344
  "div",
8984
9345
  {
8985
9346
  className: "sia-query-form__field",
8986
- hidden: collapsed && index >= Math.min(limit, fittingCount),
9347
+ "data-settings-hidden": !entry.visible || void 0,
9348
+ hidden: !entry.visible || collapsed && entry.visibleIndex >= Math.min(limit, fittingCount),
8987
9349
  style: entry.width !== void 0 ? {
8988
9350
  "--sia-query-item-width": typeof entry.width === "number" ? `${entry.width}px` : entry.width
8989
9351
  } : void 0,
@@ -8991,9 +9353,9 @@ function QueryForm({
8991
9353
  },
8992
9354
  entry.key
8993
9355
  )),
8994
- /* @__PURE__ */ jsxs24("div", { ref: actionsRef, className: "sia-query-form__actions", children: [
8995
- /* @__PURE__ */ jsxs24(Space.Compact, { children: [
8996
- /* @__PURE__ */ jsx26(
9356
+ /* @__PURE__ */ jsxs25("div", { ref: actionsRef, className: "sia-query-form__actions", children: [
9357
+ /* @__PURE__ */ jsxs25(Space.Compact, { children: [
9358
+ /* @__PURE__ */ jsx27(
8997
9359
  Button,
8998
9360
  {
8999
9361
  type: "submit",
@@ -9003,8 +9365,8 @@ function QueryForm({
9003
9365
  children: searchText
9004
9366
  }
9005
9367
  ),
9006
- /* @__PURE__ */ jsx26(Button, { disabled: busy, onClick: reset, children: resetText }),
9007
- onSaveQuery ? /* @__PURE__ */ jsx26(
9368
+ /* @__PURE__ */ jsx27(Button, { disabled: busy, onClick: reset, children: resetText }),
9369
+ onSaveQuery ? /* @__PURE__ */ jsx27(
9008
9370
  Button,
9009
9371
  {
9010
9372
  disabled: shortcutBusy,
@@ -9016,14 +9378,15 @@ function QueryForm({
9016
9378
  },
9017
9379
  children: saveText
9018
9380
  }
9019
- ) : null
9381
+ ) : null,
9382
+ cloudSettings.control
9020
9383
  ] }),
9021
- collapsible && entries.length > 0 ? /* @__PURE__ */ jsx26("span", { ref: toggleRef, hidden: !needsCollapse, children: /* @__PURE__ */ jsx26(
9384
+ collapsible && entries.length > 0 ? /* @__PURE__ */ jsx27("span", { ref: toggleRef, hidden: !needsCollapse, children: /* @__PURE__ */ jsx27(
9022
9385
  Button,
9023
9386
  {
9024
9387
  variant: "link",
9025
9388
  "aria-expanded": !collapsed,
9026
- icon: /* @__PURE__ */ jsx26(Icon, { name: collapsed ? "chevron-down" : "chevron-up" }),
9389
+ icon: /* @__PURE__ */ jsx27(Icon, { name: collapsed ? "chevron-down" : "chevron-up" }),
9027
9390
  iconPosition: "end",
9028
9391
  onClick: () => {
9029
9392
  setInternalCollapsed(!collapsed);
@@ -9032,13 +9395,14 @@ function QueryForm({
9032
9395
  children: collapsed ? "\u5C55\u5F00" : "\u6536\u8D77"
9033
9396
  }
9034
9397
  ) }) : null,
9035
- actionsExtra
9398
+ actionsExtra,
9399
+ cloudSettings.panel
9036
9400
  ] })
9037
9401
  ]
9038
9402
  }
9039
9403
  ),
9040
- savedQueries.length ? /* @__PURE__ */ jsxs24("div", { className: "sia-query-form__saved", "aria-label": "\u5DF2\u4FDD\u5B58\u5FEB\u6377\u67E5\u8BE2", children: [
9041
- savedQueries.map((query, index) => /* @__PURE__ */ jsx26(
9404
+ savedQueries.length ? /* @__PURE__ */ jsxs25("div", { className: "sia-query-form__saved", "aria-label": "\u5DF2\u4FDD\u5B58\u5FEB\u6377\u67E5\u8BE2", children: [
9405
+ savedQueries.map((query, index) => /* @__PURE__ */ jsx27(
9042
9406
  Tag,
9043
9407
  {
9044
9408
  status: query.status ?? ["processing", "success", "warning", "error"][index % 4],
@@ -9064,11 +9428,11 @@ function QueryForm({
9064
9428
  )),
9065
9429
  " "
9066
9430
  ] }) : null,
9067
- error ? /* @__PURE__ */ jsx26("p", { className: "sia-query-form__error", role: "alert", children: error }) : null
9431
+ error ? /* @__PURE__ */ jsx27("p", { className: "sia-query-form__error", role: "alert", children: error }) : null
9068
9432
  ]
9069
9433
  }
9070
9434
  ),
9071
- /* @__PURE__ */ jsxs24(
9435
+ /* @__PURE__ */ jsxs25(
9072
9436
  Modal,
9073
9437
  {
9074
9438
  open: saveOpen,
@@ -9080,7 +9444,7 @@ function QueryForm({
9080
9444
  if (!saveLock.current) setSaveOpen(next);
9081
9445
  },
9082
9446
  children: [
9083
- /* @__PURE__ */ jsx26(
9447
+ /* @__PURE__ */ jsx27(
9084
9448
  Input,
9085
9449
  {
9086
9450
  autoFocus: true,
@@ -9099,7 +9463,7 @@ function QueryForm({
9099
9463
  }
9100
9464
  }
9101
9465
  ),
9102
- saveError ? /* @__PURE__ */ jsx26("p", { className: "sia-query-form__error", role: "alert", children: saveError }) : null
9466
+ saveError ? /* @__PURE__ */ jsx27("p", { className: "sia-query-form__error", role: "alert", children: saveError }) : null
9103
9467
  ]
9104
9468
  }
9105
9469
  )
@@ -9108,7 +9472,7 @@ function QueryForm({
9108
9472
 
9109
9473
  // src/components/NumberRange.tsx
9110
9474
  import { forwardRef as forwardRef8 } from "react";
9111
- import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
9475
+ import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
9112
9476
  var NumberRange = forwardRef8(function NumberRange2({
9113
9477
  value,
9114
9478
  defaultValue = [null, null],
@@ -9137,7 +9501,7 @@ var NumberRange = forwardRef8(function NumberRange2({
9137
9501
  setValue2(index === 0 ? [next, range[1]] : [range[0], next]);
9138
9502
  }
9139
9503
  const inputProps = { min, max, step, precision, size, status, disabled, readOnly, placeholderMode, controls: false };
9140
- return /* @__PURE__ */ jsxs25(
9504
+ return /* @__PURE__ */ jsxs26(
9141
9505
  "span",
9142
9506
  {
9143
9507
  ...props,
@@ -9146,7 +9510,7 @@ var NumberRange = forwardRef8(function NumberRange2({
9146
9510
  "aria-disabled": disabled || void 0,
9147
9511
  className: `sia-number-range sia-number-range--${size} sia-number-range--${status}${disabled ? " is-disabled" : ""} ${className}`.trim(),
9148
9512
  children: [
9149
- /* @__PURE__ */ jsx27(
9513
+ /* @__PURE__ */ jsx28(
9150
9514
  InputNumber,
9151
9515
  {
9152
9516
  ...inputProps,
@@ -9158,8 +9522,8 @@ var NumberRange = forwardRef8(function NumberRange2({
9158
9522
  onChange: (next) => change(0, next)
9159
9523
  }
9160
9524
  ),
9161
- /* @__PURE__ */ jsx27(Icon, { className: "sia-number-range__separator", name: "tilde", size: 12, strokeWidth: 1.5, "aria-hidden": "true" }),
9162
- /* @__PURE__ */ jsx27(
9525
+ /* @__PURE__ */ jsx28(Icon, { className: "sia-number-range__separator", name: "tilde", size: 12, strokeWidth: 1.5, "aria-hidden": "true" }),
9526
+ /* @__PURE__ */ jsx28(
9163
9527
  InputNumber,
9164
9528
  {
9165
9529
  ...inputProps,
@@ -9171,7 +9535,7 @@ var NumberRange = forwardRef8(function NumberRange2({
9171
9535
  onChange: (next) => change(1, next)
9172
9536
  }
9173
9537
  ),
9174
- allowClear && !disabled && !readOnly && range.some((item) => item !== null) ? /* @__PURE__ */ jsx27("button", { type: "button", className: "sia-number-range__clear", "aria-label": "\u6E05\u9664\u6570\u5B57\u533A\u95F4", onClick: () => setValue2([null, null]), children: /* @__PURE__ */ jsx27(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null
9538
+ allowClear && !disabled && !readOnly && range.some((item) => item !== null) ? /* @__PURE__ */ jsx28("button", { type: "button", className: "sia-number-range__clear", "aria-label": "\u6E05\u9664\u6570\u5B57\u533A\u95F4", onClick: () => setValue2([null, null]), children: /* @__PURE__ */ jsx28(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null
9175
9539
  ]
9176
9540
  }
9177
9541
  );