@fjyueke/arco-mcp 1.0.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/README.md +85 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +244 -0
- package/metaData/components/action-sheet/doc.md +102 -0
- package/metaData/components/action-sheet/example/index.tsx +199 -0
- package/metaData/components/action-sheet/example/methods.tsx +6 -0
- package/metaData/components/avatar/doc.md +57 -0
- package/metaData/components/avatar/example/group.tsx +69 -0
- package/metaData/components/avatar/example/index.tsx +196 -0
- package/metaData/components/badge/doc.md +28 -0
- package/metaData/components/badge/example/index.tsx +128 -0
- package/metaData/components/button/doc.md +45 -0
- package/metaData/components/button/example/index.tsx +264 -0
- package/metaData/components/carousel/doc.md +89 -0
- package/metaData/components/carousel/example/index.tsx +1481 -0
- package/metaData/components/cell/doc.md +68 -0
- package/metaData/components/cell/example/arrow.tsx +13 -0
- package/metaData/components/cell/example/cell.tsx +71 -0
- package/metaData/components/cell/example/group.tsx +63 -0
- package/metaData/components/cell/example/index.tsx +19 -0
- package/metaData/components/checkbox/doc.md +91 -0
- package/metaData/components/checkbox/example/checkbox.tsx +158 -0
- package/metaData/components/checkbox/example/group.tsx +103 -0
- package/metaData/components/checkbox/example/index.tsx +25 -0
- package/metaData/components/circle-progress/doc.md +40 -0
- package/metaData/components/circle-progress/example/index.tsx +323 -0
- package/metaData/components/collapse/doc.md +74 -0
- package/metaData/components/collapse/example/collapse.tsx +183 -0
- package/metaData/components/collapse/example/group.tsx +136 -0
- package/metaData/components/collapse/example/index.tsx +16 -0
- package/metaData/components/collapse/example/utils.tsx +20 -0
- package/metaData/components/context-provider/doc.md +44 -0
- package/metaData/components/context-provider/example/index.tsx +208 -0
- package/metaData/components/count-down/doc.md +40 -0
- package/metaData/components/count-down/example/hooks.tsx +118 -0
- package/metaData/components/count-down/example/index.tsx +63 -0
- package/metaData/components/date-picker/doc.md +102 -0
- package/metaData/components/date-picker/example/index.tsx +545 -0
- package/metaData/components/dialog/doc.md +200 -0
- package/metaData/components/dialog/example/index.tsx +328 -0
- package/metaData/components/dialog/example/methods.tsx +56 -0
- package/metaData/components/divider/doc.md +25 -0
- package/metaData/components/divider/example/index.tsx +87 -0
- package/metaData/components/dropdown/doc.md +80 -0
- package/metaData/components/dropdown/example/dropdown.tsx +308 -0
- package/metaData/components/dropdown/example/index.tsx +19 -0
- package/metaData/components/dropdown/example/options.tsx +103 -0
- package/metaData/components/dropdown-menu/doc.md +91 -0
- package/metaData/components/dropdown-menu/example/dropdown-menu.tsx +270 -0
- package/metaData/components/dropdown-menu/example/index.tsx +16 -0
- package/metaData/components/ellipsis/doc.md +33 -0
- package/metaData/components/ellipsis/example/index.tsx +93 -0
- package/metaData/components/ellipsis/example/js-ellipsis.tsx +229 -0
- package/metaData/components/ellipsis/example/native-ellipsis.tsx +48 -0
- package/metaData/components/form/doc.md +90 -0
- package/metaData/components/form/example/form-item-context.tsx +8 -0
- package/metaData/components/form/example/form-item.tsx +378 -0
- package/metaData/components/form/example/index.tsx +87 -0
- package/metaData/components/form/example/linked-container.tsx +66 -0
- package/metaData/components/grid/doc.md +39 -0
- package/metaData/components/grid/example/index.tsx +252 -0
- package/metaData/components/icon/doc.md +15 -0
- package/metaData/components/icon/example/index.tsx +32 -0
- package/metaData/components/image/doc.md +62 -0
- package/metaData/components/image/example/index.tsx +528 -0
- package/metaData/components/image-picker/doc.md +116 -0
- package/metaData/components/image-picker/example/add-icon.tsx +14 -0
- package/metaData/components/image-picker/example/index.tsx +175 -0
- package/metaData/components/image-preview/doc.md +119 -0
- package/metaData/components/image-preview/example/index.tsx +1290 -0
- package/metaData/components/image-preview/example/methods.tsx +72 -0
- package/metaData/components/index-bar/doc.md +83 -0
- package/metaData/components/index-bar/example/group.tsx +93 -0
- package/metaData/components/index-bar/example/index.tsx +271 -0
- package/metaData/components/index-bar/example/side-bar.tsx +82 -0
- package/metaData/components/input/doc.md +60 -0
- package/metaData/components/input/example/hooks.tsx +259 -0
- package/metaData/components/input/example/index.tsx +134 -0
- package/metaData/components/input/example/props.tsx +183 -0
- package/metaData/components/keyboard/doc.md +73 -0
- package/metaData/components/keyboard/example/index.tsx +238 -0
- package/metaData/components/load-more/doc.md +48 -0
- package/metaData/components/load-more/example/index.tsx +395 -0
- package/metaData/components/loading/doc.md +34 -0
- package/metaData/components/loading/example/index.tsx +312 -0
- package/metaData/components/masking/doc.md +93 -0
- package/metaData/components/masking/example/index.tsx +410 -0
- package/metaData/components/masking/example/methods.tsx +88 -0
- package/metaData/components/nav-bar/doc.md +40 -0
- package/metaData/components/nav-bar/example/back-icon.tsx +28 -0
- package/metaData/components/nav-bar/example/index.tsx +305 -0
- package/metaData/components/notice-bar/doc.md +34 -0
- package/metaData/components/notice-bar/example/index.tsx +294 -0
- package/metaData/components/notify/doc.md +81 -0
- package/metaData/components/notify/example/index.tsx +171 -0
- package/metaData/components/notify/example/methods.tsx +83 -0
- package/metaData/components/pagination/doc.md +41 -0
- package/metaData/components/pagination/example/arrow.tsx +14 -0
- package/metaData/components/pagination/example/index.tsx +292 -0
- package/metaData/components/picker/doc.md +89 -0
- package/metaData/components/picker/example/index.tsx +217 -0
- package/metaData/components/picker-view/doc.md +57 -0
- package/metaData/components/picker-view/example/cascader.tsx +141 -0
- package/metaData/components/picker-view/example/index.tsx +297 -0
- package/metaData/components/picker-view/example/multi-picker.tsx +66 -0
- package/metaData/components/picker-view/example/picker-cell.tsx +416 -0
- package/metaData/components/popover/doc.md +144 -0
- package/metaData/components/popover/example/index.tsx +23 -0
- package/metaData/components/popover/example/menu.tsx +145 -0
- package/metaData/components/popover/example/popover-inner.tsx +147 -0
- package/metaData/components/popover/example/popover.tsx +268 -0
- package/metaData/components/popup/doc.md +101 -0
- package/metaData/components/popup/example/index.tsx +125 -0
- package/metaData/components/popup/example/methods.tsx +6 -0
- package/metaData/components/popup-swiper/doc.md +108 -0
- package/metaData/components/popup-swiper/example/index.tsx +332 -0
- package/metaData/components/popup-swiper/example/methods.tsx +6 -0
- package/metaData/components/portal/doc.md +14 -0
- package/metaData/components/portal/example/index.tsx +35 -0
- package/metaData/components/progress/doc.md +42 -0
- package/metaData/components/progress/example/index.tsx +256 -0
- package/metaData/components/pull-refresh/doc.md +37 -0
- package/metaData/components/pull-refresh/example/android-pull-refresh.tsx +260 -0
- package/metaData/components/pull-refresh/example/index.tsx +44 -0
- package/metaData/components/pull-refresh/example/ios-pull-refresh.tsx +216 -0
- package/metaData/components/radio/doc.md +89 -0
- package/metaData/components/radio/example/group.tsx +92 -0
- package/metaData/components/radio/example/index.tsx +25 -0
- package/metaData/components/radio/example/radio.tsx +22 -0
- package/metaData/components/rate/doc.md +33 -0
- package/metaData/components/rate/example/index.tsx +281 -0
- package/metaData/components/search-bar/doc.md +97 -0
- package/metaData/components/search-bar/example/association.tsx +89 -0
- package/metaData/components/search-bar/example/cancel-button.tsx +34 -0
- package/metaData/components/search-bar/example/highlight.tsx +66 -0
- package/metaData/components/search-bar/example/index.tsx +251 -0
- package/metaData/components/show-monitor/doc.md +34 -0
- package/metaData/components/show-monitor/example/index.tsx +646 -0
- package/metaData/components/skeleton/doc.md +101 -0
- package/metaData/components/skeleton/example/elements.tsx +290 -0
- package/metaData/components/skeleton/example/index.tsx +96 -0
- package/metaData/components/skeleton/example/skeleton-context.tsx +7 -0
- package/metaData/components/slider/doc.md +42 -0
- package/metaData/components/slider/example/index.tsx +326 -0
- package/metaData/components/slider/example/marks.tsx +50 -0
- package/metaData/components/slider/example/popover.tsx +38 -0
- package/metaData/components/slider/example/thumb.tsx +48 -0
- package/metaData/components/slider/example/useSliderIcon.tsx +38 -0
- package/metaData/components/slider/example/useSliderInit.tsx +170 -0
- package/metaData/components/stepper/doc.md +46 -0
- package/metaData/components/stepper/example/index.tsx +166 -0
- package/metaData/components/stepper/example/useButtonClick.tsx +74 -0
- package/metaData/components/stepper/example/useInputEvent.tsx +65 -0
- package/metaData/components/stepper/example/useValue.tsx +43 -0
- package/metaData/components/steps/doc.md +57 -0
- package/metaData/components/steps/example/index.tsx +123 -0
- package/metaData/components/steps/example/step.tsx +126 -0
- package/metaData/components/sticky/doc.md +45 -0
- package/metaData/components/sticky/example/index.tsx +430 -0
- package/metaData/components/swipe-action/doc.md +44 -0
- package/metaData/components/swipe-action/example/index.tsx +338 -0
- package/metaData/components/swipe-action/example/item.tsx +40 -0
- package/metaData/components/swipe-load/doc.md +43 -0
- package/metaData/components/swipe-load/example/index.tsx +339 -0
- package/metaData/components/swipe-load/example/type.tsx +153 -0
- package/metaData/components/switch/doc.md +38 -0
- package/metaData/components/switch/example/index.tsx +237 -0
- package/metaData/components/tab-bar/doc.md +57 -0
- package/metaData/components/tab-bar/example/index.tsx +18 -0
- package/metaData/components/tab-bar/example/item.tsx +74 -0
- package/metaData/components/tab-bar/example/tab-bar.tsx +105 -0
- package/metaData/components/tabs/doc.md +187 -0
- package/metaData/components/tabs/example/index.tsx +514 -0
- package/metaData/components/tabs/example/tab-cell-underline.tsx +320 -0
- package/metaData/components/tabs/example/tab-cell.tsx +433 -0
- package/metaData/components/tabs/example/tab-pane.tsx +349 -0
- package/metaData/components/tag/doc.md +80 -0
- package/metaData/components/tag/example/index.tsx +23 -0
- package/metaData/components/tag/example/list.tsx +97 -0
- package/metaData/components/tag/example/tag.tsx +85 -0
- package/metaData/components/textarea/doc.md +67 -0
- package/metaData/components/textarea/example/index.tsx +258 -0
- package/metaData/components/toast/doc.md +90 -0
- package/metaData/components/toast/example/index.tsx +335 -0
- package/metaData/components/toast/example/methods.tsx +87 -0
- package/metaData/components/transition/doc.md +19 -0
- package/metaData/components/transition/example/index.tsx +113 -0
- package/metaData/components/uploader/doc.md +82 -0
- package/metaData/components/uploader/example/index.tsx +208 -0
- package/metaData/components-index.json +242 -0
- package/package.json +56 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
### 导航
|
|
2
|
+
|
|
3
|
+
# 下拉选择菜单 DropdownMenu
|
|
4
|
+
|
|
5
|
+
下拉选择组件,点击选择器(select)展开下拉框(dropdown),展示选择项(options),兼容多个选择器的情况。
|
|
6
|
+
|
|
7
|
+
======
|
|
8
|
+
|
|
9
|
+
> 属性/Props
|
|
10
|
+
|
|
11
|
+
|参数|描述|类型|默认值|
|
|
12
|
+
|----------|-------------|------|------|
|
|
13
|
+
|className|自定义类名|string|-|
|
|
14
|
+
|style|自定义样式|CSSProperties|-|
|
|
15
|
+
|defaultSelectIndex|初始被选择的选择器的序号|number|-|
|
|
16
|
+
|selectIndex|(受控) 被选择的选择器的序号|number|-|
|
|
17
|
+
|disabled|选择器禁用状态|boolean\[\]|-|
|
|
18
|
+
|selectTips|选择器的说明|string\[\]|-|
|
|
19
|
+
|onSelectChange|当选中的选择器改变的时候触发的回调函数|(selectIndex: number) =\> void|-|
|
|
20
|
+
|icon|选择器右侧的图标|ReactNode|-|
|
|
21
|
+
|defaultShowDropdown|初始状态,下拉框状态|boolean|-|
|
|
22
|
+
|showDropdown|可选受控,组件挂载时下拉框的状态|boolean|-|
|
|
23
|
+
|onDropdownChange|下拉框展示状态改变时触发的回调函数|(dropdown: boolean, selectIndex?: number) =\> void|-|
|
|
24
|
+
|getContainer|获得下拉框的容器|() =\> HTMLDivElement|-|
|
|
25
|
+
|chooseAndClose|选择后是否收起面板,仅单选有效|boolean|true|
|
|
26
|
+
|onCancel|取消选择|() =\> void|-|
|
|
27
|
+
|children|自定义下拉框元素|ReactNode|-|
|
|
28
|
+
|extraForDropdown|dropdown参数|DropdownCommonProps|-|
|
|
29
|
+
|multiple|是否支持多选|boolean|false|
|
|
30
|
+
|options|下拉框展示的选择项,其中级联选项仅单选支持|string\[\] \| OptionsItem\[\]\[\] \| CascadeOptions\[\]|必填|
|
|
31
|
+
|defaultValues|初始选择项|ReactText\[\] \| ReactText\[\]\[\]|-|
|
|
32
|
+
|values|(受控) 每个选择器选中的项|ReactText\[\] \| ReactText\[\]\[\]|-|
|
|
33
|
+
|renderSelectLabel|自定义选择器|((op: OptionsItem, index: number) =\> ReactNode) \| ((op: OptionsItem\[\], index: number) =\> ReactNode)|-|
|
|
34
|
+
|onOptionClick|点击选项时触发的回调函数|((value: ReactText, item: OptionsItem, selectIndex?: number) =\> void) \| ((selected: boolean, val: ReactText, item: OptionsItem, selectIndex?: number) =\> void)|-|
|
|
35
|
+
|onOptionChange|选项改变时触发的回调函数|((value: ReactText, item: OptionsItem, selectIndex?: number) =\> void) \| ((vals: ReactText\[\], item: OptionsItem, selectIndex?: number) =\> void)|-|
|
|
36
|
+
|onValuesChange|所有选择器选项总值改变时的回调函数|((values: ReactText\[\]) =\> void) \| ((values: ReactText\[\]\[\]) =\> void)|-|
|
|
37
|
+
|getFormattedOptions|格式化传入的options|((options: string\[\] \| OptionsItem\[\]\[\] \| CascadeOptions\[\], values?: ReactText\[\]) =\> \{ formattedOptions: OptionsItem\[\]\[\]; formattedValue: ReactText\[\]; \}) \| ((options: string\[\] \| \.\.\. 1 more \.\.\. \| CascadeOptions\[\], values?: ReactText\[\]\[\]) =\> \{ \.\.\.; \})|-|
|
|
38
|
+
|
|
39
|
+
> 引用/Refs
|
|
40
|
+
|
|
41
|
+
|参数|描述|类型|
|
|
42
|
+
|----------|-------------|------|
|
|
43
|
+
|dom|最外层元素 DOM|HTMLDivElement|
|
|
44
|
+
|
|
45
|
+
> DropdownCommonProps
|
|
46
|
+
|
|
47
|
+
|参数|描述|类型|默认值|
|
|
48
|
+
|----------|-------------|------|------|
|
|
49
|
+
|className|自定义类名|string|-|
|
|
50
|
+
|style|自定义样式|CSSProperties|-|
|
|
51
|
+
|extraNode|下拉框底部元素|ReactNode|-|
|
|
52
|
+
|top|定位下拉框出现的位置|number|-|
|
|
53
|
+
|bottom|向上展开时下拉框出现的位置|number|-|
|
|
54
|
+
|direction|展开方向|"up" \| "down"|"down"|
|
|
55
|
+
|height|受控模式,下拉框高度|number|-|
|
|
56
|
+
|maxHeight|下拉框最大的高度|number|500|
|
|
57
|
+
|clickOtherToClose|点击其他区域是否取消选择|boolean|true|
|
|
58
|
+
|touchToClose|是否在触发touchstart时就取消选择,否则在click之后再取消选择|boolean|true|
|
|
59
|
+
|dropdownAnimationTimeout|展开收起动画的时间|number|300|
|
|
60
|
+
|dropdownAnimationFunction|展开收起动画曲线函数|string|"cubic-bezier(0.32, 0.96, 0.6, 1)"|
|
|
61
|
+
|showMask|是否展示遮罩层|boolean|true|
|
|
62
|
+
|maskAnimationTimeout|蒙层动画时长|number|500|
|
|
63
|
+
|maskAnimationFunction|蒙层动画函数|string|"cubic-bezier(0.32, 0.96, 0.6, 1)"|
|
|
64
|
+
|useColumn|使用多列标签样式,传 true 为 4 列,传数字为指定 n 列|number \| boolean|false|
|
|
65
|
+
|optionIcon|选项附带图标|ReactNode|-|
|
|
66
|
+
|mountOnEnter|是否在打开下拉框时再加载内容|boolean|true|
|
|
67
|
+
|unmountOnExit|是否在退出时卸载内容|boolean|true|
|
|
68
|
+
|preventBodyScroll|弹窗打开时是否禁止body的滚动|boolean|true|
|
|
69
|
+
|initialBodyOverflow|页面初始 overflow 状态,即关闭弹窗时 overflow 应该还原的状态|string|第一个全屏组件(弹窗、toast等)打开时页面overflow值|
|
|
70
|
+
|getAnchorElement|用于定位的元素,优先级低于top/bottom|() =\> HTMLElement|当前DOM所在位置的父元素|
|
|
71
|
+
|isStopTouchEl|点击某元素时是否阻止关闭面板, 优先级高于\`getStopTouchElement\`,当 clickOtherToClose=true 时有效|(el: HTMLElement) =\> boolean|-|
|
|
72
|
+
|getStopTouchElements|可阻止关闭面板的元素,当 clickOtherToClose=true 时有效|() =\> HTMLElement\[\]|当前组件的父元素|
|
|
73
|
+
|getScrollContainer|内容内部滚动区域容器,在该容器中未滚动到顶部或底部时会释放滚动|() =\> HTMLElement \| HTMLElement\[\]|-|
|
|
74
|
+
|getPortalContainer|获取挂载容器|() =\> HTMLElement|-|
|
|
75
|
+
|
|
76
|
+
> OptionsItem
|
|
77
|
+
|
|
78
|
+
|参数|描述|类型|
|
|
79
|
+
|----------|-------------|------|
|
|
80
|
+
|label|选项名称|ReactNode|
|
|
81
|
+
|value|选项标识|ReactText|
|
|
82
|
+
|disabled|选项是否可用,默认false表示可用|boolean|
|
|
83
|
+
|
|
84
|
+
> CascadeOptions
|
|
85
|
+
|
|
86
|
+
|参数|描述|类型|
|
|
87
|
+
|----------|-------------|------|
|
|
88
|
+
|children|级联选择的下一级内容|OptionsItem\[\]|
|
|
89
|
+
|label|选项名称|ReactNode|
|
|
90
|
+
|value|选项标识|ReactText|
|
|
91
|
+
|disabled|选项是否可用,默认false表示可用|boolean|
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useRef,
|
|
3
|
+
useState,
|
|
4
|
+
forwardRef,
|
|
5
|
+
Ref,
|
|
6
|
+
useImperativeHandle,
|
|
7
|
+
useMemo,
|
|
8
|
+
useEffect,
|
|
9
|
+
useContext,
|
|
10
|
+
} from 'react';
|
|
11
|
+
import { cls } from '@arco-design/mobile-utils';
|
|
12
|
+
import { GlobalContext } from '../context-provider';
|
|
13
|
+
import { DropdownMenuProps, DropdownMenuRef } from './type';
|
|
14
|
+
import {
|
|
15
|
+
getFormattedOptions as defaultFormatFunc,
|
|
16
|
+
isCascadeArray,
|
|
17
|
+
isClassNameDom,
|
|
18
|
+
isRefDom,
|
|
19
|
+
} from './helper';
|
|
20
|
+
import { DropdownProps, DropdownRef, OptionsItem, OptionValueType } from '../dropdown';
|
|
21
|
+
import IconTriDown from '../icon/IconTriDown';
|
|
22
|
+
|
|
23
|
+
export function componentGenerator<
|
|
24
|
+
P extends DropdownProps = DropdownProps,
|
|
25
|
+
R extends DropdownRef = DropdownRef,
|
|
26
|
+
>(Comp: React.ForwardRefExoticComponent<P & React.RefAttributes<R>>) {
|
|
27
|
+
return forwardRef((props: DropdownMenuProps, ref: Ref<DropdownMenuRef>) => {
|
|
28
|
+
const {
|
|
29
|
+
className = '',
|
|
30
|
+
style = {},
|
|
31
|
+
options = [],
|
|
32
|
+
disabled = [],
|
|
33
|
+
selectTips = [],
|
|
34
|
+
values,
|
|
35
|
+
defaultValues = [],
|
|
36
|
+
icon,
|
|
37
|
+
chooseAndClose = true,
|
|
38
|
+
selectIndex,
|
|
39
|
+
defaultSelectIndex = 0,
|
|
40
|
+
showDropdown,
|
|
41
|
+
defaultShowDropdown = false,
|
|
42
|
+
onValuesChange,
|
|
43
|
+
onSelectChange,
|
|
44
|
+
onDropdownChange,
|
|
45
|
+
getFormattedOptions = defaultFormatFunc,
|
|
46
|
+
getContainer,
|
|
47
|
+
children,
|
|
48
|
+
extraForDropdown,
|
|
49
|
+
} = props;
|
|
50
|
+
const { prefixCls, locale } = useContext(GlobalContext);
|
|
51
|
+
const [innerValues, setInnerValues] = useState(defaultValues);
|
|
52
|
+
const [defaultTop, setDefaultTop] = useState(0);
|
|
53
|
+
const currentValues = values !== void 0 ? values : innerValues;
|
|
54
|
+
|
|
55
|
+
const [innerShowDropdown, setInnerShowDropdown] = useState(defaultShowDropdown);
|
|
56
|
+
const dropdownShown = showDropdown !== void 0 ? showDropdown : innerShowDropdown;
|
|
57
|
+
|
|
58
|
+
const [innerSelectedIndex, setInnerSelectedIndex] = useState(defaultSelectIndex);
|
|
59
|
+
const selectedIndex = selectIndex !== void 0 ? selectIndex : innerSelectedIndex;
|
|
60
|
+
|
|
61
|
+
const selectWrapper = useRef<HTMLDivElement>(null);
|
|
62
|
+
const domRef = useRef<HTMLDivElement | null>(null);
|
|
63
|
+
const defaultOpItem: OptionsItem = {
|
|
64
|
+
label: locale?.DropdownMenu.select,
|
|
65
|
+
value: -1,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 更新选项数组和选择情况
|
|
70
|
+
* @en Update options list and selection
|
|
71
|
+
*/
|
|
72
|
+
const { formattedOptions } = useMemo(() => {
|
|
73
|
+
return getFormattedOptions(options, currentValues as any);
|
|
74
|
+
}, [options, currentValues]);
|
|
75
|
+
|
|
76
|
+
const selectedOptions = useMemo(
|
|
77
|
+
() =>
|
|
78
|
+
formattedOptions.map((ops, index) => {
|
|
79
|
+
if (props.multiple) {
|
|
80
|
+
const value = (currentValues[index] as OptionValueType[]) || [];
|
|
81
|
+
const opItems = ops.reduce(
|
|
82
|
+
(acc, op) => [...acc, ...(value.includes(op.value) ? [op] : [])],
|
|
83
|
+
[],
|
|
84
|
+
);
|
|
85
|
+
return opItems.length ? opItems : [defaultOpItem];
|
|
86
|
+
}
|
|
87
|
+
const value = currentValues[index];
|
|
88
|
+
return ops.find(op => op.value === value) || ops[0];
|
|
89
|
+
}),
|
|
90
|
+
[formattedOptions, currentValues, props.multiple],
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 当下拉框的状态变化
|
|
95
|
+
* @en When the state of the dropdown box changes
|
|
96
|
+
*/
|
|
97
|
+
const handleShowDropdownChange = (show: boolean, index?: number) => {
|
|
98
|
+
onDropdownChange && onDropdownChange(show, index);
|
|
99
|
+
setInnerShowDropdown(show);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const handleSelectedIndexChange = (idx: number) => {
|
|
103
|
+
setInnerSelectedIndex(idx);
|
|
104
|
+
onSelectChange?.(idx);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const handleValuesChange = (val: OptionValueType | OptionValueType[]) => {
|
|
108
|
+
let newValue = [...currentValues] as any;
|
|
109
|
+
// 级联情况下 selectedIndex 之后的选项值重置
|
|
110
|
+
// @en Option values are reset after selectedIndex in case of cascade
|
|
111
|
+
if (isCascadeArray(options)) {
|
|
112
|
+
newValue = newValue.slice(0, selectedIndex);
|
|
113
|
+
}
|
|
114
|
+
newValue[selectedIndex] = val;
|
|
115
|
+
newValue = getFormattedOptions(options, newValue).formattedValue;
|
|
116
|
+
setInnerValues(newValue);
|
|
117
|
+
onValuesChange?.(newValue);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 处理选择框的点击事件
|
|
122
|
+
* @en Handle click event of dropdown box
|
|
123
|
+
*/
|
|
124
|
+
const handleSelectClick = idx => {
|
|
125
|
+
if (disabled[idx]) return;
|
|
126
|
+
if (Number(idx) === selectedIndex) {
|
|
127
|
+
handleShowDropdownChange(!dropdownShown, idx);
|
|
128
|
+
} else {
|
|
129
|
+
handleSelectedIndexChange(idx);
|
|
130
|
+
if (!dropdownShown) handleShowDropdownChange(true, idx);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 判断是否为当前实例下的选择框
|
|
136
|
+
* @en Determine whether it is the dropdown box under the current instance
|
|
137
|
+
*/
|
|
138
|
+
const isCurrentSelectEl = (target: HTMLElement) => {
|
|
139
|
+
const { isStopTouchEl } = extraForDropdown || {};
|
|
140
|
+
return (
|
|
141
|
+
(isRefDom(target, selectWrapper) && isClassNameDom(target, 'select-item')) ||
|
|
142
|
+
isStopTouchEl?.(target) ||
|
|
143
|
+
false
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
useImperativeHandle(ref, () => ({
|
|
148
|
+
dom: domRef.current,
|
|
149
|
+
}));
|
|
150
|
+
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
const defaultContainer = selectWrapper.current;
|
|
153
|
+
const container = getContainer ? getContainer() || defaultContainer : defaultContainer;
|
|
154
|
+
setDefaultTop(container?.getBoundingClientRect().bottom || 0);
|
|
155
|
+
}, [getContainer, dropdownShown]);
|
|
156
|
+
|
|
157
|
+
const onCancel = props.onCancel || (() => handleShowDropdownChange(false));
|
|
158
|
+
const dropdownCommonProps = {
|
|
159
|
+
showDropdown: dropdownShown,
|
|
160
|
+
top: extraForDropdown?.top || defaultTop,
|
|
161
|
+
onCancel,
|
|
162
|
+
...(extraForDropdown || {}),
|
|
163
|
+
isStopTouchEl: isCurrentSelectEl,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const renderSelectedLabel = (op: OptionsItem | OptionsItem[], index: number) => {
|
|
167
|
+
if (props.multiple === true) {
|
|
168
|
+
const multipleOp = (op as OptionsItem[]) || [];
|
|
169
|
+
return props.renderSelectLabel ? (
|
|
170
|
+
props.renderSelectLabel(multipleOp, index)
|
|
171
|
+
) : (
|
|
172
|
+
<div className={cls(`${prefixCls}-select-item-label-text`)}>
|
|
173
|
+
{multipleOp.map(item => item.label).join(',')}
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
const singleOp = (op as OptionsItem) || [];
|
|
178
|
+
return props.renderSelectLabel ? (
|
|
179
|
+
props.renderSelectLabel(singleOp, index)
|
|
180
|
+
) : (
|
|
181
|
+
<div className={cls(`${prefixCls}-select-item-label-text`)}>{singleOp.label}</div>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<div
|
|
187
|
+
ref={domRef}
|
|
188
|
+
className={cls(`${prefixCls}-dropdown-menu all-border-box`, className, {
|
|
189
|
+
show: dropdownShown,
|
|
190
|
+
})}
|
|
191
|
+
style={style}
|
|
192
|
+
>
|
|
193
|
+
<div className={cls(`${prefixCls}-select`)} ref={selectWrapper}>
|
|
194
|
+
{selectedOptions.map((op, index) => {
|
|
195
|
+
const tip = selectTips[index] || '';
|
|
196
|
+
return (
|
|
197
|
+
<div
|
|
198
|
+
className={cls(`${prefixCls}-select-item`, {
|
|
199
|
+
'is-disabled': disabled[index],
|
|
200
|
+
'is-selected': dropdownShown && selectedIndex === index,
|
|
201
|
+
})}
|
|
202
|
+
key={index}
|
|
203
|
+
data-idx={index}
|
|
204
|
+
onClick={() => handleSelectClick(index)}
|
|
205
|
+
>
|
|
206
|
+
{tip.length > 0 && (
|
|
207
|
+
<span className={cls(`${prefixCls}-select-item-tip`)}>
|
|
208
|
+
{tip}
|
|
209
|
+
</span>
|
|
210
|
+
)}
|
|
211
|
+
<div className={cls(`${prefixCls}-select-item-label`)}>
|
|
212
|
+
{renderSelectedLabel(op, index)}
|
|
213
|
+
{icon === void 0 ? (
|
|
214
|
+
<IconTriDown
|
|
215
|
+
className={cls(`${prefixCls}-select-item-icon`, {
|
|
216
|
+
'is-show': dropdownShown && selectedIndex === index,
|
|
217
|
+
})}
|
|
218
|
+
/>
|
|
219
|
+
) : (
|
|
220
|
+
icon
|
|
221
|
+
)}
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
);
|
|
225
|
+
})}
|
|
226
|
+
{props.multiple === true ? (
|
|
227
|
+
<Comp
|
|
228
|
+
{...({
|
|
229
|
+
multiple: true,
|
|
230
|
+
options: formattedOptions[selectedIndex] || [],
|
|
231
|
+
selectedValue:
|
|
232
|
+
(currentValues[selectedIndex] as OptionValueType[]) || [],
|
|
233
|
+
onOptionClick: (selected, val, op) => {
|
|
234
|
+
props.onOptionClick?.(selected, val, op, selectedIndex);
|
|
235
|
+
},
|
|
236
|
+
onOptionChange: (val, op) => {
|
|
237
|
+
props.onOptionChange?.(val, op, selectedIndex);
|
|
238
|
+
handleValuesChange(val);
|
|
239
|
+
},
|
|
240
|
+
...dropdownCommonProps,
|
|
241
|
+
children,
|
|
242
|
+
} as P)}
|
|
243
|
+
/>
|
|
244
|
+
) : (
|
|
245
|
+
<Comp
|
|
246
|
+
{...({
|
|
247
|
+
multiple: props.multiple,
|
|
248
|
+
options: formattedOptions[selectedIndex] || [],
|
|
249
|
+
selectedValue:
|
|
250
|
+
(currentValues[selectedIndex] as OptionValueType) || 0,
|
|
251
|
+
onOptionClick: (val, op) => {
|
|
252
|
+
props.onOptionClick?.(val, op, selectedIndex);
|
|
253
|
+
if (chooseAndClose) {
|
|
254
|
+
handleShowDropdownChange(false, selectedIndex);
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
onOptionChange: (val, op) => {
|
|
258
|
+
props.onOptionChange?.(val, op, selectedIndex);
|
|
259
|
+
handleValuesChange(val);
|
|
260
|
+
},
|
|
261
|
+
...dropdownCommonProps,
|
|
262
|
+
children,
|
|
263
|
+
} as P)}
|
|
264
|
+
/>
|
|
265
|
+
)}
|
|
266
|
+
</div>
|
|
267
|
+
</div>
|
|
268
|
+
);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { componentGenerator } from './dropdown-menu';
|
|
2
|
+
import Dropdown from '../dropdown';
|
|
3
|
+
|
|
4
|
+
export * from './type';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 下拉选择组件,点击选择器(select)展开下拉框(dropdown),展示选择项(options),兼容多个选择器的情况。
|
|
8
|
+
* @en Dropdown component, click the selector (select) to expand the dropdown box (dropdown), display the options (options), compatible with multiple selectors.
|
|
9
|
+
* @type 导航
|
|
10
|
+
* @type_en Navigation
|
|
11
|
+
* @name 下拉选择菜单
|
|
12
|
+
* @name_en DropdownMenu
|
|
13
|
+
*/
|
|
14
|
+
const DropdownMenu = componentGenerator(Dropdown);
|
|
15
|
+
|
|
16
|
+
export default DropdownMenu;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
### 信息展示
|
|
2
|
+
|
|
3
|
+
# 文本缩略 Ellipsis
|
|
4
|
+
|
|
5
|
+
文本缩略组件,支持多行缩略、富文本、自定义缩略符、尾字符过滤等。如果传入的文本内容中包含换行符号`\n`,建议将`\n`替换为`<br/>`,并设置`dangerouslyUseInnerHTML=true`。
|
|
6
|
+
|
|
7
|
+
======
|
|
8
|
+
|
|
9
|
+
> 属性/Props
|
|
10
|
+
|
|
11
|
+
|参数|描述|类型|默认值|
|
|
12
|
+
|----------|-------------|------|------|
|
|
13
|
+
|className|自定义类名|string|-|
|
|
14
|
+
|maxHeight|最大显示高度,单位 px,优先级高于 maxLine|number|-|
|
|
15
|
+
|endExcludes|文本结尾处(缩略符之前)需要过滤掉的字符|string\[\]|[]|
|
|
16
|
+
|reflowOnResize|容器大小变化时是否自适应,使用原生缩略时默认为 true|boolean|false|
|
|
17
|
+
|floatEllipsisNode|文本缩略时,缩略符节点是否浮在文本右下角(默认加渐变色背景)|boolean|false|
|
|
18
|
+
|onReflow|文本缩略处理的完成回调|(ellipsis: boolean, text: string) =\> void|-|
|
|
19
|
+
|text|需要缩略的文本内容|string|必填|
|
|
20
|
+
|ellipsis|是否开启缩略|boolean|true|
|
|
21
|
+
|maxLine|最大显示行数|number|1|
|
|
22
|
+
|dangerouslyUseInnerHTML|是否使用 innerHTML 插入文本(警告:务必确保 text 安全可靠,否则易导致 XSS 漏洞)|boolean|false|
|
|
23
|
+
|ellipsisNode|自定义缩略符节点,文本缩略时插入文本尾部|ReactNode|"..."|
|
|
24
|
+
|collapseNode|自定义收起符节点,不为空且文本展开时插入文本尾部|ReactNode|-|
|
|
25
|
+
|onEllipsisNodeClick|缩略节点点击事件|(e: MouseEvent\<HTMLSpanElement, MouseEvent\>) =\> void|-|
|
|
26
|
+
|onCollapseNodeClick|收起节点点击事件|(e: MouseEvent\<HTMLSpanElement, MouseEvent\>) =\> void|-|
|
|
27
|
+
|
|
28
|
+
> 引用/Refs
|
|
29
|
+
|
|
30
|
+
|参数|描述|类型|
|
|
31
|
+
|----------|-------------|------|
|
|
32
|
+
|dom|最外层元素 DOM|HTMLDivElement|
|
|
33
|
+
|reflow|控制容器重新编排|() =\> void|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React, { useRef, forwardRef, Ref, useImperativeHandle } from 'react';
|
|
2
|
+
import { cls } from '@arco-design/mobile-utils';
|
|
3
|
+
|
|
4
|
+
import { ContextLayout } from '../context-provider';
|
|
5
|
+
|
|
6
|
+
import { isSupportWebkitLineClamp } from './utils/is';
|
|
7
|
+
import JsEllipsis from './components/js-ellipsis';
|
|
8
|
+
import NativeEllipsis from './components/native-ellipsis';
|
|
9
|
+
import { EllipsisProps, EllipsisRef, JsEllipsisRef } from './type';
|
|
10
|
+
|
|
11
|
+
export * from './type';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 文本缩略组件,支持多行缩略、富文本、自定义缩略符、尾字符过滤等。如果传入的文本内容中包含换行符号`\n`,建议将`\n`替换为`<br/>`,并设置`dangerouslyUseInnerHTML=true`。
|
|
15
|
+
* @en Text ellipsis component supports multi-line abbreviations, rich text, custom abbreviations, tail character filtering, etc. If the incoming text contains newline characters `\n`, it is recommended to replace `\n` with `<br/>`, and set `dangerouslyUseInnerHTML=true`.
|
|
16
|
+
* @type 信息展示
|
|
17
|
+
* @type_en Data Display
|
|
18
|
+
* @name 文本缩略
|
|
19
|
+
* @name_en Ellipsis
|
|
20
|
+
*/
|
|
21
|
+
const Ellipsis = forwardRef((props: EllipsisProps, ref: Ref<EllipsisRef>) => {
|
|
22
|
+
const {
|
|
23
|
+
className,
|
|
24
|
+
text,
|
|
25
|
+
dangerouslyUseInnerHTML,
|
|
26
|
+
maxLine = 1,
|
|
27
|
+
maxHeight,
|
|
28
|
+
ellipsis = true,
|
|
29
|
+
ellipsisNode = '...',
|
|
30
|
+
collapseNode = '',
|
|
31
|
+
endExcludes,
|
|
32
|
+
reflowOnResize = false,
|
|
33
|
+
floatEllipsisNode = false,
|
|
34
|
+
onReflow,
|
|
35
|
+
onCollapseNodeClick,
|
|
36
|
+
onEllipsisNodeClick,
|
|
37
|
+
} = props;
|
|
38
|
+
const domRef = useRef<HTMLDivElement | null>(null);
|
|
39
|
+
const jsEllipsisRef = useRef<JsEllipsisRef>(null);
|
|
40
|
+
|
|
41
|
+
const useNativeEllipsis =
|
|
42
|
+
isSupportWebkitLineClamp() &&
|
|
43
|
+
maxHeight === void 0 &&
|
|
44
|
+
(!endExcludes || endExcludes.length === 0) &&
|
|
45
|
+
!onReflow &&
|
|
46
|
+
(floatEllipsisNode || (ellipsisNode === '...' && !onEllipsisNodeClick));
|
|
47
|
+
|
|
48
|
+
useImperativeHandle(ref, () => ({
|
|
49
|
+
dom: domRef.current,
|
|
50
|
+
reflow: jsEllipsisRef?.current?.reflow,
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<ContextLayout>
|
|
55
|
+
{({ prefixCls }) => (
|
|
56
|
+
<div className={cls(`${prefixCls}-ellipsis`, className)} ref={domRef}>
|
|
57
|
+
{useNativeEllipsis ? (
|
|
58
|
+
<NativeEllipsis
|
|
59
|
+
prefixCls={`${prefixCls}-ellipsis`}
|
|
60
|
+
ellipsis={ellipsis}
|
|
61
|
+
dangerouslyUseInnerHTML={dangerouslyUseInnerHTML}
|
|
62
|
+
text={text}
|
|
63
|
+
maxLine={maxLine}
|
|
64
|
+
ellipsisNode={ellipsisNode}
|
|
65
|
+
collapseNode={collapseNode}
|
|
66
|
+
onEllipsisNodeClick={onEllipsisNodeClick}
|
|
67
|
+
onCollapseNodeClick={onCollapseNodeClick}
|
|
68
|
+
/>
|
|
69
|
+
) : (
|
|
70
|
+
<JsEllipsis
|
|
71
|
+
ref={jsEllipsisRef}
|
|
72
|
+
prefixCls={`${prefixCls}-ellipsis`}
|
|
73
|
+
text={text}
|
|
74
|
+
ellipsis={ellipsis}
|
|
75
|
+
dangerouslyUseInnerHTML={dangerouslyUseInnerHTML}
|
|
76
|
+
maxLine={maxLine}
|
|
77
|
+
maxHeight={maxHeight}
|
|
78
|
+
ellipsisNode={ellipsisNode}
|
|
79
|
+
collapseNode={collapseNode}
|
|
80
|
+
endExcludes={endExcludes}
|
|
81
|
+
reflowOnResize={reflowOnResize}
|
|
82
|
+
onReflow={onReflow}
|
|
83
|
+
onEllipsisNodeClick={onEllipsisNodeClick}
|
|
84
|
+
onCollapseNodeClick={onCollapseNodeClick}
|
|
85
|
+
/>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
)}
|
|
89
|
+
</ContextLayout>
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export default Ellipsis;
|