@gm-pc/react 1.29.0-beta.2 → 1.30.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/component/list/base.tsx +8 -2
- package/src/component/list/style.less +2 -0
- package/src/component/list/types.ts +3 -1
- package/src/component/loading/types.ts +1 -1
- package/src/component/more_select/base.tsx +446 -86
- package/src/component/more_select/more_select.tsx +12 -1
- package/src/component/more_select/stories.tsx +92 -0
- package/src/component/more_select/style.less +4 -0
- package/src/component/more_select/types.ts +36 -5
- package/src/component/nav/nav.tsx +0 -3
- package/src/component/nav/types.ts +0 -1
- package/src/component/switch/style.less +4 -0
- package/src/component/switch/switch.tsx +7 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gm-pc/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.0-beta.4",
|
|
4
4
|
"description": "观麦前端基础组件库",
|
|
5
5
|
"author": "liyatang <liyatang@qq.com>",
|
|
6
6
|
"homepage": "https://github.com/gmfe/gm-pc#readme",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@gm-common/hooks": "^2.10.0",
|
|
26
26
|
"@gm-common/tool": "^2.10.0",
|
|
27
|
-
"@gm-pc/locales": "^1.
|
|
27
|
+
"@gm-pc/locales": "^1.30.0-beta.4",
|
|
28
28
|
"big.js": "^6.0.1",
|
|
29
29
|
"classnames": "^2.2.5",
|
|
30
30
|
"lodash": "^4.17.19",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"react-router-dom": "^5.2.0",
|
|
49
49
|
"react-window": "^1.8.5"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "5b1cebbcf101effbeaf2c4f9a49489b59cc4a1c3"
|
|
52
52
|
}
|
|
@@ -4,12 +4,14 @@ import { xor, flatMap, isNil, noop } from 'lodash'
|
|
|
4
4
|
import { ListBaseProps } from './types'
|
|
5
5
|
import { ListDataItem } from '../../types'
|
|
6
6
|
import { ConfigConsumer } from '../config_provider'
|
|
7
|
+
import SVGOk from '../../svg/ok.svg'
|
|
7
8
|
|
|
8
9
|
class Base<V = any> extends Component<ListBaseProps<V>> {
|
|
9
10
|
static defaultProps = {
|
|
10
11
|
onSelect: noop,
|
|
11
12
|
renderItem: (value: any) => value.text,
|
|
12
13
|
getItemProps: () => ({}),
|
|
14
|
+
showSelectedIcon: true,
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
private _listRef = createRef<HTMLDivElement>()
|
|
@@ -61,9 +63,9 @@ class Base<V = any> extends Component<ListBaseProps<V>> {
|
|
|
61
63
|
}
|
|
62
64
|
const { multiple, selected, onSelect } = this.props
|
|
63
65
|
if (multiple) {
|
|
64
|
-
onSelect && onSelect(xor(selected, [item.value]))
|
|
66
|
+
onSelect && onSelect(xor(selected, [item.value]), item)
|
|
65
67
|
} else {
|
|
66
|
-
onSelect && onSelect([item.value])
|
|
68
|
+
onSelect && onSelect([item.value], item)
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -79,6 +81,7 @@ class Base<V = any> extends Component<ListBaseProps<V>> {
|
|
|
79
81
|
className,
|
|
80
82
|
willActiveIndex,
|
|
81
83
|
getItemProps,
|
|
84
|
+
showSelectedIcon,
|
|
82
85
|
...rest
|
|
83
86
|
} = this.props
|
|
84
87
|
|
|
@@ -115,6 +118,9 @@ class Base<V = any> extends Component<ListBaseProps<V>> {
|
|
|
115
118
|
onClick={() => this._handleSelect(item)}
|
|
116
119
|
>
|
|
117
120
|
{renderItem!(item, index)}
|
|
121
|
+
{multiple && showSelectedIcon && selected.includes(item.value) && (
|
|
122
|
+
<SVGOk />
|
|
123
|
+
)}
|
|
118
124
|
</div>
|
|
119
125
|
)
|
|
120
126
|
})}
|
|
@@ -12,12 +12,14 @@ interface CommonListProps<V> {
|
|
|
12
12
|
getItemProps?(item: ListDataItem<V>): HTMLAttributes<HTMLDivElement>
|
|
13
13
|
className?: string
|
|
14
14
|
style?: CSSProperties
|
|
15
|
+
/** 是否显示选中状态的图标,默认为 true */
|
|
16
|
+
showSelectedIcon?: boolean
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
interface ListBaseProps<V> extends CommonListProps<V> {
|
|
18
20
|
data: ListGroupDataItem<V>[]
|
|
19
21
|
selected: V[]
|
|
20
|
-
onSelect?(selected: V[]): void
|
|
22
|
+
onSelect?(selected: V[], item: ListDataItem<V>): void
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
interface ListProps<V> extends CommonListProps<V> {
|
|
@@ -20,12 +20,20 @@ import { getLocale } from '@gm-pc/locales'
|
|
|
20
20
|
import { ListBase } from '../list'
|
|
21
21
|
import { findDOMNode } from 'react-dom'
|
|
22
22
|
import { ConfigConsumer, ConfigProvider, ConfigProviderProps } from '../config_provider'
|
|
23
|
-
|
|
23
|
+
import { Checkbox } from '../checkbox'
|
|
24
|
+
import { Switch } from '../switch'
|
|
24
25
|
interface MoreSelectBaseState {
|
|
26
|
+
canClear?: boolean
|
|
25
27
|
searchValue: string
|
|
26
28
|
loading: boolean
|
|
27
29
|
/* keyboard 默认第一个位置 */
|
|
28
30
|
willActiveIndex: number | null
|
|
31
|
+
isCheckedAll: boolean
|
|
32
|
+
isFilterDelete: boolean
|
|
33
|
+
displayCount: number
|
|
34
|
+
// isPopupJustOpened: boolean
|
|
35
|
+
previousSelected?: MoreSelectDataItem<V>[]
|
|
36
|
+
previousCurrentSelected: MoreSelectDataItem<V>[]
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
// @todo keydown item disabled
|
|
@@ -41,6 +49,11 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
41
49
|
searchValue: '',
|
|
42
50
|
loading: false,
|
|
43
51
|
willActiveIndex: this.props.isKeyboard ? 0 : null,
|
|
52
|
+
isCheckedAll: false,
|
|
53
|
+
isFilterDelete: true,
|
|
54
|
+
displayCount: 0,
|
|
55
|
+
previousSelected: [],
|
|
56
|
+
previousCurrentSelected: [],
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
private _isUnmounted = false
|
|
@@ -48,6 +61,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
48
61
|
private _selectionRef = createRef<HTMLDivElement>()
|
|
49
62
|
private _popoverRef = createRef<Popover>()
|
|
50
63
|
private _inputRef = createRef<HTMLInputElement>()
|
|
64
|
+
private _resizeObserver: ResizeObserver | null = null
|
|
51
65
|
|
|
52
66
|
private _filterData: MoreSelectGroupDataItem<V>[] | undefined
|
|
53
67
|
|
|
@@ -62,8 +76,42 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
78
|
|
|
79
|
+
componentDidMount() {
|
|
80
|
+
const { maxTagCount, tagItemWidth = 80, omittedTagWidth = 45 } = this.props
|
|
81
|
+
if (maxTagCount === 'responsive' && this._selectionRef.current) {
|
|
82
|
+
// HACK: 首次计算
|
|
83
|
+
setTimeout(() => {
|
|
84
|
+
if (this._selectionRef.current) {
|
|
85
|
+
const { width } = this._selectionRef.current.getBoundingClientRect()
|
|
86
|
+
const availableWidth = width - omittedTagWidth
|
|
87
|
+
const newDisplayCount = Math.floor(availableWidth / tagItemWidth)
|
|
88
|
+
if (this.state.displayCount !== newDisplayCount) {
|
|
89
|
+
this.setState({ displayCount: newDisplayCount > 0 ? newDisplayCount : 0 })
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}, 0)
|
|
93
|
+
|
|
94
|
+
this._resizeObserver = new ResizeObserver((entries) => {
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
const { width } = entry.contentRect
|
|
97
|
+
// Estimate item width, let's say 80px.
|
|
98
|
+
const availableWidth = width - omittedTagWidth
|
|
99
|
+
const newDisplayCount = Math.floor(availableWidth / tagItemWidth)
|
|
100
|
+
|
|
101
|
+
if (this.state.displayCount !== newDisplayCount) {
|
|
102
|
+
this.setState({ displayCount: newDisplayCount })
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
this._resizeObserver.observe(this._selectionRef.current)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
65
110
|
componentWillUnmount() {
|
|
66
|
-
this._isUnmounted =
|
|
111
|
+
this._isUnmounted = true
|
|
112
|
+
if (this._resizeObserver) {
|
|
113
|
+
this._resizeObserver.disconnect()
|
|
114
|
+
}
|
|
67
115
|
}
|
|
68
116
|
|
|
69
117
|
public apiDoFocus = (): void => {
|
|
@@ -104,6 +152,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
104
152
|
}
|
|
105
153
|
})
|
|
106
154
|
})
|
|
155
|
+
console.log(data, selected)
|
|
107
156
|
selected.forEach((item) => {
|
|
108
157
|
let flag = true // 判断当前已选择的选项中是否存在不在当前data里面的,解决onSearch异步,true则表示都不在data里面
|
|
109
158
|
data.forEach((group) => {
|
|
@@ -113,6 +162,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
113
162
|
items.push(item)
|
|
114
163
|
}
|
|
115
164
|
})
|
|
165
|
+
console.log(items)
|
|
116
166
|
onSelect(items)
|
|
117
167
|
|
|
118
168
|
if (!multiple) {
|
|
@@ -130,8 +180,18 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
130
180
|
event: ChangeEvent<HTMLInputElement>,
|
|
131
181
|
isInitSearch?: boolean
|
|
132
182
|
): void => {
|
|
183
|
+
const { onSearch } = this.props
|
|
133
184
|
const searchValue = event.target.value
|
|
134
185
|
this.setState({ searchValue })
|
|
186
|
+
this.setState({
|
|
187
|
+
previousSelected: this.props.selected,
|
|
188
|
+
previousCurrentSelected: this.props.selected,
|
|
189
|
+
})
|
|
190
|
+
if (onSearch && !this._isUnmounted) {
|
|
191
|
+
this.setState({
|
|
192
|
+
loading: true,
|
|
193
|
+
})
|
|
194
|
+
}
|
|
135
195
|
this._debounceDoSearch(searchValue)
|
|
136
196
|
setTimeout(() => {
|
|
137
197
|
// eslint-disable-next-line no-unused-expressions
|
|
@@ -145,28 +205,37 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
145
205
|
private _doSearch = (query: string): void => {
|
|
146
206
|
const { onSearch, data = [] } = this.props
|
|
147
207
|
if (!this._isUnmounted && onSearch) {
|
|
148
|
-
const result = onSearch(query, data)
|
|
149
|
-
if (!result) {
|
|
150
|
-
return
|
|
151
|
-
}
|
|
152
208
|
this.setState({ loading: true })
|
|
153
|
-
|
|
209
|
+
const result = onSearch(query, data)
|
|
154
210
|
Promise.resolve(result).finally(() => {
|
|
155
|
-
|
|
211
|
+
setTimeout(() => {
|
|
212
|
+
this.setState({ loading: false })
|
|
213
|
+
}, 50)
|
|
156
214
|
})
|
|
157
215
|
}
|
|
158
216
|
}
|
|
159
217
|
|
|
160
218
|
private _debounceDoSearch = _.debounce(this._doSearch, this.props.delay)
|
|
161
219
|
|
|
162
|
-
private _handleClear = (clearItem: MoreSelectDataItem<V>, event
|
|
163
|
-
event
|
|
220
|
+
private _handleClear = (clearItem: MoreSelectDataItem<V>, event?: MouseEvent): void => {
|
|
221
|
+
if (event) {
|
|
222
|
+
event.stopPropagation()
|
|
223
|
+
}
|
|
164
224
|
const { onSelect = _.noop, selected = [] } = this.props
|
|
165
225
|
const willSelected = selected.filter((item) => item.value !== clearItem.value)
|
|
166
226
|
onSelect(willSelected)
|
|
167
227
|
}
|
|
168
228
|
|
|
169
|
-
private
|
|
229
|
+
private _handleClearAll = (event: MouseEvent): void => {
|
|
230
|
+
event.stopPropagation()
|
|
231
|
+
const { onSelect = _.noop } = this.props
|
|
232
|
+
onSelect([])
|
|
233
|
+
this.setState({
|
|
234
|
+
previousCurrentSelected: [],
|
|
235
|
+
})
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private _handlePopupKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {
|
|
170
239
|
const { onKeyDown } = this.props
|
|
171
240
|
let willActiveIndex = this.state.willActiveIndex as number
|
|
172
241
|
if (!onKeyDown) {
|
|
@@ -201,9 +270,9 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
201
270
|
}
|
|
202
271
|
|
|
203
272
|
private _getFilterData = () => {
|
|
204
|
-
const { data = [], renderListFilter, renderListFilterType } = this.props
|
|
273
|
+
const { data = [], renderListFilter, renderListFilterType, onSearch } = this.props
|
|
205
274
|
const { searchValue } = this.state
|
|
206
|
-
let filterData: MoreSelectGroupDataItem<V>[]
|
|
275
|
+
let filterData: MoreSelectGroupDataItem<V>[] = []
|
|
207
276
|
if (renderListFilter) {
|
|
208
277
|
filterData = renderListFilter(data, searchValue)
|
|
209
278
|
} else if (renderListFilterType === 'pinyin') {
|
|
@@ -232,19 +301,267 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
232
301
|
)
|
|
233
302
|
}
|
|
234
303
|
|
|
235
|
-
|
|
304
|
+
renderBottom = () => {
|
|
236
305
|
const {
|
|
237
306
|
selected = [],
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
307
|
+
isShowDeletedSwitch = true,
|
|
308
|
+
isShowCheckedAll = true,
|
|
309
|
+
} = this.props
|
|
310
|
+
const { isCheckedAll, isFilterDelete } = this.state
|
|
311
|
+
const flatFilterData = this._getFlatFilterData()
|
|
312
|
+
|
|
313
|
+
// 根据过滤状态决定是否过滤已删除商品
|
|
314
|
+
const availableData = isFilterDelete
|
|
315
|
+
? flatFilterData.filter((item) => !item.deleted)
|
|
316
|
+
: flatFilterData
|
|
317
|
+
|
|
318
|
+
// 检查是否所有可用数据都被选中
|
|
319
|
+
const allSelected =
|
|
320
|
+
availableData.length > 0 &&
|
|
321
|
+
availableData.every((item) =>
|
|
322
|
+
selected.some((selectedItem) => selectedItem.value === item.value)
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
<Flex
|
|
327
|
+
justifyBetween
|
|
328
|
+
className='tw-p-[8px] gm-more-select-default-bottom'
|
|
329
|
+
alignCenter
|
|
330
|
+
>
|
|
331
|
+
{isShowCheckedAll && (
|
|
332
|
+
<Checkbox
|
|
333
|
+
checked={allSelected}
|
|
334
|
+
onChange={(e) => {
|
|
335
|
+
const isChecked = e.target.checked
|
|
336
|
+
this.setState({
|
|
337
|
+
isCheckedAll: isChecked,
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
if (isChecked) {
|
|
341
|
+
// 全选当前过滤后的可用数据
|
|
342
|
+
const valuesToSelect = availableData.map((item) => item.value)
|
|
343
|
+
const prevSelectedValue = selected.map((item) => item.value)
|
|
344
|
+
// console.log(valuesToSelect, selected)
|
|
345
|
+
const newSelected = Array.from(
|
|
346
|
+
new Set([...prevSelectedValue, ...valuesToSelect])
|
|
347
|
+
)
|
|
348
|
+
this._handleSelect(newSelected)
|
|
349
|
+
// 更新 previousCurrentSelected
|
|
350
|
+
this.setState({
|
|
351
|
+
previousCurrentSelected: Array.from(
|
|
352
|
+
new Set([...this.state.previousCurrentSelected, ...availableData])
|
|
353
|
+
),
|
|
354
|
+
})
|
|
355
|
+
} else {
|
|
356
|
+
// 取消全选 - 只反勾选availableData的数据
|
|
357
|
+
const { selected = [] } = this.props
|
|
358
|
+
const availableValues = availableData.map((item) => item.value)
|
|
359
|
+
const newSelected = selected.filter(
|
|
360
|
+
(item) => !availableValues.includes(item.value)
|
|
361
|
+
)
|
|
362
|
+
this._handleSelect(newSelected.map((item) => item.value))
|
|
363
|
+
// 更新 previousCurrentSelected
|
|
364
|
+
this.setState({
|
|
365
|
+
previousCurrentSelected: this.state.previousCurrentSelected.filter(
|
|
366
|
+
(item) => !availableValues.includes(item.value)
|
|
367
|
+
),
|
|
368
|
+
})
|
|
369
|
+
}
|
|
370
|
+
}}
|
|
371
|
+
>
|
|
372
|
+
全选({availableData.length})
|
|
373
|
+
</Checkbox>
|
|
374
|
+
)}
|
|
375
|
+
{isShowDeletedSwitch && (
|
|
376
|
+
<Flex alignCenter>
|
|
377
|
+
<Flex row>
|
|
378
|
+
<Switch
|
|
379
|
+
size='small'
|
|
380
|
+
style={{ width: 32 }}
|
|
381
|
+
checked={isFilterDelete}
|
|
382
|
+
onChange={(open) => {
|
|
383
|
+
this.setState({
|
|
384
|
+
isFilterDelete: open,
|
|
385
|
+
})
|
|
386
|
+
// if (isCheckedAll) {
|
|
387
|
+
// const newAvailableData = open
|
|
388
|
+
// ? flatFilterData.filter((item) => !item.deleted)
|
|
389
|
+
// : flatFilterData
|
|
390
|
+
|
|
391
|
+
// const valuesToSelect = newAvailableData.map((item) => item.value)
|
|
392
|
+
// this._handleSelect(valuesToSelect)
|
|
393
|
+
// }
|
|
394
|
+
}}
|
|
395
|
+
/>
|
|
396
|
+
</Flex>
|
|
397
|
+
<span className='gm-margin-left-5'>过滤已删除数据</span>
|
|
398
|
+
</Flex>
|
|
399
|
+
)}
|
|
400
|
+
</Flex>
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
renderContent = () => {
|
|
405
|
+
const { loading, willActiveIndex, isFilterDelete } = this.state
|
|
406
|
+
|
|
407
|
+
if (loading) {
|
|
408
|
+
return (
|
|
409
|
+
<Flex alignCenter justifyCenter className='gm-bg gm-padding-5'>
|
|
410
|
+
<Loading size='20px' />
|
|
411
|
+
</Flex>
|
|
412
|
+
)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
let filterData = this._getFilterData()
|
|
416
|
+
|
|
417
|
+
// 如果开启了过滤已删除商品功能,需要过滤掉已删除的商品
|
|
418
|
+
if (isFilterDelete) {
|
|
419
|
+
filterData = filterData
|
|
420
|
+
.map((group) => ({
|
|
421
|
+
...group,
|
|
422
|
+
children: group.children.filter((item) => !item.deleted),
|
|
423
|
+
}))
|
|
424
|
+
.filter((group) => group.children.length > 0)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (!loading && filterData.length === 0) {
|
|
428
|
+
return this._renderEmpty()
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (!loading && filterData.length > 0) {
|
|
432
|
+
const {
|
|
433
|
+
selected = [],
|
|
434
|
+
multiple,
|
|
435
|
+
isGroupList,
|
|
436
|
+
renderListItem,
|
|
437
|
+
listHeight,
|
|
438
|
+
showSelectedIcon,
|
|
439
|
+
} = this.props
|
|
440
|
+
const { previousSelected = [], previousCurrentSelected = [] } = this.state
|
|
441
|
+
|
|
442
|
+
const selectedValues = new Set(previousSelected?.map((v) => v.value))
|
|
443
|
+
|
|
444
|
+
// 分离已勾选和未勾选的数据
|
|
445
|
+
const availableGroups: MoreSelectGroupDataItem<V>[] = []
|
|
446
|
+
// 已选中区域直接使用 selected 构建,不受筛选影响
|
|
447
|
+
const selectedGroups: MoreSelectGroupDataItem<V>[] = []
|
|
448
|
+
|
|
449
|
+
if (multiple) {
|
|
450
|
+
filterData.forEach((group) => {
|
|
451
|
+
const availableChildren = group.children.filter((item) => {
|
|
452
|
+
// return true
|
|
453
|
+
return !selectedValues.has(item.value)
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
if (availableChildren.length > 0) {
|
|
457
|
+
availableGroups.push({
|
|
458
|
+
...group,
|
|
459
|
+
children: availableChildren,
|
|
460
|
+
})
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
if (previousSelected.length > 0) {
|
|
465
|
+
selectedGroups.push({
|
|
466
|
+
label: '',
|
|
467
|
+
children: previousSelected,
|
|
468
|
+
})
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return (
|
|
473
|
+
<div style={{ height: listHeight, overflow: 'auto' }}>
|
|
474
|
+
{previousSelected.length > 0 && multiple && !this.state.searchValue && (
|
|
475
|
+
<>
|
|
476
|
+
<div className='gm-more-select-section-title gm-padding-5 gm-text-desc gm-text-12'>
|
|
477
|
+
已选中
|
|
478
|
+
</div>
|
|
479
|
+
<ListBase
|
|
480
|
+
showSelectedIcon={showSelectedIcon}
|
|
481
|
+
selected={previousCurrentSelected.map((v) => v.value)}
|
|
482
|
+
data={selectedGroups}
|
|
483
|
+
multiple={multiple}
|
|
484
|
+
isGroupList={false}
|
|
485
|
+
className='gm-border-0'
|
|
486
|
+
renderItem={renderListItem}
|
|
487
|
+
onSelect={(v, target) => {
|
|
488
|
+
// 判断是勾选还是反选:如果 v 中包含 target.value,说明是勾选操作;否则是反选操作
|
|
489
|
+
const isChecked = v.includes(target.value)
|
|
490
|
+
if (isChecked) {
|
|
491
|
+
// 勾选:添加到 previousCurrentSelected
|
|
492
|
+
this.setState({
|
|
493
|
+
previousCurrentSelected: [
|
|
494
|
+
...this.state.previousCurrentSelected,
|
|
495
|
+
target,
|
|
496
|
+
],
|
|
497
|
+
})
|
|
498
|
+
const newSelected = [...selected, target]
|
|
499
|
+
|
|
500
|
+
this.props.onSelect(newSelected)
|
|
501
|
+
} else {
|
|
502
|
+
// 反选:从 previousCurrentSelected 中移除
|
|
503
|
+
this.setState({
|
|
504
|
+
previousCurrentSelected: this.state.previousCurrentSelected?.filter(
|
|
505
|
+
(item) => item.value !== target.value
|
|
506
|
+
),
|
|
507
|
+
})
|
|
508
|
+
const newSelected = selected.filter(
|
|
509
|
+
(item) => item.value !== target.value
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
this.props.onSelect(newSelected)
|
|
513
|
+
}
|
|
514
|
+
}}
|
|
515
|
+
isScrollTo={false}
|
|
516
|
+
/>
|
|
517
|
+
</>
|
|
518
|
+
)}
|
|
519
|
+
<>
|
|
520
|
+
{multiple && !this.state.searchValue && (
|
|
521
|
+
<div className='gm-more-select-section-title gm-padding-5 gm-text-desc gm-text-12'>
|
|
522
|
+
未选中
|
|
523
|
+
</div>
|
|
524
|
+
)}
|
|
525
|
+
|
|
526
|
+
<ListBase
|
|
527
|
+
showSelectedIcon={showSelectedIcon}
|
|
528
|
+
selected={selected?.map((v) => v.value)}
|
|
529
|
+
data={multiple && !this.state.searchValue ? availableGroups : filterData}
|
|
530
|
+
multiple={multiple}
|
|
531
|
+
isGroupList={isGroupList}
|
|
532
|
+
className='gm-border-0'
|
|
533
|
+
renderItem={renderListItem}
|
|
534
|
+
onSelect={this._handleSelect}
|
|
535
|
+
isScrollTo
|
|
536
|
+
willActiveIndex={willActiveIndex!}
|
|
537
|
+
/>
|
|
538
|
+
</>
|
|
539
|
+
</div>
|
|
540
|
+
)
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
private _renderList = (config: ConfigProviderProps): ReactNode => {
|
|
545
|
+
const {
|
|
241
546
|
searchPlaceholder,
|
|
242
547
|
listHeight,
|
|
243
548
|
popupClassName,
|
|
244
549
|
renderCustomizedBottom,
|
|
550
|
+
isRenderDefaultBottom = false,
|
|
245
551
|
} = this.props
|
|
246
|
-
const { loading, searchValue, willActiveIndex } = this.state
|
|
247
|
-
|
|
552
|
+
const { loading, searchValue, willActiveIndex, isFilterDelete } = this.state
|
|
553
|
+
let filterData = this._getFilterData()
|
|
554
|
+
|
|
555
|
+
// 如果开启了过滤已删除商品功能,需要过滤掉已删除的商品
|
|
556
|
+
if (isFilterDelete) {
|
|
557
|
+
filterData = filterData
|
|
558
|
+
.map((group) => ({
|
|
559
|
+
...group,
|
|
560
|
+
children: group.children.filter((item) => !item.deleted),
|
|
561
|
+
}))
|
|
562
|
+
.filter((group) => group.children.length > 0)
|
|
563
|
+
}
|
|
564
|
+
|
|
248
565
|
return (
|
|
249
566
|
<ConfigProvider {...config}>
|
|
250
567
|
<div
|
|
@@ -260,32 +577,14 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
260
577
|
placeholder={searchPlaceholder}
|
|
261
578
|
/>
|
|
262
579
|
</div>
|
|
263
|
-
<div style={{ height: listHeight }}>
|
|
264
|
-
{loading && (
|
|
265
|
-
<Flex alignCenter justifyCenter className='gm-bg gm-padding-5'>
|
|
266
|
-
<Loading size='20px' />
|
|
267
|
-
</Flex>
|
|
268
|
-
)}
|
|
269
|
-
{!loading && !filterData.length && this._renderEmpty()}
|
|
270
|
-
{!loading && !!filterData.length && (
|
|
271
|
-
<ListBase
|
|
272
|
-
selected={selected.map((v) => v.value)}
|
|
273
|
-
data={filterData}
|
|
274
|
-
multiple={multiple}
|
|
275
|
-
isGroupList={isGroupList}
|
|
276
|
-
className='gm-border-0'
|
|
277
|
-
renderItem={renderListItem}
|
|
278
|
-
onSelect={this._handleSelect}
|
|
279
|
-
isScrollTo
|
|
280
|
-
willActiveIndex={willActiveIndex!}
|
|
281
|
-
style={{ height: listHeight }}
|
|
282
|
-
/>
|
|
283
|
-
)}
|
|
284
|
-
</div>
|
|
580
|
+
<div style={{ height: listHeight }}>{this.renderContent()}</div>
|
|
285
581
|
{!loading &&
|
|
286
582
|
!!filterData.length &&
|
|
287
|
-
renderCustomizedBottom
|
|
288
|
-
|
|
583
|
+
(renderCustomizedBottom
|
|
584
|
+
? renderCustomizedBottom(this._popoverRef, this.renderBottom)
|
|
585
|
+
: isRenderDefaultBottom
|
|
586
|
+
? this.renderBottom()
|
|
587
|
+
: null)}
|
|
289
588
|
</div>
|
|
290
589
|
</ConfigProvider>
|
|
291
590
|
)
|
|
@@ -299,15 +598,21 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
299
598
|
}
|
|
300
599
|
|
|
301
600
|
private _handlePopoverVisibleChange = (active: boolean) => {
|
|
302
|
-
if (active
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
this.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
601
|
+
if (active) {
|
|
602
|
+
this.setState({
|
|
603
|
+
previousSelected: this.props.selected,
|
|
604
|
+
previousCurrentSelected: this.props.selected,
|
|
605
|
+
})
|
|
606
|
+
if (this.props.searchOnActive) {
|
|
607
|
+
const searchValue = localStorage.getItem('_GM-PC_MORESELECT_SEARCHVALUE')
|
|
608
|
+
if (searchValue) {
|
|
609
|
+
this.setState({ searchValue })
|
|
610
|
+
setTimeout(() => {
|
|
611
|
+
// eslint-disable-next-line no-unused-expressions
|
|
612
|
+
this._inputRef.current?.select()
|
|
613
|
+
this._debounceDoSearch(searchValue)
|
|
614
|
+
}, 0)
|
|
615
|
+
}
|
|
311
616
|
}
|
|
312
617
|
}
|
|
313
618
|
}
|
|
@@ -325,7 +630,94 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
325
630
|
style,
|
|
326
631
|
popoverType,
|
|
327
632
|
children,
|
|
633
|
+
maxTagCount,
|
|
634
|
+
maxTagPlaceholder,
|
|
328
635
|
} = this.props
|
|
636
|
+
|
|
637
|
+
// 处理 maxTagCount 逻辑
|
|
638
|
+
const renderSelectedItems = () => {
|
|
639
|
+
if (!multiple || !maxTagCount || selected.length === 0) {
|
|
640
|
+
return selected.map((item) => (
|
|
641
|
+
<Flex key={item.value as any} className='gm-more-select-selected-item'>
|
|
642
|
+
<Popover
|
|
643
|
+
disabled={!this.props.isKeyboard}
|
|
644
|
+
type='hover'
|
|
645
|
+
popup={<div className='gm-padding-10'>{item.text}</div>}
|
|
646
|
+
>
|
|
647
|
+
<Flex flex column>
|
|
648
|
+
{renderSelected!(item)}
|
|
649
|
+
</Flex>
|
|
650
|
+
</Popover>
|
|
651
|
+
{multiple ? (
|
|
652
|
+
<SVGRemove
|
|
653
|
+
className='gm-cursor gm-more-select-clear-btn'
|
|
654
|
+
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
655
|
+
/>
|
|
656
|
+
) : (
|
|
657
|
+
!disabledClose && ( // 是否不限时清除按钮,仅单选可用
|
|
658
|
+
<SVGCloseCircle
|
|
659
|
+
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
660
|
+
className='gm-cursor gm-more-select-clear-btn'
|
|
661
|
+
/>
|
|
662
|
+
)
|
|
663
|
+
)}
|
|
664
|
+
</Flex>
|
|
665
|
+
))
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// 处理 maxTagCount 逻辑
|
|
669
|
+
const isResponsive = maxTagCount === 'responsive'
|
|
670
|
+
let displayCount: number
|
|
671
|
+
|
|
672
|
+
if (isResponsive) {
|
|
673
|
+
displayCount = this.state.displayCount
|
|
674
|
+
} else {
|
|
675
|
+
displayCount = maxTagCount as number
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
const itemsToShow = selected.slice(0, displayCount)
|
|
679
|
+
const omittedItems = selected.slice(displayCount)
|
|
680
|
+
const omittedCount = selected.length - displayCount
|
|
681
|
+
|
|
682
|
+
return (
|
|
683
|
+
<>
|
|
684
|
+
{itemsToShow.map((item) => (
|
|
685
|
+
<Flex key={item.value as any} className='gm-more-select-selected-item'>
|
|
686
|
+
<Popover
|
|
687
|
+
disabled={!this.props.isKeyboard}
|
|
688
|
+
type='hover'
|
|
689
|
+
popup={<div className='gm-padding-10'>{item.text}</div>}
|
|
690
|
+
>
|
|
691
|
+
<Flex flex column>
|
|
692
|
+
{renderSelected!(item)}
|
|
693
|
+
</Flex>
|
|
694
|
+
</Popover>
|
|
695
|
+
<SVGRemove
|
|
696
|
+
className='gm-cursor gm-more-select-clear-btn'
|
|
697
|
+
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
698
|
+
/>
|
|
699
|
+
</Flex>
|
|
700
|
+
))}
|
|
701
|
+
{omittedCount > 0 && (
|
|
702
|
+
<Flex
|
|
703
|
+
key='omitted'
|
|
704
|
+
className='gm-more-select-selected-item gm-more-select-omitted-item'
|
|
705
|
+
>
|
|
706
|
+
{maxTagPlaceholder ? (
|
|
707
|
+
maxTagPlaceholder(omittedItems, omittedCount)
|
|
708
|
+
) : (
|
|
709
|
+
<span className='gm-more-select-omitted-count'>+{omittedCount}...</span>
|
|
710
|
+
)}
|
|
711
|
+
</Flex>
|
|
712
|
+
)}
|
|
713
|
+
<SVGRemove
|
|
714
|
+
className='gm-cursor gm-more-select-clear-btn'
|
|
715
|
+
onClick={disabled ? _.noop : this._handleClearAll}
|
|
716
|
+
/>
|
|
717
|
+
</>
|
|
718
|
+
)
|
|
719
|
+
}
|
|
720
|
+
|
|
329
721
|
return (
|
|
330
722
|
<ConfigConsumer>
|
|
331
723
|
{(config) => (
|
|
@@ -340,7 +732,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
340
732
|
},
|
|
341
733
|
className
|
|
342
734
|
)}
|
|
343
|
-
style={style}
|
|
735
|
+
style={style as any}
|
|
344
736
|
>
|
|
345
737
|
<Popover
|
|
346
738
|
ref={this._popoverRef}
|
|
@@ -358,39 +750,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
358
750
|
className='gm-more-select-selected'
|
|
359
751
|
>
|
|
360
752
|
{selected.length !== 0 ? (
|
|
361
|
-
|
|
362
|
-
<Flex
|
|
363
|
-
key={item.value as any}
|
|
364
|
-
className='gm-more-select-selected-item'
|
|
365
|
-
>
|
|
366
|
-
<Popover
|
|
367
|
-
disabled={!this.props.isKeyboard}
|
|
368
|
-
type='hover'
|
|
369
|
-
popup={<div className='gm-padding-10'>{item.text}</div>}
|
|
370
|
-
>
|
|
371
|
-
<Flex flex column>
|
|
372
|
-
{renderSelected!(item)}
|
|
373
|
-
</Flex>
|
|
374
|
-
</Popover>
|
|
375
|
-
{multiple ? (
|
|
376
|
-
<SVGRemove
|
|
377
|
-
className='gm-cursor gm-more-select-clear-btn'
|
|
378
|
-
onClick={
|
|
379
|
-
disabled ? _.noop : this._handleClear.bind(this, item)
|
|
380
|
-
}
|
|
381
|
-
/>
|
|
382
|
-
) : (
|
|
383
|
-
!disabledClose && ( // 是否不限时清除按钮,仅单选可用
|
|
384
|
-
<SVGCloseCircle
|
|
385
|
-
onClick={
|
|
386
|
-
disabled ? _.noop : this._handleClear.bind(this, item)
|
|
387
|
-
}
|
|
388
|
-
className='gm-cursor gm-more-select-clear-btn'
|
|
389
|
-
/>
|
|
390
|
-
)
|
|
391
|
-
)}
|
|
392
|
-
</Flex>
|
|
393
|
-
))
|
|
753
|
+
renderSelectedItems()
|
|
394
754
|
) : (
|
|
395
755
|
// 加多个 避免对齐问题,有文本才有对齐
|
|
396
756
|
<div className='gm-text-placeholder'>{placeholder} </div>
|
|
@@ -8,10 +8,17 @@ class MoreSelect<V = any> extends Component<MoreSelectProps<V>> {
|
|
|
8
8
|
renderSelected: (item: MoreSelectDataItem<any>) => item.text,
|
|
9
9
|
renderListItem: (item: MoreSelectDataItem<any>) => item.text,
|
|
10
10
|
delay: 500,
|
|
11
|
-
listHeight: '
|
|
11
|
+
listHeight: '280px',
|
|
12
12
|
renderListFilterType: 'default',
|
|
13
13
|
popoverType: 'focus',
|
|
14
14
|
onKeyDown: _.noop,
|
|
15
|
+
/** 是否展示全选以及过滤已删除商品 */
|
|
16
|
+
isRenderDefaultBottom: false,
|
|
17
|
+
/** 是否展示已删除商品 */
|
|
18
|
+
isShowDeletedSwitch: true,
|
|
19
|
+
/** 是否展示全选 */
|
|
20
|
+
isShowCheckedAll: true,
|
|
21
|
+
showSelectedIcon: true,
|
|
15
22
|
}
|
|
16
23
|
|
|
17
24
|
private _moreSelectBaseRef = createRef<MoreSelectBase>()
|
|
@@ -85,6 +92,8 @@ class MoreSelect<V = any> extends Component<MoreSelectProps<V>> {
|
|
|
85
92
|
onSearch,
|
|
86
93
|
onClick,
|
|
87
94
|
renderListFilter,
|
|
95
|
+
maxTagCount,
|
|
96
|
+
maxTagPlaceholder,
|
|
88
97
|
...rest
|
|
89
98
|
} = this.props
|
|
90
99
|
let tempSelect = selected as MoreSelectDataItem<V>[]
|
|
@@ -129,6 +138,8 @@ class MoreSelect<V = any> extends Component<MoreSelectProps<V>> {
|
|
|
129
138
|
isGroupList={isGroupList}
|
|
130
139
|
onSearch={onSearch && this._handleSearch}
|
|
131
140
|
renderListFilter={renderListFilter && this._renderListFilter}
|
|
141
|
+
maxTagCount={maxTagCount}
|
|
142
|
+
maxTagPlaceholder={maxTagPlaceholder}
|
|
132
143
|
/>
|
|
133
144
|
)
|
|
134
145
|
}
|
|
@@ -318,6 +318,98 @@ export const ComMoreSelectWithIsGroupListMultiple = () => (
|
|
|
318
318
|
/>
|
|
319
319
|
)
|
|
320
320
|
|
|
321
|
+
export const ComMoreSelectWithMaxTagCount = () => {
|
|
322
|
+
// 创建一个包含多个选项的数据集
|
|
323
|
+
const manyOptions = [
|
|
324
|
+
{ value: 1, text: '选项1' },
|
|
325
|
+
{ value: 2, text: '选项2' },
|
|
326
|
+
{ value: 3, text: '选项3' },
|
|
327
|
+
{ value: 4, text: '选项4' },
|
|
328
|
+
{ value: 5, text: '选项5' },
|
|
329
|
+
{ value: 6, text: '选项6' },
|
|
330
|
+
{ value: 7, text: '选项7' },
|
|
331
|
+
{ value: 8, text: '选项8' },
|
|
332
|
+
]
|
|
333
|
+
|
|
334
|
+
// 预选多个选项
|
|
335
|
+
const preSelected = manyOptions.slice(0, 6)
|
|
336
|
+
|
|
337
|
+
return (
|
|
338
|
+
<div style={{ width: '300px' }}>
|
|
339
|
+
<h3>maxTagCount 示例</h3>
|
|
340
|
+
|
|
341
|
+
<div style={{ marginBottom: '20px' }}>
|
|
342
|
+
<h4>不使用 maxTagCount(显示所有选项)</h4>
|
|
343
|
+
<MoreSelect<number>
|
|
344
|
+
multiple
|
|
345
|
+
data={manyOptions}
|
|
346
|
+
selected={preSelected}
|
|
347
|
+
onSelect={(selected) => {
|
|
348
|
+
console.log('不限制显示数量:', selected)
|
|
349
|
+
}}
|
|
350
|
+
/>
|
|
351
|
+
</div>
|
|
352
|
+
|
|
353
|
+
<div style={{ marginBottom: '20px' }}>
|
|
354
|
+
<h4>maxTagCount={2}(最多显示2个选项)</h4>
|
|
355
|
+
<MoreSelect<number>
|
|
356
|
+
multiple
|
|
357
|
+
maxTagCount={2}
|
|
358
|
+
data={manyOptions}
|
|
359
|
+
selected={preSelected}
|
|
360
|
+
onSelect={(selected) => {
|
|
361
|
+
console.log('最多显示2个:', selected)
|
|
362
|
+
}}
|
|
363
|
+
/>
|
|
364
|
+
</div>
|
|
365
|
+
|
|
366
|
+
<div style={{ marginBottom: '20px' }}>
|
|
367
|
+
<h4>maxTagCount={3}(最多显示3个选项)</h4>
|
|
368
|
+
<MoreSelect<number>
|
|
369
|
+
multiple
|
|
370
|
+
maxTagCount={3}
|
|
371
|
+
data={manyOptions}
|
|
372
|
+
selected={preSelected}
|
|
373
|
+
onSelect={(selected) => {
|
|
374
|
+
console.log('最多显示3个:', selected)
|
|
375
|
+
}}
|
|
376
|
+
/>
|
|
377
|
+
</div>
|
|
378
|
+
|
|
379
|
+
<div style={{ marginBottom: '20px' }}>
|
|
380
|
+
<h4>maxTagCount=responsive(响应式模式)</h4>
|
|
381
|
+
<MoreSelect<number>
|
|
382
|
+
multiple
|
|
383
|
+
maxTagCount='responsive'
|
|
384
|
+
data={manyOptions}
|
|
385
|
+
selected={preSelected}
|
|
386
|
+
onSelect={(selected) => {
|
|
387
|
+
console.log('响应式模式:', selected)
|
|
388
|
+
}}
|
|
389
|
+
/>
|
|
390
|
+
</div>
|
|
391
|
+
|
|
392
|
+
<div style={{ marginBottom: '20px' }}>
|
|
393
|
+
<h4>自定义 maxTagPlaceholder</h4>
|
|
394
|
+
<MoreSelect<number>
|
|
395
|
+
multiple
|
|
396
|
+
maxTagCount={2}
|
|
397
|
+
maxTagPlaceholder={(omittedValues, omittedCount) => (
|
|
398
|
+
<span style={{ color: '#1890ff', fontWeight: 'bold' }}>
|
|
399
|
+
还有{omittedCount}项未显示
|
|
400
|
+
</span>
|
|
401
|
+
)}
|
|
402
|
+
data={manyOptions}
|
|
403
|
+
selected={preSelected}
|
|
404
|
+
onSelect={(selected) => {
|
|
405
|
+
console.log('自定义占位符:', selected)
|
|
406
|
+
}}
|
|
407
|
+
/>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
)
|
|
411
|
+
}
|
|
412
|
+
|
|
321
413
|
export default {
|
|
322
414
|
title: '表单/MoreSelect',
|
|
323
415
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { Popover } from '@gm-pc/react'
|
|
2
1
|
import { CSSProperties, ReactNode, KeyboardEvent } from 'react'
|
|
2
|
+
import { Popover } from '../popover'
|
|
3
3
|
|
|
4
4
|
/** 普通的数据格式 */
|
|
5
5
|
interface MoreSelectDataItem<V extends string | number = string> {
|
|
6
6
|
value: V
|
|
7
7
|
text: string
|
|
8
8
|
disabled?: boolean
|
|
9
|
+
/** 是否已删除 */
|
|
10
|
+
deleted?: boolean
|
|
9
11
|
[key: string]: any
|
|
10
12
|
}
|
|
11
13
|
|
|
@@ -36,10 +38,13 @@ interface MoreSelectCommonProps<V extends string | number = string> {
|
|
|
36
38
|
renderListItem?(value: MoreSelectDataItem<V>, index: number): ReactNode
|
|
37
39
|
|
|
38
40
|
/** 自定义popup底部渲染 */
|
|
39
|
-
renderCustomizedBottom?(
|
|
41
|
+
renderCustomizedBottom?(
|
|
42
|
+
ref: React.RefObject<Popover>,
|
|
43
|
+
defaultBottom: () => ReactNode
|
|
44
|
+
): ReactNode
|
|
40
45
|
|
|
41
46
|
/**
|
|
42
|
-
*
|
|
47
|
+
* 自定义"空状态"渲染
|
|
43
48
|
*
|
|
44
49
|
* 若函数返回 undefined 则使用默认的空状态
|
|
45
50
|
*/
|
|
@@ -60,6 +65,25 @@ interface MoreSelectCommonProps<V extends string | number = string> {
|
|
|
60
65
|
/** 目前为了 keyboard */
|
|
61
66
|
isKeyboard?: boolean
|
|
62
67
|
onKeyDown?(event: KeyboardEvent): void
|
|
68
|
+
|
|
69
|
+
/** 最多显示的选中项数量,超出部分会折叠 */
|
|
70
|
+
maxTagCount?: number | 'responsive'
|
|
71
|
+
/** 自定义超出 maxTagCount 时显示的内容 */
|
|
72
|
+
maxTagPlaceholder?: (
|
|
73
|
+
omittedValues: MoreSelectDataItem<V>[],
|
|
74
|
+
omittedCount: number
|
|
75
|
+
) => ReactNode
|
|
76
|
+
|
|
77
|
+
/** 是否展示全选以及过滤已删除商品 */
|
|
78
|
+
isRenderDefaultBottom?: boolean
|
|
79
|
+
/** 是否展示已删除商品 */
|
|
80
|
+
isShowDeletedSwitch?: boolean
|
|
81
|
+
/** 是否展示全选 */
|
|
82
|
+
isShowCheckedAll?: boolean
|
|
83
|
+
/** 当设置 maxTagCount 的时候的宽度, 根据这个去计算显示内容 */
|
|
84
|
+
tagItemWidth?: number
|
|
85
|
+
/** +N 显示的宽度 */
|
|
86
|
+
omittedTagWidth?: number
|
|
63
87
|
}
|
|
64
88
|
|
|
65
89
|
interface MoreSelectBaseProps<V extends string | number = string>
|
|
@@ -69,7 +93,7 @@ interface MoreSelectBaseProps<V extends string | number = string>
|
|
|
69
93
|
onSelect(selected: MoreSelectDataItem<V>[]): void
|
|
70
94
|
|
|
71
95
|
/** 搜索回调 */
|
|
72
|
-
onSearch?(searchWord: string, data: MoreSelectGroupDataItem<V>[]): Promise<
|
|
96
|
+
onSearch?(searchWord: string, data: MoreSelectGroupDataItem<V>[]): Promise<any> | any
|
|
73
97
|
/** 点击回调 */
|
|
74
98
|
onClick?(selected: MoreSelectSelected<V>[]): void
|
|
75
99
|
|
|
@@ -80,6 +104,13 @@ interface MoreSelectBaseProps<V extends string | number = string>
|
|
|
80
104
|
): MoreSelectGroupDataItem<V>[]
|
|
81
105
|
/** 是否在active的时候搜索,订单业务相关,searchValue放在localstorage */
|
|
82
106
|
searchOnActive?: boolean
|
|
107
|
+
/** 是否展示全选以及过滤已删除商品 */
|
|
108
|
+
isRenderDefaultBottom?: boolean
|
|
109
|
+
/** 是否展示已删除商品 */
|
|
110
|
+
isShowDeletedSwitch?: boolean
|
|
111
|
+
/** 是否展示全选 */
|
|
112
|
+
isShowCheckedAll?: boolean
|
|
113
|
+
showSelectedIcon?: boolean
|
|
83
114
|
}
|
|
84
115
|
|
|
85
116
|
type MoreSelectData<V extends string | number = string> =
|
|
@@ -98,7 +129,7 @@ interface MoreSelectProps<V extends string | number = string>
|
|
|
98
129
|
onSelect?(selected?: MoreSelectSelected<V>): void
|
|
99
130
|
onChange?(value: V | V[]): void
|
|
100
131
|
/** 搜索回调 */
|
|
101
|
-
onSearch?(searchWord: string, data: MoreSelectData<V>): Promise<void> |
|
|
132
|
+
onSearch?(searchWord: string, data: MoreSelectData<V>): Promise<void | any> | any
|
|
102
133
|
/** 点击回调 */
|
|
103
134
|
onClick?(selected: MoreSelectSelected<V>[]): void
|
|
104
135
|
|
|
@@ -13,7 +13,6 @@ const Nav: FC<NavProps> = ({
|
|
|
13
13
|
onPushCreate,
|
|
14
14
|
showActive,
|
|
15
15
|
other,
|
|
16
|
-
otherFirst,
|
|
17
16
|
className,
|
|
18
17
|
style,
|
|
19
18
|
footerImage,
|
|
@@ -79,8 +78,6 @@ const Nav: FC<NavProps> = ({
|
|
|
79
78
|
>
|
|
80
79
|
<div className='gm-nav-logo'>{logo}</div>
|
|
81
80
|
<Flex flex column className='gm-nav-content'>
|
|
82
|
-
{otherFirst}
|
|
83
|
-
|
|
84
81
|
{data.map((one) => (
|
|
85
82
|
<NavItem
|
|
86
83
|
key={one.link}
|
|
@@ -11,6 +11,7 @@ interface SwitchProps {
|
|
|
11
11
|
onChange?(checked: boolean): void
|
|
12
12
|
className?: string
|
|
13
13
|
style?: CSSProperties
|
|
14
|
+
size?: 'small' | 'middle'
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
interface SwitchState {
|
|
@@ -26,10 +27,11 @@ class Switch extends Component<SwitchProps, SwitchState> {
|
|
|
26
27
|
on: '',
|
|
27
28
|
off: '',
|
|
28
29
|
onChange: _.noop,
|
|
30
|
+
size: 'middle',
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
readonly state: SwitchState = {
|
|
32
|
-
checked: this.props.checked,
|
|
34
|
+
checked: !!this.props.checked,
|
|
33
35
|
labelWidth: null,
|
|
34
36
|
isReady: false,
|
|
35
37
|
}
|
|
@@ -53,7 +55,7 @@ class Switch extends Component<SwitchProps, SwitchState> {
|
|
|
53
55
|
UNSAFE_componentWillReceiveProps(nextProps: Readonly<SwitchProps>) {
|
|
54
56
|
if ('checked' in nextProps) {
|
|
55
57
|
this.setState({
|
|
56
|
-
checked: nextProps.checked,
|
|
58
|
+
checked: !!nextProps.checked,
|
|
57
59
|
})
|
|
58
60
|
}
|
|
59
61
|
}
|
|
@@ -82,6 +84,7 @@ class Switch extends Component<SwitchProps, SwitchState> {
|
|
|
82
84
|
disabled,
|
|
83
85
|
on,
|
|
84
86
|
off,
|
|
87
|
+
size,
|
|
85
88
|
...rest
|
|
86
89
|
} = this.props
|
|
87
90
|
|
|
@@ -101,8 +104,9 @@ class Switch extends Component<SwitchProps, SwitchState> {
|
|
|
101
104
|
ref={this._inputOffRef}
|
|
102
105
|
className={classNames('gm-switch gm-switch-' + type, className, {
|
|
103
106
|
disabled,
|
|
107
|
+
[`gm-switch-${size}`]: size,
|
|
104
108
|
})}
|
|
105
|
-
style={style}
|
|
109
|
+
style={style as any}
|
|
106
110
|
data-attr={this.state.labelWidth}
|
|
107
111
|
disabled={disabled}
|
|
108
112
|
type='checkbox'
|