@gm-pc/react 1.28.0-beta.4 → 1.29.0-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/loading/types.ts +1 -1
- package/src/component/more_select/base.tsx +75 -292
- package/src/component/more_select/more_select.tsx +0 -10
- package/src/component/more_select/stories.tsx +0 -92
- package/src/component/more_select/style.less +0 -4
- package/src/component/more_select/types.ts +5 -35
- package/src/component/nav/nav.tsx +3 -0
- package/src/component/nav/types.ts +1 -0
- package/src/component/switch/style.less +0 -4
- package/src/component/switch/switch.tsx +3 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gm-pc/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.0-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.
|
|
27
|
+
"@gm-pc/locales": "^1.29.0-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": "71157a29a2684a64359ea15e50eb43d64cee12f5"
|
|
52
52
|
}
|
|
@@ -20,16 +20,12 @@ 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
|
-
|
|
24
|
-
import { Switch } from '../switch'
|
|
23
|
+
|
|
25
24
|
interface MoreSelectBaseState {
|
|
26
25
|
searchValue: string
|
|
27
26
|
loading: boolean
|
|
28
27
|
/* keyboard 默认第一个位置 */
|
|
29
28
|
willActiveIndex: number | null
|
|
30
|
-
isCheckedAll: boolean
|
|
31
|
-
isFilterDelete: boolean
|
|
32
|
-
displayCount: number
|
|
33
29
|
}
|
|
34
30
|
|
|
35
31
|
// @todo keydown item disabled
|
|
@@ -45,9 +41,6 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
45
41
|
searchValue: '',
|
|
46
42
|
loading: false,
|
|
47
43
|
willActiveIndex: this.props.isKeyboard ? 0 : null,
|
|
48
|
-
isCheckedAll: false,
|
|
49
|
-
isFilterDelete: true,
|
|
50
|
-
displayCount: 0,
|
|
51
44
|
}
|
|
52
45
|
|
|
53
46
|
private _isUnmounted = false
|
|
@@ -55,7 +48,6 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
55
48
|
private _selectionRef = createRef<HTMLDivElement>()
|
|
56
49
|
private _popoverRef = createRef<Popover>()
|
|
57
50
|
private _inputRef = createRef<HTMLInputElement>()
|
|
58
|
-
private _resizeObserver: ResizeObserver | null = null
|
|
59
51
|
|
|
60
52
|
private _filterData: MoreSelectGroupDataItem<V>[] | undefined
|
|
61
53
|
|
|
@@ -70,42 +62,8 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
70
62
|
}
|
|
71
63
|
}
|
|
72
64
|
|
|
73
|
-
componentDidMount() {
|
|
74
|
-
const { maxTagCount, tagItemWidth = 80, omittedTagWidth = 45 } = this.props
|
|
75
|
-
if (maxTagCount === 'responsive' && this._selectionRef.current) {
|
|
76
|
-
// HACK: 首次计算
|
|
77
|
-
setTimeout(() => {
|
|
78
|
-
if (this._selectionRef.current) {
|
|
79
|
-
const { width } = this._selectionRef.current.getBoundingClientRect()
|
|
80
|
-
const availableWidth = width - omittedTagWidth
|
|
81
|
-
const newDisplayCount = Math.floor(availableWidth / tagItemWidth)
|
|
82
|
-
if (this.state.displayCount !== newDisplayCount) {
|
|
83
|
-
this.setState({ displayCount: newDisplayCount > 0 ? newDisplayCount : 0 })
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}, 0)
|
|
87
|
-
|
|
88
|
-
this._resizeObserver = new ResizeObserver((entries) => {
|
|
89
|
-
for (const entry of entries) {
|
|
90
|
-
const { width } = entry.contentRect
|
|
91
|
-
// Estimate item width, let's say 80px.
|
|
92
|
-
const availableWidth = width - omittedTagWidth
|
|
93
|
-
const newDisplayCount = Math.floor(availableWidth / tagItemWidth)
|
|
94
|
-
|
|
95
|
-
if (this.state.displayCount !== newDisplayCount) {
|
|
96
|
-
this.setState({ displayCount: newDisplayCount })
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
this._resizeObserver.observe(this._selectionRef.current)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
65
|
componentWillUnmount() {
|
|
105
|
-
this._isUnmounted =
|
|
106
|
-
if (this._resizeObserver) {
|
|
107
|
-
this._resizeObserver.disconnect()
|
|
108
|
-
}
|
|
66
|
+
this._isUnmounted = false
|
|
109
67
|
}
|
|
110
68
|
|
|
111
69
|
public apiDoFocus = (): void => {
|
|
@@ -172,14 +130,8 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
172
130
|
event: ChangeEvent<HTMLInputElement>,
|
|
173
131
|
isInitSearch?: boolean
|
|
174
132
|
): void => {
|
|
175
|
-
const { onSearch } = this.props
|
|
176
133
|
const searchValue = event.target.value
|
|
177
134
|
this.setState({ searchValue })
|
|
178
|
-
if (onSearch && !this._isUnmounted) {
|
|
179
|
-
this.setState({
|
|
180
|
-
loading: true,
|
|
181
|
-
})
|
|
182
|
-
}
|
|
183
135
|
this._debounceDoSearch(searchValue)
|
|
184
136
|
setTimeout(() => {
|
|
185
137
|
// eslint-disable-next-line no-unused-expressions
|
|
@@ -193,12 +145,14 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
193
145
|
private _doSearch = (query: string): void => {
|
|
194
146
|
const { onSearch, data = [] } = this.props
|
|
195
147
|
if (!this._isUnmounted && onSearch) {
|
|
196
|
-
this.setState({ loading: true })
|
|
197
148
|
const result = onSearch(query, data)
|
|
149
|
+
if (!result) {
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
this.setState({ loading: true })
|
|
153
|
+
|
|
198
154
|
Promise.resolve(result).finally(() => {
|
|
199
|
-
|
|
200
|
-
this.setState({ loading: false })
|
|
201
|
-
}, 50)
|
|
155
|
+
this.setState({ loading: false })
|
|
202
156
|
})
|
|
203
157
|
}
|
|
204
158
|
}
|
|
@@ -212,7 +166,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
212
166
|
onSelect(willSelected)
|
|
213
167
|
}
|
|
214
168
|
|
|
215
|
-
private _handlePopupKeyDown = (event: KeyboardEvent
|
|
169
|
+
private _handlePopupKeyDown = (event: KeyboardEvent): void => {
|
|
216
170
|
const { onKeyDown } = this.props
|
|
217
171
|
let willActiveIndex = this.state.willActiveIndex as number
|
|
218
172
|
if (!onKeyDown) {
|
|
@@ -247,9 +201,9 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
247
201
|
}
|
|
248
202
|
|
|
249
203
|
private _getFilterData = () => {
|
|
250
|
-
const { data = [], renderListFilter, renderListFilterType
|
|
204
|
+
const { data = [], renderListFilter, renderListFilterType } = this.props
|
|
251
205
|
const { searchValue } = this.state
|
|
252
|
-
let filterData: MoreSelectGroupDataItem<V>[]
|
|
206
|
+
let filterData: MoreSelectGroupDataItem<V>[]
|
|
253
207
|
if (renderListFilter) {
|
|
254
208
|
filterData = renderListFilter(data, searchValue)
|
|
255
209
|
} else if (renderListFilterType === 'pinyin') {
|
|
@@ -278,157 +232,19 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
278
232
|
)
|
|
279
233
|
}
|
|
280
234
|
|
|
281
|
-
renderBottom = () => {
|
|
282
|
-
const {
|
|
283
|
-
selected = [],
|
|
284
|
-
isShowDeletedSwitch = true,
|
|
285
|
-
isShowCheckedAll = true,
|
|
286
|
-
} = this.props
|
|
287
|
-
const { isCheckedAll, isFilterDelete } = this.state
|
|
288
|
-
const flatFilterData = this._getFlatFilterData()
|
|
289
|
-
|
|
290
|
-
// 根据过滤状态决定是否过滤已删除商品
|
|
291
|
-
const availableData = isFilterDelete
|
|
292
|
-
? flatFilterData.filter((item) => !item.deleted)
|
|
293
|
-
: flatFilterData
|
|
294
|
-
|
|
295
|
-
// 检查是否所有可用数据都被选中
|
|
296
|
-
const allSelected =
|
|
297
|
-
availableData.length > 0 &&
|
|
298
|
-
availableData.every((item) =>
|
|
299
|
-
selected.some((selectedItem) => selectedItem.value === item.value)
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
return (
|
|
303
|
-
<Flex
|
|
304
|
-
justifyBetween
|
|
305
|
-
className='tw-p-[8px] gm-more-select-default-bottom'
|
|
306
|
-
alignCenter
|
|
307
|
-
>
|
|
308
|
-
{isShowCheckedAll && (
|
|
309
|
-
<Checkbox
|
|
310
|
-
checked={allSelected}
|
|
311
|
-
onChange={(e) => {
|
|
312
|
-
const isChecked = e.target.checked
|
|
313
|
-
this.setState({
|
|
314
|
-
isCheckedAll: isChecked,
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
if (isChecked) {
|
|
318
|
-
// 全选当前过滤后的可用数据
|
|
319
|
-
const valuesToSelect = availableData.map((item) => item.value)
|
|
320
|
-
this._handleSelect(valuesToSelect)
|
|
321
|
-
} else {
|
|
322
|
-
// 取消全选
|
|
323
|
-
this._handleSelect([])
|
|
324
|
-
}
|
|
325
|
-
}}
|
|
326
|
-
>
|
|
327
|
-
全选({availableData.length})
|
|
328
|
-
</Checkbox>
|
|
329
|
-
)}
|
|
330
|
-
{isShowDeletedSwitch && (
|
|
331
|
-
<Flex alignCenter>
|
|
332
|
-
<Flex row>
|
|
333
|
-
<Switch
|
|
334
|
-
size='small'
|
|
335
|
-
style={{ width: 32 }}
|
|
336
|
-
checked={isFilterDelete}
|
|
337
|
-
onChange={(open) => {
|
|
338
|
-
this.setState({
|
|
339
|
-
isFilterDelete: open,
|
|
340
|
-
})
|
|
341
|
-
if (isCheckedAll) {
|
|
342
|
-
const newAvailableData = open
|
|
343
|
-
? flatFilterData.filter((item) => !item.deleted)
|
|
344
|
-
: flatFilterData
|
|
345
|
-
|
|
346
|
-
const valuesToSelect = newAvailableData.map((item) => item.value)
|
|
347
|
-
this._handleSelect(valuesToSelect)
|
|
348
|
-
}
|
|
349
|
-
}}
|
|
350
|
-
/>
|
|
351
|
-
</Flex>
|
|
352
|
-
<span className='gm-margin-left-5'>过滤已删除数据</span>
|
|
353
|
-
</Flex>
|
|
354
|
-
)}
|
|
355
|
-
</Flex>
|
|
356
|
-
)
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
renderContent = () => {
|
|
360
|
-
const { loading, willActiveIndex, isFilterDelete } = this.state
|
|
361
|
-
|
|
362
|
-
if (loading) {
|
|
363
|
-
return (
|
|
364
|
-
<Flex alignCenter justifyCenter className='gm-bg gm-padding-5'>
|
|
365
|
-
<Loading size='20px' />
|
|
366
|
-
</Flex>
|
|
367
|
-
)
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
let filterData = this._getFilterData()
|
|
371
|
-
|
|
372
|
-
// 如果开启了过滤已删除商品功能,需要过滤掉已删除的商品
|
|
373
|
-
if (isFilterDelete) {
|
|
374
|
-
filterData = filterData
|
|
375
|
-
.map((group) => ({
|
|
376
|
-
...group,
|
|
377
|
-
children: group.children.filter((item) => !item.deleted),
|
|
378
|
-
}))
|
|
379
|
-
.filter((group) => group.children.length > 0)
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
if (!loading && filterData.length === 0) {
|
|
383
|
-
return this._renderEmpty()
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
if (!loading && filterData.length > 0) {
|
|
387
|
-
const {
|
|
388
|
-
selected = [],
|
|
389
|
-
multiple,
|
|
390
|
-
isGroupList,
|
|
391
|
-
renderListItem,
|
|
392
|
-
listHeight,
|
|
393
|
-
} = this.props
|
|
394
|
-
return (
|
|
395
|
-
<ListBase
|
|
396
|
-
selected={selected.map((v) => v.value)}
|
|
397
|
-
data={filterData}
|
|
398
|
-
multiple={multiple}
|
|
399
|
-
isGroupList={isGroupList}
|
|
400
|
-
className='gm-border-0'
|
|
401
|
-
renderItem={renderListItem}
|
|
402
|
-
onSelect={this._handleSelect}
|
|
403
|
-
isScrollTo
|
|
404
|
-
willActiveIndex={willActiveIndex!}
|
|
405
|
-
style={{ height: listHeight }}
|
|
406
|
-
/>
|
|
407
|
-
)
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
235
|
private _renderList = (config: ConfigProviderProps): ReactNode => {
|
|
412
236
|
const {
|
|
237
|
+
selected = [],
|
|
238
|
+
multiple,
|
|
239
|
+
isGroupList,
|
|
240
|
+
renderListItem,
|
|
413
241
|
searchPlaceholder,
|
|
414
242
|
listHeight,
|
|
415
243
|
popupClassName,
|
|
416
244
|
renderCustomizedBottom,
|
|
417
|
-
isRenderDefaultBottom = false,
|
|
418
245
|
} = this.props
|
|
419
|
-
const { loading, searchValue, willActiveIndex
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
// 如果开启了过滤已删除商品功能,需要过滤掉已删除的商品
|
|
423
|
-
if (isFilterDelete) {
|
|
424
|
-
filterData = filterData
|
|
425
|
-
.map((group) => ({
|
|
426
|
-
...group,
|
|
427
|
-
children: group.children.filter((item) => !item.deleted),
|
|
428
|
-
}))
|
|
429
|
-
.filter((group) => group.children.length > 0)
|
|
430
|
-
}
|
|
431
|
-
|
|
246
|
+
const { loading, searchValue, willActiveIndex } = this.state
|
|
247
|
+
const filterData = this._getFilterData()
|
|
432
248
|
return (
|
|
433
249
|
<ConfigProvider {...config}>
|
|
434
250
|
<div
|
|
@@ -444,14 +260,32 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
444
260
|
placeholder={searchPlaceholder}
|
|
445
261
|
/>
|
|
446
262
|
</div>
|
|
447
|
-
<div style={{ height: listHeight }}>
|
|
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>
|
|
448
285
|
{!loading &&
|
|
449
286
|
!!filterData.length &&
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
: isRenderDefaultBottom
|
|
453
|
-
? this.renderBottom()
|
|
454
|
-
: null)}
|
|
287
|
+
renderCustomizedBottom &&
|
|
288
|
+
renderCustomizedBottom(this._popoverRef)}
|
|
455
289
|
</div>
|
|
456
290
|
</ConfigProvider>
|
|
457
291
|
)
|
|
@@ -491,90 +325,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
491
325
|
style,
|
|
492
326
|
popoverType,
|
|
493
327
|
children,
|
|
494
|
-
maxTagCount,
|
|
495
|
-
maxTagPlaceholder,
|
|
496
328
|
} = this.props
|
|
497
|
-
|
|
498
|
-
// 处理 maxTagCount 逻辑
|
|
499
|
-
const renderSelectedItems = () => {
|
|
500
|
-
if (!multiple || !maxTagCount || selected.length === 0) {
|
|
501
|
-
return selected.map((item) => (
|
|
502
|
-
<Flex key={item.value as any} className='gm-more-select-selected-item'>
|
|
503
|
-
<Popover
|
|
504
|
-
disabled={!this.props.isKeyboard}
|
|
505
|
-
type='hover'
|
|
506
|
-
popup={<div className='gm-padding-10'>{item.text}</div>}
|
|
507
|
-
>
|
|
508
|
-
<Flex flex column>
|
|
509
|
-
{renderSelected!(item)}
|
|
510
|
-
</Flex>
|
|
511
|
-
</Popover>
|
|
512
|
-
{multiple ? (
|
|
513
|
-
<SVGRemove
|
|
514
|
-
className='gm-cursor gm-more-select-clear-btn'
|
|
515
|
-
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
516
|
-
/>
|
|
517
|
-
) : (
|
|
518
|
-
!disabledClose && ( // 是否不限时清除按钮,仅单选可用
|
|
519
|
-
<SVGCloseCircle
|
|
520
|
-
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
521
|
-
className='gm-cursor gm-more-select-clear-btn'
|
|
522
|
-
/>
|
|
523
|
-
)
|
|
524
|
-
)}
|
|
525
|
-
</Flex>
|
|
526
|
-
))
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// 处理 maxTagCount 逻辑
|
|
530
|
-
const isResponsive = maxTagCount === 'responsive'
|
|
531
|
-
let displayCount: number
|
|
532
|
-
|
|
533
|
-
if (isResponsive) {
|
|
534
|
-
displayCount = this.state.displayCount
|
|
535
|
-
} else {
|
|
536
|
-
displayCount = maxTagCount as number
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
const itemsToShow = selected.slice(0, displayCount)
|
|
540
|
-
const omittedItems = selected.slice(displayCount)
|
|
541
|
-
const omittedCount = selected.length - displayCount
|
|
542
|
-
|
|
543
|
-
return (
|
|
544
|
-
<>
|
|
545
|
-
{itemsToShow.map((item) => (
|
|
546
|
-
<Flex key={item.value as any} className='gm-more-select-selected-item'>
|
|
547
|
-
<Popover
|
|
548
|
-
disabled={!this.props.isKeyboard}
|
|
549
|
-
type='hover'
|
|
550
|
-
popup={<div className='gm-padding-10'>{item.text}</div>}
|
|
551
|
-
>
|
|
552
|
-
<Flex flex column>
|
|
553
|
-
{renderSelected!(item)}
|
|
554
|
-
</Flex>
|
|
555
|
-
</Popover>
|
|
556
|
-
<SVGRemove
|
|
557
|
-
className='gm-cursor gm-more-select-clear-btn'
|
|
558
|
-
onClick={disabled ? _.noop : this._handleClear.bind(this, item)}
|
|
559
|
-
/>
|
|
560
|
-
</Flex>
|
|
561
|
-
))}
|
|
562
|
-
{omittedCount > 0 && (
|
|
563
|
-
<Flex
|
|
564
|
-
key='omitted'
|
|
565
|
-
className='gm-more-select-selected-item gm-more-select-omitted-item'
|
|
566
|
-
>
|
|
567
|
-
{maxTagPlaceholder ? (
|
|
568
|
-
maxTagPlaceholder(omittedItems, omittedCount)
|
|
569
|
-
) : (
|
|
570
|
-
<span className='gm-more-select-omitted-count'>+{omittedCount}...</span>
|
|
571
|
-
)}
|
|
572
|
-
</Flex>
|
|
573
|
-
)}
|
|
574
|
-
</>
|
|
575
|
-
)
|
|
576
|
-
}
|
|
577
|
-
|
|
578
329
|
return (
|
|
579
330
|
<ConfigConsumer>
|
|
580
331
|
{(config) => (
|
|
@@ -589,7 +340,7 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
589
340
|
},
|
|
590
341
|
className
|
|
591
342
|
)}
|
|
592
|
-
style={style
|
|
343
|
+
style={style}
|
|
593
344
|
>
|
|
594
345
|
<Popover
|
|
595
346
|
ref={this._popoverRef}
|
|
@@ -607,7 +358,39 @@ class MoreSelectBase<V extends string | number = string> extends Component<
|
|
|
607
358
|
className='gm-more-select-selected'
|
|
608
359
|
>
|
|
609
360
|
{selected.length !== 0 ? (
|
|
610
|
-
|
|
361
|
+
selected.map((item) => (
|
|
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
|
+
))
|
|
611
394
|
) : (
|
|
612
395
|
// 加多个 避免对齐问题,有文本才有对齐
|
|
613
396
|
<div className='gm-text-placeholder'>{placeholder} </div>
|
|
@@ -12,12 +12,6 @@ class MoreSelect<V = any> extends Component<MoreSelectProps<V>> {
|
|
|
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
15
|
}
|
|
22
16
|
|
|
23
17
|
private _moreSelectBaseRef = createRef<MoreSelectBase>()
|
|
@@ -91,8 +85,6 @@ class MoreSelect<V = any> extends Component<MoreSelectProps<V>> {
|
|
|
91
85
|
onSearch,
|
|
92
86
|
onClick,
|
|
93
87
|
renderListFilter,
|
|
94
|
-
maxTagCount,
|
|
95
|
-
maxTagPlaceholder,
|
|
96
88
|
...rest
|
|
97
89
|
} = this.props
|
|
98
90
|
let tempSelect = selected as MoreSelectDataItem<V>[]
|
|
@@ -137,8 +129,6 @@ class MoreSelect<V = any> extends Component<MoreSelectProps<V>> {
|
|
|
137
129
|
isGroupList={isGroupList}
|
|
138
130
|
onSearch={onSearch && this._handleSearch}
|
|
139
131
|
renderListFilter={renderListFilter && this._renderListFilter}
|
|
140
|
-
maxTagCount={maxTagCount}
|
|
141
|
-
maxTagPlaceholder={maxTagPlaceholder}
|
|
142
132
|
/>
|
|
143
133
|
)
|
|
144
134
|
}
|
|
@@ -318,98 +318,6 @@ 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
|
-
|
|
413
321
|
export default {
|
|
414
322
|
title: '表单/MoreSelect',
|
|
415
323
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
+
import { Popover } from '@gm-pc/react'
|
|
1
2
|
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
|
|
11
9
|
[key: string]: any
|
|
12
10
|
}
|
|
13
11
|
|
|
@@ -38,13 +36,10 @@ interface MoreSelectCommonProps<V extends string | number = string> {
|
|
|
38
36
|
renderListItem?(value: MoreSelectDataItem<V>, index: number): ReactNode
|
|
39
37
|
|
|
40
38
|
/** 自定义popup底部渲染 */
|
|
41
|
-
renderCustomizedBottom?(
|
|
42
|
-
ref: React.RefObject<Popover>,
|
|
43
|
-
defaultBottom: () => ReactNode
|
|
44
|
-
): ReactNode
|
|
39
|
+
renderCustomizedBottom?(ref: React.RefObject<Popover>): ReactNode
|
|
45
40
|
|
|
46
41
|
/**
|
|
47
|
-
*
|
|
42
|
+
* 自定义“空状态”渲染
|
|
48
43
|
*
|
|
49
44
|
* 若函数返回 undefined 则使用默认的空状态
|
|
50
45
|
*/
|
|
@@ -65,25 +60,6 @@ interface MoreSelectCommonProps<V extends string | number = string> {
|
|
|
65
60
|
/** 目前为了 keyboard */
|
|
66
61
|
isKeyboard?: boolean
|
|
67
62
|
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
|
|
87
63
|
}
|
|
88
64
|
|
|
89
65
|
interface MoreSelectBaseProps<V extends string | number = string>
|
|
@@ -93,7 +69,7 @@ interface MoreSelectBaseProps<V extends string | number = string>
|
|
|
93
69
|
onSelect(selected: MoreSelectDataItem<V>[]): void
|
|
94
70
|
|
|
95
71
|
/** 搜索回调 */
|
|
96
|
-
onSearch?(searchWord: string, data: MoreSelectGroupDataItem<V>[]): Promise<
|
|
72
|
+
onSearch?(searchWord: string, data: MoreSelectGroupDataItem<V>[]): Promise<void> | void
|
|
97
73
|
/** 点击回调 */
|
|
98
74
|
onClick?(selected: MoreSelectSelected<V>[]): void
|
|
99
75
|
|
|
@@ -104,12 +80,6 @@ interface MoreSelectBaseProps<V extends string | number = string>
|
|
|
104
80
|
): MoreSelectGroupDataItem<V>[]
|
|
105
81
|
/** 是否在active的时候搜索,订单业务相关,searchValue放在localstorage */
|
|
106
82
|
searchOnActive?: boolean
|
|
107
|
-
/** 是否展示全选以及过滤已删除商品 */
|
|
108
|
-
isRenderDefaultBottom?: boolean
|
|
109
|
-
/** 是否展示已删除商品 */
|
|
110
|
-
isShowDeletedSwitch?: boolean
|
|
111
|
-
/** 是否展示全选 */
|
|
112
|
-
isShowCheckedAll?: boolean
|
|
113
83
|
}
|
|
114
84
|
|
|
115
85
|
type MoreSelectData<V extends string | number = string> =
|
|
@@ -128,7 +98,7 @@ interface MoreSelectProps<V extends string | number = string>
|
|
|
128
98
|
onSelect?(selected?: MoreSelectSelected<V>): void
|
|
129
99
|
onChange?(value: V | V[]): void
|
|
130
100
|
/** 搜索回调 */
|
|
131
|
-
onSearch?(searchWord: string, data: MoreSelectData<V>): Promise<void
|
|
101
|
+
onSearch?(searchWord: string, data: MoreSelectData<V>): Promise<void> | void
|
|
132
102
|
/** 点击回调 */
|
|
133
103
|
onClick?(selected: MoreSelectSelected<V>[]): void
|
|
134
104
|
|
|
@@ -13,6 +13,7 @@ const Nav: FC<NavProps> = ({
|
|
|
13
13
|
onPushCreate,
|
|
14
14
|
showActive,
|
|
15
15
|
other,
|
|
16
|
+
otherFirst,
|
|
16
17
|
className,
|
|
17
18
|
style,
|
|
18
19
|
footerImage,
|
|
@@ -78,6 +79,8 @@ const Nav: FC<NavProps> = ({
|
|
|
78
79
|
>
|
|
79
80
|
<div className='gm-nav-logo'>{logo}</div>
|
|
80
81
|
<Flex flex column className='gm-nav-content'>
|
|
82
|
+
{otherFirst}
|
|
83
|
+
|
|
81
84
|
{data.map((one) => (
|
|
82
85
|
<NavItem
|
|
83
86
|
key={one.link}
|
|
@@ -11,7 +11,6 @@ interface SwitchProps {
|
|
|
11
11
|
onChange?(checked: boolean): void
|
|
12
12
|
className?: string
|
|
13
13
|
style?: CSSProperties
|
|
14
|
-
size?: 'small' | 'middle'
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
interface SwitchState {
|
|
@@ -27,11 +26,10 @@ class Switch extends Component<SwitchProps, SwitchState> {
|
|
|
27
26
|
on: '',
|
|
28
27
|
off: '',
|
|
29
28
|
onChange: _.noop,
|
|
30
|
-
size: 'middle',
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
readonly state: SwitchState = {
|
|
34
|
-
checked:
|
|
32
|
+
checked: this.props.checked,
|
|
35
33
|
labelWidth: null,
|
|
36
34
|
isReady: false,
|
|
37
35
|
}
|
|
@@ -55,7 +53,7 @@ class Switch extends Component<SwitchProps, SwitchState> {
|
|
|
55
53
|
UNSAFE_componentWillReceiveProps(nextProps: Readonly<SwitchProps>) {
|
|
56
54
|
if ('checked' in nextProps) {
|
|
57
55
|
this.setState({
|
|
58
|
-
checked:
|
|
56
|
+
checked: nextProps.checked,
|
|
59
57
|
})
|
|
60
58
|
}
|
|
61
59
|
}
|
|
@@ -84,7 +82,6 @@ class Switch extends Component<SwitchProps, SwitchState> {
|
|
|
84
82
|
disabled,
|
|
85
83
|
on,
|
|
86
84
|
off,
|
|
87
|
-
size,
|
|
88
85
|
...rest
|
|
89
86
|
} = this.props
|
|
90
87
|
|
|
@@ -104,9 +101,8 @@ class Switch extends Component<SwitchProps, SwitchState> {
|
|
|
104
101
|
ref={this._inputOffRef}
|
|
105
102
|
className={classNames('gm-switch gm-switch-' + type, className, {
|
|
106
103
|
disabled,
|
|
107
|
-
[`gm-switch-${size}`]: size,
|
|
108
104
|
})}
|
|
109
|
-
style={style
|
|
105
|
+
style={style}
|
|
110
106
|
data-attr={this.state.labelWidth}
|
|
111
107
|
disabled={disabled}
|
|
112
108
|
type='checkbox'
|