@canvas-components/react-components 0.2.1 → 0.3.2

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.d.cts CHANGED
@@ -23,6 +23,12 @@ declare const ReactCheckbox: react.ForwardRefExoticComponent<ReactCheckboxProps
23
23
 
24
24
  /** 通用过滤条件操作符。 */
25
25
  type ReactFilterConditionOperator = "none" | "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "between" | "notBetween" | "startsWith" | "notStartsWith" | "endsWith" | "notEndsWith" | "includes" | "notIncludes" | "blank" | "notBlank";
26
+ /** 通用过滤条件。 */
27
+ interface ReactFilterPanelCondition {
28
+ operator: ReactFilterConditionOperator;
29
+ value?: string;
30
+ secondValue?: string;
31
+ }
26
32
  /** 通用过滤面板草稿。 */
27
33
  interface ReactFilterPanelValue {
28
34
  keyword: string;
@@ -37,6 +43,8 @@ interface ReactFilterPanelValue {
37
43
  secondConditionOperator?: ReactFilterConditionOperator;
38
44
  secondConditionValue?: string;
39
45
  secondConditionSecondValue?: string;
46
+ /** 动态条件列表;存在时优先于旧的两条件字段。 */
47
+ conditions?: ReactFilterPanelCondition[];
40
48
  }
41
49
  /** 通用过滤候选项。 */
42
50
  interface ReactFilterPanelOption {
@@ -67,6 +75,9 @@ interface ReactFilterPanelTexts {
67
75
  relationOrLabel: string;
68
76
  resetAction: string;
69
77
  applyAction: string;
78
+ conditionLabel?: string;
79
+ addConditionAction?: string;
80
+ deleteConditionAction?: string;
70
81
  }
71
82
  /** 通用过滤面板请求。 */
72
83
  interface ReactFilterPanelRequest {
@@ -1130,4 +1141,4 @@ declare function useReactContentScale(): ReactContentScaleValue;
1130
1141
  */
1131
1142
  declare const REACT_COMPONENT_PREFIX = "canvas-react";
1132
1143
 
1133
- export { REACT_COMPONENT_PREFIX, ReactAutoComplete, type ReactAutoCompleteProps, ReactCheckbox, type ReactCheckboxProps, type ReactCheckboxRef, ReactColorPicker, type ReactColorPickerProps, ReactContentScaleProvider, type ReactContentScaleValue, ReactDatePicker, type ReactDatePickerProps, ReactDateRangePicker, type ReactDateRangePickerProps, ReactDateTimePicker, type ReactDateTimePickerProps, ReactDateTimeRangePicker, type ReactDateTimeRangePickerProps, type ReactFilterConditionOperator, ReactFilterPanel, type ReactFilterPanelOption, type ReactFilterPanelRequest, type ReactFilterPanelTexts, type ReactFilterPanelValue, ReactImagePreview, type ReactImagePreviewProps, ReactInput, ReactInputNumber, type ReactInputNumberProps, type ReactInputProps, ReactInputRange, type ReactInputRangeProps, type ReactInputRangeValue, ReactModal, type ReactModalButtonProps, type ReactModalCancelEvent, type ReactModalProps, ReactMonthPicker, type ReactMonthPickerProps, ReactNumberInput, type ReactNumberInputProps, ReactPagination, type ReactPaginationProps, ReactPopconfirm, type ReactPopconfirmButtonProps, type ReactPopconfirmPlacement, type ReactPopconfirmProps, ReactPopup, type ReactPopupProps, ReactQuarterPicker, type ReactQuarterPickerProps, type ReactResizablePanel, type ReactResizablePanelSizes, ReactResizablePanels, type ReactResizablePanelsDirection, type ReactResizablePanelsProps, type ReactResizablePanelsResizeInfo, ReactSelect, type ReactSelectChangeInfo, type ReactSelectFilterOption, type ReactSelectOption, type ReactSelectProps, ReactTimePicker, type ReactTimePickerProps, ReactTimeRangePicker, type ReactTimeRangePickerProps, ReactTransition, type ReactTransitionDuration, type ReactTransitionOptions, type ReactTransitionPhase, type ReactTransitionProps, type ReactTransitionState, ReactVirtualList, type ReactVirtualListProps, type ReactVirtualListRef, ReactYearPicker, type ReactYearPickerProps, resolveResizablePanelSizes, useReactContentScale, useReactTransition };
1144
+ export { REACT_COMPONENT_PREFIX, ReactAutoComplete, type ReactAutoCompleteProps, ReactCheckbox, type ReactCheckboxProps, type ReactCheckboxRef, ReactColorPicker, type ReactColorPickerProps, ReactContentScaleProvider, type ReactContentScaleValue, ReactDatePicker, type ReactDatePickerProps, ReactDateRangePicker, type ReactDateRangePickerProps, ReactDateTimePicker, type ReactDateTimePickerProps, ReactDateTimeRangePicker, type ReactDateTimeRangePickerProps, type ReactFilterConditionOperator, ReactFilterPanel, type ReactFilterPanelCondition, type ReactFilterPanelOption, type ReactFilterPanelRequest, type ReactFilterPanelTexts, type ReactFilterPanelValue, ReactImagePreview, type ReactImagePreviewProps, ReactInput, ReactInputNumber, type ReactInputNumberProps, type ReactInputProps, ReactInputRange, type ReactInputRangeProps, type ReactInputRangeValue, ReactModal, type ReactModalButtonProps, type ReactModalCancelEvent, type ReactModalProps, ReactMonthPicker, type ReactMonthPickerProps, ReactNumberInput, type ReactNumberInputProps, ReactPagination, type ReactPaginationProps, ReactPopconfirm, type ReactPopconfirmButtonProps, type ReactPopconfirmPlacement, type ReactPopconfirmProps, ReactPopup, type ReactPopupProps, ReactQuarterPicker, type ReactQuarterPickerProps, type ReactResizablePanel, type ReactResizablePanelSizes, ReactResizablePanels, type ReactResizablePanelsDirection, type ReactResizablePanelsProps, type ReactResizablePanelsResizeInfo, ReactSelect, type ReactSelectChangeInfo, type ReactSelectFilterOption, type ReactSelectOption, type ReactSelectProps, ReactTimePicker, type ReactTimePickerProps, ReactTimeRangePicker, type ReactTimeRangePickerProps, ReactTransition, type ReactTransitionDuration, type ReactTransitionOptions, type ReactTransitionPhase, type ReactTransitionProps, type ReactTransitionState, ReactVirtualList, type ReactVirtualListProps, type ReactVirtualListRef, ReactYearPicker, type ReactYearPickerProps, resolveResizablePanelSizes, useReactContentScale, useReactTransition };
package/dist/index.d.ts CHANGED
@@ -23,6 +23,12 @@ declare const ReactCheckbox: react.ForwardRefExoticComponent<ReactCheckboxProps
23
23
 
24
24
  /** 通用过滤条件操作符。 */
25
25
  type ReactFilterConditionOperator = "none" | "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "between" | "notBetween" | "startsWith" | "notStartsWith" | "endsWith" | "notEndsWith" | "includes" | "notIncludes" | "blank" | "notBlank";
26
+ /** 通用过滤条件。 */
27
+ interface ReactFilterPanelCondition {
28
+ operator: ReactFilterConditionOperator;
29
+ value?: string;
30
+ secondValue?: string;
31
+ }
26
32
  /** 通用过滤面板草稿。 */
27
33
  interface ReactFilterPanelValue {
28
34
  keyword: string;
@@ -37,6 +43,8 @@ interface ReactFilterPanelValue {
37
43
  secondConditionOperator?: ReactFilterConditionOperator;
38
44
  secondConditionValue?: string;
39
45
  secondConditionSecondValue?: string;
46
+ /** 动态条件列表;存在时优先于旧的两条件字段。 */
47
+ conditions?: ReactFilterPanelCondition[];
40
48
  }
41
49
  /** 通用过滤候选项。 */
42
50
  interface ReactFilterPanelOption {
@@ -67,6 +75,9 @@ interface ReactFilterPanelTexts {
67
75
  relationOrLabel: string;
68
76
  resetAction: string;
69
77
  applyAction: string;
78
+ conditionLabel?: string;
79
+ addConditionAction?: string;
80
+ deleteConditionAction?: string;
70
81
  }
71
82
  /** 通用过滤面板请求。 */
72
83
  interface ReactFilterPanelRequest {
@@ -1130,4 +1141,4 @@ declare function useReactContentScale(): ReactContentScaleValue;
1130
1141
  */
1131
1142
  declare const REACT_COMPONENT_PREFIX = "canvas-react";
1132
1143
 
1133
- export { REACT_COMPONENT_PREFIX, ReactAutoComplete, type ReactAutoCompleteProps, ReactCheckbox, type ReactCheckboxProps, type ReactCheckboxRef, ReactColorPicker, type ReactColorPickerProps, ReactContentScaleProvider, type ReactContentScaleValue, ReactDatePicker, type ReactDatePickerProps, ReactDateRangePicker, type ReactDateRangePickerProps, ReactDateTimePicker, type ReactDateTimePickerProps, ReactDateTimeRangePicker, type ReactDateTimeRangePickerProps, type ReactFilterConditionOperator, ReactFilterPanel, type ReactFilterPanelOption, type ReactFilterPanelRequest, type ReactFilterPanelTexts, type ReactFilterPanelValue, ReactImagePreview, type ReactImagePreviewProps, ReactInput, ReactInputNumber, type ReactInputNumberProps, type ReactInputProps, ReactInputRange, type ReactInputRangeProps, type ReactInputRangeValue, ReactModal, type ReactModalButtonProps, type ReactModalCancelEvent, type ReactModalProps, ReactMonthPicker, type ReactMonthPickerProps, ReactNumberInput, type ReactNumberInputProps, ReactPagination, type ReactPaginationProps, ReactPopconfirm, type ReactPopconfirmButtonProps, type ReactPopconfirmPlacement, type ReactPopconfirmProps, ReactPopup, type ReactPopupProps, ReactQuarterPicker, type ReactQuarterPickerProps, type ReactResizablePanel, type ReactResizablePanelSizes, ReactResizablePanels, type ReactResizablePanelsDirection, type ReactResizablePanelsProps, type ReactResizablePanelsResizeInfo, ReactSelect, type ReactSelectChangeInfo, type ReactSelectFilterOption, type ReactSelectOption, type ReactSelectProps, ReactTimePicker, type ReactTimePickerProps, ReactTimeRangePicker, type ReactTimeRangePickerProps, ReactTransition, type ReactTransitionDuration, type ReactTransitionOptions, type ReactTransitionPhase, type ReactTransitionProps, type ReactTransitionState, ReactVirtualList, type ReactVirtualListProps, type ReactVirtualListRef, ReactYearPicker, type ReactYearPickerProps, resolveResizablePanelSizes, useReactContentScale, useReactTransition };
1144
+ export { REACT_COMPONENT_PREFIX, ReactAutoComplete, type ReactAutoCompleteProps, ReactCheckbox, type ReactCheckboxProps, type ReactCheckboxRef, ReactColorPicker, type ReactColorPickerProps, ReactContentScaleProvider, type ReactContentScaleValue, ReactDatePicker, type ReactDatePickerProps, ReactDateRangePicker, type ReactDateRangePickerProps, ReactDateTimePicker, type ReactDateTimePickerProps, ReactDateTimeRangePicker, type ReactDateTimeRangePickerProps, type ReactFilterConditionOperator, ReactFilterPanel, type ReactFilterPanelCondition, type ReactFilterPanelOption, type ReactFilterPanelRequest, type ReactFilterPanelTexts, type ReactFilterPanelValue, ReactImagePreview, type ReactImagePreviewProps, ReactInput, ReactInputNumber, type ReactInputNumberProps, type ReactInputProps, ReactInputRange, type ReactInputRangeProps, type ReactInputRangeValue, ReactModal, type ReactModalButtonProps, type ReactModalCancelEvent, type ReactModalProps, ReactMonthPicker, type ReactMonthPickerProps, ReactNumberInput, type ReactNumberInputProps, ReactPagination, type ReactPaginationProps, ReactPopconfirm, type ReactPopconfirmButtonProps, type ReactPopconfirmPlacement, type ReactPopconfirmProps, ReactPopup, type ReactPopupProps, ReactQuarterPicker, type ReactQuarterPickerProps, type ReactResizablePanel, type ReactResizablePanelSizes, ReactResizablePanels, type ReactResizablePanelsDirection, type ReactResizablePanelsProps, type ReactResizablePanelsResizeInfo, ReactSelect, type ReactSelectChangeInfo, type ReactSelectFilterOption, type ReactSelectOption, type ReactSelectProps, ReactTimePicker, type ReactTimePickerProps, ReactTimeRangePicker, type ReactTimeRangePickerProps, ReactTransition, type ReactTransitionDuration, type ReactTransitionOptions, type ReactTransitionPhase, type ReactTransitionProps, type ReactTransitionState, ReactVirtualList, type ReactVirtualListProps, type ReactVirtualListRef, ReactYearPicker, type ReactYearPickerProps, resolveResizablePanelSizes, useReactContentScale, useReactTransition };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { forwardRef, useRef, useEffect, useImperativeHandle, createContext, useState, useMemo, useLayoutEffect, useContext } from 'react';
2
+ import { forwardRef, useRef, useEffect, useImperativeHandle, createContext, useState, useMemo, useLayoutEffect, useContext, Fragment as Fragment$1 } from 'react';
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
  import { createPortal } from 'react-dom';
5
5
 
@@ -26,7 +26,7 @@ function styleInject(css, { insertAt } = {}) {
26
26
  }
27
27
 
28
28
  // src/styles/variables.css
29
- styleInject(":root {\n --canvas-react-color-primary: #1677ff;\n --canvas-react-color-primary-hover: #4096ff;\n --canvas-react-color-border: #d9d9d9;\n --canvas-react-color-border-strong: #bfbfbf;\n --canvas-react-color-text: #1f2937;\n --canvas-react-color-text-muted: #6b7280;\n --canvas-react-color-bg: #ffffff;\n --canvas-react-color-bg-soft: #f5f5f5;\n --canvas-react-color-bg-hover: #f3f4f6;\n --canvas-react-color-bg-active: #e6f4ff;\n --canvas-react-shadow-focus: 0 0 0 2px rgba(22, 119, 255, 0.12);\n --canvas-react-shadow-popup: 0 8px 24px rgba(15, 23, 42, 0.16);\n --canvas-react-radius-sm: 6px;\n --canvas-react-radius-md: 8px;\n --canvas-react-control-height: 32px;\n --canvas-react-font-size: 14px;\n --canvas-react-control-padding-inline: 11px;\n --canvas-react-control-padding-block: 0px;\n --canvas-react-content-zoom: 1;\n}\n*,\n*::before,\n*::after {\n scrollbar-width: thin;\n scrollbar-color: #aeb4bd transparent;\n}\n*::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n*::-webkit-scrollbar-track {\n background: transparent;\n}\n*::-webkit-scrollbar-thumb {\n min-height: 32px;\n border: 2px solid transparent;\n border-radius: 999px;\n background: #aeb4bd;\n background-clip: content-box;\n}\n*::-webkit-scrollbar-thumb:hover {\n background: #8f98a5;\n background-clip: content-box;\n}\n*::-webkit-scrollbar-corner {\n background: transparent;\n}\n");
29
+ styleInject(':root {\n --canvas-react-color-primary: #1677ff;\n --canvas-react-color-primary-hover: #4096ff;\n --canvas-react-color-border: #d9d9d9;\n --canvas-react-color-border-strong: #bfbfbf;\n --canvas-react-color-text: #1f2937;\n --canvas-react-color-text-muted: #6b7280;\n --canvas-react-color-bg: #ffffff;\n --canvas-react-color-bg-soft: #f5f5f5;\n --canvas-react-color-bg-hover: #f3f4f6;\n --canvas-react-color-bg-active: #e6f4ff;\n --canvas-react-shadow-focus: 0 0 0 2px rgba(22, 119, 255, 0.12);\n --canvas-react-shadow-popup: 0 8px 24px rgba(15, 23, 42, 0.16);\n --canvas-react-radius-sm: 6px;\n --canvas-react-radius-md: 8px;\n --canvas-react-control-height: 32px;\n --canvas-react-font-size: 14px;\n --canvas-react-control-padding-inline: 11px;\n --canvas-react-control-padding-block: 0px;\n --canvas-react-content-zoom: 1;\n}\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"]),\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"]) * {\n scrollbar-width: thin;\n scrollbar-color: #aeb4bd transparent;\n}\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"])::-webkit-scrollbar,\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"]) *::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"])::-webkit-scrollbar-track,\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"]) *::-webkit-scrollbar-track {\n background: transparent;\n}\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"])::-webkit-scrollbar-thumb,\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"]) *::-webkit-scrollbar-thumb {\n min-height: 32px;\n border: 2px solid transparent;\n border-radius: 999px;\n background: #aeb4bd;\n background-clip: content-box;\n}\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"])::-webkit-scrollbar-thumb:hover,\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"]) *::-webkit-scrollbar-thumb:hover {\n background: #8f98a5;\n background-clip: content-box;\n}\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"])::-webkit-scrollbar-corner,\n:where(.canvas-list-table-root, .react-list-table-shell, .react-xlsx-table-shell, [class^=canvas-react-], [class*=" canvas-react-"]) *::-webkit-scrollbar-corner {\n background: transparent;\n}\n');
30
30
 
31
31
  // src/shared/class-names.ts
32
32
  function joinClassNames(...values) {
@@ -1107,16 +1107,31 @@ var operators = [
1107
1107
  ];
1108
1108
  function ReactFilterPanel(props) {
1109
1109
  const { request } = props;
1110
- const [draft, setDraft] = useState(request?.value ?? null);
1110
+ const [draft, setDraft] = useState(() => createDraft(request?.value));
1111
1111
  const [tab, setTab] = useState(resolveTab(request?.value));
1112
1112
  const [options, setOptions] = useState(request?.options ?? []);
1113
1113
  const [loading, setLoading] = useState(Boolean(request?.loadOptions));
1114
+ const conditionListRef = useRef(null);
1115
+ const [conditionListOverflowing, setConditionListOverflowing] = useState(false);
1114
1116
  useEffect(() => {
1115
- setDraft(request?.value ?? null);
1117
+ setDraft(createDraft(request?.value));
1116
1118
  setTab(resolveTab(request?.value));
1117
1119
  setOptions(request?.options ?? []);
1118
1120
  setLoading(Boolean(request?.loadOptions));
1119
1121
  }, [request]);
1122
+ useLayoutEffect(() => {
1123
+ const element = conditionListRef.current;
1124
+ if (!element || tab !== "condition") {
1125
+ setConditionListOverflowing(false);
1126
+ return;
1127
+ }
1128
+ const measure = () => setConditionListOverflowing(element.scrollHeight > element.clientHeight + 1);
1129
+ measure();
1130
+ if (typeof ResizeObserver === "undefined") return;
1131
+ const observer = new ResizeObserver(measure);
1132
+ observer.observe(element);
1133
+ return () => observer.disconnect();
1134
+ }, [draft?.conditions, tab]);
1120
1135
  useEffect(() => {
1121
1136
  if (!request?.loadOptions) return;
1122
1137
  const controller = new AbortController();
@@ -1151,6 +1166,20 @@ function ReactFilterPanel(props) {
1151
1166
  const allChecked = visibleKeys.length > 0 && selectedCount === visibleKeys.length;
1152
1167
  const allCount = request.options.find((item) => item.kind === "all")?.count ?? visibleOptions.filter((item) => item.kind === "value").reduce((sum, item) => sum + item.count, 0);
1153
1168
  const update = (patch) => setDraft((current) => ({ ...current ?? request.value, ...patch }));
1169
+ const updateConditions = (conditions) => {
1170
+ const first = conditions[0] ?? createEmptyCondition();
1171
+ const second = conditions[1] ?? createEmptyCondition();
1172
+ update({
1173
+ conditions,
1174
+ filterType: "condition",
1175
+ conditionOperator: first.operator,
1176
+ conditionValue: first.value ?? "",
1177
+ conditionSecondValue: first.secondValue ?? "",
1178
+ secondConditionOperator: second.operator,
1179
+ secondConditionValue: second.value ?? "",
1180
+ secondConditionSecondValue: second.secondValue ?? ""
1181
+ });
1182
+ };
1154
1183
  const toggle = (keys, checked) => {
1155
1184
  const next = new Set(draft.selectedKeys ?? []);
1156
1185
  keys.forEach((key) => checked ? next.add(key) : next.delete(key));
@@ -1257,97 +1286,138 @@ function ReactFilterPanel(props) {
1257
1286
  )
1258
1287
  }
1259
1288
  ) })
1260
- ] }) : /* @__PURE__ */ jsxs("div", { style: { marginTop: 12, display: "grid", gap: 12, minHeight: 290, alignContent: "start", flex: "1 1 auto" }, children: [
1261
- /* @__PURE__ */ jsx(
1262
- ConditionEditor,
1263
- {
1264
- label: request.texts.firstConditionLabel,
1265
- operator: draft.conditionOperator ?? "none",
1266
- value: draft.conditionValue ?? "",
1267
- secondValue: draft.conditionSecondValue ?? "",
1268
- texts: request.texts,
1269
- onChange: (patch) => update(patch),
1270
- onSubmit: apply
1271
- }
1272
- ),
1273
- /* @__PURE__ */ jsxs("div", { children: [
1274
- /* @__PURE__ */ jsx("div", { style: fieldLabelStyle, children: request.texts.relationLabel }),
1275
- /* @__PURE__ */ jsx(
1276
- ReactSelect,
1277
- {
1278
- value: draft.conditionRelation === "or" ? "or" : "and",
1279
- allowClear: false,
1280
- options: [{ label: request.texts.relationAndLabel, value: "and" }, { label: request.texts.relationOrLabel, value: "or" }],
1281
- onChange: (value) => update({ conditionRelation: value, filterType: "condition" }),
1282
- style: { width: "100%" }
1283
- }
1284
- )
1285
- ] }),
1286
- /* @__PURE__ */ jsx(
1287
- ConditionEditor,
1289
+ ] }) : /* @__PURE__ */ jsx("div", { style: { marginTop: 12, display: "flex", flexDirection: "column", gap: 10, minHeight: 0, flex: "1 1 auto" }, children: /* @__PURE__ */ jsx(
1290
+ "div",
1291
+ {
1292
+ ref: conditionListRef,
1293
+ className: "react-filter-panel-condition-list",
1294
+ style: { ...conditionListStyle, overflowY: conditionListOverflowing ? "auto" : "hidden" },
1295
+ children: (draft.conditions ?? []).map((condition, index, conditions) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
1296
+ index > 0 ? /* @__PURE__ */ jsxs("div", { className: "react-filter-panel-condition-relation", style: conditionRowStyle, children: [
1297
+ /* @__PURE__ */ jsx("span", { style: inlineLabelStyle, children: request.texts.relationLabel }),
1298
+ /* @__PURE__ */ jsx(
1299
+ ReactSelect,
1300
+ {
1301
+ value: draft.conditionRelation === "or" ? "or" : "and",
1302
+ allowClear: false,
1303
+ options: [{ label: request.texts.relationAndLabel, value: "and" }, { label: request.texts.relationOrLabel, value: "or" }],
1304
+ onChange: (value) => update({ conditionRelation: value, filterType: "condition" }),
1305
+ style: { width: "100%" }
1306
+ }
1307
+ ),
1308
+ /* @__PURE__ */ jsx("span", {})
1309
+ ] }) : null,
1310
+ /* @__PURE__ */ jsx(
1311
+ ConditionEditor,
1312
+ {
1313
+ label: resolveConditionLabel(request.texts, index),
1314
+ condition,
1315
+ texts: request.texts,
1316
+ canDelete: conditions.length > 1,
1317
+ onDelete: () => updateConditions(conditions.filter((_item, itemIndex) => itemIndex !== index)),
1318
+ onChange: (nextCondition) => updateConditions(conditions.map((item, itemIndex) => itemIndex === index ? nextCondition : item)),
1319
+ onSubmit: apply
1320
+ }
1321
+ )
1322
+ ] }, index))
1323
+ }
1324
+ ) }),
1325
+ /* @__PURE__ */ jsxs("div", { className: "react-filter-panel-footer", style: footerStyle, children: [
1326
+ tab === "condition" ? /* @__PURE__ */ jsxs(
1327
+ "button",
1288
1328
  {
1289
- second: true,
1290
- label: request.texts.secondConditionLabel,
1291
- operator: draft.secondConditionOperator ?? "none",
1292
- value: draft.secondConditionValue ?? "",
1293
- secondValue: draft.secondConditionSecondValue ?? "",
1294
- texts: request.texts,
1295
- onChange: (patch) => update(patch),
1296
- onSubmit: apply
1329
+ type: "button",
1330
+ style: addConditionStyle,
1331
+ onClick: () => updateConditions([...draft.conditions ?? [], createEmptyCondition()]),
1332
+ children: [
1333
+ "+ ",
1334
+ request.texts.addConditionAction ?? "\u65B0\u589E\u6761\u4EF6"
1335
+ ]
1297
1336
  }
1298
- )
1299
- ] }),
1300
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
1301
- /* @__PURE__ */ jsx("button", { type: "button", style: actionStyle(false), onClick: () => {
1302
- request.onReset();
1303
- request.onClose();
1304
- }, children: request.texts.resetAction }),
1305
- /* @__PURE__ */ jsx("button", { type: "button", style: actionStyle(true), onClick: apply, children: request.texts.applyAction })
1337
+ ) : null,
1338
+ /* @__PURE__ */ jsxs("div", { className: "react-filter-panel-footer-actions", style: footerActionsStyle, children: [
1339
+ /* @__PURE__ */ jsx("button", { type: "button", style: actionStyle(false), onClick: () => {
1340
+ request.onReset();
1341
+ request.onClose();
1342
+ }, children: request.texts.resetAction }),
1343
+ /* @__PURE__ */ jsx("button", { type: "button", style: actionStyle(true), onClick: apply, children: request.texts.applyAction })
1344
+ ] })
1306
1345
  ] })
1307
1346
  ] })
1308
1347
  }
1309
1348
  );
1310
1349
  }
1311
1350
  function ConditionEditor(props) {
1312
- const prefix = props.second ? "secondCondition" : "condition";
1313
- const hidesValue = ["none", "blank", "notBlank"].includes(props.operator);
1314
- const needsSecond = ["between", "notBetween"].includes(props.operator);
1315
- return /* @__PURE__ */ jsxs("div", { children: [
1316
- /* @__PURE__ */ jsx("div", { style: fieldLabelStyle, children: props.label }),
1317
- /* @__PURE__ */ jsx(
1318
- ReactSelect,
1319
- {
1320
- value: props.operator,
1321
- options: operators,
1322
- allowClear: false,
1323
- onChange: (value) => props.onChange({ [`${prefix}Operator`]: value, filterType: "condition" }),
1324
- style: { width: "100%" }
1325
- }
1326
- ),
1327
- hidesValue ? null : /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 8, marginTop: 8 }, children: [
1351
+ const hidesValue = ["none", "blank", "notBlank"].includes(props.condition.operator);
1352
+ const needsSecond = ["between", "notBetween"].includes(props.condition.operator);
1353
+ return /* @__PURE__ */ jsxs("div", { style: conditionEditorStyle, children: [
1354
+ /* @__PURE__ */ jsxs("div", { className: "react-filter-panel-condition-row", style: conditionRowStyle, children: [
1355
+ /* @__PURE__ */ jsx("span", { style: inlineLabelStyle, children: props.label }),
1356
+ /* @__PURE__ */ jsx(
1357
+ ReactSelect,
1358
+ {
1359
+ value: props.condition.operator,
1360
+ options: operators,
1361
+ allowClear: false,
1362
+ onChange: (value) => props.onChange({ ...props.condition, operator: value }),
1363
+ style: { width: "100%" }
1364
+ }
1365
+ ),
1366
+ props.canDelete ? /* @__PURE__ */ jsx(
1367
+ "button",
1368
+ {
1369
+ type: "button",
1370
+ title: `${props.texts.deleteConditionAction ?? "\u5220\u9664\u6761\u4EF6"} ${props.label}`,
1371
+ "aria-label": `${props.texts.deleteConditionAction ?? "\u5220\u9664\u6761\u4EF6"} ${props.label}`,
1372
+ style: deleteConditionStyle,
1373
+ onClick: props.onDelete,
1374
+ children: "\xD7"
1375
+ }
1376
+ ) : /* @__PURE__ */ jsx("span", {})
1377
+ ] }),
1378
+ hidesValue ? null : /* @__PURE__ */ jsxs("div", { style: conditionValueStyle, children: [
1328
1379
  /* @__PURE__ */ jsx(
1329
1380
  ReactInput,
1330
1381
  {
1331
- value: props.value,
1382
+ value: props.condition.value ?? "",
1332
1383
  placeholder: props.texts.firstValuePlaceholder,
1333
1384
  onPressEnter: props.onSubmit,
1334
- onChange: (event) => props.onChange({ [`${prefix}Value`]: event.target.value, filterType: "condition" }),
1385
+ onChange: (event) => props.onChange({ ...props.condition, value: event.target.value }),
1335
1386
  style: { width: "100%" }
1336
1387
  }
1337
1388
  ),
1338
1389
  needsSecond ? /* @__PURE__ */ jsx(
1339
1390
  ReactInput,
1340
1391
  {
1341
- value: props.secondValue,
1392
+ value: props.condition.secondValue ?? "",
1342
1393
  placeholder: props.texts.secondValuePlaceholder,
1343
1394
  onPressEnter: props.onSubmit,
1344
- onChange: (event) => props.onChange({ [`${prefix}SecondValue`]: event.target.value, filterType: "condition" }),
1395
+ onChange: (event) => props.onChange({ ...props.condition, secondValue: event.target.value }),
1345
1396
  style: { width: "100%" }
1346
1397
  }
1347
1398
  ) : null
1348
1399
  ] })
1349
1400
  ] });
1350
1401
  }
1402
+ function createDraft(value) {
1403
+ if (!value) return null;
1404
+ return { ...value, conditions: resolveDraftConditions(value) };
1405
+ }
1406
+ function resolveDraftConditions(value) {
1407
+ if (value.conditions?.length) return value.conditions.map((condition) => ({ ...condition }));
1408
+ return [
1409
+ { operator: value.conditionOperator ?? "none", value: value.conditionValue ?? "", secondValue: value.conditionSecondValue ?? "" },
1410
+ { operator: value.secondConditionOperator ?? "none", value: value.secondConditionValue ?? "", secondValue: value.secondConditionSecondValue ?? "" }
1411
+ ];
1412
+ }
1413
+ function createEmptyCondition() {
1414
+ return { operator: "none", value: "", secondValue: "" };
1415
+ }
1416
+ function resolveConditionLabel(texts, index) {
1417
+ if (index === 0) return texts.firstConditionLabel;
1418
+ if (index === 1) return texts.secondConditionLabel;
1419
+ return `${texts.conditionLabel ?? "\u6761\u4EF6"} ${index + 1}`;
1420
+ }
1351
1421
  function resolveTab(value) {
1352
1422
  return value?.filterType === "condition" || value?.conditionOperator && value.conditionOperator !== "none" ? "condition" : "value";
1353
1423
  }
@@ -1359,7 +1429,15 @@ function optionLabel(item, texts) {
1359
1429
  var checkLabelStyle = { display: "inline-flex", alignItems: "center", gap: 8, color: "#374151", fontSize: 14 };
1360
1430
  var optionStyle = { display: "flex", alignItems: "center", gap: 8, minHeight: 40, padding: "4px 8px", borderRadius: 6, color: "#374151", fontSize: 14, cursor: "pointer", boxSizing: "border-box" };
1361
1431
  var optionTextStyle = { display: "block", flex: "1 1 0", width: 0, minWidth: 0, overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis" };
1362
- var fieldLabelStyle = { marginBottom: 6, fontSize: 12, color: "#6b7280" };
1432
+ var conditionListStyle = { display: "grid", gap: 8, minHeight: 0, flex: "1 1 auto", alignContent: "start", paddingRight: 3 };
1433
+ var conditionEditorStyle = { display: "grid", gap: 8 };
1434
+ var conditionRowStyle = { display: "grid", gridTemplateColumns: "56px minmax(0, 1fr) 22px", alignItems: "center", gap: 8 };
1435
+ var inlineLabelStyle = { color: "#6b7280", fontSize: 12, whiteSpace: "nowrap" };
1436
+ var conditionValueStyle = { display: "grid", gap: 8, marginLeft: 64, marginRight: 30 };
1437
+ var addConditionStyle = { height: 32, padding: "0 10px", border: "1px solid #91caff", borderRadius: 6, background: "#f0f7ff", color: "#1677ff", cursor: "pointer", whiteSpace: "nowrap" };
1438
+ var deleteConditionStyle = { width: 22, height: 22, padding: 0, border: 0, borderRadius: 4, background: "transparent", color: "#9ca3af", fontSize: 18, lineHeight: "20px", cursor: "pointer" };
1439
+ var footerStyle = { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 };
1440
+ var footerActionsStyle = { display: "flex", gap: 8, marginLeft: "auto" };
1363
1441
  function tabStyle(active) {
1364
1442
  return { flex: 1, height: 32, border: active ? "1px solid #1677ff" : "1px solid #d9d9d9", borderRadius: 6, background: active ? "#e6f4ff" : "#fff", color: active ? "#1677ff" : "#374151", cursor: "pointer" };
1365
1443
  }