@gm-pc/react 1.28.1-beta.1 → 1.28.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/more_select/base.tsx +77 -26
- package/src/component/more_select/more_select.tsx +1 -0
- package/src/component/more_select/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gm-pc/react",
|
|
3
|
-
"version": "1.28.1-beta.
|
|
3
|
+
"version": "1.28.1-beta.2",
|
|
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.28.1-beta.
|
|
27
|
+
"@gm-pc/locales": "^1.28.1-beta.2",
|
|
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": "16774306f2bd425112cf4279f4aa844b5ec9d2ee"
|
|
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> {
|
|
@@ -31,6 +31,9 @@ interface MoreSelectBaseState {
|
|
|
31
31
|
isCheckedAll: boolean
|
|
32
32
|
isFilterDelete: boolean
|
|
33
33
|
displayCount: number
|
|
34
|
+
// isPopupJustOpened: boolean
|
|
35
|
+
previousSelected?: MoreSelectDataItem<V>[]
|
|
36
|
+
previousCurrentSelected: MoreSelectDataItem<V>[]
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
// @todo keydown item disabled
|
|
@@ -49,6 +52,8 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
49
52
|
isCheckedAll: false,
|
|
50
53
|
isFilterDelete: true,
|
|
51
54
|
displayCount: 0,
|
|
55
|
+
previousSelected: [],
|
|
56
|
+
previousCurrentSelected: [],
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
private _isUnmounted = false
|
|
@@ -176,6 +181,10 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
176
181
|
const { onSearch } = this.props
|
|
177
182
|
const searchValue = event.target.value
|
|
178
183
|
this.setState({ searchValue })
|
|
184
|
+
this.setState({
|
|
185
|
+
previousSelected: this.props.selected,
|
|
186
|
+
previousCurrentSelected: this.props.selected,
|
|
187
|
+
})
|
|
179
188
|
if (onSearch && !this._isUnmounted) {
|
|
180
189
|
this.setState({
|
|
181
190
|
loading: true,
|
|
@@ -206,8 +215,10 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
206
215
|
|
|
207
216
|
private _debounceDoSearch = _.debounce(this._doSearch, this.props.delay)
|
|
208
217
|
|
|
209
|
-
private _handleClear = (clearItem: MoreSelectDataItem<V>, event
|
|
210
|
-
event
|
|
218
|
+
private _handleClear = (clearItem: MoreSelectDataItem<V>, event?: MouseEvent): void => {
|
|
219
|
+
if (event) {
|
|
220
|
+
event.stopPropagation()
|
|
221
|
+
}
|
|
211
222
|
const { onSelect = _.noop, selected = [] } = this.props
|
|
212
223
|
const willSelected = selected.filter((item) => item.value !== clearItem.value)
|
|
213
224
|
onSelect(willSelected)
|
|
@@ -299,9 +310,6 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
299
310
|
? flatFilterData.filter((item) => !item.deleted)
|
|
300
311
|
: flatFilterData
|
|
301
312
|
|
|
302
|
-
// 计算总数:availableData + selected,过滤重复值
|
|
303
|
-
const totalCount = _.uniqBy([...availableData, ...selected], 'value').length
|
|
304
|
-
|
|
305
313
|
// 检查是否所有可用数据都被选中
|
|
306
314
|
const allSelected =
|
|
307
315
|
availableData.length > 0 &&
|
|
@@ -333,6 +341,12 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
333
341
|
new Set([...prevSelectedValue, ...valuesToSelect])
|
|
334
342
|
)
|
|
335
343
|
this._handleSelect(newSelected)
|
|
344
|
+
// 更新 previousCurrentSelected
|
|
345
|
+
this.setState({
|
|
346
|
+
previousCurrentSelected: Array.from(
|
|
347
|
+
new Set([...this.state.previousCurrentSelected, ...availableData])
|
|
348
|
+
),
|
|
349
|
+
})
|
|
336
350
|
} else {
|
|
337
351
|
// 取消全选 - 只反勾选availableData的数据
|
|
338
352
|
const { selected = [] } = this.props
|
|
@@ -341,10 +355,16 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
341
355
|
(item) => !availableValues.includes(item.value)
|
|
342
356
|
)
|
|
343
357
|
this._handleSelect(newSelected.map((item) => item.value))
|
|
358
|
+
// 更新 previousCurrentSelected
|
|
359
|
+
this.setState({
|
|
360
|
+
previousCurrentSelected: this.state.previousCurrentSelected.filter(
|
|
361
|
+
(item) => !availableValues.includes(item.value)
|
|
362
|
+
),
|
|
363
|
+
})
|
|
344
364
|
}
|
|
345
365
|
}}
|
|
346
366
|
>
|
|
347
|
-
全选({
|
|
367
|
+
全选({availableData.length})
|
|
348
368
|
</Checkbox>
|
|
349
369
|
)}
|
|
350
370
|
{isShowDeletedSwitch && (
|
|
@@ -410,9 +430,11 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
410
430
|
isGroupList,
|
|
411
431
|
renderListItem,
|
|
412
432
|
listHeight,
|
|
433
|
+
showSelectedIcon,
|
|
413
434
|
} = this.props
|
|
435
|
+
const { previousSelected = [], previousCurrentSelected = [] } = this.state
|
|
414
436
|
|
|
415
|
-
const selectedValues = new Set(
|
|
437
|
+
const selectedValues = new Set(previousSelected?.map((v) => v.value))
|
|
416
438
|
|
|
417
439
|
// 分离已勾选和未勾选的数据
|
|
418
440
|
const availableGroups: MoreSelectGroupDataItem<V>[] = []
|
|
@@ -421,9 +443,10 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
421
443
|
|
|
422
444
|
if (multiple) {
|
|
423
445
|
filterData.forEach((group) => {
|
|
424
|
-
const availableChildren = group.children.filter(
|
|
425
|
-
|
|
426
|
-
|
|
446
|
+
const availableChildren = group.children.filter((item) => {
|
|
447
|
+
// return true
|
|
448
|
+
return !selectedValues.has(item.value)
|
|
449
|
+
})
|
|
427
450
|
|
|
428
451
|
if (availableChildren.length > 0) {
|
|
429
452
|
availableGroups.push({
|
|
@@ -433,43 +456,65 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
433
456
|
}
|
|
434
457
|
})
|
|
435
458
|
|
|
436
|
-
if (
|
|
459
|
+
if (previousSelected.length > 0) {
|
|
437
460
|
selectedGroups.push({
|
|
438
461
|
label: '',
|
|
439
|
-
children:
|
|
462
|
+
children: previousSelected,
|
|
440
463
|
})
|
|
441
464
|
}
|
|
442
465
|
}
|
|
443
466
|
|
|
444
467
|
return (
|
|
445
468
|
<div style={{ height: listHeight, overflow: 'auto' }}>
|
|
446
|
-
{
|
|
469
|
+
{previousSelected.length > 0 && multiple && !this.state.searchValue && (
|
|
447
470
|
<>
|
|
448
471
|
<div className='gm-more-select-section-title gm-padding-5 gm-text-desc gm-text-12'>
|
|
449
472
|
已选中
|
|
450
473
|
</div>
|
|
451
474
|
<ListBase
|
|
452
|
-
|
|
475
|
+
showSelectedIcon={showSelectedIcon}
|
|
476
|
+
selected={previousCurrentSelected.map((v) => v.value)}
|
|
453
477
|
data={selectedGroups}
|
|
454
478
|
multiple={multiple}
|
|
455
479
|
isGroupList={false}
|
|
456
480
|
className='gm-border-0'
|
|
457
481
|
renderItem={renderListItem}
|
|
458
|
-
onSelect={
|
|
482
|
+
onSelect={(v, target) => {
|
|
483
|
+
this._handleSelect(v)
|
|
484
|
+
// 判断是勾选还是反选:如果 v 中包含 target.value,说明是勾选操作;否则是反选操作
|
|
485
|
+
const isChecked = v.includes(target.value)
|
|
486
|
+
if (isChecked) {
|
|
487
|
+
// 勾选:添加到 previousCurrentSelected
|
|
488
|
+
this.setState({
|
|
489
|
+
previousCurrentSelected: [
|
|
490
|
+
...this.state.previousCurrentSelected,
|
|
491
|
+
target,
|
|
492
|
+
],
|
|
493
|
+
})
|
|
494
|
+
} else {
|
|
495
|
+
// 反选:从 previousCurrentSelected 中移除
|
|
496
|
+
this.setState({
|
|
497
|
+
previousCurrentSelected: this.state.previousCurrentSelected?.filter(
|
|
498
|
+
(item) => item.value !== target.value
|
|
499
|
+
),
|
|
500
|
+
})
|
|
501
|
+
}
|
|
502
|
+
}}
|
|
459
503
|
isScrollTo={false}
|
|
460
504
|
/>
|
|
461
505
|
</>
|
|
462
506
|
)}
|
|
463
507
|
<>
|
|
464
|
-
{multiple && (
|
|
508
|
+
{multiple && !this.state.searchValue && (
|
|
465
509
|
<div className='gm-more-select-section-title gm-padding-5 gm-text-desc gm-text-12'>
|
|
466
510
|
未选中
|
|
467
511
|
</div>
|
|
468
512
|
)}
|
|
469
513
|
|
|
470
514
|
<ListBase
|
|
515
|
+
showSelectedIcon={showSelectedIcon}
|
|
471
516
|
selected={selected?.map((v) => v.value)}
|
|
472
|
-
data={multiple ? availableGroups : filterData}
|
|
517
|
+
data={multiple && !this.state.searchValue ? availableGroups : filterData}
|
|
473
518
|
multiple={multiple}
|
|
474
519
|
isGroupList={isGroupList}
|
|
475
520
|
className='gm-border-0'
|
|
@@ -541,15 +586,21 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
541
586
|
}
|
|
542
587
|
|
|
543
588
|
private _handlePopoverVisibleChange = (active: boolean) => {
|
|
544
|
-
if (active
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
this.
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
589
|
+
if (active) {
|
|
590
|
+
this.setState({
|
|
591
|
+
previousSelected: this.props.selected,
|
|
592
|
+
previousCurrentSelected: this.props.selected,
|
|
593
|
+
})
|
|
594
|
+
if (this.props.searchOnActive) {
|
|
595
|
+
const searchValue = localStorage.getItem('_GM-PC_MORESELECT_SEARCHVALUE')
|
|
596
|
+
if (searchValue) {
|
|
597
|
+
this.setState({ searchValue })
|
|
598
|
+
setTimeout(() => {
|
|
599
|
+
// eslint-disable-next-line no-unused-expressions
|
|
600
|
+
this._inputRef.current?.select()
|
|
601
|
+
this._debounceDoSearch(searchValue)
|
|
602
|
+
}, 0)
|
|
603
|
+
}
|
|
553
604
|
}
|
|
554
605
|
}
|
|
555
606
|
}
|