-
Notifications
You must be signed in to change notification settings - Fork 138
/
CreateSelectSegment.tsx
127 lines (106 loc) Β· 4.17 KB
/
CreateSelectSegment.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/
import type { PanelRenderContext, Segment, SelectPanelData, SelectSearchField } from '../types'
import type { ProSearchLocale } from '@idux/pro/locales'
import { isNil, toString } from 'lodash-es'
import { type VKey, convertArray } from '@idux/cdk/utils'
import SelectPanel from '../panel/SelectPanel'
import { filterDataSource, getSelectDataSourceKeys, getSelectableCommonParams } from '../utils'
const defaultSeparator = '|'
export function createSelectSegment(
prefixCls: string,
config: SelectSearchField['fieldConfig'],
locale: ProSearchLocale,
): Segment<VKey | VKey[] | undefined> {
const { dataSource, separator, searchable, showSelectAll, searchFn, multiple, virtual, onSearch } = config
const panelRenderer = (context: PanelRenderContext<VKey | VKey[] | undefined>) => {
const { setValue, ok, cancel, setOnKeyDown, renderLocation } = context
const keys = getSelectDataSourceKeys(dataSource)
const { panelValue, searchInput, handleChange } = getSelectableCommonParams(
context,
!!multiple,
renderLocation === 'individual' ? separator ?? defaultSeparator : undefined,
!multiple || renderLocation === 'quick-select-panel',
)
const handleSelectAll = () => {
const selectableKeys = getSelectDataSourceKeys(filterDataSource(dataSource, option => !option.disabled))
setValue(selectableKeys.length !== panelValue?.length ? selectableKeys : undefined)
}
return (
<SelectPanel
value={panelValue}
allSelected={panelValue && panelValue.length > 0 && keys.length <= panelValue.length}
dataSource={dataSource}
multiple={multiple}
virtual={virtual}
autoHeight={renderLocation === 'quick-select-panel'}
setOnKeyDown={setOnKeyDown}
showSelectAll={renderLocation === 'individual' && showSelectAll}
showFooter={renderLocation === 'individual'}
setInactiveOnMouseLeave={renderLocation === 'quick-select-panel'}
searchValue={searchable ? searchInput : ''}
searchFn={searchFn}
onChange={handleChange}
onSelectAllClick={handleSelectAll}
onConfirm={ok}
onCancel={cancel}
onSearch={onSearch}
/>
)
}
return {
name: 'select',
inputClassName: [`${prefixCls}-select-segment-input`],
containerClassName: [`${prefixCls}-select-segment-container`],
parse: input => parseInput(input, config, locale.allSelected),
format: value => formatValue(value, config, locale.allSelected),
panelRenderer,
}
}
function parseInput(
input: string,
config: SelectSearchField['fieldConfig'],
allSelected: string,
): VKey | VKey[] | undefined {
const { concludeAllSelected, separator, dataSource, multiple } = config
const trimedInput = input.trim()
const keys =
concludeAllSelected && trimedInput === allSelected
? dataSource.map(data => data.key)
: getKeyByLabels(dataSource, trimedInput.split(separator ?? defaultSeparator))
return multiple ? (keys.length > 0 ? keys : undefined) : keys[0]
}
function formatValue(
value: VKey | VKey[] | undefined,
config: SelectSearchField['fieldConfig'],
allSelected: string,
): string {
const { concludeAllSelected, dataSource, separator } = config
if (isNil(value)) {
return ''
}
const values = convertArray(value)
if (concludeAllSelected && values.length > 0 && values.length >= dataSource.length) {
return allSelected
}
return getLabelByKeys(dataSource, convertArray(value)).join(` ${separator ?? defaultSeparator} `)
}
function getLabelByKeys(dataSource: SelectPanelData[], keys: VKey[]): (string | number)[] {
if (keys.length <= 0) {
return []
}
return filterDataSource(dataSource, option => keys.includes(option.key)).map(data => data.label)
}
function getKeyByLabels(dataSource: SelectPanelData[], labels: string[]): VKey[] {
if (labels.length <= 0) {
return []
}
return filterDataSource(
dataSource,
option => labels.findIndex(label => label.trim() === toString(option.label).trim()) > -1,
).map(data => data.key)
}