@gm-pc/react 1.27.5-beta.0 → 1.28.0-alpha.0
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/loading/types.ts +1 -1
- package/src/component/more_select/base.tsx +379 -147
- package/src/component/more_select/more_select.tsx +11 -1
- package/src/component/more_select/stories.tsx +92 -0
- package/src/component/more_select/style.less +4 -12
- package/src/component/more_select/types.ts +35 -7
- package/src/component/pagination/left.tsx +11 -7
- 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.28.0-alpha.0",
|
|
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.28.0-alpha.0",
|
|
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": "5349cb6157a22e000f906b3e19fa944ecd48d8d8"
|
|
52
52
|
}
|
|
@@ -20,13 +20,17 @@ 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 {
|
|
25
|
-
|
|
26
|
+
canClear?: boolean
|
|
27
|
+
searchValue: string
|
|
26
28
|
loading: boolean
|
|
27
29
|
/* keyboard 默认第一个位置 */
|
|
28
30
|
willActiveIndex: number | null
|
|
29
|
-
|
|
31
|
+
isCheckedAll: boolean
|
|
32
|
+
isFilterDelete: boolean
|
|
33
|
+
displayCount: number
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
// @todo keydown item disabled
|
|
@@ -39,10 +43,12 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
39
43
|
static renderListFilterPinYin = renderListFilterPinYin
|
|
40
44
|
|
|
41
45
|
readonly state: MoreSelectBaseState = {
|
|
42
|
-
searchValue:
|
|
46
|
+
searchValue: '',
|
|
43
47
|
loading: false,
|
|
44
48
|
willActiveIndex: this.props.isKeyboard ? 0 : null,
|
|
45
|
-
|
|
49
|
+
isCheckedAll: false,
|
|
50
|
+
isFilterDelete: true,
|
|
51
|
+
displayCount: 0,
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
private _isUnmounted = false
|
|
@@ -50,6 +56,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
50
56
|
private _selectionRef = createRef<HTMLDivElement>()
|
|
51
57
|
private _popoverRef = createRef<Popover>()
|
|
52
58
|
private _inputRef = createRef<HTMLInputElement>()
|
|
59
|
+
private _resizeObserver: ResizeObserver | null = null
|
|
53
60
|
|
|
54
61
|
private _filterData: MoreSelectGroupDataItem<V>[] | undefined
|
|
55
62
|
|
|
@@ -64,8 +71,42 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
componentDidMount() {
|
|
75
|
+
const { maxTagCount, tagItemWidth = 80, omittedTagWidth = 45 } = this.props
|
|
76
|
+
if (maxTagCount === 'responsive' && this._selectionRef.current) {
|
|
77
|
+
// HACK: 首次计算
|
|
78
|
+
setTimeout(() => {
|
|
79
|
+
if (this._selectionRef.current) {
|
|
80
|
+
const { width } = this._selectionRef.current.getBoundingClientRect()
|
|
81
|
+
const availableWidth = width - omittedTagWidth
|
|
82
|
+
const newDisplayCount = Math.floor(availableWidth / tagItemWidth)
|
|
83
|
+
if (this.state.displayCount !== newDisplayCount) {
|
|
84
|
+
this.setState({ displayCount: newDisplayCount > 0 ? newDisplayCount : 0 })
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}, 0)
|
|
88
|
+
|
|
89
|
+
this._resizeObserver = new ResizeObserver((entries) => {
|
|
90
|
+
for (const entry of entries) {
|
|
91
|
+
const { width } = entry.contentRect
|
|
92
|
+
// Estimate item width, let's say 80px.
|
|
93
|
+
const availableWidth = width - omittedTagWidth
|
|
94
|
+
const newDisplayCount = Math.floor(availableWidth / tagItemWidth)
|
|
95
|
+
|
|
96
|
+
if (this.state.displayCount !== newDisplayCount) {
|
|
97
|
+
this.setState({ displayCount: newDisplayCount })
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
this._resizeObserver.observe(this._selectionRef.current)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
67
105
|
componentWillUnmount() {
|
|
68
|
-
this._isUnmounted =
|
|
106
|
+
this._isUnmounted = true
|
|
107
|
+
if (this._resizeObserver) {
|
|
108
|
+
this._resizeObserver.disconnect()
|
|
109
|
+
}
|
|
69
110
|
}
|
|
70
111
|
|
|
71
112
|
public apiDoFocus = (): void => {
|
|
@@ -132,13 +173,15 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
132
173
|
event: ChangeEvent<HTMLInputElement>,
|
|
133
174
|
isInitSearch?: boolean
|
|
134
175
|
): void => {
|
|
176
|
+
const { onSearch } = this.props
|
|
135
177
|
const searchValue = event.target.value
|
|
136
178
|
this.setState({ searchValue })
|
|
137
|
-
this.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
179
|
+
if (onSearch && !this._isUnmounted) {
|
|
180
|
+
this.setState({
|
|
181
|
+
loading: true,
|
|
182
|
+
})
|
|
141
183
|
}
|
|
184
|
+
this._debounceDoSearch(searchValue)
|
|
142
185
|
setTimeout(() => {
|
|
143
186
|
// eslint-disable-next-line no-unused-expressions
|
|
144
187
|
isInitSearch && this._inputRef.current?.select()
|
|
@@ -151,14 +194,12 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
151
194
|
private _doSearch = (query: string): void => {
|
|
152
195
|
const { onSearch, data = [] } = this.props
|
|
153
196
|
if (!this._isUnmounted && onSearch) {
|
|
154
|
-
const result = onSearch(query, data)
|
|
155
|
-
if (!result) {
|
|
156
|
-
return
|
|
157
|
-
}
|
|
158
197
|
this.setState({ loading: true })
|
|
159
|
-
|
|
198
|
+
const result = onSearch(query, data)
|
|
160
199
|
Promise.resolve(result).finally(() => {
|
|
161
|
-
|
|
200
|
+
setTimeout(() => {
|
|
201
|
+
this.setState({ loading: false })
|
|
202
|
+
}, 50)
|
|
162
203
|
})
|
|
163
204
|
}
|
|
164
205
|
}
|
|
@@ -172,7 +213,13 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
172
213
|
onSelect(willSelected)
|
|
173
214
|
}
|
|
174
215
|
|
|
175
|
-
private
|
|
216
|
+
private _handleClearAll = (event: MouseEvent): void => {
|
|
217
|
+
event.stopPropagation()
|
|
218
|
+
const { onSelect = _.noop } = this.props
|
|
219
|
+
onSelect([])
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private _handlePopupKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {
|
|
176
223
|
const { onKeyDown } = this.props
|
|
177
224
|
let willActiveIndex = this.state.willActiveIndex as number
|
|
178
225
|
if (!onKeyDown) {
|
|
@@ -207,9 +254,9 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
207
254
|
}
|
|
208
255
|
|
|
209
256
|
private _getFilterData = () => {
|
|
210
|
-
const { data = [], renderListFilter, renderListFilterType } = this.props
|
|
257
|
+
const { data = [], renderListFilter, renderListFilterType, onSearch } = this.props
|
|
211
258
|
const { searchValue } = this.state
|
|
212
|
-
let filterData: MoreSelectGroupDataItem<V>[]
|
|
259
|
+
let filterData: MoreSelectGroupDataItem<V>[] = []
|
|
213
260
|
if (renderListFilter) {
|
|
214
261
|
filterData = renderListFilter(data, searchValue)
|
|
215
262
|
} else if (renderListFilterType === 'pinyin') {
|
|
@@ -238,68 +285,246 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
238
285
|
)
|
|
239
286
|
}
|
|
240
287
|
|
|
241
|
-
|
|
242
|
-
const {
|
|
243
|
-
|
|
288
|
+
renderBottom = () => {
|
|
289
|
+
const {
|
|
290
|
+
selected = [],
|
|
291
|
+
isShowDeletedSwitch = true,
|
|
292
|
+
isShowCheckedAll = true,
|
|
293
|
+
} = this.props
|
|
294
|
+
const { isCheckedAll, isFilterDelete } = this.state
|
|
295
|
+
const flatFilterData = this._getFlatFilterData()
|
|
296
|
+
|
|
297
|
+
// 根据过滤状态决定是否过滤已删除商品
|
|
298
|
+
const availableData = isFilterDelete
|
|
299
|
+
? flatFilterData.filter((item) => !item.deleted)
|
|
300
|
+
: flatFilterData
|
|
301
|
+
|
|
302
|
+
// 检查是否所有可用数据都被选中
|
|
303
|
+
const allSelected =
|
|
304
|
+
availableData.length > 0 &&
|
|
305
|
+
availableData.every((item) =>
|
|
306
|
+
selected.some((selectedItem) => selectedItem.value === item.value)
|
|
307
|
+
)
|
|
308
|
+
|
|
244
309
|
return (
|
|
245
|
-
<
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
310
|
+
<Flex
|
|
311
|
+
justifyBetween
|
|
312
|
+
className='tw-p-[8px] gm-more-select-default-bottom'
|
|
313
|
+
alignCenter
|
|
314
|
+
>
|
|
315
|
+
{isShowCheckedAll && (
|
|
316
|
+
<Checkbox
|
|
317
|
+
checked={allSelected}
|
|
318
|
+
onChange={(e) => {
|
|
319
|
+
const isChecked = e.target.checked
|
|
320
|
+
this.setState({
|
|
321
|
+
isCheckedAll: isChecked,
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
if (isChecked) {
|
|
325
|
+
// 全选当前过滤后的可用数据
|
|
326
|
+
const valuesToSelect = availableData.map((item) => item.value)
|
|
327
|
+
const prevSelectedValue = selected.map((item) => item.value)
|
|
328
|
+
// console.log(valuesToSelect, selected)
|
|
329
|
+
const newSelected = Array.from(
|
|
330
|
+
new Set([...prevSelectedValue, ...valuesToSelect])
|
|
331
|
+
)
|
|
332
|
+
this._handleSelect(newSelected)
|
|
333
|
+
} else {
|
|
334
|
+
// 取消全选 - 只反勾选availableData的数据
|
|
335
|
+
const { selected = [] } = this.props
|
|
336
|
+
const availableValues = availableData.map((item) => item.value)
|
|
337
|
+
const newSelected = selected.filter(
|
|
338
|
+
(item) => !availableValues.includes(item.value)
|
|
339
|
+
)
|
|
340
|
+
this._handleSelect(newSelected.map((item) => item.value))
|
|
341
|
+
}
|
|
342
|
+
}}
|
|
343
|
+
>
|
|
344
|
+
全选({availableData.length})
|
|
345
|
+
</Checkbox>
|
|
346
|
+
)}
|
|
347
|
+
{isShowDeletedSwitch && (
|
|
348
|
+
<Flex alignCenter>
|
|
349
|
+
<Flex row>
|
|
350
|
+
<Switch
|
|
351
|
+
size='small'
|
|
352
|
+
style={{ width: 32 }}
|
|
353
|
+
checked={isFilterDelete}
|
|
354
|
+
onChange={(open) => {
|
|
355
|
+
this.setState({
|
|
356
|
+
isFilterDelete: open,
|
|
357
|
+
})
|
|
358
|
+
// if (isCheckedAll) {
|
|
359
|
+
// const newAvailableData = open
|
|
360
|
+
// ? flatFilterData.filter((item) => !item.deleted)
|
|
361
|
+
// : flatFilterData
|
|
362
|
+
|
|
363
|
+
// const valuesToSelect = newAvailableData.map((item) => item.value)
|
|
364
|
+
// this._handleSelect(valuesToSelect)
|
|
365
|
+
// }
|
|
366
|
+
}}
|
|
367
|
+
/>
|
|
368
|
+
</Flex>
|
|
369
|
+
<span className='gm-margin-left-5'>过滤已删除数据</span>
|
|
370
|
+
</Flex>
|
|
371
|
+
)}
|
|
372
|
+
</Flex>
|
|
254
373
|
)
|
|
255
374
|
}
|
|
256
375
|
|
|
376
|
+
renderContent = () => {
|
|
377
|
+
const { loading, willActiveIndex, isFilterDelete } = this.state
|
|
378
|
+
|
|
379
|
+
if (loading) {
|
|
380
|
+
return (
|
|
381
|
+
<Flex alignCenter justifyCenter className='gm-bg gm-padding-5'>
|
|
382
|
+
<Loading size='20px' />
|
|
383
|
+
</Flex>
|
|
384
|
+
)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
let filterData = this._getFilterData()
|
|
388
|
+
|
|
389
|
+
// 如果开启了过滤已删除商品功能,需要过滤掉已删除的商品
|
|
390
|
+
if (isFilterDelete) {
|
|
391
|
+
filterData = filterData
|
|
392
|
+
.map((group) => ({
|
|
393
|
+
...group,
|
|
394
|
+
children: group.children.filter((item) => !item.deleted),
|
|
395
|
+
}))
|
|
396
|
+
.filter((group) => group.children.length > 0)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (!loading && filterData.length === 0) {
|
|
400
|
+
return this._renderEmpty()
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (!loading && filterData.length > 0) {
|
|
404
|
+
const {
|
|
405
|
+
selected = [],
|
|
406
|
+
multiple,
|
|
407
|
+
isGroupList,
|
|
408
|
+
renderListItem,
|
|
409
|
+
listHeight,
|
|
410
|
+
} = this.props
|
|
411
|
+
|
|
412
|
+
const selectedValues = new Set(selected?.map((v) => v.value))
|
|
413
|
+
|
|
414
|
+
// 分离已勾选和未勾选的数据
|
|
415
|
+
const availableGroups: MoreSelectGroupDataItem<V>[] = []
|
|
416
|
+
// 已选中区域直接使用 selected 构建,不受筛选影响
|
|
417
|
+
const selectedGroups: MoreSelectGroupDataItem<V>[] = []
|
|
418
|
+
|
|
419
|
+
if (multiple) {
|
|
420
|
+
filterData.forEach((group) => {
|
|
421
|
+
const availableChildren = group.children.filter(
|
|
422
|
+
(item) => !selectedValues.has(item.value)
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
if (availableChildren.length > 0) {
|
|
426
|
+
availableGroups.push({
|
|
427
|
+
...group,
|
|
428
|
+
children: availableChildren,
|
|
429
|
+
})
|
|
430
|
+
}
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
if (selected.length > 0) {
|
|
434
|
+
selectedGroups.push({
|
|
435
|
+
label: '',
|
|
436
|
+
children: selected,
|
|
437
|
+
})
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return (
|
|
442
|
+
<div style={{ height: listHeight, overflow: 'auto' }}>
|
|
443
|
+
{selected.length > 0 && multiple && (
|
|
444
|
+
<>
|
|
445
|
+
<div className='gm-more-select-section-title gm-padding-5 gm-text-desc gm-text-12'>
|
|
446
|
+
已选中
|
|
447
|
+
</div>
|
|
448
|
+
<ListBase
|
|
449
|
+
selected={selected.map((v) => v.value)}
|
|
450
|
+
data={selectedGroups}
|
|
451
|
+
multiple={multiple}
|
|
452
|
+
isGroupList={false}
|
|
453
|
+
className='gm-border-0'
|
|
454
|
+
renderItem={renderListItem}
|
|
455
|
+
onSelect={this._handleSelect}
|
|
456
|
+
isScrollTo={false}
|
|
457
|
+
/>
|
|
458
|
+
</>
|
|
459
|
+
)}
|
|
460
|
+
<>
|
|
461
|
+
{multiple && (
|
|
462
|
+
<div className='gm-more-select-section-title gm-padding-5 gm-text-desc gm-text-12'>
|
|
463
|
+
未选中
|
|
464
|
+
</div>
|
|
465
|
+
)}
|
|
466
|
+
|
|
467
|
+
<ListBase
|
|
468
|
+
selected={selected?.map((v) => v.value)}
|
|
469
|
+
data={multiple ? availableGroups : filterData}
|
|
470
|
+
multiple={multiple}
|
|
471
|
+
isGroupList={isGroupList}
|
|
472
|
+
className='gm-border-0'
|
|
473
|
+
renderItem={renderListItem}
|
|
474
|
+
onSelect={this._handleSelect}
|
|
475
|
+
isScrollTo
|
|
476
|
+
willActiveIndex={willActiveIndex!}
|
|
477
|
+
/>
|
|
478
|
+
</>
|
|
479
|
+
</div>
|
|
480
|
+
)
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
257
484
|
private _renderList = (config: ConfigProviderProps): ReactNode => {
|
|
258
485
|
const {
|
|
259
|
-
|
|
260
|
-
multiple,
|
|
261
|
-
isGroupList,
|
|
262
|
-
renderListItem,
|
|
486
|
+
searchPlaceholder,
|
|
263
487
|
listHeight,
|
|
264
488
|
popupClassName,
|
|
265
489
|
renderCustomizedBottom,
|
|
266
|
-
|
|
490
|
+
isRenderDefaultBottom = false,
|
|
267
491
|
} = this.props
|
|
268
|
-
const { loading, willActiveIndex } = this.state
|
|
269
|
-
|
|
492
|
+
const { loading, searchValue, willActiveIndex, isFilterDelete } = this.state
|
|
493
|
+
let filterData = this._getFilterData()
|
|
494
|
+
|
|
495
|
+
// 如果开启了过滤已删除商品功能,需要过滤掉已删除的商品
|
|
496
|
+
if (isFilterDelete) {
|
|
497
|
+
filterData = filterData
|
|
498
|
+
.map((group) => ({
|
|
499
|
+
...group,
|
|
500
|
+
children: group.children.filter((item) => !item.deleted),
|
|
501
|
+
}))
|
|
502
|
+
.filter((group) => group.children.length > 0)
|
|
503
|
+
}
|
|
504
|
+
|
|
270
505
|
return (
|
|
271
506
|
<ConfigProvider {...config}>
|
|
272
507
|
<div
|
|
273
508
|
className={classNames('gm-more-select-popup', popupClassName)}
|
|
274
509
|
onKeyDown={this._handlePopupKeyDown}
|
|
275
510
|
>
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
{!loading && !!filterData.length && (
|
|
285
|
-
<ListBase
|
|
286
|
-
selected={selected.map((v) => v.value)}
|
|
287
|
-
data={filterData}
|
|
288
|
-
multiple={multiple}
|
|
289
|
-
isGroupList={isGroupList}
|
|
290
|
-
className='gm-border-0'
|
|
291
|
-
renderItem={renderListItem}
|
|
292
|
-
onSelect={this._handleSelect}
|
|
293
|
-
isScrollTo
|
|
294
|
-
willActiveIndex={willActiveIndex!}
|
|
295
|
-
style={{ height: listHeight }}
|
|
296
|
-
/>
|
|
297
|
-
)}
|
|
511
|
+
<div className='gm-more-select-popup-input'>
|
|
512
|
+
<Input
|
|
513
|
+
ref={this._inputRef}
|
|
514
|
+
autoFocus
|
|
515
|
+
value={searchValue}
|
|
516
|
+
onChange={this._handleChange}
|
|
517
|
+
placeholder={searchPlaceholder}
|
|
518
|
+
/>
|
|
298
519
|
</div>
|
|
520
|
+
<div style={{ height: listHeight }}>{this.renderContent()}</div>
|
|
299
521
|
{!loading &&
|
|
300
522
|
!!filterData.length &&
|
|
301
|
-
renderCustomizedBottom
|
|
302
|
-
|
|
523
|
+
(renderCustomizedBottom
|
|
524
|
+
? renderCustomizedBottom(this._popoverRef, this.renderBottom)
|
|
525
|
+
: isRenderDefaultBottom
|
|
526
|
+
? this.renderBottom()
|
|
527
|
+
: null)}
|
|
303
528
|
</div>
|
|
304
529
|
</ConfigProvider>
|
|
305
530
|
)
|
|
@@ -313,16 +538,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
313
538
|
}
|
|
314
539
|
|
|
315
540
|
private _handlePopoverVisibleChange = (active: boolean) => {
|
|
316
|
-
if (this.props.
|
|
317
|
-
this.setState({
|
|
318
|
-
isOpen: active,
|
|
319
|
-
})
|
|
320
|
-
if (!this.props.multiple && !active) {
|
|
321
|
-
this.setState({ searchValue: undefined })
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (active && this.props.searchOnActive && !this.props.isSameAntd) {
|
|
541
|
+
if (active && this.props.searchOnActive) {
|
|
326
542
|
const searchValue = localStorage.getItem('_GM-PC_MORESELECT_SEARCHVALUE')
|
|
327
543
|
if (searchValue) {
|
|
328
544
|
this.setState({ searchValue })
|
|
@@ -348,10 +564,93 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
348
564
|
style,
|
|
349
565
|
popoverType,
|
|
350
566
|
children,
|
|
351
|
-
|
|
352
|
-
|
|
567
|
+
maxTagCount,
|
|
568
|
+
maxTagPlaceholder,
|
|
353
569
|
} = this.props
|
|
354
|
-
|
|
570
|
+
|
|
571
|
+
// 处理 maxTagCount 逻辑
|
|
572
|
+
const renderSelectedItems = () => {
|
|
573
|
+
if (!multiple || !maxTagCount || selected.length === 0) {
|
|
574
|
+
return selected.map((item) => (
|
|
575
|
+
<Flex key={item.value as any} className='gm-more-select-selected-item'>
|
|
576
|
+
<Popover
|
|
577
|
+
disabled={!this.props.isKeyboard}
|
|
578
|
+
type='hover'
|
|
579
|
+
popup={<div className='gm-padding-10'>{item.text}</div>}
|
|
580
|
+
>
|
|
581
|
+
<Flex flex column>
|
|
582
|
+
{renderSelected!(item)}
|
|
583
|
+
</Flex>
|
|
584
|
+
</Popover>
|
|
585
|
+
{multiple ? (
|
|
586
|
+
<SVGRemove
|
|
587
|
+
className='gm-cursor gm-more-select-clear-btn'
|
|
588
|
+
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
589
|
+
/>
|
|
590
|
+
) : (
|
|
591
|
+
!disabledClose && ( // 是否不限时清除按钮,仅单选可用
|
|
592
|
+
<SVGCloseCircle
|
|
593
|
+
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
594
|
+
className='gm-cursor gm-more-select-clear-btn'
|
|
595
|
+
/>
|
|
596
|
+
)
|
|
597
|
+
)}
|
|
598
|
+
</Flex>
|
|
599
|
+
))
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// 处理 maxTagCount 逻辑
|
|
603
|
+
const isResponsive = maxTagCount === 'responsive'
|
|
604
|
+
let displayCount: number
|
|
605
|
+
|
|
606
|
+
if (isResponsive) {
|
|
607
|
+
displayCount = this.state.displayCount
|
|
608
|
+
} else {
|
|
609
|
+
displayCount = maxTagCount as number
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
const itemsToShow = selected.slice(0, displayCount)
|
|
613
|
+
const omittedItems = selected.slice(displayCount)
|
|
614
|
+
const omittedCount = selected.length - displayCount
|
|
615
|
+
|
|
616
|
+
return (
|
|
617
|
+
<>
|
|
618
|
+
{itemsToShow.map((item) => (
|
|
619
|
+
<Flex key={item.value as any} className='gm-more-select-selected-item'>
|
|
620
|
+
<Popover
|
|
621
|
+
disabled={!this.props.isKeyboard}
|
|
622
|
+
type='hover'
|
|
623
|
+
popup={<div className='gm-padding-10'>{item.text}</div>}
|
|
624
|
+
>
|
|
625
|
+
<Flex flex column>
|
|
626
|
+
{renderSelected!(item)}
|
|
627
|
+
</Flex>
|
|
628
|
+
</Popover>
|
|
629
|
+
<SVGRemove
|
|
630
|
+
className='gm-cursor gm-more-select-clear-btn'
|
|
631
|
+
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
632
|
+
/>
|
|
633
|
+
</Flex>
|
|
634
|
+
))}
|
|
635
|
+
{omittedCount > 0 && (
|
|
636
|
+
<Flex
|
|
637
|
+
key='omitted'
|
|
638
|
+
className='gm-more-select-selected-item gm-more-select-omitted-item'
|
|
639
|
+
>
|
|
640
|
+
{maxTagPlaceholder ? (
|
|
641
|
+
maxTagPlaceholder(omittedItems, omittedCount)
|
|
642
|
+
) : (
|
|
643
|
+
<span className='gm-more-select-omitted-count'>+{omittedCount}...</span>
|
|
644
|
+
)}
|
|
645
|
+
</Flex>
|
|
646
|
+
)}
|
|
647
|
+
<SVGRemove
|
|
648
|
+
className='gm-cursor gm-more-select-clear-btn'
|
|
649
|
+
onClick={disabled ? _.noop : this._handleClearAll}
|
|
650
|
+
/>
|
|
651
|
+
</>
|
|
652
|
+
)
|
|
653
|
+
}
|
|
355
654
|
|
|
356
655
|
return (
|
|
357
656
|
<ConfigConsumer>
|
|
@@ -367,15 +666,13 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
367
666
|
},
|
|
368
667
|
className
|
|
369
668
|
)}
|
|
370
|
-
style={style}
|
|
669
|
+
style={style as any}
|
|
371
670
|
>
|
|
372
671
|
<Popover
|
|
373
672
|
ref={this._popoverRef}
|
|
374
673
|
type={popoverType}
|
|
375
674
|
popup={() => this._renderList(config)}
|
|
376
|
-
disabled={
|
|
377
|
-
disabled || (!isSameAntd ? false : this.state.searchValue === undefined)
|
|
378
|
-
}
|
|
675
|
+
disabled={disabled}
|
|
379
676
|
isInPopup={isInPopup}
|
|
380
677
|
onVisibleChange={this._handlePopoverVisibleChange}
|
|
381
678
|
>
|
|
@@ -384,78 +681,13 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
384
681
|
ref={this._selectionRef}
|
|
385
682
|
tabIndex={0}
|
|
386
683
|
wrap
|
|
387
|
-
className=
|
|
388
|
-
'gm-more-select-selected': true,
|
|
389
|
-
'gm-more-select-selected-antd': isSameAntd,
|
|
390
|
-
})}
|
|
684
|
+
className='gm-more-select-selected'
|
|
391
685
|
>
|
|
392
686
|
{selected.length !== 0 ? (
|
|
393
|
-
|
|
394
|
-
<Flex
|
|
395
|
-
key={item.value as any}
|
|
396
|
-
className='gm-more-select-selected-item'
|
|
397
|
-
alignCenter
|
|
398
|
-
>
|
|
399
|
-
<Popover
|
|
400
|
-
disabled={!this.props.isKeyboard}
|
|
401
|
-
type='hover'
|
|
402
|
-
popup={<div className='gm-padding-10'>{item.text}</div>}
|
|
403
|
-
>
|
|
404
|
-
<Flex flex column>
|
|
405
|
-
{isSameAntd ? (
|
|
406
|
-
<div className='gm-more-select-popup-input'>
|
|
407
|
-
<Input
|
|
408
|
-
ref={this._inputRef}
|
|
409
|
-
value={
|
|
410
|
-
!this.state.isOpen
|
|
411
|
-
? renderSelected!(item)
|
|
412
|
-
: searchValue
|
|
413
|
-
}
|
|
414
|
-
onChange={this._handleChange}
|
|
415
|
-
placeholder={searchPlaceholder}
|
|
416
|
-
className='gm-more-select-popup-input-no-border'
|
|
417
|
-
/>
|
|
418
|
-
</div>
|
|
419
|
-
) : (
|
|
420
|
-
renderSelected!(item)
|
|
421
|
-
)}
|
|
422
|
-
</Flex>
|
|
423
|
-
</Popover>
|
|
424
|
-
{multiple ? (
|
|
425
|
-
<SVGRemove
|
|
426
|
-
className='gm-cursor gm-more-select-clear-btn'
|
|
427
|
-
onClick={
|
|
428
|
-
disabled ? _.noop : this._handleClear.bind(this, item)
|
|
429
|
-
}
|
|
430
|
-
/>
|
|
431
|
-
) : (
|
|
432
|
-
!disabledClose && ( // 是否不限时清除按钮,仅单选可用
|
|
433
|
-
<SVGCloseCircle
|
|
434
|
-
onClick={
|
|
435
|
-
disabled ? _.noop : this._handleClear.bind(this, item)
|
|
436
|
-
}
|
|
437
|
-
className='gm-cursor gm-more-select-clear-btn'
|
|
438
|
-
/>
|
|
439
|
-
)
|
|
440
|
-
)}
|
|
441
|
-
</Flex>
|
|
442
|
-
))
|
|
687
|
+
renderSelectedItems()
|
|
443
688
|
) : (
|
|
444
689
|
// 加多个 避免对齐问题,有文本才有对齐
|
|
445
|
-
|
|
446
|
-
{isSameAntd ? (
|
|
447
|
-
<Input
|
|
448
|
-
ref={this._inputRef}
|
|
449
|
-
value={searchValue}
|
|
450
|
-
onChange={this._handleChange}
|
|
451
|
-
placeholder={searchPlaceholder}
|
|
452
|
-
className='gm-more-select-popup-input-no-border'
|
|
453
|
-
/>
|
|
454
|
-
) : (
|
|
455
|
-
<div className='gm-text-placeholder'>{placeholder} </div>
|
|
456
|
-
)}
|
|
457
|
-
</>
|
|
458
|
-
//
|
|
690
|
+
<div className='gm-text-placeholder'>{placeholder} </div>
|
|
459
691
|
)}
|
|
460
692
|
</Flex>
|
|
461
693
|
)}
|
|
@@ -8,10 +8,16 @@ 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,
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
private _moreSelectBaseRef = createRef<MoreSelectBase>()
|
|
@@ -85,6 +91,8 @@ class MoreSelect<V = any> extends Component<MoreSelectProps<V>> {
|
|
|
85
91
|
onSearch,
|
|
86
92
|
onClick,
|
|
87
93
|
renderListFilter,
|
|
94
|
+
maxTagCount,
|
|
95
|
+
maxTagPlaceholder,
|
|
88
96
|
...rest
|
|
89
97
|
} = this.props
|
|
90
98
|
let tempSelect = selected as MoreSelectDataItem<V>[]
|
|
@@ -129,6 +137,8 @@ class MoreSelect<V = any> extends Component<MoreSelectProps<V>> {
|
|
|
129
137
|
isGroupList={isGroupList}
|
|
130
138
|
onSearch={onSearch && this._handleSearch}
|
|
131
139
|
renderListFilter={renderListFilter && this._renderListFilter}
|
|
140
|
+
maxTagCount={maxTagCount}
|
|
141
|
+
maxTagPlaceholder={maxTagPlaceholder}
|
|
132
142
|
/>
|
|
133
143
|
)
|
|
134
144
|
}
|
|
@@ -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
|
}
|
|
@@ -14,15 +14,10 @@
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
.gm-more-select-selected-antd {
|
|
18
|
-
padding: 0 12px;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
17
|
.gm-more-select-clear-btn {
|
|
22
18
|
position: absolute;
|
|
23
|
-
right:
|
|
24
|
-
top:
|
|
25
|
-
transform: translateY(-50%);
|
|
19
|
+
right: 5px;
|
|
20
|
+
top: 7px;
|
|
26
21
|
cursor: pointer;
|
|
27
22
|
color: var(--gm-color-desc);
|
|
28
23
|
}
|
|
@@ -76,9 +71,6 @@
|
|
|
76
71
|
}
|
|
77
72
|
}
|
|
78
73
|
|
|
79
|
-
.gm-more-select-
|
|
80
|
-
border:
|
|
81
|
-
border-radius: 0 !important;
|
|
82
|
-
padding: 0 !important;
|
|
83
|
-
box-shadow: none !important;
|
|
74
|
+
.gm-more-select-default-bottom {
|
|
75
|
+
border-top: 1px solid var(--gm-color-border);
|
|
84
76
|
}
|
|
@@ -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,8 +104,12 @@ interface MoreSelectBaseProps<V extends string | number = string>
|
|
|
80
104
|
): MoreSelectGroupDataItem<V>[]
|
|
81
105
|
/** 是否在active的时候搜索,订单业务相关,searchValue放在localstorage */
|
|
82
106
|
searchOnActive?: boolean
|
|
83
|
-
/**
|
|
84
|
-
|
|
107
|
+
/** 是否展示全选以及过滤已删除商品 */
|
|
108
|
+
isRenderDefaultBottom?: boolean
|
|
109
|
+
/** 是否展示已删除商品 */
|
|
110
|
+
isShowDeletedSwitch?: boolean
|
|
111
|
+
/** 是否展示全选 */
|
|
112
|
+
isShowCheckedAll?: boolean
|
|
85
113
|
}
|
|
86
114
|
|
|
87
115
|
type MoreSelectData<V extends string | number = string> =
|
|
@@ -100,7 +128,7 @@ interface MoreSelectProps<V extends string | number = string>
|
|
|
100
128
|
onSelect?(selected?: MoreSelectSelected<V>): void
|
|
101
129
|
onChange?(value: V | V[]): void
|
|
102
130
|
/** 搜索回调 */
|
|
103
|
-
onSearch?(searchWord: string, data: MoreSelectData<V>): Promise<void> |
|
|
131
|
+
onSearch?(searchWord: string, data: MoreSelectData<V>): Promise<void | any> | any
|
|
104
132
|
/** 点击回调 */
|
|
105
133
|
onClick?(selected: MoreSelectSelected<V>[]): void
|
|
106
134
|
|
|
@@ -6,13 +6,17 @@ import _ from 'lodash'
|
|
|
6
6
|
import { getLocale } from '@gm-pc/locales'
|
|
7
7
|
|
|
8
8
|
function getLimitData(limit: number, pageSizeOptions?: string[]) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
{ value:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
let limitData = []
|
|
10
|
+
if (pageSizeOptions) {
|
|
11
|
+
limitData = pageSizeOptions.map((v) => ({ value: Number(v), text: v }))
|
|
12
|
+
} else {
|
|
13
|
+
limitData = [
|
|
14
|
+
{ value: limit, text: limit + '' },
|
|
15
|
+
{ value: 10, text: '10' },
|
|
16
|
+
{ value: 20, text: '20' },
|
|
17
|
+
{ value: 50, text: '50' },
|
|
18
|
+
]
|
|
19
|
+
}
|
|
16
20
|
|
|
17
21
|
return _.orderBy(
|
|
18
22
|
_.uniqBy(limitData, (v) => v.value),
|
|
@@ -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'
|