@kne/react-filter 0.1.28 → 1.0.1

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.
@@ -1,942 +1,2306 @@
1
- import React, { createContext, useContext, useState, useEffect, useRef, useMemo, cloneElement } from 'react';
2
- import { Space, Popover, Tag, message, Button, Tooltip, InputNumber, Input, Select, Checkbox, Radio, DatePicker, Divider, Row, Col } from 'antd';
3
- import useEvent from '@kne/use-event';
4
1
  import classnames from 'classnames';
5
- import { createCitySelect, apis, RemoteData, DisplayCity } from '@kne/react-city-select';
6
- import { get, isFunction, isEqual, findIndex, isNumber } from 'lodash';
7
- import useSimulationBlur from '@kne/use-simulation-blur';
8
- import moment from 'moment';
9
-
10
- const context$1 = createContext({});
11
- const {
12
- Consumer,
13
- Provider: Provider$1
14
- } = context$1;
15
- const useConsumer = () => useContext(context$1);
2
+ import { useContext as useContext$1, createContext, useState, useRef, useCallback, useEffect, createElement, useMemo } from 'react';
3
+ import { Space, Row, Col, Tag, Button, Dropdown, Input, InputNumber, DatePicker, Flex, Select, App } from 'antd';
4
+ import { useIntl, createWithIntlProvider } from '@kne/react-intl';
5
+ import get from 'lodash/get';
6
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
7
+ import clone from 'lodash/clone';
8
+ import { createPortal } from 'react-dom';
9
+ import isNumber from 'lodash/isNumber';
10
+ import SuperSelect from '@kne/super-select';
11
+ import { SelectFunction, SelectIndustry, SelectAddress, createAddressApi } from '@kne/super-select-plus';
12
+ import '@kne/super-select-plus/dist/index.css';
13
+ import dayjs from 'dayjs';
14
+ import transform from 'lodash/transform';
15
+ import { useSearchParams } from 'react-router-dom';
16
+ import isEqual from 'lodash/isEqual';
16
17
 
17
18
  function _extends() {
18
- _extends = Object.assign ? Object.assign.bind() : function (target) {
19
- for (var i = 1; i < arguments.length; i++) {
20
- var source = arguments[i];
21
-
22
- for (var key in source) {
23
- if (Object.prototype.hasOwnProperty.call(source, key)) {
24
- target[key] = source[key];
25
- }
26
- }
19
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
20
+ for (var e = 1; e < arguments.length; e++) {
21
+ var t = arguments[e];
22
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
27
23
  }
28
-
29
- return target;
30
- };
31
- return _extends.apply(this, arguments);
24
+ return n;
25
+ }, _extends.apply(null, arguments);
32
26
  }
33
-
34
- function _objectWithoutPropertiesLoose(source, excluded) {
35
- if (source == null) return {};
36
- var target = {};
37
- var sourceKeys = Object.keys(source);
38
- var key, i;
39
-
40
- for (i = 0; i < sourceKeys.length; i++) {
41
- key = sourceKeys[i];
42
- if (excluded.indexOf(key) >= 0) continue;
43
- target[key] = source[key];
27
+ function _objectWithoutPropertiesLoose(r, e) {
28
+ if (null == r) return {};
29
+ var t = {};
30
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
31
+ if (-1 !== e.indexOf(n)) continue;
32
+ t[n] = r[n];
44
33
  }
45
-
46
- return target;
34
+ return t;
47
35
  }
48
36
 
49
- const _excluded$9 = ["label", "labelHidden", "isMore", "moreTrigger"];
37
+ var style$1 = {"filter":"kne-react-filter_b3gMw","filter-item-icon":"kne-react-filter_e3V6h","filter-item-option-icon":"kne-react-filter_dLoYj","filter-title":"kne-react-filter_khFt2","filter-title-hidden":"kne-react-filter_j2mP1","ad-filter-title":"kne-react-filter_HptIY","ad-filter-line":"kne-react-filter_7Ob6-","filter-line":"kne-react-filter_Y9XTa","clean-btn":"kne-react-filter_CJ935","filter-item":"kne-react-filter_JpaMr","un-expand":"kne-react-filter_LfQME","ad-filter-selected":"kne-react-filter_pBsaE","filter-label":"kne-react-filter_Bx3s8","filter-item-wrap":"kne-react-filter_Co4Pg","option":"kne-react-filter_G1cRp","is-active":"kne-react-filter_Aab98","is-visited":"kne-react-filter_Ww12R","un-expand-shadow":"kne-react-filter_2ExqW","filter-item-label":"kne-react-filter_JAmeE","filter-item-field":"kne-react-filter_WvRvl","filter-drop-tag":"kne-react-filter_dG8rq","filter-list":"kne-react-filter_qlWu6","filter-list-scroll-wrap":"kne-react-filter_oaIF4","filter-list-scroll":"kne-react-filter_Jq43Q","filter-scroll-next":"kne-react-filter_BdfSI","filter-list-tag":"kne-react-filter_LV2VI","filter-tag":"kne-react-filter_yyR3u","filter-tag-value":"kne-react-filter_8nm8n","filter-value-tag":"kne-react-filter_tWyCr","filter-value-tag-label":"kne-react-filter_XPzrL","filter-value-tag-content":"kne-react-filter_6e79l","pop-util-content":"kne-react-filter_g-hXk","pop-util-body":"kne-react-filter_4n4MP","date-range-picker-popup":"kne-react-filter_6Zx60","pop-util-overlay":"kne-react-filter_m7Csi","pop-util-mask":"kne-react-filter_o2B3k","pop-util-mask-fade-in":"kne-react-filter_oCXiX","pop-util-mask-leave":"kne-react-filter_qGnRO","pop-util-mask-fade-out":"kne-react-filter_cDx1y","field-item-mobile-popup":"kne-react-filter_wq5nf","pop-util-mobile-expand-down":"kne-react-filter_6RxjE","date-picker-popup":"kne-react-filter_iwLs2","pop-util-mobile-collapse-up":"kne-react-filter_009r-","pop-util-footer":"kne-react-filter_iqe8W","pop-util-text":"kne-react-filter_72gGQ","filter-item-inner":"kne-react-filter_cYX12","filter-item-text":"kne-react-filter_cnMY-","filter-item-number-range":"kne-react-filter_Cv2Bw","filter-item-custom":"kne-react-filter_CBczA","filter-item-custom-active":"kne-react-filter_ldxUR","filter-item-number-range-split":"kne-react-filter_4p3C9","filter-item-number-input":"kne-react-filter_yy1y1","range-picker":"kne-react-filter_81zQn","cascader-select-wrap":"kne-react-filter_UHBfi","cascader-dropdown-menu":"kne-react-filter_bY8JQ","filter-advanced":"kne-react-filter_rg45N","filter-advanced-item-other":"kne-react-filter_HcsA8","filter-advanced-item-other-inner":"kne-react-filter_4Bqtz","filter-advanced-more":"kne-react-filter_jVH7z","filter-scroll-next-icon":"kne-react-filter_Fd6ab"};
38
+
39
+ const context = /*#__PURE__*/createContext({});
40
+ const {
41
+ Provider
42
+ } = context;
43
+ const useContext = () => useContext$1(context);
50
44
 
51
- const PopContent = props => {
52
- const [visible, setVisible] = useState(false);
45
+ const Line$1 = ({
46
+ list,
47
+ children
48
+ }) => {
53
49
  const {
54
- emitter
55
- } = useConsumer();
56
- useEffect(() => {
57
- emitter.addListener('change', () => {
58
- setVisible(false);
59
- });
60
- }, []);
61
- return /*#__PURE__*/React.createElement(Popover, _extends({}, props, {
62
- visible: visible,
63
- onVisibleChange: setVisible
64
- }));
50
+ value,
51
+ onChange
52
+ } = useContext();
53
+ return /*#__PURE__*/jsxs("div", {
54
+ className: style$1['filter-line'],
55
+ children: [list.filter(item => !!item.type).map((item, index) => {
56
+ if (typeof item === 'function') {
57
+ return item(props => {
58
+ return {
59
+ index,
60
+ value: value ? get(value.get(props == null ? void 0 : props.name), 'value') : props == null ? void 0 : props.value,
61
+ onChange: onChange ? value => onChange({
62
+ name: props == null ? void 0 : props.name,
63
+ label: props == null ? void 0 : props.label,
64
+ value
65
+ }) : props == null ? void 0 : props.onChange
66
+ };
67
+ });
68
+ }
69
+ const ComponentItem = item.type;
70
+ return /*#__PURE__*/createElement(ComponentItem, _extends({}, Object.assign({}, item.props, {
71
+ value: value ? get(value.get(item.props.name), 'value') : item.props.value,
72
+ onChange: onChange ? value => onChange({
73
+ name: item.props.name,
74
+ label: item.props.label,
75
+ value
76
+ }) : item.props.onChange
77
+ }), {
78
+ key: item.key || item.props.name || index
79
+ }));
80
+ }), children]
81
+ });
65
82
  };
66
-
67
- const FilterItem = ({
83
+ const FilterLines = ({
68
84
  className,
85
+ list: _list = [],
86
+ displayLine: _displayLine = 1,
69
87
  label,
70
- labelHidden,
71
- isMore,
72
- moreTrigger,
73
- onClick,
88
+ extra,
74
89
  children
75
90
  }) => {
76
- if (isMore) {
77
- return /*#__PURE__*/React.createElement("div", {
78
- className: classnames("react-filter-item-label", "is-more", className)
79
- }, children ? /*#__PURE__*/React.createElement(PopContent, {
80
- content: children,
81
- trigger: moreTrigger,
82
- placement: "bottom",
83
- overlayClassName: "react-filter-item-popover"
84
- }, /*#__PURE__*/React.createElement("a", {
85
- className: "react-filter-item-more"
86
- }, label)) : /*#__PURE__*/React.createElement("a", {
87
- className: "react-filter-item-more",
88
- onClick: onClick
89
- }, label));
90
- }
91
+ const hasMore = _list.length > _displayLine;
92
+ const mobileList = _list.reduce((result, item) => result.concat(Array.isArray(item) ? item : [item]), []);
93
+ const [isExpand, setIsExpand] = useState(false);
94
+ const [isMobile, setIsMobile] = useState(false);
95
+ const [showScrollNext, setShowScrollNext] = useState(false);
96
+ const scrollRef = useRef(null);
97
+ const {
98
+ formatMessage
99
+ } = useIntl({
100
+ moduleName: 'Filter'
101
+ });
102
+ const updateScrollNextVisible = useCallback(() => {
103
+ const el = scrollRef.current;
104
+ if (!el) {
105
+ setShowScrollNext(false);
106
+ return;
107
+ }
108
+ setShowScrollNext(el.scrollWidth > el.clientWidth && el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
109
+ }, []);
110
+ useEffect(() => {
111
+ if (typeof window === 'undefined') return;
112
+ const mediaQuery = window.matchMedia('(max-width: 768px)');
113
+ const updateIsMobile = () => {
114
+ setIsMobile(mediaQuery.matches);
115
+ };
116
+ updateIsMobile();
117
+ mediaQuery.addEventListener ? mediaQuery.addEventListener('change', updateIsMobile) : mediaQuery.addListener(updateIsMobile);
118
+ return () => {
119
+ mediaQuery.removeEventListener ? mediaQuery.removeEventListener('change', updateIsMobile) : mediaQuery.removeListener(updateIsMobile);
120
+ };
121
+ }, []);
122
+ useEffect(() => {
123
+ if (!isMobile) {
124
+ setShowScrollNext(false);
125
+ return;
126
+ }
127
+ const el = scrollRef.current;
128
+ if (!el) return;
129
+ updateScrollNextVisible();
130
+ const update = () => {
131
+ updateScrollNextVisible();
132
+ };
133
+ el.addEventListener('scroll', update);
134
+ window.addEventListener('resize', update);
135
+ const rafId = window.requestAnimationFrame(update);
136
+ return () => {
137
+ el.removeEventListener('scroll', update);
138
+ window.removeEventListener('resize', update);
139
+ window.cancelAnimationFrame(rafId);
140
+ };
141
+ }, [isMobile, _list, updateScrollNextVisible]);
142
+ const scrollToNext = useCallback(() => {
143
+ const el = scrollRef.current;
144
+ if (!el) return;
145
+ el.scrollTo({
146
+ left: el.scrollLeft + el.clientWidth * 0.8,
147
+ behavior: 'smooth'
148
+ });
149
+ }, []);
150
+ const scrollItemIntoView = useCallback(e => {
151
+ if (!isMobile) return;
152
+ const container = scrollRef.current;
153
+ const item = e.target.closest(`.${style$1['filter-item-wrap']}`) || e.target.closest(`.${style$1['filter-item']}`);
154
+ if (!container || !item) return;
155
+ item.scrollIntoView({
156
+ behavior: 'smooth',
157
+ block: 'nearest',
158
+ inline: 'center'
159
+ });
160
+ }, [isMobile]);
161
+ return /*#__PURE__*/jsxs(Fragment, {
162
+ children: [/*#__PURE__*/jsxs(Space, {
163
+ className: classnames(style$1['filter-title'], 'filter-title', className),
164
+ align: "top",
165
+ size: 16,
166
+ children: [/*#__PURE__*/jsx("span", {
167
+ className: style$1['filter-label'],
168
+ children: _list && _list.length > 0 && (label || formatMessage({
169
+ id: 'filterText'
170
+ }))
171
+ }), /*#__PURE__*/jsxs(Row, {
172
+ justify: "space-between",
173
+ wrap: false,
174
+ align: "top",
175
+ children: [/*#__PURE__*/jsx(Col, {
176
+ className: style$1['filter-list'],
177
+ flex: 1,
178
+ children: /*#__PURE__*/jsxs("div", {
179
+ className: style$1['filter-list-scroll-wrap'],
180
+ children: [/*#__PURE__*/jsx("div", {
181
+ className: style$1['filter-list-scroll'],
182
+ ref: scrollRef,
183
+ onClick: scrollItemIntoView,
184
+ children: (isMobile ? mobileList : _list.slice(0, _displayLine)).map((item, index) => /*#__PURE__*/jsx(Line$1, {
185
+ list: isMobile ? [item] : item,
186
+ children: !isMobile && hasMore && isExpand === false && index === _displayLine - 1 ? /*#__PURE__*/jsxs(Space, {
187
+ size: 4,
188
+ className: classnames(style$1['filter-item'], style$1['option']),
189
+ onClick: () => {
190
+ setIsExpand(value => !value);
191
+ },
192
+ children: [formatMessage({
193
+ id: 'moreText'
194
+ }), /*#__PURE__*/jsx("span", {
195
+ className: style$1['filter-item-option-icon'],
196
+ children: "\u25BC"
197
+ })]
198
+ }) : null
199
+ }, index))
200
+ }), isMobile && showScrollNext ? /*#__PURE__*/jsx("button", {
201
+ type: "button",
202
+ className: style$1['filter-scroll-next'],
203
+ onClick: scrollToNext,
204
+ "aria-label": "scroll next",
205
+ children: /*#__PURE__*/jsx("span", {
206
+ className: style$1['filter-scroll-next-icon'],
207
+ children: "\u203A"
208
+ })
209
+ }) : null]
210
+ })
211
+ }), /*#__PURE__*/jsx(Col, {
212
+ children: extra
213
+ })]
214
+ })]
215
+ }), /*#__PURE__*/jsx(Space, {
216
+ className: classnames(style$1['filter-title'], 'filter-title-wrap'),
217
+ align: "center",
218
+ size: 16,
219
+ children: children
220
+ }), /*#__PURE__*/jsxs(Space, {
221
+ className: classnames(style$1['filter-title'], 'filter-title-wrap', {
222
+ [style$1['filter-title-hidden']]: isMobile || !(hasMore && isExpand)
223
+ }),
224
+ align: "top",
225
+ size: 16,
226
+ children: [/*#__PURE__*/jsx("span", {
227
+ className: style$1['filter-label'],
228
+ children: formatMessage({
229
+ id: 'moreText'
230
+ })
231
+ }), /*#__PURE__*/jsx("div", {
232
+ className: style$1['filter-list'],
233
+ children: _list.slice(_displayLine).map((item, index) => /*#__PURE__*/jsx(Line$1, {
234
+ list: item,
235
+ children: index === _list.length - _displayLine - 1 && /*#__PURE__*/jsxs(Fragment, {
236
+ children: [/*#__PURE__*/jsx(Space, {
237
+ size: 4,
238
+ className: classnames(style$1['un-expand-shadow']),
239
+ children: /*#__PURE__*/jsxs(Space, {
240
+ size: 4,
241
+ className: classnames(style$1['option'], style$1['filter-item']),
242
+ children: [formatMessage({
243
+ id: 'toggleUpText'
244
+ }), /*#__PURE__*/jsx("span", {
245
+ className: style$1['filter-item-option-icon'],
246
+ children: "\u25B2"
247
+ })]
248
+ })
249
+ }), /*#__PURE__*/jsx(Space, {
250
+ size: 4,
251
+ className: classnames(style$1['un-expand']),
252
+ onClick: () => {
253
+ setIsExpand(value => !value);
254
+ },
255
+ children: /*#__PURE__*/jsxs(Space, {
256
+ size: 4,
257
+ className: classnames(style$1['option'], style$1['filter-item']),
258
+ children: [formatMessage({
259
+ id: 'toggleUpText'
260
+ }), /*#__PURE__*/jsx("span", {
261
+ className: style$1['filter-item-option-icon'],
262
+ children: "\u25B2"
263
+ })]
264
+ })
265
+ })]
266
+ })
267
+ }, index))
268
+ })]
269
+ })]
270
+ });
271
+ };
91
272
 
92
- return /*#__PURE__*/React.createElement(Space, {
93
- className: classnames('react-filter-item', className)
94
- }, labelHidden ? null : /*#__PURE__*/React.createElement("div", {
95
- className: "react-filter-item-label"
96
- }, label, ":"), /*#__PURE__*/React.createElement("div", {
97
- className: "react-filter-item-children"
98
- }, children));
273
+ const message$1 = {
274
+ filterText: '筛选',
275
+ moreText: '更多',
276
+ selectedText: '您已选择',
277
+ clearAllText: '清空全部',
278
+ toggleUpText: '收起',
279
+ selectedTextAdvanced: '已选',
280
+ clearText: '清空筛选',
281
+ otherText: '其他',
282
+ cancelText: '取消',
283
+ determineText: '确定',
284
+ year: '年',
285
+ over: '{count}{unit}以上',
286
+ lessThan: '{count}{unit}以下',
287
+ inputPlaceholder: '请输入{label}',
288
+ pleaseInput: '请输入',
289
+ defaultInputPlaceholder: '请输入{label}',
290
+ maxSelectedCount: '最多选择{count}项',
291
+ customTime: '自定义时间',
292
+ monthly: '按月',
293
+ weekly: '按周',
294
+ last7Days: '近7天',
295
+ thisMonth: '本月',
296
+ last3Months: '近三个月',
297
+ thisYear: '当年',
298
+ fullYear: '本年度',
299
+ pleaseSelect: '请选择'
99
300
  };
100
301
 
101
- const withFilterItem = WrappedComponent => _ref => {
102
- let {
103
- label,
104
- labelHidden,
105
- isMore,
106
- moreTrigger
107
- } = _ref,
108
- props = _objectWithoutPropertiesLoose(_ref, _excluded$9);
109
-
110
- return /*#__PURE__*/React.createElement(FilterItem, {
111
- label: label,
112
- labelHidden: labelHidden,
113
- isMore: isMore,
114
- moreTrigger: moreTrigger
115
- }, /*#__PURE__*/React.createElement(WrappedComponent, _extends({}, props, {
116
- label: label,
117
- isMore: isMore
118
- })));
302
+ const message = {
303
+ filterText: 'Filter',
304
+ moreText: 'More',
305
+ selectedText: 'Selected',
306
+ clearAllText: 'Clear All',
307
+ toggleUpText: 'Pack Up',
308
+ selectedTextAdvanced: 'Selected',
309
+ clearText: 'Clear Filter',
310
+ otherText: 'Other',
311
+ cancelText: 'Cancel',
312
+ determineText: 'Determine',
313
+ year: 'year',
314
+ over: 'over {count} {unit}s',
315
+ lessThan: 'less than {count} {unit}s',
316
+ inputPlaceholder: 'Please enter {label}',
317
+ pleaseInput: 'Please enter ',
318
+ defaultInputPlaceholder: 'Please enter {label}',
319
+ maxSelectedCount: 'Select up to {count} items',
320
+ customTime: 'Custom Time',
321
+ monthly: 'Monthly',
322
+ weekly: 'Weekly',
323
+ last7Days: 'Last 7 Days',
324
+ thisMonth: 'This Month',
325
+ last3Months: 'Last 3 Months',
326
+ thisYear: 'Year to Date',
327
+ fullYear: 'Full Year',
328
+ pleaseSelect: 'Please Select'
119
329
  };
120
330
 
121
- const _excluded$8 = ["value", "label"];
122
- const {
123
- CheckableTag
124
- } = Tag;
125
- const context = createContext({});
126
- const {
127
- Provider
128
- } = context;
331
+ const withLocale = createWithIntlProvider({
332
+ defaultLocale: 'zh-CN',
333
+ messages: {
334
+ 'zh-CN': message$1,
335
+ 'en-US': message
336
+ },
337
+ namespace: 'react-filter'
338
+ });
129
339
 
130
- const List = ({
131
- label,
132
- labelHidden,
133
- name,
134
- size,
135
- children,
136
- options,
137
- more,
138
- isMore
340
+ const FilterValueDisplay = withLocale(({
341
+ value: filterValue,
342
+ extraExpand,
343
+ onChange
139
344
  }) => {
140
345
  const {
141
- value,
142
- onChange
143
- } = useConsumer();
346
+ formatMessage
347
+ } = useIntl({
348
+ moduleName: 'Filter'
349
+ });
350
+ return /*#__PURE__*/jsxs(Space, {
351
+ className: style$1['filter-title'],
352
+ align: "top",
353
+ size: 16,
354
+ children: [/*#__PURE__*/jsx("span", {
355
+ className: style$1['filter-label'],
356
+ children: formatMessage({
357
+ id: 'selectedText'
358
+ })
359
+ }), /*#__PURE__*/jsxs("div", {
360
+ className: style$1['filter-line'],
361
+ children: [filterValue.map(({
362
+ name,
363
+ label,
364
+ value
365
+ }, index) => {
366
+ const valueLabel = Array.isArray(value) ? value.map(item => item.label).join(',') : value == null ? void 0 : value.label;
367
+ return /*#__PURE__*/jsxs(Tag, {
368
+ closable: true,
369
+ className: style$1['filter-value-tag'],
370
+ onClose: () => {
371
+ const newValue = filterValue.slice(0);
372
+ newValue.splice(index, 1);
373
+ onChange(newValue);
374
+ },
375
+ children: [/*#__PURE__*/jsxs("span", {
376
+ className: style$1['filter-value-tag-label'],
377
+ children: [label, ":"]
378
+ }), /*#__PURE__*/jsx("span", {
379
+ className: style$1['filter-value-tag-content'],
380
+ children: valueLabel
381
+ })]
382
+ }, name);
383
+ }), /*#__PURE__*/jsxs(Space, {
384
+ size: 4,
385
+ className: classnames(style$1['un-expand-shadow']),
386
+ children: [extraExpand, /*#__PURE__*/jsx(Button, {
387
+ size: "small",
388
+ children: formatMessage({
389
+ id: 'clearAllText'
390
+ })
391
+ })]
392
+ }), /*#__PURE__*/jsxs(Space, {
393
+ size: 4,
394
+ className: classnames(style$1['un-expand']),
395
+ children: [extraExpand, /*#__PURE__*/jsx(Button, {
396
+ size: "small",
397
+ onClick: () => {
398
+ onChange([]);
399
+ },
400
+ children: formatMessage({
401
+ id: 'clearAllText'
402
+ })
403
+ })]
404
+ })]
405
+ })]
406
+ });
407
+ });
144
408
 
145
- const currentValue = (() => {
146
- const originValue = get(value, name);
409
+ const isNotEmpty$2 = value => {
410
+ if (value === null || value === undefined) return false;
411
+ if (typeof value === 'string' && value.trim() === '') return false;
412
+ if (Array.isArray(value) && value.length === 0) return false;
413
+ return true;
414
+ };
415
+ const FilterProvider = ({
416
+ children,
417
+ value: valueBase,
418
+ onChange,
419
+ defaultValue: _defaultValue = []
420
+ }) => {
421
+ const value = useMemo(() => {
422
+ return (valueBase || _defaultValue).filter(item => isNotEmpty$2(item.value));
423
+ }, [valueBase, _defaultValue]);
424
+ const filterValue = useMemo(() => {
425
+ return new Map(value.map(item => [item.name, item]));
426
+ }, [value]);
427
+ return /*#__PURE__*/jsx(Provider, {
428
+ value: {
429
+ value: filterValue,
430
+ onChange: item => {
431
+ const newFilterValue = clone(filterValue);
432
+ item.value ? newFilterValue.set(item.name, item) : newFilterValue.delete(item.name);
433
+ onChange == null || onChange(Array.from(newFilterValue.values()));
434
+ }
435
+ },
436
+ children: typeof children === 'function' ? children({
437
+ value,
438
+ onChange
439
+ }) : children
440
+ });
441
+ };
147
442
 
148
- if (size === 1) {
149
- return originValue !== void 0 ? [originValue] : [];
150
- } else {
151
- return originValue || [];
443
+ const _excluded$f = ["children", "className"];
444
+ const FilterOuter = _ref => {
445
+ let {
446
+ children,
447
+ className
448
+ } = _ref,
449
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$f);
450
+ return /*#__PURE__*/jsx(FilterProvider, _extends({}, props, {
451
+ children: context => /*#__PURE__*/jsx("div", {
452
+ className: classnames(style$1['filter'], 'filter', className),
453
+ children: children(_extends({}, context, {
454
+ props
455
+ }))
456
+ })
457
+ }));
458
+ };
459
+
460
+ const _excluded$e = ["defaultValue"],
461
+ _excluded2 = ["extraExpand"];
462
+ const Filter = withLocale(_ref => {
463
+ let {
464
+ defaultValue = []
465
+ } = _ref,
466
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$e);
467
+ return /*#__PURE__*/jsx(FilterOuter, _extends({}, props, {
468
+ defaultValue: defaultValue,
469
+ children: ({
470
+ props: filterProps = {},
471
+ value,
472
+ onChange
473
+ }) => {
474
+ const {
475
+ extraExpand
476
+ } = filterProps,
477
+ others = _objectWithoutPropertiesLoose(filterProps, _excluded2);
478
+ return /*#__PURE__*/jsxs(Fragment, {
479
+ children: [/*#__PURE__*/jsx(FilterLines, _extends({}, others)), value && value.length > 0 && /*#__PURE__*/jsx(FilterValueDisplay, {
480
+ value: value,
481
+ onChange: onChange,
482
+ extraExpand: extraExpand
483
+ })]
484
+ });
152
485
  }
153
- })();
486
+ }));
487
+ });
154
488
 
155
- const changeHandler = value => {
156
- if (size === 1) {
157
- return onChange(name, value[0]);
158
- } else {
159
- return onChange(name, value);
489
+ const FilterItem = withLocale(({
490
+ open,
491
+ active,
492
+ label,
493
+ children
494
+ }) => {
495
+ return /*#__PURE__*/jsx(Space, {
496
+ className: style$1['filter-item-wrap'],
497
+ children: /*#__PURE__*/jsxs("div", {
498
+ className: classnames(style$1['filter-item'], {
499
+ [style$1['is-active']]: active,
500
+ [style$1['is-visited']]: open
501
+ }),
502
+ children: [/*#__PURE__*/jsxs(Space, {
503
+ className: style$1['filter-item-label'],
504
+ size: 4,
505
+ children: [/*#__PURE__*/jsx("div", {
506
+ children: label
507
+ }), /*#__PURE__*/jsx("span", {
508
+ className: style$1['filter-item-icon'],
509
+ children: "\u25BC"
510
+ })]
511
+ }), /*#__PURE__*/jsx("div", {
512
+ className: style$1['filter-item-field'],
513
+ children: children
514
+ })]
515
+ })
516
+ });
517
+ });
518
+
519
+ const _excluded$d = ["value", "onChange", "interceptor", "label", "render"];
520
+ const isNotEmpty$1 = value => {
521
+ if (value === null || value === undefined) return false;
522
+ if (typeof value === 'string' && value.trim() === '') return false;
523
+ return !(Array.isArray(value) && value.length === 0);
524
+ };
525
+ const MASK_ANIMATION_DURATION$1 = 180;
526
+ const FIELD_MOBILE_POPUP_CLASS = 'react-filter-field-mobile-popup';
527
+ const MOBILE_POPUP_OFFSET$1 = 4;
528
+ const withFieldItem = (WrappedComponent, options = {}) => _ref => {
529
+ let {
530
+ value,
531
+ onChange,
532
+ interceptor,
533
+ label,
534
+ render
535
+ } = _ref,
536
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$d);
537
+ const [open, setOpen] = useState(false);
538
+ const [isMobile, setIsMobile] = useState(false);
539
+ const [renderMask, setRenderMask] = useState(false);
540
+ const [maskClosing, setMaskClosing] = useState(false);
541
+ const [popupMetrics, setPopupMetrics] = useState({
542
+ top: 0,
543
+ pageTop: 0,
544
+ height: 0
545
+ });
546
+ const triggerRef = useRef(null);
547
+ const setMobilePopupVariables = useCallback(metrics => {
548
+ if (typeof document === 'undefined') return;
549
+ document.body.style.setProperty('--react-filter-field-mobile-height', `${metrics.height}px`);
550
+ document.body.style.setProperty('--react-filter-popover-mobile-height', `${metrics.height}px`);
551
+ document.body.style.setProperty('--react-filter-field-mobile-top', `${metrics.pageTop}px`);
552
+ }, []);
553
+ const updatePopupMetrics = useCallback(() => {
554
+ if (typeof window === 'undefined' || !triggerRef.current) return;
555
+ const rect = triggerRef.current.getBoundingClientRect();
556
+ const top = Math.max(rect.bottom + MOBILE_POPUP_OFFSET$1, 0);
557
+ const metrics = {
558
+ top,
559
+ pageTop: top + window.scrollY,
560
+ height: Math.max(window.innerHeight - top, 0)
561
+ };
562
+ setPopupMetrics(metrics);
563
+ setMobilePopupVariables(metrics);
564
+ }, [setMobilePopupVariables]);
565
+ useEffect(() => {
566
+ if (typeof window === 'undefined') return;
567
+ const mediaQuery = window.matchMedia('(max-width: 768px)');
568
+ const updateIsMobile = () => {
569
+ setIsMobile(mediaQuery.matches);
570
+ };
571
+ updateIsMobile();
572
+ mediaQuery.addEventListener ? mediaQuery.addEventListener('change', updateIsMobile) : mediaQuery.addListener(updateIsMobile);
573
+ return () => {
574
+ mediaQuery.removeEventListener ? mediaQuery.removeEventListener('change', updateIsMobile) : mediaQuery.removeListener(updateIsMobile);
575
+ };
576
+ }, []);
577
+ useEffect(() => {
578
+ if (!open || !isMobile) return;
579
+ updatePopupMetrics();
580
+ window.addEventListener('resize', updatePopupMetrics);
581
+ window.addEventListener('scroll', updatePopupMetrics, true);
582
+ return () => {
583
+ window.removeEventListener('resize', updatePopupMetrics);
584
+ window.removeEventListener('scroll', updatePopupMetrics, true);
585
+ };
586
+ }, [isMobile, open, updatePopupMetrics]);
587
+ useEffect(() => {
588
+ if (typeof document === 'undefined' || !isMobile || popupMetrics.height <= 0) return;
589
+ setMobilePopupVariables(popupMetrics);
590
+ return () => {
591
+ document.body.style.removeProperty('--react-filter-field-mobile-height');
592
+ document.body.style.removeProperty('--react-filter-popover-mobile-height');
593
+ document.body.style.removeProperty('--react-filter-field-mobile-top');
594
+ };
595
+ }, [isMobile, popupMetrics, setMobilePopupVariables]);
596
+ useEffect(() => {
597
+ if (open && isMobile) {
598
+ setRenderMask(true);
599
+ setMaskClosing(false);
600
+ return;
601
+ }
602
+ if (!renderMask) return;
603
+ setMaskClosing(true);
604
+ const timer = setTimeout(() => {
605
+ setRenderMask(false);
606
+ setMaskClosing(false);
607
+ }, MASK_ANIMATION_DURATION$1);
608
+ return () => {
609
+ clearTimeout(timer);
610
+ };
611
+ }, [isMobile, open, renderMask]);
612
+ const closeFieldItem = useCallback(() => {
613
+ setOpen(false);
614
+ props.onOpenChange && props.onOpenChange(false);
615
+ props.onDropdownVisibleChange && props.onDropdownVisibleChange(false);
616
+ }, [props]);
617
+ const handleOpenChange = useCallback(open => {
618
+ if (open && isMobile) {
619
+ updatePopupMetrics();
160
620
  }
621
+ setOpen(open);
622
+ props.onOpenChange && props.onOpenChange(open);
623
+ props.onDropdownVisibleChange && props.onDropdownVisibleChange(open);
624
+ }, [isMobile, props, updatePopupMetrics]);
625
+ const mobilePopupStyle = isMobile ? {
626
+ '--react-filter-field-mobile-height': `${popupMetrics.height}px`,
627
+ '--react-filter-popover-mobile-height': `${popupMetrics.height}px`,
628
+ '--react-filter-field-mobile-top': `${popupMetrics.pageTop}px`,
629
+ top: popupMetrics.pageTop,
630
+ left: 0
631
+ } : undefined;
632
+ const mergePopupClassNames = classNames => {
633
+ var _classNames$popup;
634
+ if (!isMobile) return classNames;
635
+ return Object.assign({}, classNames, {
636
+ popup: Object.assign({}, classNames == null ? void 0 : classNames.popup, {
637
+ root: classnames(classNames == null || (_classNames$popup = classNames.popup) == null ? void 0 : _classNames$popup.root, style$1['field-item-mobile-popup'], FIELD_MOBILE_POPUP_CLASS)
638
+ })
639
+ });
161
640
  };
641
+ const mergePopupStyles = styles => {
642
+ var _styles$popup;
643
+ if (!isMobile) return styles;
644
+ return Object.assign({}, styles, {
645
+ popup: Object.assign({}, styles == null ? void 0 : styles.popup, {
646
+ root: Object.assign({}, styles == null || (_styles$popup = styles.popup) == null ? void 0 : _styles$popup.root, mobilePopupStyle)
647
+ })
648
+ });
649
+ };
650
+ const renderChildren = otherProps => /*#__PURE__*/jsx(WrappedComponent, _extends({
651
+ allowClear: false
652
+ }, Object.assign({}, props, otherProps), {
653
+ className: style$1['filter-item-inner'],
654
+ value: typeof (interceptor == null ? void 0 : interceptor.input) === 'function' ? interceptor.input(value) : value,
655
+ onChange: typeof (interceptor == null ? void 0 : interceptor.output) === 'function' ? (...args) => onChange(interceptor.output(...args)) : onChange,
656
+ valueType: "all",
657
+ onOpenChange: handleOpenChange,
658
+ onDropdownVisibleChange: handleOpenChange,
659
+ popupClassName: classnames(props.popupClassName, isMobile && style$1['field-item-mobile-popup'], isMobile && FIELD_MOBILE_POPUP_CLASS),
660
+ dropdownClassName: classnames(props.dropdownClassName, isMobile && style$1['field-item-mobile-popup'], isMobile && FIELD_MOBILE_POPUP_CLASS),
661
+ overlayClassName: classnames(props.overlayClassName, isMobile && style$1['field-item-mobile-popup'], isMobile && FIELD_MOBILE_POPUP_CLASS),
662
+ overlayStyle: Object.assign({}, props.overlayStyle, mobilePopupStyle),
663
+ popupStyle: Object.assign({}, props.popupStyle, mobilePopupStyle),
664
+ dropdownStyle: Object.assign({}, props.dropdownStyle, mobilePopupStyle),
665
+ classNames: mergePopupClassNames(props.classNames),
666
+ styles: mergePopupStyles(props.styles),
667
+ transitionName: isMobile ? '' : props.transitionName,
668
+ autoAdjustOverflow: isMobile ? false : props.autoAdjustOverflow,
669
+ align: isMobile ? {
670
+ offset: [0, 0]
671
+ } : props.align,
672
+ isPopup: options.forcePopup ? true : props.isPopup,
673
+ overlayWidth: isMobile && options.forcePopup ? typeof window === 'undefined' ? props.overlayWidth : window.innerWidth : props.overlayWidth
674
+ }));
675
+ return /*#__PURE__*/jsxs(Fragment, {
676
+ children: [renderMask && typeof document !== 'undefined' && /*#__PURE__*/createPortal(/*#__PURE__*/jsx("div", {
677
+ className: classnames(style$1['pop-util-mask'], maskClosing && style$1['pop-util-mask-leave']),
678
+ style: {
679
+ top: popupMetrics.top,
680
+ height: popupMetrics.height
681
+ },
682
+ onClick: closeFieldItem
683
+ }), document.body), /*#__PURE__*/jsx("span", {
684
+ ref: triggerRef,
685
+ children: /*#__PURE__*/jsx(FilterItem, {
686
+ label: label,
687
+ open: open,
688
+ active: isNotEmpty$1(value),
689
+ children: typeof render === 'function' ? render({
690
+ children: renderChildren
691
+ }) : renderChildren()
692
+ })
693
+ })]
694
+ });
695
+ };
696
+
697
+ const isNotEmpty = value => {
698
+ if (value === null || value === undefined) return false;
699
+ if (typeof value === 'string' && value.trim() === '') return false;
700
+ if (Array.isArray(value) && value.length === 0) return false;
701
+ return true;
702
+ };
703
+ const MASK_ANIMATION_DURATION = 180;
704
+ const MOBILE_POPUP_OFFSET = 4;
705
+ const PopoverItem = withLocale(({
706
+ value,
707
+ label,
708
+ onValidate,
709
+ overlayClassName,
710
+ placement: _placement = 'bottomLeft',
711
+ onOpenChange,
712
+ onChange,
713
+ children
714
+ }) => {
715
+ const [state, setState] = useState(value);
716
+ const [open, setOpen] = useState(false);
717
+ const [isMobile, setIsMobile] = useState(false);
718
+ const [renderMask, setRenderMask] = useState(false);
719
+ const [maskClosing, setMaskClosing] = useState(false);
720
+ const [popupMetrics, setPopupMetrics] = useState({
721
+ top: 0,
722
+ pageTop: 0,
723
+ height: 0
724
+ });
725
+ const triggerRef = useRef(null);
726
+ const disabled = useMemo(() => {
727
+ return onValidate && !onValidate(state);
728
+ }, [onValidate, state]);
729
+ const {
730
+ formatMessage
731
+ } = useIntl({
732
+ moduleName: 'Filter'
733
+ });
734
+ useEffect(() => {
735
+ if (typeof window === 'undefined') return;
736
+ const mediaQuery = window.matchMedia('(max-width: 768px)');
737
+ const updateIsMobile = () => {
738
+ setIsMobile(mediaQuery.matches);
739
+ };
740
+ updateIsMobile();
741
+ mediaQuery.addEventListener ? mediaQuery.addEventListener('change', updateIsMobile) : mediaQuery.addListener(updateIsMobile);
742
+ return () => {
743
+ mediaQuery.removeEventListener ? mediaQuery.removeEventListener('change', updateIsMobile) : mediaQuery.removeListener(updateIsMobile);
744
+ };
745
+ }, []);
746
+ const updatePopupMetrics = useCallback(() => {
747
+ if (typeof window === 'undefined' || !triggerRef.current) return;
748
+ const rect = triggerRef.current.getBoundingClientRect();
749
+ const top = Math.max(rect.bottom + MOBILE_POPUP_OFFSET, 0);
750
+ setPopupMetrics({
751
+ top,
752
+ pageTop: top + window.scrollY,
753
+ height: Math.max(window.innerHeight - top, 0)
754
+ });
755
+ }, []);
756
+ useEffect(() => {
757
+ if (!open || !isMobile) return;
758
+ updatePopupMetrics();
759
+ window.addEventListener('resize', updatePopupMetrics);
760
+ window.addEventListener('scroll', updatePopupMetrics, true);
761
+ return () => {
762
+ window.removeEventListener('resize', updatePopupMetrics);
763
+ window.removeEventListener('scroll', updatePopupMetrics, true);
764
+ };
765
+ }, [isMobile, open, updatePopupMetrics]);
766
+ useEffect(() => {
767
+ if (open && isMobile) {
768
+ setRenderMask(true);
769
+ setMaskClosing(false);
770
+ return;
771
+ }
772
+ if (!renderMask) return;
773
+ setMaskClosing(true);
774
+ const timer = setTimeout(() => {
775
+ setRenderMask(false);
776
+ setMaskClosing(false);
777
+ }, MASK_ANIMATION_DURATION);
778
+ return () => {
779
+ clearTimeout(timer);
780
+ };
781
+ }, [isMobile, open, renderMask]);
782
+ const closeDropdown = useCallback(() => {
783
+ setOpen(false);
784
+ onOpenChange && onOpenChange(false);
785
+ }, [onOpenChange]);
786
+ const handleOpenChange = useCallback(open => {
787
+ if (open && isMobile) {
788
+ updatePopupMetrics();
789
+ }
790
+ setOpen(open);
791
+ setState(value);
792
+ onOpenChange && onOpenChange(open);
793
+ }, [isMobile, onOpenChange, updatePopupMetrics, value]);
794
+ const mobileOverlayStyle = isMobile ? {
795
+ '--react-filter-popover-mobile-height': `${popupMetrics.height}px`,
796
+ top: popupMetrics.pageTop,
797
+ left: 0
798
+ } : undefined;
799
+ const overlayContent = /*#__PURE__*/jsxs("div", {
800
+ className: style$1['pop-util-body'],
801
+ onClick: e => {
802
+ e.stopPropagation();
803
+ },
804
+ children: [/*#__PURE__*/jsx("div", {
805
+ className: style$1['pop-util-content'],
806
+ children: children({
807
+ value: state,
808
+ onChange: setState
809
+ })
810
+ }), /*#__PURE__*/jsxs(Row, {
811
+ className: style$1['pop-util-footer'],
812
+ justify: "end",
813
+ gutter: 8,
814
+ children: [/*#__PURE__*/jsx(Col, {
815
+ children: /*#__PURE__*/jsx(Button, {
816
+ size: "small",
817
+ onClick: closeDropdown,
818
+ children: formatMessage({
819
+ id: 'cancelText'
820
+ })
821
+ })
822
+ }), /*#__PURE__*/jsx(Col, {
823
+ children: /*#__PURE__*/jsx(Button, {
824
+ size: "small",
825
+ type: "primary",
826
+ disabled: disabled,
827
+ onClick: () => {
828
+ closeDropdown();
829
+ onChange && onChange(state);
830
+ },
831
+ children: formatMessage({
832
+ id: 'determineText'
833
+ })
834
+ })
835
+ })]
836
+ })]
837
+ });
838
+ return /*#__PURE__*/jsxs(Fragment, {
839
+ children: [renderMask && typeof document !== 'undefined' && /*#__PURE__*/createPortal(/*#__PURE__*/jsx("div", {
840
+ className: classnames(style$1['pop-util-mask'], maskClosing && style$1['pop-util-mask-leave']),
841
+ style: {
842
+ top: popupMetrics.top,
843
+ height: popupMetrics.height
844
+ },
845
+ onClick: closeDropdown
846
+ }), document.body), /*#__PURE__*/jsx(Dropdown, {
847
+ open: open,
848
+ trigger: ['click'],
849
+ placement: isMobile ? 'bottomLeft' : _placement,
850
+ autoAdjustOverflow: !isMobile,
851
+ align: isMobile ? {
852
+ offset: [0, 0]
853
+ } : undefined,
854
+ overlayClassName: classnames(style$1['pop-util-overlay'], overlayClassName),
855
+ overlayStyle: mobileOverlayStyle,
856
+ onOpenChange: handleOpenChange,
857
+ menu: {
858
+ items: [{
859
+ key: 'content',
860
+ label: null
861
+ }]
862
+ },
863
+ dropdownRender: () => overlayContent,
864
+ children: /*#__PURE__*/jsx("span", {
865
+ ref: triggerRef,
866
+ children: /*#__PURE__*/jsx(FilterItem, {
867
+ open: open,
868
+ active: isNotEmpty(value),
869
+ label: label
870
+ })
871
+ })
872
+ })]
873
+ });
874
+ });
162
875
 
163
- const createCheckedChangeHandler = value => checked => {
164
- if (checked) {
165
- let newList = currentValue.slice(0);
876
+ const _excluded$c = ["label", "value", "onChange", "placeholder", "onValidate", "overlayClassName", "placement", "onOpenChange"];
877
+ const InputFilterItem$2 = withLocale(_ref => {
878
+ let {
879
+ label,
880
+ value,
881
+ onChange,
882
+ placeholder,
883
+ onValidate,
884
+ overlayClassName,
885
+ placement,
886
+ onOpenChange
887
+ } = _ref,
888
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$c);
889
+ return /*#__PURE__*/jsx(PopoverItem, {
890
+ label: label,
891
+ value: value,
892
+ onChange: onChange,
893
+ onValidate,
894
+ overlayClassName,
895
+ placement,
896
+ onOpenChange,
897
+ children: ({
898
+ value,
899
+ onChange
900
+ }) => /*#__PURE__*/jsx(Input, _extends({}, props, {
901
+ placeholder: placeholder || `请输入${label}`,
902
+ className: style$1['filter-item-text'],
903
+ value: get(value, 'value', ''),
904
+ onChange: e => onChange(e.target.value ? {
905
+ label: e.target.value,
906
+ value: e.target.value
907
+ } : null)
908
+ }))
909
+ });
910
+ });
166
911
 
167
- if (currentValue.length < size) {
168
- newList.push(value);
912
+ const _excluded$b = ["label", "value", "onChange", "placeholder", "onValidate", "overlayClassName", "placement", "onOpenChange", "unit"];
913
+ const computedFilterValue = (range, unit, formatMessage) => {
914
+ if (!isNumber(range[0]) && !isNumber(range[1])) {
915
+ return null;
916
+ }
917
+ return {
918
+ label: (range => {
919
+ if (isNumber(range[0]) && isNumber(range[1])) {
920
+ return `${range[0]}-${range[1]}${unit || ''}`;
169
921
  }
170
-
171
- if (currentValue.length === size && size === 1) {
172
- newList = [value];
922
+ if (isNumber(range[0])) {
923
+ return formatMessage({
924
+ id: 'over'
925
+ }, {
926
+ count: range[0],
927
+ unit
928
+ });
173
929
  }
174
-
175
- if (currentValue.length >= size && size > 1) {
176
- message.error(`最多选择${size}个`);
177
- return;
930
+ if (isNumber(range[1])) {
931
+ return formatMessage({
932
+ id: 'lessThan'
933
+ }, {
934
+ count: range[1],
935
+ unit
936
+ });
178
937
  }
179
-
180
- changeHandler(newList);
181
- } else {
182
- const newList = currentValue.slice(0);
183
- newList.splice(findIndex(currentValue, item => item.value === value.value), 1);
184
- changeHandler(newList);
185
- }
938
+ })(range),
939
+ value: [range[0] || null, range[1] || null]
186
940
  };
941
+ };
942
+ const defaultPropsOnValidate = value => {
943
+ const range = get(value, 'value');
944
+ return !(range && isNumber(range[0]) && isNumber(range[1]) && range[1] < range[0]);
945
+ };
946
+ const NumberRangeFilterItem$1 = withLocale(_ref => {
947
+ let {
948
+ label,
949
+ value,
950
+ onChange,
951
+ placeholder,
952
+ onValidate = defaultPropsOnValidate,
953
+ overlayClassName,
954
+ placement,
955
+ onOpenChange,
956
+ unit
957
+ } = _ref,
958
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$b);
959
+ const {
960
+ formatMessage
961
+ } = useIntl({
962
+ moduleName: 'Filter'
963
+ });
964
+ return /*#__PURE__*/jsx(PopoverItem, {
965
+ label: label,
966
+ value: value,
967
+ onChange: onChange,
968
+ onValidate,
969
+ overlayClassName,
970
+ placement,
971
+ onOpenChange,
972
+ children: ({
973
+ value,
974
+ onChange
975
+ }) => /*#__PURE__*/jsxs(Space.Compact, {
976
+ children: [/*#__PURE__*/jsx(InputNumber, _extends({}, props, {
977
+ placeholder: placeholder || `${formatMessage({
978
+ id: 'pleaseInput'
979
+ })}${label}`,
980
+ className: style$1['filter-item-number-range'],
981
+ value: get(value, 'value[0]', ''),
982
+ onChange: target => {
983
+ onChange(computedFilterValue([target, get(value, 'value[1]')], unit, formatMessage));
984
+ }
985
+ })), /*#__PURE__*/jsx(Input, {
986
+ style: {
987
+ width: 30,
988
+ borderLeft: 0,
989
+ borderRight: 0,
990
+ pointerEvents: 'none'
991
+ },
992
+ placeholder: "~",
993
+ disabled: true
994
+ }), /*#__PURE__*/jsx(InputNumber, _extends({}, props, {
995
+ placeholder: placeholder || `${formatMessage({
996
+ id: 'pleaseInput'
997
+ })}${label}`,
998
+ className: style$1['filter-item-number-range'],
999
+ value: get(value, 'value[1]', ''),
1000
+ onChange: target => {
1001
+ onChange(computedFilterValue([get(value, 'value[0]'), target], unit, formatMessage));
1002
+ }
1003
+ })), unit && /*#__PURE__*/jsx(Input, {
1004
+ style: {
1005
+ width: 50,
1006
+ borderLeft: 0
1007
+ },
1008
+ value: unit,
1009
+ disabled: true
1010
+ })]
1011
+ })
1012
+ });
1013
+ });
187
1014
 
188
- const computedChildren = (() => {
189
- if (Array.isArray(options)) {
190
- return options.map(({
191
- label,
192
- value
193
- }) => /*#__PURE__*/React.createElement(List.Item, {
194
- key: value,
195
- value: value,
196
- label: label
197
- }));
198
- }
199
-
200
- if (isFunction(children)) {
201
- return children({
202
- value: currentValue,
203
- onChange: changeHandler
1015
+ const _excluded$a = ["value", "onChange", "picker"];
1016
+ const DatePickerFilterItem = withLocale(withFieldItem(_ref => {
1017
+ var _props$classNames, _props$classNames2;
1018
+ let {
1019
+ value,
1020
+ onChange,
1021
+ picker = 'date'
1022
+ } = _ref,
1023
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$a);
1024
+ return /*#__PURE__*/jsx(DatePicker, _extends({}, props, {
1025
+ picker: picker,
1026
+ classNames: _extends({}, props.classNames, {
1027
+ popup: _extends({}, (_props$classNames = props.classNames) == null ? void 0 : _props$classNames.popup, {
1028
+ root: classnames((_props$classNames2 = props.classNames) == null || (_props$classNames2 = _props$classNames2.popup) == null ? void 0 : _props$classNames2.root, style$1['date-picker-popup'])
1029
+ })
1030
+ }),
1031
+ value: value && dayjs(value.value),
1032
+ onChange: value => {
1033
+ const {
1034
+ format
1035
+ } = Object.assign({
1036
+ format: 'YYYY-MM-DD'
1037
+ }, props);
1038
+ value && onChange({
1039
+ label: picker !== 'date' ? `${value.startOf(picker).format(format)}~${value.endOf(picker).format(format)}` : value.format(format),
1040
+ value: new Date(value.startOf(picker).valueOf())
204
1041
  });
205
1042
  }
1043
+ }));
1044
+ }));
1045
+
1046
+ const _excluded$9 = ["value", "onChange", "header"];
1047
+ const DateRangePickerFilterItem = withLocale(withFieldItem(_ref => {
1048
+ var _props$classNames, _props$classNames2;
1049
+ let {
1050
+ value,
1051
+ onChange,
1052
+ header
1053
+ } = _ref,
1054
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$9);
1055
+ return /*#__PURE__*/jsxs(Flex, {
1056
+ vertical: true,
1057
+ children: [typeof header === 'function' ? header({
1058
+ value,
1059
+ onChange
1060
+ }) : header, /*#__PURE__*/jsx(DatePicker.RangePicker, _extends({}, props, {
1061
+ allowEmpty: [false, false],
1062
+ classNames: _extends({}, props.classNames, {
1063
+ popup: _extends({}, (_props$classNames = props.classNames) == null ? void 0 : _props$classNames.popup, {
1064
+ root: classnames((_props$classNames2 = props.classNames) == null || (_props$classNames2 = _props$classNames2.popup) == null ? void 0 : _props$classNames2.root, style$1['date-range-picker-popup'])
1065
+ })
1066
+ }),
1067
+ value: value && Array.isArray(value.value) && value.value.length === 2 && value.value.map(item => dayjs(item)),
1068
+ onChange: value => {
1069
+ const {
1070
+ format
1071
+ } = Object.assign({
1072
+ format: 'YYYY-MM-DD'
1073
+ }, props);
1074
+ onChange({
1075
+ label: value.map(item => item.format(format)).join('~'),
1076
+ value: value.map(item => new Date(item.valueOf()))
1077
+ });
1078
+ }
1079
+ }))]
1080
+ });
1081
+ }));
206
1082
 
207
- return children;
208
- })();
1083
+ var style = {"shortcuts-container":"kne-react-filter_3w4Bb","shortcut-item":"kne-react-filter_myRhG","is-active":"kne-react-filter_FowoG"};
209
1084
 
210
- return /*#__PURE__*/React.createElement(FilterItem, {
211
- label: label,
212
- labelHidden: labelHidden
213
- }, /*#__PURE__*/React.createElement(Provider, {
214
- value: {
215
- currentValue,
216
- createCheckedChangeHandler
1085
+ const _excluded$8 = ["value", "onChange", "defaultValue", "shortcuts", "shortcutOptions"];
1086
+ const TypeDateRangePickerField = _ref => {
1087
+ let {
1088
+ value: valueProp,
1089
+ onChange: onChangeProp,
1090
+ defaultValue,
1091
+ shortcuts = true,
1092
+ shortcutOptions
1093
+ } = _ref,
1094
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$8);
1095
+ const {
1096
+ formatMessage
1097
+ } = useIntl({
1098
+ moduleName: 'Filter'
1099
+ });
1100
+ const typeList = new Map([['date', formatMessage({
1101
+ id: 'customTime'
1102
+ })], ['month', formatMessage({
1103
+ id: 'monthly'
1104
+ })], ['week', formatMessage({
1105
+ id: 'weekly'
1106
+ })]]);
1107
+ const defaultShortcuts = useMemo(() => [{
1108
+ label: formatMessage({
1109
+ id: 'last7Days'
1110
+ }),
1111
+ getValue: () => [dayjs().subtract(7, 'day').startOf('day'), dayjs().endOf('day')]
1112
+ }, {
1113
+ label: formatMessage({
1114
+ id: 'thisMonth'
1115
+ }),
1116
+ getValue: () => [dayjs().startOf('month'), dayjs().endOf('month')]
1117
+ }, {
1118
+ label: formatMessage({
1119
+ id: 'last3Months'
1120
+ }),
1121
+ getValue: () => [dayjs().subtract(3, 'month').startOf('day'), dayjs().endOf('day')]
1122
+ }, {
1123
+ label: formatMessage({
1124
+ id: 'thisYear'
1125
+ }),
1126
+ getValue: () => [dayjs().startOf('year'), dayjs().endOf('day')]
1127
+ }, {
1128
+ label: formatMessage({
1129
+ id: 'fullYear'
1130
+ }),
1131
+ getValue: () => [dayjs().startOf('year'), dayjs().endOf('year')]
1132
+ }], [formatMessage]);
1133
+ const currentShortcuts = shortcutOptions !== undefined ? shortcutOptions : shortcuts ? defaultShortcuts : null;
1134
+ const isControlled = valueProp !== undefined;
1135
+ const innerValueRef = useRef(defaultValue || {
1136
+ type: 'date',
1137
+ value: null
1138
+ });
1139
+ const value = isControlled ? valueProp : innerValueRef.current;
1140
+ const onChange = useCallback(newValue => {
1141
+ if (!isControlled) {
1142
+ innerValueRef.current = typeof newValue === 'function' ? newValue(innerValueRef.current) : newValue;
217
1143
  }
218
- }, computedChildren, more ? (() => {
219
- if (isFunction(more)) {
220
- return more({
221
- name,
222
- size,
223
- label,
224
- value: currentValue,
225
- onChange: changeHandler
226
- });
1144
+ onChangeProp == null || onChangeProp(typeof newValue === 'function' ? newValue(value) : newValue);
1145
+ }, [isControlled, onChangeProp, value]);
1146
+ const handleShortcutClick = useCallback(shortcut => {
1147
+ const [start, end] = shortcut.getValue();
1148
+ const type = 'date';
1149
+ onChange({
1150
+ type,
1151
+ value: [start.startOf(type).toDate(), end.endOf(type).toDate()]
1152
+ });
1153
+ }, [onChange]);
1154
+ const isShortcutActive = useCallback(shortcut => {
1155
+ if (!(value != null && value.value) || !Array.isArray(value.value) || value.value.length !== 2) {
1156
+ return false;
1157
+ }
1158
+ const [start, end] = shortcut.getValue();
1159
+ const type = (value == null ? void 0 : value.type) || 'date';
1160
+ const valueStart = dayjs(value.value[0]).startOf(type);
1161
+ const valueEnd = dayjs(value.value[1]).endOf(type);
1162
+ const shortcutStart = start.startOf(type);
1163
+ const shortcutEnd = end.endOf(type);
1164
+ return valueStart.isSame(shortcutStart, type) && valueEnd.isSame(shortcutEnd, type);
1165
+ }, [value]);
1166
+ const renderShortcuts = useMemo(() => {
1167
+ if (!currentShortcuts || currentShortcuts.length === 0) {
1168
+ return null;
227
1169
  }
1170
+ return /*#__PURE__*/jsx("div", {
1171
+ className: style['shortcuts-container'],
1172
+ children: currentShortcuts.map((shortcut, index) => /*#__PURE__*/jsx("span", {
1173
+ className: classnames(style['shortcut-item'], {
1174
+ [style['is-active']]: isShortcutActive(shortcut)
1175
+ }),
1176
+ onClick: () => handleShortcutClick(shortcut),
1177
+ children: shortcut.label
1178
+ }, index))
1179
+ });
1180
+ }, [currentShortcuts, handleShortcutClick, isShortcutActive]);
1181
+ return /*#__PURE__*/jsxs(Flex, {
1182
+ vertical: true,
1183
+ gap: 0,
1184
+ children: [/*#__PURE__*/jsxs(Space.Compact, {
1185
+ children: [/*#__PURE__*/jsx(Select, {
1186
+ style: {
1187
+ width: '120px'
1188
+ },
1189
+ value: (value == null ? void 0 : value.type) || 'date',
1190
+ onChange: typeValue => {
1191
+ onChange(currentValue => {
1192
+ var _currentValue$value;
1193
+ if (!(currentValue != null && (_currentValue$value = currentValue.value) != null && _currentValue$value.length)) {
1194
+ return {
1195
+ value: null,
1196
+ type: typeValue || 'date'
1197
+ };
1198
+ }
1199
+ const startTime = dayjs(currentValue.value[0]);
1200
+ const endTime = dayjs(currentValue.value[1]);
1201
+ return {
1202
+ value: [startTime.isValid() ? startTime.startOf(typeValue || 'date').toDate() : null, endTime.isValid() ? endTime.endOf(typeValue || 'date').toDate() : null],
1203
+ type: typeValue || 'date'
1204
+ };
1205
+ });
1206
+ },
1207
+ options: Array.from(typeList).map(([val, label]) => ({
1208
+ label,
1209
+ value: val
1210
+ }))
1211
+ }), /*#__PURE__*/jsx(DatePicker.RangePicker, _extends({}, props, {
1212
+ picker: (value == null ? void 0 : value.type) || 'date',
1213
+ value: Array.isArray(value == null ? void 0 : value.value) && value.value.length === 2 ? value.value.map(item => item && dayjs(item)) : null,
1214
+ onChange: dateValue => {
1215
+ onChange(currentValue => {
1216
+ return Object.assign({
1217
+ type: 'date'
1218
+ }, currentValue, {
1219
+ value: dateValue && dateValue[0] && dateValue[1] ? [dateValue[0].startOf((currentValue == null ? void 0 : currentValue.type) || 'date').toDate(), dateValue[1].endOf((currentValue == null ? void 0 : currentValue.type) || 'date').toDate()] : null
1220
+ });
1221
+ });
1222
+ }
1223
+ }))]
1224
+ }), renderShortcuts]
1225
+ });
1226
+ };
228
1227
 
1228
+ const _excluded$7 = ["label", "value", "onChange"];
1229
+ const TypeDateRangePickerFilterItem = withLocale(_ref => {
1230
+ let {
1231
+ label,
1232
+ value,
1233
+ onChange
1234
+ } = _ref,
1235
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$7);
1236
+ return /*#__PURE__*/jsx(PopoverItem, {
1237
+ label: label,
1238
+ value: value,
1239
+ onChange: onChange,
1240
+ onValidate: item => {
1241
+ const itemValue = item == null ? void 0 : item.value;
1242
+ return (itemValue == null ? void 0 : itemValue.type) && Array.isArray(itemValue == null ? void 0 : itemValue.value) && itemValue.value.length === 2;
1243
+ },
1244
+ children: ({
1245
+ value,
1246
+ onChange
1247
+ }) => /*#__PURE__*/jsx(TypeDateRangePickerField, _extends({}, props, {
1248
+ className: style$1['filter-item-text'],
1249
+ value: get(value, 'value'),
1250
+ onChange: pickerValue => {
1251
+ const {
1252
+ format = 'YYYY-MM-DD'
1253
+ } = props;
1254
+ const val = (pickerValue == null ? void 0 : pickerValue.value) || [];
1255
+ let displayLabel = '';
1256
+ if (val[0] && !val[1]) {
1257
+ displayLabel = `${dayjs(val[0]).format(format)}以后`;
1258
+ } else if (!val[0] && val[1]) {
1259
+ displayLabel = `${dayjs(val[1]).format(format)}以前`;
1260
+ } else if (val[0] && val[1]) {
1261
+ displayLabel = `${dayjs(val[0]).format(format)}~${dayjs(val[1]).format(format)}`;
1262
+ }
1263
+ onChange({
1264
+ label: displayLabel,
1265
+ value: pickerValue
1266
+ });
1267
+ }
1268
+ }))
1269
+ });
1270
+ });
1271
+
1272
+ const _excluded$6 = ["placeholder", "label"];
1273
+ const withInputDefaultPlaceholder = WrappedComponent => withLocale(_ref => {
1274
+ let {
1275
+ placeholder,
1276
+ label
1277
+ } = _ref,
1278
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$6);
1279
+ const {
1280
+ formatMessage
1281
+ } = useIntl({
1282
+ moduleName: 'Filter'
1283
+ });
1284
+ return /*#__PURE__*/jsx(WrappedComponent, _extends({}, props, {
1285
+ label: label,
1286
+ placeholder: placeholder || formatMessage({
1287
+ id: 'defaultInputPlaceholder'
1288
+ }, {
1289
+ label
1290
+ })
1291
+ }));
1292
+ });
1293
+ const InputFilterItem$1 = withInputDefaultPlaceholder(InputFilterItem$2);
1294
+ const NumberRangeFilterItem = withInputDefaultPlaceholder(NumberRangeFilterItem$1);
1295
+ const SuperSelectFilterItem = withFieldItem(SuperSelect, {
1296
+ forcePopup: true
1297
+ });
1298
+ const SelectFunctionFilterItem = withFieldItem(SelectFunction, {
1299
+ forcePopup: true
1300
+ });
1301
+ const SelectIndustryFilterItem = withFieldItem(SelectIndustry, {
1302
+ forcePopup: true
1303
+ });
1304
+ const SelectAddressFilterItem = withFieldItem(SelectAddress, {
1305
+ forcePopup: true
1306
+ });
1307
+
1308
+ var fields$1 = {
1309
+ __proto__: null,
1310
+ InputFilterItem: InputFilterItem$1,
1311
+ NumberRangeFilterItem: NumberRangeFilterItem,
1312
+ SuperSelectFilterItem: SuperSelectFilterItem,
1313
+ SelectFunctionFilterItem: SelectFunctionFilterItem,
1314
+ SelectIndustryFilterItem: SelectIndustryFilterItem,
1315
+ SelectAddressFilterItem: SelectAddressFilterItem,
1316
+ DatePickerFilterItem: DatePickerFilterItem,
1317
+ DateRangePickerFilterItem: DateRangePickerFilterItem,
1318
+ TypeDateRangePickerFilterItem: TypeDateRangePickerFilterItem
1319
+ };
1320
+
1321
+ const getFilterValue = filterValue => {
1322
+ return transform(filterValue, (result, {
1323
+ name,
1324
+ value
1325
+ }) => {
1326
+ result[name] = Array.isArray(value) ? value.map(({
1327
+ value
1328
+ }) => value) : value == null ? void 0 : value.value;
1329
+ }, {});
1330
+ };
1331
+
1332
+ const _excluded$5 = ["name", "label"];
1333
+ const withFilterValue = WrappedComponent => {
1334
+ return _ref => {
1335
+ let {
1336
+ name,
1337
+ label
1338
+ } = _ref,
1339
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$5);
229
1340
  const {
230
- children,
231
- onClick
232
- } = more;
233
- return /*#__PURE__*/React.createElement(List.Item, _extends({}, more, {
234
- onClick: e => {
235
- onClick({
236
- name,
237
- label,
238
- value: currentValue,
239
- onChange: changeHandler
240
- }, e);
241
- },
242
- label: children || "其他"
1341
+ value,
1342
+ onChange
1343
+ } = useContext();
1344
+ return /*#__PURE__*/jsx(WrappedComponent, _extends({}, props, {
1345
+ label: label,
1346
+ onChange: onChange ? value => onChange({
1347
+ name,
1348
+ label,
1349
+ value
1350
+ }) : props.onChange,
1351
+ value: value ? get(value.get(name), 'value') : props.value
243
1352
  }));
244
- })() : null));
1353
+ };
245
1354
  };
246
1355
 
247
- List.Item = _ref => {
1356
+ const _excluded$4 = ["label", "onChange", "value", "placeholder"];
1357
+ const {
1358
+ Search
1359
+ } = Input;
1360
+ const SearchInput = withFilterValue(_ref => {
248
1361
  let {
249
- value,
250
- label
251
- } = _ref,
252
- props = _objectWithoutPropertiesLoose(_ref, _excluded$8);
253
-
254
- const {
255
- currentValue,
256
- createCheckedChangeHandler
257
- } = useContext(context);
258
- const itemProps = {};
259
-
260
- if (value !== void 0) {
261
- itemProps.checked = currentValue.findIndex(item => isEqual(get(item, 'value'), value)) > -1;
262
- itemProps.onChange = createCheckedChangeHandler({
263
1362
  label,
264
- value
265
- });
266
- }
267
-
268
- return /*#__PURE__*/React.createElement(CheckableTag, _extends({}, props, itemProps), label);
269
- };
1363
+ onChange,
1364
+ value,
1365
+ placeholder
1366
+ } = _ref,
1367
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$4);
1368
+ const {
1369
+ formatMessage
1370
+ } = useIntl({
1371
+ moduleName: 'Filter'
1372
+ });
1373
+ return /*#__PURE__*/jsx(Search, _extends({}, props, {
1374
+ placeholder: placeholder || formatMessage({
1375
+ id: 'inputPlaceholder'
1376
+ }, {
1377
+ label
1378
+ }),
1379
+ value: (value == null ? void 0 : value.value) || '',
1380
+ onSearch: value => {
1381
+ onChange({
1382
+ label: value,
1383
+ value
1384
+ });
1385
+ }
1386
+ }));
1387
+ });
270
1388
 
271
- List.defaultProps = {
272
- size: 2
1389
+ /**
1390
+ * 从筛选值中提取原始值数组。
1391
+ * 支持:原始值、{ value } 对象、{ id } 对象、以及它们的数组。
1392
+ *
1393
+ * @example
1394
+ * pickSelectValues([{ value: 1 }, { id: 2 }, '3'])
1395
+ * // => ['1', '2', '3']
1396
+ *
1397
+ * pickSelectValues({ value: 'open' })
1398
+ * // => ['open']
1399
+ *
1400
+ * pickSelectValues(null)
1401
+ * // => []
1402
+ */
1403
+ const pickSelectValues = value => {
1404
+ if (value == null || value === '') {
1405
+ return [];
1406
+ }
1407
+ const list = Array.isArray(value) ? value : [value];
1408
+ return list.map(item => {
1409
+ if (item == null) {
1410
+ return null;
1411
+ }
1412
+ if (typeof item !== 'object') {
1413
+ return String(item);
1414
+ }
1415
+ if (item.value != null && item.value !== '') {
1416
+ return String(item.value);
1417
+ }
1418
+ if (item.id != null && item.id !== '') {
1419
+ return String(item.id);
1420
+ }
1421
+ return null;
1422
+ }).filter(Boolean);
273
1423
  };
274
1424
 
275
- const _excluded$7 = ["label", "labelHidden", "name", "size", "isMore"];
276
- const {
277
- Item
278
- } = List;
279
-
280
- const City = _ref => {
281
- let {
282
- label,
283
- labelHidden,
284
- name,
285
- size
286
- } = _ref;
287
- _objectWithoutPropertiesLoose(_ref, _excluded$7);
288
-
289
- return /*#__PURE__*/React.createElement(List, {
290
- labelHidden: labelHidden,
291
- label: label,
292
- name: name,
293
- size: size,
294
- more: {
295
- children: "其他",
296
- onClick: ({
297
- value,
298
- onChange
299
- }) => {
300
- createCitySelect({
301
- size,
302
- defaultValue: value.map(({
1425
+ /**
1426
+ * 声明式创建 mapFilterValue 函数。
1427
+ *
1428
+ * Filter.getFilterValue 默认只读取 { value },而 SuperSelectFilterItem
1429
+ * 组件使用 { id, name } 格式,需要额外处理。此工具通过声明字段映射规则,
1430
+ * 自动生成符合 (filter, getFilterValue) => value 签名的函数。
1431
+ *
1432
+ * @param {Object} fieldMappers - 字段名到映射规则的映射
1433
+ * @param {'string'} fieldMappers[field] - 确保值为字符串类型
1434
+ * @param {'multi'} fieldMappers[field] - 多选,从 filter entry 提取值数组
1435
+ * @param {'single'} fieldMappers[field] - 单选,从 filter entry 提取第一个值
1436
+ * @param {Function} fieldMappers[field] - 自定义转换,接收 (rawValue, { entry, filter, value }) 返回新值
1437
+ *
1438
+ * @example
1439
+ * const mapFilterValue = createFilterValueMapper({
1440
+ * id: 'string',
1441
+ * roles: 'multi',
1442
+ * tenantOrgId: 'single',
1443
+ * status: (rawValue) => normalizeStatus(rawValue)
1444
+ * });
1445
+ *
1446
+ * // 使用方式与手写 mapFilterValue 一致
1447
+ * const filterValue = mapFilterValue(filter, Filter.getFilterValue);
1448
+ *
1449
+ * // 也可直接传给 BizUnit 的 options.mapFilterValue
1450
+ * <BizUnit options={{ mapFilterValue }} />
1451
+ */
1452
+ const createFilterValueMapper = fieldMappers => {
1453
+ return (filter, getFilterValue) => {
1454
+ const value = getFilterValue(filter);
1455
+ Object.entries(fieldMappers).forEach(([fieldName, mapper]) => {
1456
+ const entry = filter.find(item => item.name === fieldName);
1457
+ if (mapper === 'string') {
1458
+ if (value[fieldName] != null && value[fieldName] !== '') {
1459
+ value[fieldName] = String(value[fieldName]);
1460
+ }
1461
+ } else if (mapper === 'multi') {
1462
+ if (entry) {
1463
+ const values = pickSelectValues(entry.value);
1464
+ if (values.length) {
1465
+ value[fieldName] = values;
1466
+ } else {
1467
+ delete value[fieldName];
1468
+ }
1469
+ }
1470
+ } else if (mapper === 'single') {
1471
+ if (entry) {
1472
+ const values = pickSelectValues(entry.value);
1473
+ if (values[0] != null) {
1474
+ value[fieldName] = values[0];
1475
+ } else {
1476
+ delete value[fieldName];
1477
+ }
1478
+ } else if (value[fieldName] != null && typeof value[fieldName] === 'object') {
1479
+ const values = pickSelectValues(value[fieldName]);
1480
+ if (values.length) {
1481
+ value[fieldName] = values[0];
1482
+ } else {
1483
+ delete value[fieldName];
1484
+ }
1485
+ }
1486
+ } else if (typeof mapper === 'function') {
1487
+ let rawValue = value[fieldName];
1488
+ if (rawValue != null && typeof rawValue === 'object' && 'value' in rawValue) {
1489
+ rawValue = rawValue.value;
1490
+ }
1491
+ if (rawValue != null && rawValue !== '') {
1492
+ const result = mapper(rawValue, {
1493
+ entry,
1494
+ filter,
303
1495
  value
304
- }) => value),
305
- onChange: value => {
306
- Promise.all(value.map(id => apis.getCity(id).then(({
307
- city
308
- }) => ({
309
- label: city.name,
310
- value: city.code
311
- })))).then(value => onChange(value));
1496
+ });
1497
+ if (result != null && result !== '') {
1498
+ value[fieldName] = result;
1499
+ } else {
1500
+ delete value[fieldName];
312
1501
  }
313
- });
314
- }
315
- }
316
- }, ({
317
- value: currentValue
318
- }) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(RemoteData, {
319
- loader: apis.getChinaHotCities
320
- }, data => {
321
- const otherList = currentValue.filter(({
322
- value: code
323
- }) => !data.find(item => item.code === code));
324
- let extraLength = 0;
325
- data.forEach((item, index) => {
326
- if (currentValue.findIndex(({
327
- value
328
- }) => value === item.code) > -1 && index >= data.length - otherList.length) {
329
- extraLength += 1;
1502
+ }
330
1503
  }
331
1504
  });
332
- return /*#__PURE__*/React.createElement(React.Fragment, null, otherList.map(({
333
- value: code
334
- }) => {
335
- return /*#__PURE__*/React.createElement(DisplayCity, {
336
- id: code,
337
- key: code
338
- }, ({
339
- city: item
340
- }) => {
341
- return /*#__PURE__*/React.createElement(Item, {
342
- value: code,
343
- label: item.name
344
- });
345
- });
346
- }), data.filter((item, index) => currentValue.findIndex(({
347
- value
348
- }) => value === item.code) > -1 || index < data.length - otherList.length - extraLength).map(item => /*#__PURE__*/React.createElement(Item, {
349
- key: item.code,
350
- value: item.code,
351
- label: item.name
352
- })));
353
- })));
354
- };
355
-
356
- const SearchButton = ({
357
- name,
358
- isMore,
359
- template,
360
- children,
361
- defaultValue,
362
- defaultActive,
363
- onBlur,
364
- onSearch,
365
- onBeforeSearch,
366
- onActiveChange,
367
- buttonText
368
- }) => {
369
- const {
370
- value: aValue,
371
- onChange
372
- } = useConsumer();
373
- const currentValue = aValue[name];
374
- const initCurrentValue = get(currentValue, "value");
375
- const [value, setValue] = useState(defaultValue || initCurrentValue);
376
- const [active, setActive] = useState(defaultActive);
1505
+ return value;
1506
+ };
1507
+ };
377
1508
 
378
- const withTemplate = (value = '') => ({
379
- value,
380
- label: isFunction(template) ? template(value) : value.toString()
381
- });
1509
+ /**
1510
+ * 创建 URL 参数读取器,自动追踪已消费的参数 key。
1511
+ *
1512
+ * @param {URLSearchParams} searchParams - React Router 的 searchParams 对象
1513
+ * @returns {{ take: (key: string) => string|null, getConsumedKeys: () => string[] }}
1514
+ *
1515
+ * @example
1516
+ * const { take, getConsumedKeys } = createUrlParamsReader(searchParams);
1517
+ * const orgId = take('tenantOrgId');
1518
+ * const orgName = take('orgName');
1519
+ * // getConsumedKeys() => ['tenantOrgId', 'orgName']
1520
+ */
1521
+ const createUrlParamsReader = searchParams => {
1522
+ const consumedKeys = [];
1523
+ const take = key => {
1524
+ if (!searchParams.has(key)) return null;
1525
+ consumedKeys.push(key);
1526
+ return searchParams.get(key);
1527
+ };
1528
+ const getConsumedKeys = () => consumedKeys;
1529
+ return {
1530
+ take,
1531
+ getConsumedKeys
1532
+ };
1533
+ };
382
1534
 
383
- useEffect(() => {
384
- setValue(initCurrentValue);
385
- }, [initCurrentValue]);
386
- const ref = useSimulationBlur(() => {
387
- setValue(initCurrentValue);
388
- setActive(false);
389
- onBlur && onBlur();
390
- });
391
- const activeChangeRef = useRef(onActiveChange);
392
- activeChangeRef.current = onActiveChange;
393
- useEffect(() => {
394
- activeChangeRef.current && activeChangeRef.current(active);
395
- }, [active]);
396
- return /*#__PURE__*/React.createElement("div", {
397
- className: classnames("react-filter-search-button", {
398
- "is-active": active && !isMore
399
- }),
400
- ref: ref,
401
- onMouseEnter: () => {
402
- !active && setActive(true);
403
- },
404
- onMouseLeave: () => {
405
- active && initCurrentValue === value && setActive(false);
1535
+ /**
1536
+ * 从 URL 参数中移除已消费的 key,返回新的 URLSearchParams 或 null(无变化时)。
1537
+ *
1538
+ * @param {URLSearchParams} searchParams - 当前 URL 参数
1539
+ * @param {string[]} consumedKeys - 需要移除的 key 列表
1540
+ * @returns {URLSearchParams|null}
1541
+ */
1542
+ const stripConsumedUrlParams = (searchParams, consumedKeys) => {
1543
+ if (!(consumedKeys != null && consumedKeys.length)) return null;
1544
+ const next = new URLSearchParams(searchParams);
1545
+ let changed = false;
1546
+ consumedKeys.forEach(key => {
1547
+ if (next.has(key)) {
1548
+ next.delete(key);
1549
+ changed = true;
406
1550
  }
407
- }, /*#__PURE__*/React.createElement(Space, {
408
- className: "inner",
409
- size: 0
410
- }, /*#__PURE__*/React.createElement("div", null, children({
411
- value,
412
- setValue,
413
- setActive
414
- })), active || isMore ? /*#__PURE__*/React.createElement(Button, {
415
- className: classnames("react-filter-search-confirm", {
416
- "is-more": isMore
417
- }),
418
- size: "small",
419
- type: "primary",
420
- onClick: e => {
421
- e.stopPropagation();
422
-
423
- if (onBeforeSearch && onBeforeSearch(value) === false) {
424
- return;
425
- }
1551
+ });
1552
+ return changed ? next : null;
1553
+ };
426
1554
 
427
- onChange(name, withTemplate(value));
428
- setActive(false);
429
- onSearch && onSearch({
430
- value
431
- });
432
- }
433
- }, buttonText) : null));
434
- };
435
-
436
- SearchButton.defaultProps = {
437
- defaultActive: false,
438
- buttonText: "确定"
439
- };
440
-
441
- const RangeInner = ({
442
- name,
443
- isMore,
444
- defaultActive,
445
- template,
446
- onBlur,
447
- onSearch,
448
- onActiveChange,
449
- onBeforeSearch,
450
- startProps,
451
- endProps,
452
- placeholder
1555
+ /**
1556
+ * 从 URL 参数初始化 Filter 状态的 hook。
1557
+ *
1558
+ * 读取 URL 参数构建初始筛选值,并在挂载后自动清除已消费的 URL 参数。
1559
+ *
1560
+ * @param {Object} options
1561
+ * @param {Function} options.readUrlParams - 读取 URL 参数并返回 { consumedKeys: string[], ...data }
1562
+ * @param {Function} options.buildFilter - 接收 readUrlParams 的返回值,构建初始 filter 数组
1563
+ * @returns {[Array, Function]} - [filter, setFilter]
1564
+ *
1565
+ * @example
1566
+ * const [filter, setFilter] = useUrlFilter({
1567
+ * readUrlParams: (searchParams) => {
1568
+ * const { take, getConsumedKeys } = createUrlParamsReader(searchParams);
1569
+ * const orgId = take('tenantOrgId');
1570
+ * return { consumedKeys: getConsumedKeys(), orgId };
1571
+ * },
1572
+ * buildFilter: ({ orgId }) => [
1573
+ * { name: 'status', value: { label: '开启', value: 'open' } },
1574
+ * ...(orgId ? [{ name: 'tenantOrgId', value: { label: orgId, value: orgId } }] : [])
1575
+ * ]
1576
+ * });
1577
+ */
1578
+ const useUrlFilter = ({
1579
+ readUrlParams,
1580
+ buildFilter
453
1581
  }) => {
454
- const [error, setError] = useState(null);
455
-
456
- const check = value => {
457
- setError(null);
458
-
459
- if (!Array.isArray(value)) {
460
- return false;
1582
+ const [searchParams, setSearchParams] = useSearchParams();
1583
+ const urlFilterSnapshotRef = useRef(null);
1584
+ if (urlFilterSnapshotRef.current === null) {
1585
+ urlFilterSnapshotRef.current = readUrlParams(searchParams);
1586
+ }
1587
+ const [filter, setFilter] = useState(() => buildFilter(urlFilterSnapshotRef.current));
1588
+ const urlStrippedRef = useRef(false);
1589
+ useEffect(() => {
1590
+ var _urlFilterSnapshotRef;
1591
+ if (urlStrippedRef.current) return;
1592
+ urlStrippedRef.current = true;
1593
+ const nextParams = stripConsumedUrlParams(searchParams, (_urlFilterSnapshotRef = urlFilterSnapshotRef.current) == null ? void 0 : _urlFilterSnapshotRef.consumedKeys);
1594
+ if (nextParams) {
1595
+ setSearchParams(nextParams, {
1596
+ replace: true
1597
+ });
461
1598
  }
1599
+ }, [searchParams, setSearchParams]);
1600
+ return [filter, setFilter];
1601
+ };
462
1602
 
463
- if (isNumber(value[1]) && value[0] > value[1]) {
464
- setError("最大值不能小于最小值");
465
- return false;
1603
+ /**
1604
+ * 将筛选值数组序列化为 URLSearchParams,保留 label 信息以便反序列化还原完整筛选状态。
1605
+ *
1606
+ * 序列化格式(使用冒号分隔 label 和 value,逗号分隔多值):
1607
+ * - 单值且 label === value:prefix[name]=value(如输入框)
1608
+ * - 单值且 label !== value:prefix[name]=label:value
1609
+ * - 多值:prefix[name]=label1:value1,label2:value2
1610
+ *
1611
+ * @param {Array} filterValue - 筛选值数组,格式为 [{ name, label, value }, ...]
1612
+ * @param {Object} [options] - 选项
1613
+ * @param {string} [options.prefix='filterParams'] - URL 参数前缀,设为空字符串则不加前缀
1614
+ * @returns {URLSearchParams}
1615
+ *
1616
+ * @example
1617
+ * const params = filterToUrlParams([
1618
+ * { name: 'keyword', label: '关键词', value: { label: '测试', value: '测试' } },
1619
+ * { name: 'city', label: '城市', value: [{ label: '上海', value: '010' }, { label: '北京', value: '020' }] },
1620
+ * { name: 'status', label: '状态', value: { label: '启用', value: 'active' } },
1621
+ * ]);
1622
+ * // params.toString() => 'filterParams[keyword]=测试&filterParams[city]=上海:010,北京:020&filterParams[status]=启用:active'
1623
+ *
1624
+ * // 自定义前缀
1625
+ * filterToUrlParams(filterValue, { prefix: 'f' })
1626
+ * // => 'f[keyword]=测试&f[city]=上海:010,北京:020'
1627
+ *
1628
+ * // 无前缀(直接平铺)
1629
+ * filterToUrlParams(filterValue, { prefix: '' })
1630
+ * // => 'keyword=测试&city=上海:010,北京:020'
1631
+ */
1632
+ const filterToUrlParams = (filterValue, {
1633
+ prefix: _prefix = 'filterParams'
1634
+ } = {}) => {
1635
+ const params = new URLSearchParams();
1636
+ if (!Array.isArray(filterValue)) return params;
1637
+ filterValue.forEach(({
1638
+ name,
1639
+ value
1640
+ }) => {
1641
+ if (value == null || value === '') return;
1642
+ const key = _prefix ? `${_prefix}[${name}]` : name;
1643
+ if (Array.isArray(value)) {
1644
+ if (value.length === 0) return;
1645
+ const serialized = value.map(item => serializeEntry(item)).filter(Boolean).join(',');
1646
+ if (serialized) params.set(key, serialized);
1647
+ } else {
1648
+ const serialized = serializeEntry(value);
1649
+ if (serialized) params.set(key, serialized);
466
1650
  }
1651
+ });
1652
+ return params;
1653
+ };
467
1654
 
468
- if (onBeforeSearch) {
469
- return onBeforeSearch(value);
470
- }
1655
+ /**
1656
+ * 序列化单个筛选值项。
1657
+ * - label === value 时返回 value(简化格式)
1658
+ * - 否则返回 label:value
1659
+ */
1660
+ const serializeEntry = item => {
1661
+ var _item$label, _item$value;
1662
+ if (item == null) return null;
1663
+ if (typeof item !== 'object') return String(item);
1664
+ const label = (_item$label = item.label) != null ? _item$label : item.name;
1665
+ const value = (_item$value = item.value) != null ? _item$value : item.id;
1666
+ if (value == null || value === '') return null;
1667
+ if (label === value) return String(value);
1668
+ return `${label}:${value}`;
1669
+ };
471
1670
 
472
- return true;
1671
+ /**
1672
+ * 解析 URL 参数中的单个筛选值项,反序列化为 { label, value } 对象。
1673
+ * 与 filterToUrlParams 配合使用。
1674
+ *
1675
+ * 解析规则:
1676
+ * - 无冒号:label 和 value 相同,如 "测试" → { label: '测试', value: '测试' }
1677
+ * - 有冒号:冒号前为 label,冒号后为 value,如 "启用:active" → { label: '启用', value: 'active' }
1678
+ *
1679
+ * @param {string} str - URL 参数中的原始字符串
1680
+ * @returns {{ label: string, value: string }}
1681
+ *
1682
+ * @example
1683
+ * parseFilterEntry('测试')
1684
+ * // => { label: '测试', value: '测试' }
1685
+ *
1686
+ * parseFilterEntry('启用:active')
1687
+ * // => { label: '启用', value: 'active' }
1688
+ */
1689
+ const parseFilterEntry = str => {
1690
+ const colonIndex = str.indexOf(':');
1691
+ if (colonIndex === -1) {
1692
+ return {
1693
+ label: str,
1694
+ value: str
1695
+ };
1696
+ }
1697
+ return {
1698
+ label: str.slice(0, colonIndex),
1699
+ value: str.slice(colonIndex + 1)
473
1700
  };
1701
+ };
474
1702
 
475
- return /*#__PURE__*/React.createElement(SearchButton, {
476
- template: template,
477
- isMore: isMore,
478
- onBlur: onBlur,
479
- defaultActive: defaultActive,
480
- name: name,
481
- onSearch: onSearch,
482
- onBeforeSearch: value => {
483
- return check(value);
484
- },
485
- onActiveChange: active => {
486
- if (!active) {
487
- setError(null);
488
- }
1703
+ /**
1704
+ * 从 URL 参数中读取筛选值项,返回单选 { label, value } 或多选数组。
1705
+ *
1706
+ * @param {URLSearchParams} searchParams - URL 参数对象
1707
+ * @param {string} key - 参数名(不含前缀)
1708
+ * @param {Object} [options] - 选项
1709
+ * @param {boolean} [options.multi=false] - 是否多选,多选返回数组
1710
+ * @param {string} [options.prefix='filterParams'] - URL 参数前缀,设为空字符串则不加前缀
1711
+ * @returns {{ label: string, value: string } | { label: string, value: string }[] | null}
1712
+ *
1713
+ * @example
1714
+ * // URL: ?filterParams[city]=上海:010,北京:020&filterParams[status]=启用:active
1715
+ * takeFilterEntry(searchParams, 'city', { multi: true })
1716
+ * // => [{ label: '上海', value: '010' }, { label: '北京', value: '020' }]
1717
+ *
1718
+ * // 无前缀
1719
+ * takeFilterEntry(searchParams, 'keyword', { prefix: '' })
1720
+ * // => { label: '测试', value: '测试' }
1721
+ */
1722
+ const takeFilterEntry = (searchParams, key, {
1723
+ multi: _multi = false,
1724
+ prefix: _prefix2 = 'filterParams'
1725
+ } = {}) => {
1726
+ const fullKey = _prefix2 ? `${_prefix2}[${key}]` : key;
1727
+ if (!searchParams.has(fullKey)) return null;
1728
+ const raw = searchParams.get(fullKey);
1729
+ if (!raw) return null;
1730
+ if (_multi) {
1731
+ return raw.split(',').map(parseFilterEntry);
1732
+ }
489
1733
 
490
- onActiveChange && onActiveChange(active);
491
- }
492
- }, ({
493
- value,
494
- setValue,
495
- setActive
496
- }) => /*#__PURE__*/React.createElement(Tooltip, {
497
- visible: !!error,
498
- title: error,
499
- placement: "bottomRight"
500
- }, /*#__PURE__*/React.createElement(Space, {
501
- size: "small",
502
- className: "react-filter-range"
503
- }, /*#__PURE__*/React.createElement(InputNumber, _extends({
504
- size: "small"
505
- }, startProps, {
506
- value: get(value, 0),
507
- onChange: inputValue => {
508
- const target = [inputValue, get(value, 1)];
509
- check(target);
510
- setValue(target);
511
- },
512
- onFocus: () => {
513
- setActive(true);
514
- },
515
- placeholder: Array.isArray(placeholder) ? placeholder[0] : placeholder || "请输入"
516
- })), "~", /*#__PURE__*/React.createElement(InputNumber, _extends({
517
- size: "small"
518
- }, endProps, {
519
- value: get(value, 1),
520
- onChange: inputValue => {
521
- const target = [get(value, 0), inputValue];
522
- check(target);
523
- setValue(target);
524
- },
525
- onFocus: () => {
526
- setActive(true);
527
- },
528
- placeholder: Array.isArray(placeholder) ? placeholder[0] : placeholder || "请输入"
529
- })))));
1734
+ // 单选时,如果包含逗号,只取第一个
1735
+ const firstEntry = raw.includes(',') ? raw.split(',')[0] : raw;
1736
+ return parseFilterEntry(firstEntry);
530
1737
  };
531
- const Range = withFilterItem(RangeInner);
532
1738
 
533
- const _excluded$6 = ["name", "label", "isMore", "template", "defaultActive", "onBlur", "onSearch", "onBeforeSearch", "onActiveChange", "placeholder"];
534
-
535
- const withValue$1 = (WrappedComponent, options = {}) => _ref => {
536
- let {
537
- name,
538
- label,
539
- isMore,
540
- template,
541
- defaultActive,
542
- onBlur,
543
- onSearch,
544
- onBeforeSearch,
545
- onActiveChange,
546
- placeholder
547
- } = _ref,
548
- props = _objectWithoutPropertiesLoose(_ref, _excluded$6);
549
-
550
- return /*#__PURE__*/React.createElement(SearchButton, {
551
- defaultActive: defaultActive,
552
- isMore: isMore,
553
- onBlur: onBlur,
554
- template: template,
555
- name: name,
556
- onSearch: onSearch,
557
- onBeforeSearch: onBeforeSearch,
558
- onActiveChange: active => {
559
- onActiveChange && onActiveChange(active);
1739
+ /**
1740
+ * 创建 URL 筛选参数读取器,自动追踪已消费的参数 key。
1741
+ * 配合 useUrlFilter 使用,readUrlParams 返回的 consumedKeys 可被自动清除。
1742
+ *
1743
+ * @param {URLSearchParams} searchParams - React Router 的 searchParams 对象
1744
+ * @param {Object} [options] - 选项
1745
+ * @param {string} [options.prefix='filterParams'] - URL 参数前缀
1746
+ * @returns {{ takeFilterEntry, getConsumedKeys }}
1747
+ *
1748
+ * @example
1749
+ * const { takeFilterEntry, getConsumedKeys } = createUrlFilterReader(searchParams);
1750
+ * const keyword = takeFilterEntry('keyword');
1751
+ * const city = takeFilterEntry('city', { multi: true });
1752
+ * const status = takeFilterEntry('status');
1753
+ * // getConsumedKeys() => ['filterParams[keyword]', 'filterParams[city]', 'filterParams[status]']
1754
+ *
1755
+ * // 配合 useUrlFilter 使用
1756
+ * const [filter, setFilter] = useUrlFilter({
1757
+ * readUrlParams: (searchParams) => {
1758
+ * const { takeFilterEntry, getConsumedKeys } = createUrlFilterReader(searchParams);
1759
+ * const keyword = takeFilterEntry('keyword');
1760
+ * const city = takeFilterEntry('city', { multi: true });
1761
+ * return { consumedKeys: getConsumedKeys(), keyword, city };
1762
+ * },
1763
+ * buildFilter: ({ keyword, city }) => [
1764
+ * ...(keyword ? [{ name: 'keyword', label: '关键词', value: keyword }] : []),
1765
+ * ...(city ? [{ name: 'city', label: '城市', value: city }] : []),
1766
+ * ],
1767
+ * });
1768
+ */
1769
+ const createUrlFilterReader = (searchParams, {
1770
+ prefix: _prefix3 = 'filterParams'
1771
+ } = {}) => {
1772
+ const consumedKeys = [];
1773
+ const takeFilterEntry = (key, {
1774
+ multi: _multi2 = false
1775
+ } = {}) => {
1776
+ const fullKey = _prefix3 ? `${_prefix3}[${key}]` : key;
1777
+ if (!searchParams.has(fullKey)) return null;
1778
+ consumedKeys.push(fullKey);
1779
+ const raw = searchParams.get(fullKey);
1780
+ if (!raw) return null;
1781
+ if (_multi2) {
1782
+ return raw.split(',').map(parseFilterEntry);
560
1783
  }
561
- }, ({
562
- value,
563
- setValue,
564
- setActive
565
- }) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(WrappedComponent, _extends({
566
- size: "small"
567
- }, props, {
568
- placeholder: placeholder || label,
569
- value: value,
570
- onChange: e => {
571
- setValue(options.getValue ? options.getValue(e) : e.target.value.trim());
1784
+ const firstEntry = raw.includes(',') ? raw.split(',')[0] : raw;
1785
+ return parseFilterEntry(firstEntry);
1786
+ };
1787
+ const getConsumedKeys = () => consumedKeys;
1788
+ return {
1789
+ takeFilterEntry,
1790
+ getConsumedKeys
1791
+ };
1792
+ };
1793
+
1794
+ const _excluded$3 = ["consumedKeys"];
1795
+
1796
+ /**
1797
+ * 从 URL 参数初始化 Filter 状态的 hook(简化版)。
1798
+ *
1799
+ * 基于 useUrlFilter 封装,使用 createUrlFilterReader 解析 filterParams[key] 格式的 URL 参数,
1800
+ * 自动解析 label:value 格式,支持单选和多选。
1801
+ *
1802
+ * @param {string[]|Object} mapping - URL 参数映射
1803
+ * - 数组: ['tenantOrgId', 'orgName'],默认单选,自动创建 { name: key, value: { label, value } }
1804
+ * - 对象:
1805
+ * - 值为 true: 单选,使用默认转换 { name: key, value: { label, value } }
1806
+ * - 值为 { multi: true }: 多选,value 为 [{ label, value }, ...] 数组
1807
+ * - 值为函数: 自定义转换,接收解析后的值(单选为 { label, value },多选为数组),返回 filter 项或 null/falsy 跳过
1808
+ * @returns {[Array, Function]} - [filter, setFilter]
1809
+ *
1810
+ * @example
1811
+ * // 数组形式(默认单选)
1812
+ * const [filter, setFilter] = useUrlFilterValue(['keyword', 'status']);
1813
+ * // URL: ?filterParams[keyword]=前端开发&filterParams[status]=招聘中:active
1814
+ * // → filter: [
1815
+ * // { name: 'keyword', value: { label: '前端开发', value: '前端开发' } },
1816
+ * // { name: 'status', value: { label: '招聘中', value: 'active' } }
1817
+ * // ]
1818
+ *
1819
+ * @example
1820
+ * // 对象形式(多选 + 自定义)
1821
+ * const [filter, setFilter] = useUrlFilterValue({
1822
+ * keyword: true,
1823
+ * city: { multi: true },
1824
+ * status: (parsed) => parsed ? { name: 'status', value: parsed } : null
1825
+ * });
1826
+ * // URL: ?filterParams[keyword]=测试&filterParams[city]=上海:010,北京:020
1827
+ * // → keyword: { label: '测试', value: '测试' }
1828
+ * // → city: [{ label: '上海', value: '010' }, { label: '北京', value: '020' }]
1829
+ */
1830
+ const useUrlFilterValue = mapping => {
1831
+ const normalizedMapping = Array.isArray(mapping) ? mapping.reduce((acc, item) => {
1832
+ const key = typeof item === 'string' ? item : item.name;
1833
+ acc[key] = typeof item === 'string' ? true : item;
1834
+ return acc;
1835
+ }, {}) : mapping;
1836
+ return useUrlFilter({
1837
+ readUrlParams: searchParams => {
1838
+ const {
1839
+ takeFilterEntry,
1840
+ getConsumedKeys
1841
+ } = createUrlFilterReader(searchParams);
1842
+ const data = {};
1843
+ Object.entries(normalizedMapping).forEach(([key, config]) => {
1844
+ const multi = typeof config === 'object' && config !== null && config.multi;
1845
+ const val = takeFilterEntry(key, {
1846
+ multi
1847
+ });
1848
+ if (val !== null) data[key] = val;
1849
+ });
1850
+ return _extends({
1851
+ consumedKeys: getConsumedKeys()
1852
+ }, data);
572
1853
  },
573
- onFocus: () => {
574
- setActive(true);
1854
+ buildFilter: data => {
1855
+ const values = _objectWithoutPropertiesLoose(data, _excluded$3);
1856
+ const filters = [];
1857
+ Object.entries(normalizedMapping).forEach(([key, config]) => {
1858
+ if (values[key] === undefined) return;
1859
+ const parsedValue = values[key];
1860
+ if (typeof config === 'function') {
1861
+ const result = config(parsedValue);
1862
+ if (result) filters.push(result);
1863
+ } else {
1864
+ const label = typeof config === 'object' && config !== null ? config.label : key;
1865
+ filters.push({
1866
+ name: key,
1867
+ label,
1868
+ value: parsedValue
1869
+ });
1870
+ }
1871
+ });
1872
+ return filters;
575
1873
  }
576
- }))));
1874
+ });
577
1875
  };
578
1876
 
579
- const TextInner = withValue$1(Input);
580
- const Text = withFilterItem(withValue$1(Input));
581
- Text.Number = withFilterItem(withValue$1(InputNumber, {
582
- getValue: value => {
583
- return value;
1877
+ const toIdName = item => {
1878
+ if (!item) {
1879
+ return null;
584
1880
  }
585
- }));
586
-
587
- const _excluded$5 = ["name", "label", "placeholder", "isMore"];
588
- const SelectorInner = _ref => {
589
- let {
590
- name,
591
- label,
592
- placeholder
593
- } = _ref,
594
- props = _objectWithoutPropertiesLoose(_ref, _excluded$5);
1881
+ if (item.id != null) {
1882
+ return item;
1883
+ }
1884
+ if (item.value != null) {
1885
+ return {
1886
+ id: item.value,
1887
+ name: item.label
1888
+ };
1889
+ }
1890
+ return item;
1891
+ };
1892
+ const toLabelValue = item => {
1893
+ var _item$name, _item$id;
1894
+ if (!item) {
1895
+ return null;
1896
+ }
1897
+ return {
1898
+ label: (_item$name = item.name) != null ? _item$name : item.label,
1899
+ value: (_item$id = item.id) != null ? _item$id : item.value
1900
+ };
1901
+ };
595
1902
 
596
- const {
597
- value: aValue,
598
- onChange
599
- } = useConsumer();
600
- const currentValue = aValue[name];
601
- return /*#__PURE__*/React.createElement(Select, _extends({}, props, {
602
- placeholder: label || placeholder,
603
- size: "small",
604
- value: currentValue,
605
- onChange: (value, item) => {
606
- onChange(name, item);
1903
+ /**
1904
+ * 单选 SuperSelect interceptor:{id, name} ↔ {label, value}
1905
+ * 适用于 valueKey="id" labelKey="name" 的单选场景
1906
+ */
1907
+ const singleSelectInterceptor = {
1908
+ input: value => {
1909
+ if (!value) {
1910
+ return value;
607
1911
  }
608
- }));
1912
+ const item = Array.isArray(value) ? value[0] : value;
1913
+ const result = toIdName(item);
1914
+ return result;
1915
+ },
1916
+ output: selected => {
1917
+ if (!selected) {
1918
+ return selected;
1919
+ }
1920
+ const item = Array.isArray(selected) ? selected[0] : selected;
1921
+ return toLabelValue(item);
1922
+ }
609
1923
  };
610
- const Selector = withFilterItem(SelectorInner);
611
1924
 
612
- const _excluded$4 = ["name", "label", "className", "isMore"];
613
-
614
- const Check = _ref => {
615
- let {
616
- name,
617
- label,
618
- className
619
- } = _ref,
620
- props = _objectWithoutPropertiesLoose(_ref, _excluded$4);
621
-
622
- const {
623
- value: aValue,
624
- onChange
625
- } = useConsumer();
626
- const currentValue = aValue[name];
627
- return /*#__PURE__*/React.createElement(Checkbox, _extends({}, props, {
628
- className: classnames('react-filter-item', className),
629
- size: "small",
630
- checked: currentValue,
631
- onChange: e => {
632
- onChange(name, e.target.checked ? {
633
- value: true,
634
- label
635
- } : null);
1925
+ /**
1926
+ * 多选 SuperSelect interceptor:[{id, name}] ↔ [{label, value}]
1927
+ * 适用于 valueKey="id" labelKey="name" 的多选场景
1928
+ */
1929
+ const multiSelectInterceptor = {
1930
+ input: value => {
1931
+ if (!value) {
1932
+ return value;
1933
+ }
1934
+ const list = Array.isArray(value) ? value : [value];
1935
+ return list.map(toIdName).filter(Boolean);
1936
+ },
1937
+ output: selected => {
1938
+ if (!selected) {
1939
+ return selected;
636
1940
  }
637
- }), label);
1941
+ const list = Array.isArray(selected) ? selected : [selected];
1942
+ return list.map(toLabelValue).filter(Boolean);
1943
+ }
1944
+ };
1945
+ var filterInterceptors = {
1946
+ single: singleSelectInterceptor,
1947
+ multi: multiSelectInterceptor
638
1948
  };
639
1949
 
640
- const _excluded$3 = ["label", "name", "options", "isMore"];
641
- const RadioList = withFilterItem(_ref => {
1950
+ const _excluded$2 = ["value", "label", "onChange"];
1951
+ const InputFilterItem = withLocale(_ref => {
642
1952
  let {
643
- name,
644
- options
645
- } = _ref,
646
- props = _objectWithoutPropertiesLoose(_ref, _excluded$3);
647
-
1953
+ value,
1954
+ label,
1955
+ onChange
1956
+ } = _ref,
1957
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$2);
1958
+ const propsValue = value == null ? void 0 : value.value;
1959
+ const [inputValue, setInputValue] = useState(propsValue || '');
1960
+ const [active, setActive] = useState(false);
648
1961
  const {
649
- value: aValue,
650
- onChange
651
- } = useConsumer();
652
- const currentValue = aValue[name];
653
- return /*#__PURE__*/React.createElement(Radio.Group, _extends({}, props, {
654
- options: options,
655
- value: get(currentValue, 'value'),
656
- onChange: e => {
657
- const item = options.find(item => item.value === e.target.value);
658
- onChange(name, item);
1962
+ formatMessage
1963
+ } = useIntl({
1964
+ moduleName: 'Filter'
1965
+ });
1966
+ const searchHandler = () => {
1967
+ onChange(inputValue ? {
1968
+ label: inputValue,
1969
+ value: inputValue
1970
+ } : null);
1971
+ };
1972
+ const handleBlur = () => {
1973
+ setActive(false);
1974
+ searchHandler();
1975
+ };
1976
+ const inputValueRef = useRef('');
1977
+ inputValueRef.current = inputValue;
1978
+ useEffect(() => {
1979
+ if (propsValue !== inputValueRef.current) {
1980
+ setInputValue(propsValue);
659
1981
  }
660
- }));
1982
+ }, [propsValue]);
1983
+ return /*#__PURE__*/jsxs(Space.Compact, {
1984
+ children: [/*#__PURE__*/jsx(Input, _extends({
1985
+ placeholder: `${formatMessage({
1986
+ id: 'pleaseInput'
1987
+ })}${label}`
1988
+ }, props, {
1989
+ size: "small",
1990
+ value: inputValue,
1991
+ onFocus: () => {
1992
+ setActive(true);
1993
+ },
1994
+ onBlur: handleBlur,
1995
+ onChange: e => {
1996
+ setInputValue(e.target.value);
1997
+ },
1998
+ onPressEnter: searchHandler
1999
+ })), active && /*#__PURE__*/jsx(Button, {
2000
+ size: "small",
2001
+ type: "primary",
2002
+ onClick: searchHandler,
2003
+ children: formatMessage({
2004
+ id: 'determineText'
2005
+ })
2006
+ })]
2007
+ });
661
2008
  });
662
2009
 
663
- const _excluded$2 = ["label", "name", "options", "isMore"];
664
- const CheckboxList = withFilterItem(_ref => {
665
- let {
666
- name,
667
- options
668
- } = _ref,
669
- props = _objectWithoutPropertiesLoose(_ref, _excluded$2);
670
-
2010
+ const {
2011
+ CheckableTag: CheckableTag$1
2012
+ } = Tag;
2013
+ const ListFilterItem = withLocale(({
2014
+ value,
2015
+ onChange,
2016
+ label,
2017
+ single: _single = false,
2018
+ maxLength: _maxLength = 5,
2019
+ items: _items = []
2020
+ }) => {
671
2021
  const {
672
- value: aValue,
673
- onChange
674
- } = useConsumer();
675
- const currentValue = aValue[name];
676
- return /*#__PURE__*/React.createElement(Checkbox.Group, _extends({}, props, {
677
- value: (currentValue || []).map(({
678
- value
679
- }) => value),
680
- onChange: value => {
681
- const item = value.map(value => {
682
- return options.find(item => item.value === value);
683
- });
684
- console.log(item);
685
- onChange(name, item);
686
- },
687
- options: options
688
- }));
2022
+ message
2023
+ } = App.useApp();
2024
+ const {
2025
+ formatMessage
2026
+ } = useIntl({
2027
+ moduleName: 'Filter'
2028
+ });
2029
+ return /*#__PURE__*/jsx(Space, {
2030
+ size: 4,
2031
+ wrap: true,
2032
+ block: true,
2033
+ children: _items.map(({
2034
+ label: itemLabel,
2035
+ value: itemValue
2036
+ }) => {
2037
+ return /*#__PURE__*/jsx(CheckableTag$1, {
2038
+ size: "small",
2039
+ checked: _single ? isEqual(itemValue, value == null ? void 0 : value.value) : !!(value || []).find(({
2040
+ value
2041
+ }) => isEqual(itemValue, value)),
2042
+ onChange: checked => {
2043
+ if (_single) {
2044
+ onChange(checked ? {
2045
+ value: itemValue,
2046
+ label: itemLabel
2047
+ } : null);
2048
+ return;
2049
+ }
2050
+ const newValue = (value || []).slice(0);
2051
+ if (checked) {
2052
+ newValue.push({
2053
+ value: itemValue,
2054
+ label: itemLabel
2055
+ });
2056
+ } else {
2057
+ const index = newValue.findIndex(({
2058
+ value
2059
+ }) => isEqual(itemValue, value));
2060
+ if (index > -1) {
2061
+ newValue.splice(index, 1);
2062
+ }
2063
+ }
2064
+ if (newValue.length > _maxLength) {
2065
+ message.error(formatMessage({
2066
+ id: 'maxSelectedCount'
2067
+ }, {
2068
+ count: _maxLength
2069
+ }));
2070
+ return;
2071
+ }
2072
+ onChange(newValue);
2073
+ },
2074
+ children: itemLabel
2075
+ }, itemLabel);
2076
+ })
2077
+ });
689
2078
  });
690
2079
 
691
- const _excluded$1 = ["name", "label", "placeholder", "template", "isMore"];
692
-
693
- const withValue = (WrappedComponent, options = {}) => _ref => {
2080
+ const _excluded$1 = ["value", "onChange", "single", "maxLength"];
2081
+ const {
2082
+ CheckableTag
2083
+ } = Tag;
2084
+ const getLabelForLocal = (item, locale) => {
2085
+ if (locale === 'en-US') {
2086
+ return (item == null ? void 0 : item.enName) || (item == null ? void 0 : item.name);
2087
+ }
2088
+ return item == null ? void 0 : item.name;
2089
+ };
2090
+ const CityFilterItemInner = _ref => {
694
2091
  let {
695
- name,
696
- label,
697
- placeholder,
698
- template
699
- } = _ref,
700
- props = _objectWithoutPropertiesLoose(_ref, _excluded$1);
701
-
2092
+ value,
2093
+ onChange,
2094
+ single = false,
2095
+ maxLength = 5
2096
+ } = _ref,
2097
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$1);
702
2098
  const {
703
- value: aValue,
704
- onChange
705
- } = useConsumer();
706
- const currentValue = aValue[name];
707
- return /*#__PURE__*/React.createElement(WrappedComponent, _extends({}, props, {
708
- placeholder: options.range ? placeholder || [label, label] : placeholder || label,
709
- size: "small",
710
- value: currentValue && moment(currentValue),
711
- onChange: (value, item) => {
712
- onChange(name, {
713
- label: isFunction(template) ? template(item) : options.range ? item.join('~') : item,
714
- value: item
715
- });
716
- }
717
- }));
718
- };
719
-
720
- const DateTime = withFilterItem(withValue(DatePicker));
721
- DateTime.Month = withFilterItem(withValue(DatePicker.MonthPicker));
722
- DateTime.Week = withFilterItem(withValue(DatePicker.WeekPicker));
723
- DateTime.Time = withFilterItem(withValue(DatePicker.TimePicker));
724
- DateTime.YearPicker = withFilterItem(withValue(DatePicker.YearPicker));
725
- DateTime.Range = withFilterItem(withValue(DatePicker.RangePicker, {
726
- range: true
727
- }));
728
-
729
- const filterNull = item => {
730
- const target = Object.assign({}, item);
731
- Object.keys(target).forEach(key => {
732
- const item = target[key];
733
-
734
- (() => {
735
- if (Array.isArray(item) && item.length > 0 && item.every(item => item.value === void 0 || item.value === null || item.value === "")) {
736
- delete target[key];
737
- return;
738
- }
739
-
740
- if (Array.isArray(item) && item.length === 0) {
741
- delete target[key];
742
- return;
743
- }
744
-
745
- if (item && Array.isArray(item.value) && (item.value.length === 0 || item.value.every(item => item === void 0 || item === null || item === ""))) {
746
- delete target[key];
747
- return;
748
- }
749
-
750
- if (item === void 0 || item === null || !Array.isArray(item) && item && (item.value === void 0 || item.value === null || item.value === "")) {
751
- delete target[key];
752
- return;
2099
+ message
2100
+ } = App.useApp();
2101
+ const {
2102
+ locale
2103
+ } = useIntl();
2104
+ const {
2105
+ formatMessage
2106
+ } = useIntl({
2107
+ moduleName: 'Filter'
2108
+ });
2109
+ const [addressApi, setAddressApi] = useState(null);
2110
+ useEffect(() => {
2111
+ let cancelled = false;
2112
+ SelectAddress.defaultData().then(data => {
2113
+ if (!cancelled && data) {
2114
+ setAddressApi(createAddressApi(data));
753
2115
  }
754
- })();
2116
+ });
2117
+ return () => {
2118
+ cancelled = true;
2119
+ };
2120
+ }, []);
2121
+ const cityList = useMemo(() => {
2122
+ return addressApi ? addressApi.getChinaHotCities() : [];
2123
+ }, [addressApi]);
2124
+ return /*#__PURE__*/jsxs(Space, {
2125
+ size: 4,
2126
+ wrap: true,
2127
+ block: true,
2128
+ children: [cityList.map(city => {
2129
+ const label = getLabelForLocal(city, locale);
2130
+ return /*#__PURE__*/jsx(CheckableTag, {
2131
+ size: "small",
2132
+ checked: single ? (value == null ? void 0 : value.value) === city.code : !!(value || []).find(({
2133
+ value
2134
+ }) => value === city.code),
2135
+ onChange: checked => {
2136
+ if (single) {
2137
+ onChange(checked ? city : null);
2138
+ return;
2139
+ }
2140
+ const newValue = (value || []).slice(0);
2141
+ checked ? newValue.push(Object.assign({}, city, {
2142
+ label,
2143
+ value: city.code
2144
+ })) : (() => {
2145
+ const index = newValue.findIndex(({
2146
+ value
2147
+ }) => value === city.code);
2148
+ newValue.splice(index, 1);
2149
+ })();
2150
+ if (newValue.length > maxLength) {
2151
+ message.error(formatMessage({
2152
+ id: 'maxSelectedCount'
2153
+ }, {
2154
+ count: maxLength
2155
+ }));
2156
+ return;
2157
+ }
2158
+ onChange(newValue);
2159
+ },
2160
+ children: label
2161
+ }, city.code);
2162
+ }), /*#__PURE__*/jsxs(CheckableTag, {
2163
+ className: style$1['filter-advanced-item-other'],
2164
+ size: "small",
2165
+ checked: (single ? value == null ? void 0 : value.value : (value == null ? void 0 : value.length) > 0) && !cityList.find(({
2166
+ code
2167
+ }) => single ? (value == null ? void 0 : value.value) === code : !!(value || []).find(({
2168
+ value
2169
+ }) => value === code)),
2170
+ children: [formatMessage({
2171
+ id: 'otherText'
2172
+ }), /*#__PURE__*/jsx(SelectAddress, _extends({}, props, {
2173
+ className: style$1['filter-advanced-item-other-inner'],
2174
+ maxLength: maxLength,
2175
+ allowClear: false,
2176
+ value: value,
2177
+ single: single,
2178
+ onChange: value => {
2179
+ if (value.length > maxLength) {
2180
+ message.error(formatMessage({
2181
+ id: 'maxSelectedCount'
2182
+ }, {
2183
+ count: maxLength
2184
+ }));
2185
+ return;
2186
+ }
2187
+ onChange(value);
2188
+ }
2189
+ }))]
2190
+ })]
755
2191
  });
756
- return target;
757
2192
  };
2193
+ const CityFilterItem = withLocale(CityFilterItemInner);
758
2194
 
759
- const Filter = ({
760
- displayLine,
761
- defaultDisplay,
762
- isExtra,
763
- list,
764
- label,
765
- labelHidden,
766
- itemLabelHidden,
767
- unfoldText,
768
- foldText,
769
- extra,
770
- more,
771
- moreTrigger,
772
- moreLabel,
773
- value: originValue,
774
- onChange
775
- }) => {
776
- const value = useMemo(() => {
777
- return filterNull(originValue);
778
- }, [originValue]);
779
- const emitter = useEvent();
780
- const [display, setDisplay] = useState(defaultDisplay);
781
- const basicList = list.slice(0, displayLine),
782
- moreList = list.slice(displayLine);
783
-
784
- const renderList = list => list.map((item, index) => {
785
- return /*#__PURE__*/React.createElement(Space, {
786
- key: index,
787
- className: "react-filter-line"
788
- }, item.map((item, index) => cloneElement(item, {
789
- key: index,
790
- labelHidden: itemLabelHidden
791
- })));
792
- });
793
-
794
- const changeHandler = (name, item) => {
795
- const target = Object.assign({}, value, {
796
- [name]: item
797
- });
798
- const output = filterNull(target);
799
- emitter.emit('change', output);
800
- onChange(output);
801
- };
2195
+ const fields = {
2196
+ InputFilterItem,
2197
+ ListFilterItem,
2198
+ CityFilterItem
2199
+ };
802
2200
 
803
- const moreFilter = more && more.length > 0 ? /*#__PURE__*/React.createElement(Space, {
804
- className: "react-filter-line is-more"
805
- }, /*#__PURE__*/React.createElement(Space, {
806
- className: "react-filter-item"
807
- }, /*#__PURE__*/React.createElement("div", {
808
- className: "react-filter-item-label"
809
- }, moreLabel, ":"), /*#__PURE__*/React.createElement(Space, {
810
- className: "react-filter-item-children",
811
- split: /*#__PURE__*/React.createElement(Divider, {
812
- type: "vertical"
2201
+ const Line = ({
2202
+ list
2203
+ }) => {
2204
+ const {
2205
+ value,
2206
+ onChange
2207
+ } = useContext();
2208
+ return /*#__PURE__*/jsx(Flex, {
2209
+ gap: 8,
2210
+ children: list.map((item, index) => {
2211
+ const ComponentItem = item.type;
2212
+ return /*#__PURE__*/jsxs(Flex, {
2213
+ gap: 16,
2214
+ align: "center",
2215
+ children: [/*#__PURE__*/jsxs("div", {
2216
+ className: style$1['filter-label'],
2217
+ children: [item.props.label, ":"]
2218
+ }), /*#__PURE__*/jsx(Flex, {
2219
+ wrap: true,
2220
+ align: "center",
2221
+ children: /*#__PURE__*/jsx(ComponentItem, _extends({}, item.props, {
2222
+ value: value ? get(value.get(item.props.name), 'value') : item.props.value,
2223
+ onChange: onChange ? value => onChange({
2224
+ name: item.props.name,
2225
+ label: item.props.label,
2226
+ value
2227
+ }) : item.props.onChange
2228
+ }))
2229
+ })]
2230
+ }, item.key || item.props.name || index);
813
2231
  })
814
- }, more.map((item, index) => cloneElement(item, {
815
- key: index,
816
- isMore: true,
817
- moreTrigger
818
- }))))) : null;
819
- return /*#__PURE__*/React.createElement(Provider$1, {
820
- value: {
821
- value,
822
- onChange: changeHandler,
823
- emitter
824
- }
825
- }, /*#__PURE__*/React.createElement("div", {
826
- className: "react-filter"
827
- }, /*#__PURE__*/React.createElement("div", {
828
- className: "react-filter-inner"
829
- }, /*#__PURE__*/React.createElement("div", null, labelHidden ? null : /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement(FilterItem, {
830
- className: "react-filter-selected",
831
- label: label
832
- }, Object.keys(value).map(key => {
833
- const item = value[key];
834
- if (!item) return null;
835
- if (Array.isArray(item) && item.length === 0) return null;
836
- return /*#__PURE__*/React.createElement(Tag, {
837
- key: key,
838
- closable: true,
839
- onClose: () => {
840
- changeHandler(key, null);
841
- }
842
- }, Array.isArray(item) ? item.map(({
843
- label
844
- }) => label).join(",") : item.label);
845
- })), /*#__PURE__*/React.createElement("div", null, extra))), renderList(isExtra ? basicList : list), moreList.length === 0 || isExtra === false ? moreFilter : null), display && isExtra ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Divider, {
846
- className: "react-filter-divider"
847
- }), /*#__PURE__*/React.createElement("div", {
848
- className: "react-filter-inner"
849
- }, renderList(moreList)), moreList.length > 0 ? moreFilter : null) : /*#__PURE__*/React.createElement("div", {
850
- className: "react-filter-divider-close"
851
- }), isExtra && list.length > displayLine ? /*#__PURE__*/React.createElement(Row, {
852
- className: "react-filter-switch-btn",
853
- justify: "end"
854
- }, /*#__PURE__*/React.createElement(Col, null, /*#__PURE__*/React.createElement(Button, {
855
- type: "link",
856
- onClick: () => {
857
- setDisplay(display => !display);
858
- }
859
- }, display ? foldText : unfoldText))) : null));
860
- };
861
-
862
- Filter.type = {
863
- City,
864
- List,
865
- Range,
866
- Text,
867
- Selector,
868
- Check,
869
- RadioList,
870
- CheckboxList,
871
- DateTime
872
- };
873
- Filter.defaultProps = {
874
- label: '筛选项',
875
- labelHidden: false,
876
- itemLabelHidden: false,
877
- unfoldText: '展开',
878
- foldText: '收起',
879
- displayLine: 2,
880
- defaultDisplay: false,
881
- isExtra: true,
882
- list: [[]],
883
- more: [],
884
- moreTrigger: 'hover',
885
- moreLabel: '更多',
886
- value: {},
887
- extra: null,
888
- onChange: () => {}
889
- };
890
-
891
- const _excluded = ["name", "value", "children"],
892
- _excluded2 = ["type"];
893
- const withMoreExtraButton = WrappedComponent => _ref => {
894
- let {
895
- name,
896
- children
897
- } = _ref,
898
- props = _objectWithoutPropertiesLoose(_ref, _excluded);
899
-
900
- const [isEdit, setIsEdit] = useState(false);
901
- return isEdit ? /*#__PURE__*/React.createElement(WrappedComponent, _extends({
902
- defaultActive: true
903
- }, props, {
904
- name: name,
905
- onBlur: () => {
906
- setIsEdit(false);
907
- }
908
- })) : /*#__PURE__*/React.createElement(List.Item, {
909
- onClick: e => {
910
- e.stopPropagation();
911
- setIsEdit(true);
912
- },
913
- label: children || "其他"
914
2232
  });
915
2233
  };
916
- const RangeButton = withMoreExtraButton(RangeInner);
917
- const TextButton = withMoreExtraButton(TextInner);
918
- const SelectorButton = withMoreExtraButton(SelectorInner);
919
- const createExtraButton = _ref2 => {
920
- let {
921
- type
922
- } = _ref2,
923
- props = _objectWithoutPropertiesLoose(_ref2, _excluded2);
924
-
925
- return innerProps => {
926
- const mapping = {
927
- range: RangeButton,
928
- text: TextButton,
929
- selector: SelectorButton
930
- };
931
- const ExtraButtonComponent = mapping[type];
932
-
933
- if (!ExtraButtonComponent) {
934
- return null;
2234
+ const AdvancedFilter = withLocale(props => {
2235
+ const {
2236
+ formatMessage
2237
+ } = useIntl({
2238
+ moduleName: 'Filter'
2239
+ });
2240
+ return /*#__PURE__*/jsx(FilterOuter, _extends({}, props, {
2241
+ children: ({
2242
+ value,
2243
+ onChange,
2244
+ props: filterProps = {}
2245
+ }) => {
2246
+ const {
2247
+ list,
2248
+ more
2249
+ } = filterProps;
2250
+ return /*#__PURE__*/jsxs("div", {
2251
+ children: [/*#__PURE__*/jsxs(Flex, {
2252
+ gap: 8,
2253
+ vertical: true,
2254
+ className: style$1['filter-advanced'],
2255
+ children: [list && list.map((item, index) => {
2256
+ return /*#__PURE__*/jsx(Line, {
2257
+ list: item
2258
+ }, index);
2259
+ }), more && /*#__PURE__*/jsx(FilterLines, {
2260
+ className: style$1['filter-advanced-more'],
2261
+ label: `${formatMessage({
2262
+ id: 'moreText'
2263
+ })}:`,
2264
+ list: [more]
2265
+ })]
2266
+ }), value && value.length > 0 && /*#__PURE__*/jsx(FilterValueDisplay, {
2267
+ value: value,
2268
+ onChange: onChange
2269
+ })]
2270
+ });
935
2271
  }
2272
+ }));
2273
+ });
2274
+ AdvancedFilter.fields = fields;
936
2275
 
937
- return /*#__PURE__*/React.createElement(ExtraButtonComponent, _extends({}, props, innerProps));
938
- };
2276
+ const _excluded = ["children"];
2277
+ const FilterItemContainer = _ref => {
2278
+ let {
2279
+ children
2280
+ } = _ref,
2281
+ props = _objectWithoutPropertiesLoose(_ref, _excluded);
2282
+ return children(props);
939
2283
  };
940
2284
 
941
- export { FilterItem, SearchButton, createExtraButton, Filter as default, useConsumer as useFilterContext, withFilterItem, withMoreExtraButton };
2285
+ Filter.fields = fields$1;
2286
+ Filter.getFilterValue = getFilterValue;
2287
+ Filter.useFilter = useContext;
2288
+ Filter.SearchInput = SearchInput;
2289
+ Filter.withFilterValue = withFilterValue;
2290
+ Filter.FilterProvider = FilterProvider;
2291
+ Filter.pickSelectValues = pickSelectValues;
2292
+ Filter.createFilterValueMapper = createFilterValueMapper;
2293
+ Filter.useUrlFilter = useUrlFilter;
2294
+ Filter.useUrlFilterValue = useUrlFilterValue;
2295
+ Filter.createUrlParamsReader = createUrlParamsReader;
2296
+ Filter.stripConsumedUrlParams = stripConsumedUrlParams;
2297
+ Filter.filterToUrlParams = filterToUrlParams;
2298
+ Filter.parseFilterEntry = parseFilterEntry;
2299
+ Filter.takeFilterEntry = takeFilterEntry;
2300
+ Filter.createUrlFilterReader = createUrlFilterReader;
2301
+ Filter.filterInterceptors = filterInterceptors;
2302
+ Filter.singleSelectInterceptor = singleSelectInterceptor;
2303
+ Filter.multiSelectInterceptor = multiSelectInterceptor;
2304
+
2305
+ export { AdvancedFilter, DatePickerFilterItem, DateRangePickerFilterItem, FilterItem, FilterItemContainer, FilterLines, FilterProvider, FilterValueDisplay, InputFilterItem$1 as InputFilterItem, NumberRangeFilterItem, PopoverItem, SearchInput, SelectAddressFilterItem, SelectFunctionFilterItem, SelectIndustryFilterItem, SuperSelectFilterItem, TypeDateRangePickerField, TypeDateRangePickerFilterItem, createFilterValueMapper, createUrlFilterReader, createUrlParamsReader, Filter as default, fields$1 as fields, filterInterceptors, filterToUrlParams, getFilterValue, multiSelectInterceptor, parseFilterEntry, pickSelectValues, singleSelectInterceptor, stripConsumedUrlParams, takeFilterEntry, useContext as useFilter, useUrlFilter, useUrlFilterValue, withFieldItem, withFilterValue };
942
2306
  //# sourceMappingURL=index.modern.js.map