@oceanbase/design 1.0.0-alpha.15 → 1.0.0-alpha.17
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/design.min.js +1 -1
- package/es/alert/index.d.ts +1 -1
- package/es/alert/index.js +4 -2
- package/es/filter/components/CountNumber.js +2 -1
- package/es/filter/components/FilterButton.d.ts +2 -0
- package/es/filter/components/FilterButton.js +6 -3
- package/es/filter/components/FilterCascader/components/CascaderOption/OptionCheckbox.d.ts +20 -0
- package/es/filter/components/FilterCascader/components/CascaderOption/OptionCheckbox.js +101 -0
- package/es/filter/components/FilterCascader/components/CascaderOption/OptionItem.d.ts +13 -0
- package/es/filter/components/FilterCascader/components/CascaderOption/OptionItem.js +44 -0
- package/es/filter/components/FilterCascader/components/FlatCascaderContent/index.d.ts +16 -0
- package/es/filter/components/FilterCascader/components/FlatCascaderContent/index.js +64 -0
- package/es/filter/components/FilterCascader/components/NormalCascaderContent.d.ts +24 -0
- package/es/filter/components/FilterCascader/components/NormalCascaderContent.js +284 -0
- package/es/filter/components/FilterCascader/constants.d.ts +7 -0
- package/es/filter/components/FilterCascader/constants.js +8 -0
- package/es/filter/components/FilterCascader/hooks/useCascaderCallbacks.d.ts +12 -0
- package/es/filter/components/FilterCascader/hooks/useCascaderCallbacks.js +101 -0
- package/es/filter/components/FilterCascader/hooks/useCascaderLabels.d.ts +9 -0
- package/es/filter/components/FilterCascader/hooks/useCascaderLabels.js +50 -0
- package/es/filter/components/FilterCascader/hooks/useNormalizedValue.d.ts +7 -0
- package/es/filter/components/FilterCascader/hooks/useNormalizedValue.js +53 -0
- package/es/filter/components/FilterCascader/index.d.ts +5 -0
- package/es/filter/components/FilterCascader/index.js +317 -0
- package/es/filter/components/FilterCascader/types.d.ts +56 -0
- package/es/filter/components/FilterCascader/types.js +1 -0
- package/es/filter/components/FilterCascader/utils/countUtils.d.ts +13 -0
- package/es/filter/components/FilterCascader/utils/countUtils.js +48 -0
- package/es/filter/components/FilterCascader/utils/pathUtils.d.ts +17 -0
- package/es/filter/components/FilterCascader/utils/pathUtils.js +91 -0
- package/es/filter/components/FilterCheckbox.js +29 -7
- package/es/filter/components/FilterWrap.js +30 -1
- package/es/filter/components/ResponsiveFilterGroup.js +252 -359
- package/es/filter/index.d.ts +1 -1
- package/es/filter/index.js +11 -7
- package/es/filter/style/index.js +9 -2
- package/es/filter/type.d.ts +5 -0
- package/es/table/index.d.ts +2 -2
- package/lib/alert/index.d.ts +1 -1
- package/lib/alert/index.js +3 -1
- package/lib/filter/components/CountNumber.js +2 -1
- package/lib/filter/components/FilterButton.d.ts +2 -0
- package/lib/filter/components/FilterButton.js +4 -2
- package/lib/filter/components/FilterCascader/components/CascaderOption/OptionCheckbox.d.ts +20 -0
- package/lib/filter/components/FilterCascader/components/CascaderOption/OptionCheckbox.js +91 -0
- package/lib/filter/components/FilterCascader/components/CascaderOption/OptionItem.d.ts +13 -0
- package/lib/filter/components/FilterCascader/components/CascaderOption/OptionItem.js +51 -0
- package/lib/filter/components/FilterCascader/components/FlatCascaderContent/index.d.ts +16 -0
- package/lib/filter/components/FilterCascader/components/FlatCascaderContent/index.js +70 -0
- package/lib/filter/components/FilterCascader/components/NormalCascaderContent.d.ts +24 -0
- package/lib/filter/components/FilterCascader/components/NormalCascaderContent.js +263 -0
- package/lib/filter/components/FilterCascader/constants.d.ts +7 -0
- package/lib/filter/components/FilterCascader/constants.js +14 -0
- package/lib/filter/components/FilterCascader/hooks/useCascaderCallbacks.d.ts +12 -0
- package/lib/filter/components/FilterCascader/hooks/useCascaderCallbacks.js +81 -0
- package/lib/filter/components/FilterCascader/hooks/useCascaderLabels.d.ts +9 -0
- package/lib/filter/components/FilterCascader/hooks/useCascaderLabels.js +56 -0
- package/lib/filter/components/FilterCascader/hooks/useNormalizedValue.d.ts +7 -0
- package/lib/filter/components/FilterCascader/hooks/useNormalizedValue.js +48 -0
- package/lib/filter/components/FilterCascader/index.d.ts +5 -0
- package/lib/filter/components/FilterCascader/index.js +298 -0
- package/lib/filter/components/FilterCascader/types.d.ts +56 -0
- package/lib/filter/components/FilterCascader/types.js +5 -0
- package/lib/filter/components/FilterCascader/utils/countUtils.d.ts +13 -0
- package/lib/filter/components/FilterCascader/utils/countUtils.js +49 -0
- package/lib/filter/components/FilterCascader/utils/pathUtils.d.ts +17 -0
- package/lib/filter/components/FilterCascader/utils/pathUtils.js +56 -0
- package/lib/filter/components/FilterCheckbox.js +29 -7
- package/lib/filter/components/FilterWrap.js +28 -1
- package/lib/filter/components/ResponsiveFilterGroup.js +214 -340
- package/lib/filter/index.d.ts +1 -1
- package/lib/filter/index.js +11 -7
- package/lib/filter/style/index.js +10 -1
- package/lib/filter/type.d.ts +5 -0
- package/package.json +3 -3
- package/es/filter/components/FilterCascader.d.ts +0 -31
- package/es/filter/components/FilterCascader.js +0 -529
- package/lib/filter/components/FilterCascader.d.ts +0 -31
- package/lib/filter/components/FilterCascader.js +0 -449
|
@@ -15,8 +15,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
15
15
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
16
16
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
17
17
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
18
|
-
import React, { Children,
|
|
19
|
-
import { createPortal } from 'react-dom';
|
|
18
|
+
import React, { Children, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
20
19
|
import { Flex } from 'antd';
|
|
21
20
|
import { FilterOutlined } from '@oceanbase/icons';
|
|
22
21
|
import Button from "../../button";
|
|
@@ -26,33 +25,24 @@ import defaultLocale from "../../locale/en-US";
|
|
|
26
25
|
import { FilterProvider } from "../FilterContext";
|
|
27
26
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
28
27
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* <Filter.Select label="执行结果" ... />
|
|
41
|
-
* </ResponsiveFilterGroup>
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
// 检查子元素是否可以被收集
|
|
45
|
-
var isCollapsible = function isCollapsible(child) {
|
|
46
|
-
// 检查子元素的 props 中是否有 collapsible 属性
|
|
47
|
-
// 如果子元素是 Form.Item,需要检查其子元素的 props
|
|
48
|
-
var childProps = child.props;
|
|
28
|
+
// 检查元素是否是 Filter 组件(通过 __isFilterComponent 静态标记识别)
|
|
29
|
+
var isFilterComponent = function isFilterComponent(child) {
|
|
30
|
+
var _child$props;
|
|
31
|
+
var type = child.type;
|
|
32
|
+
if (type !== null && type !== void 0 && type.__isFilterComponent) return true;
|
|
33
|
+
if ((_child$props = child.props) !== null && _child$props !== void 0 && _child$props.children && /*#__PURE__*/isValidElement(child.props.children)) {
|
|
34
|
+
var innerType = child.props.children.type;
|
|
35
|
+
if (innerType !== null && innerType !== void 0 && innerType.__isFilterComponent) return true;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
};
|
|
49
39
|
|
|
50
|
-
|
|
40
|
+
// 检查子元素是否可以被折叠(只有 Filter 组件默认可折叠,其他组件需要显式设置 collapsible)
|
|
41
|
+
var isCollapsibleCheck = function isCollapsibleCheck(child) {
|
|
42
|
+
var childProps = child.props;
|
|
51
43
|
if ((childProps === null || childProps === void 0 ? void 0 : childProps.collapsible) !== undefined) {
|
|
52
44
|
return childProps.collapsible !== false;
|
|
53
45
|
}
|
|
54
|
-
|
|
55
|
-
// 如果是 Form.Item 等包装组件,检查其 children 的 collapsible
|
|
56
46
|
if (childProps !== null && childProps !== void 0 && childProps.children && /*#__PURE__*/isValidElement(childProps.children)) {
|
|
57
47
|
var _innerChild$props;
|
|
58
48
|
var innerChild = childProps.children;
|
|
@@ -60,21 +50,15 @@ var isCollapsible = function isCollapsible(child) {
|
|
|
60
50
|
return innerChild.props.collapsible !== false;
|
|
61
51
|
}
|
|
62
52
|
}
|
|
63
|
-
|
|
64
|
-
// 默认可以被收集
|
|
65
|
-
return true;
|
|
53
|
+
return isFilterComponent(child);
|
|
66
54
|
};
|
|
67
55
|
|
|
68
56
|
// 检查子元素是否应该始终折叠
|
|
69
|
-
var
|
|
57
|
+
var isAlwaysCollapseCheck = function isAlwaysCollapseCheck(child) {
|
|
70
58
|
var childProps = child.props;
|
|
71
|
-
|
|
72
|
-
// 直接检查 alwaysCollapse 属性
|
|
73
59
|
if ((childProps === null || childProps === void 0 ? void 0 : childProps.alwaysCollapse) !== undefined) {
|
|
74
60
|
return childProps.alwaysCollapse === true;
|
|
75
61
|
}
|
|
76
|
-
|
|
77
|
-
// 如果是 Form.Item 等包装组件,检查其 children 的 alwaysCollapse
|
|
78
62
|
if (childProps !== null && childProps !== void 0 && childProps.children && /*#__PURE__*/isValidElement(childProps.children)) {
|
|
79
63
|
var _innerChild$props2;
|
|
80
64
|
var innerChild = childProps.children;
|
|
@@ -82,8 +66,6 @@ var isAlwaysCollapse = function isAlwaysCollapse(child) {
|
|
|
82
66
|
return innerChild.props.alwaysCollapse === true;
|
|
83
67
|
}
|
|
84
68
|
}
|
|
85
|
-
|
|
86
|
-
// 默认不始终折叠
|
|
87
69
|
return false;
|
|
88
70
|
};
|
|
89
71
|
var ResponsiveFilterGroup = function ResponsiveFilterGroup(_ref) {
|
|
@@ -105,262 +87,182 @@ var ResponsiveFilterGroup = function ResponsiveFilterGroup(_ref) {
|
|
|
105
87
|
var _useContext = useContext(ConfigProvider.ConfigContext),
|
|
106
88
|
contextLocale = _useContext.locale;
|
|
107
89
|
var filterLocale = _objectSpread(_objectSpread(_objectSpread({}, defaultLocale.Filter), contextLocale === null || contextLocale === void 0 ? void 0 : contextLocale.Filter), customLocale);
|
|
108
|
-
// 如果没有传入 label,使用国际化默认值
|
|
109
90
|
var filterLabel = label !== null && label !== void 0 ? label : filterLocale === null || filterLocale === void 0 ? void 0 : filterLocale.filters;
|
|
110
91
|
var containerRef = useRef(null);
|
|
111
|
-
var innerFlexRef = useRef(null);
|
|
112
|
-
var measureRef = useRef(null);
|
|
113
|
-
var unmeasureRef = useRef(null);
|
|
114
|
-
var moreButtonRef = useRef(null);
|
|
115
92
|
var filterButtonRef = useRef(null);
|
|
116
|
-
var
|
|
93
|
+
var moreButtonMeasureRef = useRef(null);
|
|
94
|
+
var cachedWidths = useRef([]);
|
|
95
|
+
var _useState = useState(null),
|
|
117
96
|
_useState2 = _slicedToArray(_useState, 2),
|
|
118
97
|
visibleCount = _useState2[0],
|
|
119
|
-
setVisibleCount = _useState2[1];
|
|
98
|
+
setVisibleCount = _useState2[1];
|
|
120
99
|
var _useState3 = useState([]),
|
|
121
100
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
101
|
+
filterValues = _useState4[0],
|
|
102
|
+
setFilterValues = _useState4[1];
|
|
103
|
+
var childrenArray = useMemo(function () {
|
|
104
|
+
return Children.toArray(children).filter(isValidElement);
|
|
105
|
+
}, [children]);
|
|
106
|
+
var childInfo = useMemo(function () {
|
|
107
|
+
return childrenArray.map(function (child, index) {
|
|
108
|
+
return {
|
|
109
|
+
child: child,
|
|
110
|
+
index: index,
|
|
111
|
+
isCollapsible: isCollapsibleCheck(child),
|
|
112
|
+
isAlwaysCollapse: isAlwaysCollapseCheck(child)
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
}, [childrenArray]);
|
|
116
|
+
var collapsibleItems = useMemo(function () {
|
|
117
|
+
return childInfo.filter(function (item) {
|
|
118
|
+
return item.isCollapsible;
|
|
119
|
+
});
|
|
120
|
+
}, [childInfo]);
|
|
121
|
+
var alwaysCollapseItems = useMemo(function () {
|
|
122
|
+
return collapsibleItems.filter(function (item) {
|
|
123
|
+
return item.isAlwaysCollapse;
|
|
124
|
+
});
|
|
125
|
+
}, [collapsibleItems]);
|
|
126
|
+
var normalCollapsibleItems = useMemo(function () {
|
|
127
|
+
return collapsibleItems.filter(function (item) {
|
|
128
|
+
return !item.isAlwaysCollapse;
|
|
129
|
+
});
|
|
130
|
+
}, [collapsibleItems]);
|
|
131
|
+
|
|
132
|
+
// 当 children 结构变化(增删/重排)时才重置为测量模式
|
|
133
|
+
// 不能用 childrenArray 引用比较,因为 JSX 每次渲染都产生新引用
|
|
134
|
+
var childrenStructureKey = childrenArray.map(function (c) {
|
|
135
|
+
var _c$key;
|
|
136
|
+
return (_c$key = c.key) !== null && _c$key !== void 0 ? _c$key : c.type;
|
|
137
|
+
}).join(',');
|
|
138
|
+
var _useState5 = useState(childrenStructureKey),
|
|
126
139
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
var
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
148
|
-
var collapsibleChildren = childrenArray.filter(function (child) {
|
|
149
|
-
return isCollapsible(child);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// 分离始终折叠和普通可收集的子元素
|
|
153
|
-
var alwaysCollapseChildren = collapsibleChildren.filter(function (child) {
|
|
154
|
-
return isAlwaysCollapse(child);
|
|
155
|
-
});
|
|
156
|
-
var normalCollapsibleChildren = collapsibleChildren.filter(function (child) {
|
|
157
|
-
return !isAlwaysCollapse(child);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// 创建测量容器
|
|
161
|
-
useEffect(function () {
|
|
162
|
-
var container = document.createElement('div');
|
|
163
|
-
container.style.cssText = 'position: absolute; visibility: hidden; pointer-events: none; top: -9999px; left: -9999px;';
|
|
164
|
-
document.body.appendChild(container);
|
|
165
|
-
setMeasureContainer(container);
|
|
166
|
-
return function () {
|
|
167
|
-
document.body.removeChild(container);
|
|
168
|
-
};
|
|
169
|
-
}, []);
|
|
170
|
-
|
|
171
|
-
// 测量每个可收集子元素的宽度(只测量普通可收集的,不包括始终折叠的)
|
|
172
|
-
var measureChildren = useCallback(function () {
|
|
173
|
-
if (!measureRef.current) return;
|
|
174
|
-
|
|
175
|
-
// 测量普通可收集子元素宽度
|
|
176
|
-
var widths = [];
|
|
177
|
-
if (measureRef.current) {
|
|
178
|
-
var measureDiv = measureRef.current;
|
|
179
|
-
var measureItems = measureDiv.children;
|
|
180
|
-
for (var i = 0; i < measureItems.length; i++) {
|
|
181
|
-
var item = measureItems[i];
|
|
182
|
-
widths.push(item.offsetWidth);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
setChildWidths(widths);
|
|
186
|
-
|
|
187
|
-
// 测量 more button 的宽度
|
|
188
|
-
if (moreButtonRef.current) {
|
|
189
|
-
setActualMoreButtonWidth(moreButtonRef.current.offsetWidth);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// 测量不可收集子元素的总宽度(使用隐藏测量容器,保证与普通可收集项的测量方式一致)
|
|
193
|
-
if (unmeasureRef.current) {
|
|
194
|
-
var sum = 0;
|
|
195
|
-
var items = unmeasureRef.current.children;
|
|
196
|
-
for (var _i = 0; _i < items.length; _i++) {
|
|
197
|
-
var it = items[_i];
|
|
198
|
-
sum += it.offsetWidth;
|
|
140
|
+
prevStructureKey = _useState6[0],
|
|
141
|
+
setPrevStructureKey = _useState6[1];
|
|
142
|
+
if (childrenStructureKey !== prevStructureKey) {
|
|
143
|
+
setPrevStructureKey(childrenStructureKey);
|
|
144
|
+
setVisibleCount(null);
|
|
145
|
+
}
|
|
146
|
+
var isMeasuring = visibleCount === null;
|
|
147
|
+
|
|
148
|
+
// 纯计算函数:根据容器宽度计算可显示的可折叠项数量
|
|
149
|
+
var calculateVisibleCount = useCallback(function (containerWidth) {
|
|
150
|
+
var _moreButtonMeasureRef;
|
|
151
|
+
if (normalCollapsibleItems.length === 0) return 0;
|
|
152
|
+
var widths = cachedWidths.current;
|
|
153
|
+
if (widths.length === 0) return normalCollapsibleItems.length;
|
|
154
|
+
var uncollapsibleTotalWidth = 0;
|
|
155
|
+
var uncollapsibleCount = 0;
|
|
156
|
+
childInfo.forEach(function (info) {
|
|
157
|
+
if (!info.isCollapsible) {
|
|
158
|
+
uncollapsibleTotalWidth += widths[info.index] || 0;
|
|
159
|
+
uncollapsibleCount++;
|
|
199
160
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}, [unCollapsibleChildren.length, normalCollapsibleChildren.length, gap]);
|
|
205
|
-
|
|
206
|
-
// 计算可见的可收集子元素数量(只计算普通可收集的,不包括始终折叠的)
|
|
207
|
-
var calculateVisibleCount = useCallback(function () {
|
|
208
|
-
if (!containerRef.current) return;
|
|
209
|
-
// 如果没有普通可收集的子元素,显示全部(0表示全部折叠)
|
|
210
|
-
if (normalCollapsibleChildren.length === 0) {
|
|
211
|
-
setVisibleCount(0);
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
if (childWidths.length === 0) return;
|
|
215
|
-
|
|
216
|
-
// 可用宽度 = 容器宽度 - 不可收集子元素占用的宽度 - 可能存在的间隙
|
|
217
|
-
var containerWidth = containerRef.current.offsetWidth;
|
|
218
|
-
var gapBetweenUncollapsibleAndCollapsible = unCollapsibleChildren.length > 0 && normalCollapsibleChildren.length > 0 ? gap : 0;
|
|
219
|
-
var availableWidth = containerWidth - (unCollapsibleWidth || 0) - gapBetweenUncollapsibleAndCollapsible;
|
|
220
|
-
var totalWidth = 0;
|
|
161
|
+
});
|
|
162
|
+
var moreWidth = ((_moreButtonMeasureRef = moreButtonMeasureRef.current) === null || _moreButtonMeasureRef === void 0 ? void 0 : _moreButtonMeasureRef.offsetWidth) || 0;
|
|
163
|
+
var hasAlwaysCollapse = alwaysCollapseItems.length > 0;
|
|
164
|
+
var visibleWidth = 0;
|
|
221
165
|
var count = 0;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
var
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (totalWidth + itemWidth + reservedWidth <= availableWidth) {
|
|
233
|
-
totalWidth += itemWidth;
|
|
166
|
+
for (var i = 0; i < normalCollapsibleItems.length; i++) {
|
|
167
|
+
var itemWidth = widths[normalCollapsibleItems[i].index] || 0;
|
|
168
|
+
var newWidth = visibleWidth + itemWidth;
|
|
169
|
+
var remaining = normalCollapsibleItems.length - i - 1;
|
|
170
|
+
var needMore = remaining > 0 || hasAlwaysCollapse;
|
|
171
|
+
var totalItems = uncollapsibleCount + count + 1 + (needMore ? 1 : 0);
|
|
172
|
+
var totalGaps = totalItems > 1 ? (totalItems - 1) * gap : 0;
|
|
173
|
+
var totalWidth = uncollapsibleTotalWidth + newWidth + (needMore ? moreWidth : 0) + totalGaps;
|
|
174
|
+
if (totalWidth <= containerWidth) {
|
|
175
|
+
visibleWidth = newWidth;
|
|
234
176
|
count++;
|
|
235
177
|
} else {
|
|
236
178
|
break;
|
|
237
179
|
}
|
|
238
180
|
}
|
|
181
|
+
return count;
|
|
182
|
+
}, [childInfo, normalCollapsibleItems, alwaysCollapseItems, gap]);
|
|
239
183
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
} else if (count === 0) {
|
|
244
|
-
// 如果一个都放不下,只显示 more button
|
|
245
|
-
setVisibleCount(0);
|
|
246
|
-
} else {
|
|
247
|
-
setVisibleCount(count);
|
|
248
|
-
}
|
|
249
|
-
}, [childWidths, gap, actualMoreButtonWidth, normalCollapsibleChildren.length, alwaysCollapseChildren.length, unCollapsibleWidth, unCollapsibleChildren.length]);
|
|
184
|
+
// 使用 ref 保存最新的计算函数,避免 ResizeObserver 等 effect 频繁重建
|
|
185
|
+
var calculateRef = useRef(calculateVisibleCount);
|
|
186
|
+
calculateRef.current = calculateVisibleCount;
|
|
250
187
|
|
|
251
|
-
//
|
|
188
|
+
// Effect 1: 测量模式下,读取所有子元素宽度并计算 visibleCount
|
|
252
189
|
useLayoutEffect(function () {
|
|
253
|
-
if (
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
190
|
+
if (!containerRef.current || !isMeasuring) return;
|
|
191
|
+
var items = containerRef.current.querySelectorAll('[data-filter-item]');
|
|
192
|
+
var newWidths = [];
|
|
193
|
+
items.forEach(function (el) {
|
|
194
|
+
var idx = Number(el.dataset.filterItem);
|
|
195
|
+
if (!isNaN(idx)) {
|
|
196
|
+
newWidths[idx] = el.offsetWidth;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
cachedWidths.current = newWidths;
|
|
200
|
+
var count = calculateRef.current(containerRef.current.offsetWidth);
|
|
201
|
+
setVisibleCount(count);
|
|
202
|
+
}, [isMeasuring]);
|
|
260
203
|
|
|
261
|
-
//
|
|
204
|
+
// Effect 2: 监听容器大小变化,用缓存宽度重新计算(不需要重新测量)
|
|
262
205
|
useEffect(function () {
|
|
263
|
-
if (
|
|
264
|
-
|
|
265
|
-
|
|
206
|
+
if (!containerRef.current) return;
|
|
207
|
+
var el = containerRef.current;
|
|
208
|
+
var ro = new ResizeObserver(function () {
|
|
209
|
+
if (cachedWidths.current.length === 0) return;
|
|
210
|
+
var count = calculateRef.current(el.offsetWidth);
|
|
211
|
+
setVisibleCount(function (prev) {
|
|
212
|
+
return prev === count ? prev : count;
|
|
266
213
|
});
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// 当 childWidths 更新后计算可见数量
|
|
271
|
-
useLayoutEffect(function () {
|
|
272
|
-
calculateVisibleCount();
|
|
273
|
-
}, [childWidths, unCollapsibleWidth, calculateVisibleCount]);
|
|
274
|
-
|
|
275
|
-
// 监听窗口大小变化
|
|
276
|
-
useEffect(function () {
|
|
277
|
-
var handleResize = function handleResize() {
|
|
278
|
-
calculateVisibleCount();
|
|
279
|
-
};
|
|
280
|
-
window.addEventListener('resize', handleResize);
|
|
214
|
+
});
|
|
215
|
+
ro.observe(el);
|
|
281
216
|
return function () {
|
|
282
|
-
|
|
217
|
+
return ro.disconnect();
|
|
283
218
|
};
|
|
284
|
-
}, [
|
|
219
|
+
}, []);
|
|
285
220
|
|
|
286
|
-
//
|
|
221
|
+
// Effect 3: filterValues 变化时,more 按钮 badge 可能变化,需要重新计算
|
|
287
222
|
useEffect(function () {
|
|
288
|
-
if (!containerRef.current) return;
|
|
289
|
-
var
|
|
290
|
-
|
|
223
|
+
if (!containerRef.current || cachedWidths.current.length === 0) return;
|
|
224
|
+
var count = calculateRef.current(containerRef.current.offsetWidth);
|
|
225
|
+
setVisibleCount(function (prev) {
|
|
226
|
+
return prev === count ? prev : count;
|
|
291
227
|
});
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
var newProps = {
|
|
311
|
-
_isCollapsed: true
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
// 如果有 children,递归处理
|
|
315
|
-
if (childProps !== null && childProps !== void 0 && childProps.children) {
|
|
316
|
-
if ( /*#__PURE__*/isValidElement(childProps.children)) {
|
|
317
|
-
// 单个子元素
|
|
318
|
-
newProps.children = addIsInWrapProp(childProps.children);
|
|
319
|
-
} else if (Array.isArray(childProps.children)) {
|
|
320
|
-
// 多个子元素
|
|
321
|
-
newProps.children = childProps.children.map(function (child) {
|
|
322
|
-
if ( /*#__PURE__*/isValidElement(child)) {
|
|
323
|
-
return addIsInWrapProp(child);
|
|
324
|
-
}
|
|
325
|
-
return child;
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return /*#__PURE__*/cloneElement(element, newProps);
|
|
330
|
-
};
|
|
228
|
+
}, [filterValues]);
|
|
229
|
+
|
|
230
|
+
// --- 派生状态 ---
|
|
231
|
+
var visibleIndexSet = useMemo(function () {
|
|
232
|
+
if (visibleCount === null) return null;
|
|
233
|
+
return new Set(normalCollapsibleItems.slice(0, visibleCount).map(function (item) {
|
|
234
|
+
return item.index;
|
|
235
|
+
}));
|
|
236
|
+
}, [visibleCount, normalCollapsibleItems]);
|
|
237
|
+
var hiddenCollapsibleItems = useMemo(function () {
|
|
238
|
+
if (!visibleIndexSet) return [];
|
|
239
|
+
return normalCollapsibleItems.filter(function (item) {
|
|
240
|
+
return !visibleIndexSet.has(item.index);
|
|
241
|
+
});
|
|
242
|
+
}, [visibleIndexSet, normalCollapsibleItems]);
|
|
243
|
+
var allHiddenItems = useMemo(function () {
|
|
244
|
+
return [].concat(_toConsumableArray(alwaysCollapseItems), _toConsumableArray(hiddenCollapsibleItems));
|
|
245
|
+
}, [alwaysCollapseItems, hiddenCollapsibleItems]);
|
|
331
246
|
|
|
332
|
-
//
|
|
247
|
+
// --- 值管理 ---
|
|
333
248
|
var updateFilterValue = useCallback(function (id, _filterLabel, value, options, componentName) {
|
|
334
249
|
setFilterValues(function (prev) {
|
|
335
|
-
|
|
336
|
-
// 对于 switch 组件,false 被视为未选中状态,应该被视为空值
|
|
337
|
-
var isEmpty = value === undefined || value === null || value === '' || componentName === 'switch' && value === false ||
|
|
338
|
-
// switch 组件的 false 值视为空
|
|
339
|
-
Array.isArray(value) && value.length === 0;
|
|
250
|
+
var isEmpty = value === undefined || value === null || value === '' || componentName === 'switch' && value === false || Array.isArray(value) && value.length === 0;
|
|
340
251
|
if (isEmpty) {
|
|
341
252
|
var filtered = prev.filter(function (item) {
|
|
342
253
|
return item.id !== id;
|
|
343
254
|
});
|
|
344
|
-
|
|
345
|
-
if (filtered.length === prev.length) {
|
|
346
|
-
return prev;
|
|
347
|
-
}
|
|
348
|
-
return filtered;
|
|
255
|
+
return filtered.length === prev.length ? prev : filtered;
|
|
349
256
|
}
|
|
350
|
-
// 查找是否已存在
|
|
351
257
|
var existingIndex = prev.findIndex(function (item) {
|
|
352
258
|
return item.id === id;
|
|
353
259
|
});
|
|
354
260
|
if (existingIndex >= 0) {
|
|
355
|
-
var
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
// 如果值、选项和组件名都没变化,直接返回原数组
|
|
360
|
-
if (existingItem.value === value && optionsEqual && existingItem.componentName === componentName && existingItem.label === _filterLabel) {
|
|
261
|
+
var existing = prev[existingIndex];
|
|
262
|
+
var optionsEqual = existing.options === options || existing.options === undefined && options === undefined || existing.options !== undefined && options !== undefined && JSON.stringify(existing.options) === JSON.stringify(options);
|
|
263
|
+
if (existing.value === value && optionsEqual && existing.componentName === componentName && existing.label === _filterLabel) {
|
|
361
264
|
return prev;
|
|
362
265
|
}
|
|
363
|
-
// 更新已存在的项
|
|
364
266
|
var newValues = _toConsumableArray(prev);
|
|
365
267
|
newValues[existingIndex] = {
|
|
366
268
|
id: id,
|
|
@@ -370,43 +272,37 @@ var ResponsiveFilterGroup = function ResponsiveFilterGroup(_ref) {
|
|
|
370
272
|
componentName: componentName
|
|
371
273
|
};
|
|
372
274
|
return newValues;
|
|
373
|
-
} else {
|
|
374
|
-
// 添加新项
|
|
375
|
-
return [].concat(_toConsumableArray(prev), [{
|
|
376
|
-
id: id,
|
|
377
|
-
label: _filterLabel,
|
|
378
|
-
value: value,
|
|
379
|
-
options: options,
|
|
380
|
-
componentName: componentName
|
|
381
|
-
}]);
|
|
382
275
|
}
|
|
276
|
+
return [].concat(_toConsumableArray(prev), [{
|
|
277
|
+
id: id,
|
|
278
|
+
label: _filterLabel,
|
|
279
|
+
value: value,
|
|
280
|
+
options: options,
|
|
281
|
+
componentName: componentName
|
|
282
|
+
}]);
|
|
383
283
|
});
|
|
384
284
|
}, []);
|
|
385
285
|
var handleClearAll = function handleClearAll() {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
var childProps = child.props;
|
|
390
|
-
// 如果是 Form.Item,需要访问其子组件
|
|
286
|
+
allHiddenItems.forEach(function (item) {
|
|
287
|
+
if ( /*#__PURE__*/isValidElement(item.child)) {
|
|
288
|
+
var childProps = item.child.props;
|
|
391
289
|
if (childProps.children && /*#__PURE__*/isValidElement(childProps.children)) {
|
|
290
|
+
var _innerChildProps$onCh;
|
|
392
291
|
var innerChildProps = childProps.children.props;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
childProps.onChange(undefined);
|
|
292
|
+
(_innerChildProps$onCh = innerChildProps.onChange) === null || _innerChildProps$onCh === void 0 || _innerChildProps$onCh.call(innerChildProps, undefined);
|
|
293
|
+
} else {
|
|
294
|
+
var _childProps$onChange;
|
|
295
|
+
(_childProps$onChange = childProps.onChange) === null || _childProps$onChange === void 0 || _childProps$onChange.call(childProps, undefined);
|
|
398
296
|
}
|
|
399
297
|
}
|
|
400
298
|
});
|
|
401
|
-
// 然后清除 filterValues
|
|
402
299
|
setFilterValues([]);
|
|
403
|
-
|
|
404
|
-
onClearAll();
|
|
300
|
+
onClearAll === null || onClearAll === void 0 || onClearAll();
|
|
405
301
|
};
|
|
406
302
|
|
|
407
|
-
//
|
|
303
|
+
// --- 渲染 FilterWrap(收起的筛选项) ---
|
|
408
304
|
var renderHiddenChildren = function renderHiddenChildren() {
|
|
409
|
-
if (
|
|
305
|
+
if (allHiddenItems.length === 0) return null;
|
|
410
306
|
return /*#__PURE__*/_jsx(FilterProvider, {
|
|
411
307
|
isCollapsed: true,
|
|
412
308
|
filterValues: filterValues,
|
|
@@ -418,6 +314,7 @@ var ResponsiveFilterGroup = function ResponsiveFilterGroup(_ref) {
|
|
|
418
314
|
label: filterLabel,
|
|
419
315
|
extra: extra,
|
|
420
316
|
onClearAll: handleClearAll,
|
|
317
|
+
showCount: showCount,
|
|
421
318
|
footer: showActions && /*#__PURE__*/_jsxs(Flex, {
|
|
422
319
|
justify: "space-between",
|
|
423
320
|
children: [onApply && /*#__PURE__*/_jsx(Button, {
|
|
@@ -436,86 +333,94 @@ var ResponsiveFilterGroup = function ResponsiveFilterGroup(_ref) {
|
|
|
436
333
|
children: filterLocale === null || filterLocale === void 0 ? void 0 : filterLocale.clearAll
|
|
437
334
|
})]
|
|
438
335
|
}),
|
|
439
|
-
children:
|
|
440
|
-
if ( /*#__PURE__*/isValidElement(child)) {
|
|
441
|
-
|
|
442
|
-
var stableKey = child.key || "responsive-filter-child-".concat(index);
|
|
336
|
+
children: allHiddenItems.map(function (item, index) {
|
|
337
|
+
if ( /*#__PURE__*/isValidElement(item.child)) {
|
|
338
|
+
var stableKey = item.child.key || "responsive-filter-child-".concat(index);
|
|
443
339
|
return /*#__PURE__*/_jsx(React.Fragment, {
|
|
444
|
-
children:
|
|
340
|
+
children: item.child
|
|
445
341
|
}, stableKey);
|
|
446
342
|
}
|
|
447
|
-
return child;
|
|
343
|
+
return item.child;
|
|
448
344
|
})
|
|
449
345
|
})
|
|
450
346
|
});
|
|
451
347
|
};
|
|
452
348
|
|
|
453
|
-
//
|
|
454
|
-
//
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
349
|
+
// --- 渲染子元素 ---
|
|
350
|
+
// 所有子元素始终保持在 Flex 中的稳定位置(FilterProvider + div 包裹 + 稳定 key),
|
|
351
|
+
// 通过 CSS display 控制显隐,避免在可见/折叠间切换时卸载重挂载导致表单值丢失。
|
|
352
|
+
// FilterProvider 使隐藏的原始组件能直接感知 isCollapsed 并上报值,无需依赖 Popover 中的克隆。
|
|
353
|
+
var renderChildren = function renderChildren() {
|
|
354
|
+
var elements = [];
|
|
355
|
+
var filterWrapInserted = false;
|
|
356
|
+
var collapsibleIdx = 0;
|
|
357
|
+
childrenArray.forEach(function (child, index) {
|
|
358
|
+
var info = childInfo[index];
|
|
359
|
+
var stableKey = child.key || "filter-item-".concat(index);
|
|
360
|
+
var display;
|
|
361
|
+
var isHidden = false;
|
|
362
|
+
if (isMeasuring) {
|
|
363
|
+
display = 'inline-flex';
|
|
364
|
+
} else if (!info.isCollapsible) {
|
|
365
|
+
display = undefined;
|
|
366
|
+
} else if (info.isAlwaysCollapse) {
|
|
367
|
+
display = 'none';
|
|
368
|
+
isHidden = true;
|
|
369
|
+
} else {
|
|
370
|
+
var isVisible = collapsibleIdx < visibleCount;
|
|
371
|
+
display = isVisible ? undefined : 'none';
|
|
372
|
+
isHidden = !isVisible;
|
|
373
|
+
collapsibleIdx++;
|
|
374
|
+
}
|
|
375
|
+
elements.push( /*#__PURE__*/_jsx(FilterProvider, {
|
|
376
|
+
isCollapsed: !isMeasuring && isHidden,
|
|
377
|
+
filterValues: filterValues,
|
|
378
|
+
updateFilterValue: updateFilterValue,
|
|
379
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
380
|
+
"data-filter-item": isMeasuring ? index : undefined,
|
|
466
381
|
style: {
|
|
467
|
-
display:
|
|
382
|
+
display: display
|
|
468
383
|
},
|
|
469
384
|
children: child
|
|
470
|
-
}
|
|
471
|
-
})
|
|
472
|
-
|
|
473
|
-
|
|
385
|
+
})
|
|
386
|
+
}, stableKey));
|
|
387
|
+
if (!isMeasuring && isHidden && !filterWrapInserted && allHiddenItems.length > 0) {
|
|
388
|
+
filterWrapInserted = true;
|
|
389
|
+
elements.push( /*#__PURE__*/_jsx(React.Fragment, {
|
|
390
|
+
children: renderHiddenChildren()
|
|
391
|
+
}, "filter-wrap"));
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
if (!isMeasuring && !filterWrapInserted && allHiddenItems.length > 0) {
|
|
395
|
+
elements.push( /*#__PURE__*/_jsx(React.Fragment, {
|
|
396
|
+
children: renderHiddenChildren()
|
|
397
|
+
}, "filter-wrap"));
|
|
398
|
+
}
|
|
399
|
+
return elements;
|
|
400
|
+
};
|
|
401
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
402
|
+
ref: containerRef,
|
|
403
|
+
className: "responsive-filter-group",
|
|
404
|
+
style: _objectSpread({
|
|
405
|
+
flex: '1 1 auto',
|
|
406
|
+
minWidth: 0,
|
|
407
|
+
position: 'relative',
|
|
408
|
+
visibility: isMeasuring ? 'hidden' : undefined
|
|
409
|
+
}, style),
|
|
410
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
411
|
+
ref: moreButtonMeasureRef,
|
|
474
412
|
style: {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
413
|
+
position: 'absolute',
|
|
414
|
+
visibility: 'hidden',
|
|
415
|
+
pointerEvents: 'none',
|
|
416
|
+
top: -9999,
|
|
417
|
+
left: -9999,
|
|
418
|
+
display: 'inline-flex'
|
|
478
419
|
},
|
|
479
|
-
children:
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
style: {
|
|
484
|
-
display: 'inline-flex'
|
|
485
|
-
},
|
|
486
|
-
children: child
|
|
487
|
-
}, stableKey);
|
|
488
|
-
})
|
|
489
|
-
}), /*#__PURE__*/_jsx(FilterProvider, {
|
|
490
|
-
isCollapsed: true,
|
|
491
|
-
filterValues: filterValues,
|
|
492
|
-
updateFilterValue: updateFilterValue,
|
|
493
|
-
children: /*#__PURE__*/_jsx("div", {
|
|
494
|
-
style: {
|
|
495
|
-
position: 'absolute',
|
|
496
|
-
visibility: 'hidden',
|
|
497
|
-
pointerEvents: 'none',
|
|
498
|
-
top: -9999,
|
|
499
|
-
left: -9999
|
|
500
|
-
},
|
|
501
|
-
children: allHiddenChildren.map(function (child, index) {
|
|
502
|
-
if ( /*#__PURE__*/isValidElement(child)) {
|
|
503
|
-
return /*#__PURE__*/_jsx(React.Fragment, {
|
|
504
|
-
children: addIsInWrapProp(child)
|
|
505
|
-
}, child.key || "hidden-clone-".concat(index));
|
|
506
|
-
}
|
|
507
|
-
return child;
|
|
508
|
-
})
|
|
509
|
-
})
|
|
510
|
-
}), /*#__PURE__*/_jsx(FilterProvider, {
|
|
511
|
-
isCollapsed: true,
|
|
512
|
-
filterValues: filterValues,
|
|
513
|
-
updateFilterValue: updateFilterValue,
|
|
514
|
-
children: /*#__PURE__*/_jsx("div", {
|
|
515
|
-
ref: moreButtonRef,
|
|
516
|
-
style: {
|
|
517
|
-
display: 'inline-flex'
|
|
518
|
-
},
|
|
420
|
+
children: /*#__PURE__*/_jsx(FilterProvider, {
|
|
421
|
+
isCollapsed: true,
|
|
422
|
+
filterValues: filterValues,
|
|
423
|
+
updateFilterValue: updateFilterValue,
|
|
519
424
|
children: /*#__PURE__*/_jsx(FilterWrap, {
|
|
520
425
|
collapsed: true,
|
|
521
426
|
icon: icon,
|
|
@@ -525,23 +430,11 @@ var ResponsiveFilterGroup = function ResponsiveFilterGroup(_ref) {
|
|
|
525
430
|
children: /*#__PURE__*/_jsx("div", {})
|
|
526
431
|
})
|
|
527
432
|
})
|
|
528
|
-
})
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
style: _objectSpread({
|
|
534
|
-
flex: '1 1 auto',
|
|
535
|
-
minWidth: 0,
|
|
536
|
-
overflow: 'hidden'
|
|
537
|
-
}, style),
|
|
538
|
-
children: /*#__PURE__*/_jsxs(Flex, {
|
|
539
|
-
ref: innerFlexRef,
|
|
540
|
-
gap: gap,
|
|
541
|
-
align: "center",
|
|
542
|
-
wrap: "nowrap",
|
|
543
|
-
children: [unCollapsibleChildren, visibleCollapsibleChildren, renderHiddenChildren()]
|
|
544
|
-
})
|
|
433
|
+
}), /*#__PURE__*/_jsx(Flex, {
|
|
434
|
+
gap: gap,
|
|
435
|
+
align: "center",
|
|
436
|
+
wrap: "nowrap",
|
|
437
|
+
children: renderChildren()
|
|
545
438
|
})]
|
|
546
439
|
});
|
|
547
440
|
};
|