@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,410 @@
|
|
|
1
|
+
import type { Ref, ReactNode, CSSProperties } from 'react';
|
|
2
|
+
import React, { useRef, forwardRef, useImperativeHandle, useEffect, useState } from 'react';
|
|
3
|
+
import { cls, nextTick, componentWrapper } from '@arco-design/mobile-utils';
|
|
4
|
+
import { ContextLayout, CompWithGlobalContext } from '../context-provider';
|
|
5
|
+
import Portal from '../portal';
|
|
6
|
+
import type { TransitionProps } from '../transition';
|
|
7
|
+
import Transition from '../transition';
|
|
8
|
+
import { usePopupScroll, usePreventBodyScroll } from '../_helpers';
|
|
9
|
+
import type { OpenBaseProps } from './methods';
|
|
10
|
+
import { open } from './methods';
|
|
11
|
+
|
|
12
|
+
export * from './methods';
|
|
13
|
+
|
|
14
|
+
export interface MaskingCommonProps {
|
|
15
|
+
/**
|
|
16
|
+
* 自定义类名
|
|
17
|
+
* @en Custom classname
|
|
18
|
+
*/
|
|
19
|
+
className?: string;
|
|
20
|
+
/**
|
|
21
|
+
* 自定义蒙层类名
|
|
22
|
+
* @en Custom mask classname
|
|
23
|
+
*/
|
|
24
|
+
maskClass?: string;
|
|
25
|
+
/**
|
|
26
|
+
* 自定义蒙层样式
|
|
27
|
+
* @en Custom mask stylesheet
|
|
28
|
+
*/
|
|
29
|
+
maskStyle?: CSSProperties;
|
|
30
|
+
/**
|
|
31
|
+
* 自定义内容类名
|
|
32
|
+
* @en Custom content classname
|
|
33
|
+
*/
|
|
34
|
+
contentClass?: string;
|
|
35
|
+
/**
|
|
36
|
+
* 自定义内容样式
|
|
37
|
+
* @en Custom content stylesheet
|
|
38
|
+
*/
|
|
39
|
+
contentStyle?: CSSProperties;
|
|
40
|
+
/**
|
|
41
|
+
* 是否展示菜单(受控)
|
|
42
|
+
* @en Whether to display the menu (controlled)
|
|
43
|
+
*/
|
|
44
|
+
visible: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* 关闭菜单方法
|
|
47
|
+
* @en Close menu method
|
|
48
|
+
*/
|
|
49
|
+
close: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
50
|
+
/**
|
|
51
|
+
* 蒙层过渡动画类名
|
|
52
|
+
* @en Mask transition animation classname
|
|
53
|
+
* @default "fade"
|
|
54
|
+
*/
|
|
55
|
+
maskTransitionType?: string;
|
|
56
|
+
/**
|
|
57
|
+
* 内容过渡动画类名
|
|
58
|
+
* @en Content transition animation classname
|
|
59
|
+
* @default "fade"
|
|
60
|
+
*/
|
|
61
|
+
contentTransitionType?: string;
|
|
62
|
+
/**
|
|
63
|
+
* 内容过渡动画类名变量标识
|
|
64
|
+
* @en Content transition animation classname variable identifier
|
|
65
|
+
*/
|
|
66
|
+
contentTransitionVarType?: string;
|
|
67
|
+
/**
|
|
68
|
+
* 菜单内部内容
|
|
69
|
+
* @en Contents of menu
|
|
70
|
+
*/
|
|
71
|
+
children?: ReactNode;
|
|
72
|
+
/**
|
|
73
|
+
* 蒙层动画时长
|
|
74
|
+
* @en Mask animation duration
|
|
75
|
+
* @default 300
|
|
76
|
+
*/
|
|
77
|
+
maskTransitionTimeout?: TransitionProps['timeout'];
|
|
78
|
+
/**
|
|
79
|
+
* 内容动画时长
|
|
80
|
+
* @en Content animation duration
|
|
81
|
+
* @default 300
|
|
82
|
+
*/
|
|
83
|
+
contentTransitionTimeout?: TransitionProps['timeout'];
|
|
84
|
+
/**
|
|
85
|
+
* 点击蒙层是否关闭菜单
|
|
86
|
+
* @en Whether to click the mask to close the menu
|
|
87
|
+
* @default true
|
|
88
|
+
*/
|
|
89
|
+
maskClosable?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* 执行进场动画时点击蒙层是否可关闭菜单
|
|
92
|
+
* @en Whether the menu can be closed by clicking on the mask when performing the entry animation
|
|
93
|
+
* @default false
|
|
94
|
+
*/
|
|
95
|
+
animatingClosable?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* 是否在打开菜单时再加载内容
|
|
98
|
+
* @en Whether to reload content when the menu is opened
|
|
99
|
+
* @default true
|
|
100
|
+
*/
|
|
101
|
+
mountOnEnter?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* 是否在退出时卸载内容
|
|
104
|
+
* @en Whether to unmount content on exit
|
|
105
|
+
* @default true
|
|
106
|
+
*/
|
|
107
|
+
unmountOnExit?: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* transform方向,用于通过transform模拟横屏的情况
|
|
110
|
+
* @en The transform direction, used to simulate the situation of horizontal screen through transform
|
|
111
|
+
* @default "top"
|
|
112
|
+
*/
|
|
113
|
+
orientationDirection?: 'top' | 'bottom' | 'left' | 'right';
|
|
114
|
+
/**
|
|
115
|
+
* 弹窗打开时是否禁止body的滚动
|
|
116
|
+
* @en Whether to prohibit the scrolling of the body when the popup is opened
|
|
117
|
+
* @default true
|
|
118
|
+
*/
|
|
119
|
+
preventBodyScroll?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* 页面初始 overflow 状态,即关闭弹窗时 overflow 应该还原的状态
|
|
122
|
+
* @en The initial overflow state of the page, that is, the state in which overflow should be restored when the popup is closed
|
|
123
|
+
* @default 第一个全屏组件(弹窗、toast等)打开时页面overflow值
|
|
124
|
+
* @default_en The page overflow value when the first fullscreen component (popup, toast, etc.) is opened
|
|
125
|
+
*/
|
|
126
|
+
initialBodyOverflow?: string;
|
|
127
|
+
/**
|
|
128
|
+
* 是否禁用滚动容器手势判断,禁用后交给业务方自己判断
|
|
129
|
+
* @en Whether to disable the scrolling container gesture judgment, leave it to users to judge
|
|
130
|
+
* @default false
|
|
131
|
+
*/
|
|
132
|
+
gestureOutOfControl?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* 关闭后回调(动画执行完毕)
|
|
135
|
+
* @en Callback after closing (animation is completed)
|
|
136
|
+
*/
|
|
137
|
+
onClose?: (scene?: string) => void;
|
|
138
|
+
/**
|
|
139
|
+
* 打开后回调(动画执行完毕)
|
|
140
|
+
* @en Callback after opening (animation is completed)
|
|
141
|
+
*/
|
|
142
|
+
onOpen?: () => void;
|
|
143
|
+
/**
|
|
144
|
+
* 点击蒙层回调,maskClosable=false时也会触发
|
|
145
|
+
* @en Callback when clicking the mask , also triggered when maskClosable=false
|
|
146
|
+
*/
|
|
147
|
+
onMaskClick?: () => void;
|
|
148
|
+
/**
|
|
149
|
+
* 弹窗的touchmove回调
|
|
150
|
+
* @en Touch event callbacks for masking
|
|
151
|
+
*/
|
|
152
|
+
onTouchMove?: (e: TouchEvent, prevented: boolean, direction: 'x' | 'y') => void;
|
|
153
|
+
/**
|
|
154
|
+
* 非滚动区域或滚动到顶部及底部时的触摸事件回调
|
|
155
|
+
* @en Touch event callbacks for non-scrolling areas or when scrolling to the top and bottom
|
|
156
|
+
*/
|
|
157
|
+
onPreventTouchMove?: (e: TouchEvent, direction: 'x' | 'y') => void;
|
|
158
|
+
/**
|
|
159
|
+
* 获取挂载容器
|
|
160
|
+
* @en Get mounted container
|
|
161
|
+
*/
|
|
162
|
+
getContainer?: () => HTMLElement;
|
|
163
|
+
/**
|
|
164
|
+
* 内容内部滚动区域容器,在该容器中未滚动到顶部或底部时会释放滚动
|
|
165
|
+
* @en Container of inner scroll area in content, scroll is released when not scrolled to the top or bottom in this container
|
|
166
|
+
*/
|
|
167
|
+
getScrollContainer?: () => HTMLElement[] | HTMLElement | null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface MaskingProps extends MaskingCommonProps {
|
|
171
|
+
/**
|
|
172
|
+
* 弹窗内容是否居中
|
|
173
|
+
* @en Whether the content of the popup window is centered
|
|
174
|
+
* @default false
|
|
175
|
+
*/
|
|
176
|
+
contentAtCenter?: boolean;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface MaskingRef {
|
|
180
|
+
/**
|
|
181
|
+
* 最外层元素 DOM
|
|
182
|
+
* @en The outermost element DOM
|
|
183
|
+
*/
|
|
184
|
+
dom: HTMLDivElement | null;
|
|
185
|
+
/**
|
|
186
|
+
* 蒙层 DOM
|
|
187
|
+
* @en Mask DOM
|
|
188
|
+
*/
|
|
189
|
+
mask: HTMLDivElement | null;
|
|
190
|
+
/**
|
|
191
|
+
* 内容 DOM
|
|
192
|
+
* @en Content DOM
|
|
193
|
+
*/
|
|
194
|
+
content: HTMLDivElement | null;
|
|
195
|
+
/**
|
|
196
|
+
* 在关闭弹窗前修改 onClose 的 scene 参数值
|
|
197
|
+
* @en Modify the scene of onClose before closing the popup
|
|
198
|
+
*/
|
|
199
|
+
setCloseScene: (scene: string) => void;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const Masking = forwardRef((props: MaskingProps, ref: Ref<MaskingRef>) => {
|
|
203
|
+
const {
|
|
204
|
+
className,
|
|
205
|
+
visible = false,
|
|
206
|
+
maskClass,
|
|
207
|
+
maskStyle,
|
|
208
|
+
contentClass,
|
|
209
|
+
contentStyle,
|
|
210
|
+
close,
|
|
211
|
+
onClose,
|
|
212
|
+
onOpen,
|
|
213
|
+
onMaskClick,
|
|
214
|
+
children,
|
|
215
|
+
maskTransitionType = 'fade',
|
|
216
|
+
contentTransitionType = 'fade',
|
|
217
|
+
contentTransitionVarType,
|
|
218
|
+
maskTransitionTimeout = 300,
|
|
219
|
+
contentTransitionTimeout = 300,
|
|
220
|
+
maskClosable = true,
|
|
221
|
+
animatingClosable,
|
|
222
|
+
mountOnEnter = true,
|
|
223
|
+
unmountOnExit = true,
|
|
224
|
+
orientationDirection = 'top',
|
|
225
|
+
preventBodyScroll = true,
|
|
226
|
+
initialBodyOverflow,
|
|
227
|
+
contentAtCenter = false,
|
|
228
|
+
gestureOutOfControl = false,
|
|
229
|
+
getContainer,
|
|
230
|
+
getScrollContainer,
|
|
231
|
+
onPreventTouchMove,
|
|
232
|
+
onTouchMove,
|
|
233
|
+
} = props;
|
|
234
|
+
const domRef = useRef<HTMLDivElement>(null);
|
|
235
|
+
const maskRef = useRef<HTMLDivElement>(null);
|
|
236
|
+
const contentRef = useRef<HTMLDivElement>(null);
|
|
237
|
+
const timerRef = useRef(-1);
|
|
238
|
+
const isInitialMount = useRef(false);
|
|
239
|
+
const isAnimating = useRef(false);
|
|
240
|
+
const closeScene = useRef('');
|
|
241
|
+
const [innerVisible, setInnerVisible] = useState(visible);
|
|
242
|
+
const [outerVisible, setOuterVisible] = useState(visible);
|
|
243
|
+
const [extraClass, setExtraClass] = useState('');
|
|
244
|
+
|
|
245
|
+
useImperativeHandle(ref, () => ({
|
|
246
|
+
dom: domRef.current,
|
|
247
|
+
mask: maskRef.current,
|
|
248
|
+
content: contentRef.current,
|
|
249
|
+
setCloseScene,
|
|
250
|
+
}));
|
|
251
|
+
|
|
252
|
+
usePopupScroll(
|
|
253
|
+
innerVisible,
|
|
254
|
+
domRef.current,
|
|
255
|
+
getScrollContainer,
|
|
256
|
+
orientationDirection,
|
|
257
|
+
onPreventTouchMove,
|
|
258
|
+
onTouchMove,
|
|
259
|
+
gestureOutOfControl,
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
usePreventBodyScroll(visible, preventBodyScroll, initialBodyOverflow);
|
|
263
|
+
|
|
264
|
+
useEffect(() => {
|
|
265
|
+
if (timerRef.current >= 0) {
|
|
266
|
+
clearTimeout(timerRef.current);
|
|
267
|
+
}
|
|
268
|
+
const mounted = isInitialMount.current;
|
|
269
|
+
if (mounted) {
|
|
270
|
+
isAnimating.current = true;
|
|
271
|
+
}
|
|
272
|
+
if (!mounted && !visible && !mountOnEnter) {
|
|
273
|
+
setExtraClass('pre-mount');
|
|
274
|
+
}
|
|
275
|
+
if (visible) {
|
|
276
|
+
setOuterVisible(true);
|
|
277
|
+
nextTick(() => {
|
|
278
|
+
setInnerVisible(true);
|
|
279
|
+
execAfterOpen(() => {
|
|
280
|
+
isAnimating.current = false;
|
|
281
|
+
setExtraClass('');
|
|
282
|
+
mounted && onOpen?.();
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
} else {
|
|
286
|
+
setInnerVisible(false);
|
|
287
|
+
timerRef.current = execAfterClose(() => {
|
|
288
|
+
isAnimating.current = false;
|
|
289
|
+
setOuterVisible(false);
|
|
290
|
+
mounted && onClose?.(closeScene.current || void 0);
|
|
291
|
+
closeScene.current = '';
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
isInitialMount.current = true;
|
|
295
|
+
}, [visible]);
|
|
296
|
+
|
|
297
|
+
function setCloseScene(scene: string) {
|
|
298
|
+
closeScene.current = scene;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function execAfterClose(callback: () => void) {
|
|
302
|
+
return window.setTimeout(
|
|
303
|
+
callback,
|
|
304
|
+
Math.max(
|
|
305
|
+
getMaxTimeout(maskTransitionTimeout, 'exit'),
|
|
306
|
+
getMaxTimeout(contentTransitionTimeout, 'exit'),
|
|
307
|
+
),
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function execAfterOpen(callback: () => void) {
|
|
312
|
+
return window.setTimeout(
|
|
313
|
+
callback,
|
|
314
|
+
Math.max(
|
|
315
|
+
getMaxTimeout(maskTransitionTimeout, 'enter'),
|
|
316
|
+
getMaxTimeout(contentTransitionTimeout, 'enter'),
|
|
317
|
+
),
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function getMaxTimeout(timeout: TransitionProps['timeout'], type: 'appear' | 'enter' | 'exit') {
|
|
322
|
+
return typeof timeout === 'number' ? timeout : timeout[type] || 0;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function handleMaskAction(e: React.MouseEvent<HTMLElement, MouseEvent>) {
|
|
326
|
+
e.preventDefault();
|
|
327
|
+
e.stopPropagation();
|
|
328
|
+
onMaskClick?.();
|
|
329
|
+
if (!maskClosable || (!animatingClosable && isAnimating.current)) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
closeScene.current = 'mask';
|
|
333
|
+
close?.(e);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function renderMasking({ prefixCls }) {
|
|
337
|
+
return !mountOnEnter || outerVisible || !unmountOnExit ? (
|
|
338
|
+
<Portal getContainer={getContainer}>
|
|
339
|
+
<div
|
|
340
|
+
className={cls(`${prefixCls}-masking`, 'all-border-box', className)}
|
|
341
|
+
ref={domRef}
|
|
342
|
+
>
|
|
343
|
+
<Transition
|
|
344
|
+
in={innerVisible}
|
|
345
|
+
timeout={maskTransitionTimeout}
|
|
346
|
+
type={maskTransitionType}
|
|
347
|
+
mountOnEnter={mountOnEnter}
|
|
348
|
+
unmountOnExit={unmountOnExit}
|
|
349
|
+
nodeRef={maskRef}
|
|
350
|
+
>
|
|
351
|
+
<div
|
|
352
|
+
ref={maskRef}
|
|
353
|
+
className={cls(`${prefixCls}-masking-mask`, extraClass, maskClass)}
|
|
354
|
+
onClick={handleMaskAction}
|
|
355
|
+
style={maskStyle}
|
|
356
|
+
/>
|
|
357
|
+
</Transition>
|
|
358
|
+
<Transition
|
|
359
|
+
in={innerVisible}
|
|
360
|
+
timeout={contentTransitionTimeout}
|
|
361
|
+
type={contentTransitionType}
|
|
362
|
+
transitionVarType={contentTransitionVarType}
|
|
363
|
+
mountOnEnter={mountOnEnter}
|
|
364
|
+
unmountOnExit={unmountOnExit}
|
|
365
|
+
nodeRef={contentRef}
|
|
366
|
+
>
|
|
367
|
+
<div
|
|
368
|
+
ref={contentRef}
|
|
369
|
+
className={cls(
|
|
370
|
+
`${prefixCls}-masking-content`,
|
|
371
|
+
{ 'at-center': contentAtCenter },
|
|
372
|
+
extraClass,
|
|
373
|
+
contentClass,
|
|
374
|
+
)}
|
|
375
|
+
style={contentStyle}
|
|
376
|
+
>
|
|
377
|
+
{children}
|
|
378
|
+
</div>
|
|
379
|
+
</Transition>
|
|
380
|
+
</div>
|
|
381
|
+
</Portal>
|
|
382
|
+
) : null;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return <ContextLayout>{renderMasking}</ContextLayout>;
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
export function methodsGenerator<P extends OpenBaseProps>(Comp: React.FunctionComponent<P>) {
|
|
389
|
+
return {
|
|
390
|
+
/**
|
|
391
|
+
* 打开模态弹窗
|
|
392
|
+
* @desc {en} Open a Masking
|
|
393
|
+
* @param {MaskingProps} config Configuration
|
|
394
|
+
* @returns {{ close: () => void; update: (newConfig: MaskingProps) => void; }}
|
|
395
|
+
*/
|
|
396
|
+
open: open(Comp),
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const MaskingWithGlobalContext = CompWithGlobalContext(Masking);
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* 通用模态弹窗,内部内容自定义。默认做了防滚动穿透处理,如果弹层内容中需要滚动,则需将滚动容器传入`getScrollContainer`属性以在未滚动到顶部或底部时释放滚动。
|
|
404
|
+
* @en Generic modal popup with custom internal content. By default, anti-scroll penetration processing is performed. If scrolling is required in the content of the bullet layer, need to pass the scroll container to the `getScrollContainer` to release scrolling when it is not scrolled to the top or bottom.
|
|
405
|
+
* @type 反馈
|
|
406
|
+
* @type_en Feedback
|
|
407
|
+
* @name 模态弹窗
|
|
408
|
+
* @name_en Masking
|
|
409
|
+
*/
|
|
410
|
+
export default componentWrapper(Masking, methodsGenerator(MaskingWithGlobalContext));
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { appendElementById, removeElement, nextTick } from '@arco-design/mobile-utils';
|
|
3
|
+
import { ReactDOMRender, renderRootCache } from '../_helpers/render';
|
|
4
|
+
import { GlobalContextParams } from '../context-provider';
|
|
5
|
+
|
|
6
|
+
export interface OpenBaseProps {
|
|
7
|
+
// 从config继承的属性
|
|
8
|
+
unmountOnExit?: boolean;
|
|
9
|
+
getContainer?: () => HTMLElement;
|
|
10
|
+
onClose?: (scene?: string) => void;
|
|
11
|
+
// 强制定义的属性
|
|
12
|
+
visible: boolean;
|
|
13
|
+
close: (e) => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getOpenMethod<T extends { key?: string }, P extends OpenBaseProps>(
|
|
17
|
+
Component: React.FunctionComponent<P>,
|
|
18
|
+
containerId?: string,
|
|
19
|
+
normalize: (config: T) => P = config => config as any,
|
|
20
|
+
) {
|
|
21
|
+
return (config: T, context?: GlobalContextParams) => {
|
|
22
|
+
const baseProps: P = {
|
|
23
|
+
unmountOnExit: true,
|
|
24
|
+
...normalize(config),
|
|
25
|
+
visible: false,
|
|
26
|
+
close: () => {},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// 不同的key用不同的容器挂载
|
|
30
|
+
const id = `_${containerId || 'ARCO_MASKING'}_DIV_${config.key || ''}_`;
|
|
31
|
+
const existedDiv = baseProps.unmountOnExit ? null : document.getElementById(id);
|
|
32
|
+
const div = existedDiv || appendElementById(id, baseProps.getContainer).child;
|
|
33
|
+
let leaving = false;
|
|
34
|
+
const { render, unmount, setRootCache } = new ReactDOMRender(
|
|
35
|
+
Component,
|
|
36
|
+
div,
|
|
37
|
+
context,
|
|
38
|
+
id,
|
|
39
|
+
existedDiv ? renderRootCache[id] : undefined,
|
|
40
|
+
);
|
|
41
|
+
let dynamicProps = { ...baseProps, getContainer: () => div };
|
|
42
|
+
|
|
43
|
+
function update(newConfig: T) {
|
|
44
|
+
dynamicProps = {
|
|
45
|
+
...dynamicProps,
|
|
46
|
+
...normalize(newConfig),
|
|
47
|
+
};
|
|
48
|
+
render(dynamicProps);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function close() {
|
|
52
|
+
leaving = true;
|
|
53
|
+
dynamicProps.visible = false;
|
|
54
|
+
render(dynamicProps);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
dynamicProps.close = close;
|
|
58
|
+
dynamicProps.onClose = scene => {
|
|
59
|
+
baseProps.onClose && baseProps.onClose(scene);
|
|
60
|
+
if (baseProps.unmountOnExit) {
|
|
61
|
+
unmount();
|
|
62
|
+
removeElement(div);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
render(dynamicProps);
|
|
66
|
+
if (!baseProps.unmountOnExit) {
|
|
67
|
+
setRootCache();
|
|
68
|
+
}
|
|
69
|
+
nextTick(() => {
|
|
70
|
+
if (leaving) return;
|
|
71
|
+
dynamicProps.visible = true;
|
|
72
|
+
render(dynamicProps);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
close,
|
|
77
|
+
update,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function open<P extends OpenBaseProps>(
|
|
83
|
+
Component: React.FunctionComponent<P>,
|
|
84
|
+
containerId?: string,
|
|
85
|
+
) {
|
|
86
|
+
type Config = Omit<P, 'visible' | 'close'> & { key?: string };
|
|
87
|
+
return getOpenMethod<Config, P>(Component, containerId);
|
|
88
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
### 导航
|
|
2
|
+
|
|
3
|
+
# 导航栏 NavBar
|
|
4
|
+
|
|
5
|
+
导航栏组件,支持吸顶和沉浸式,支持在指定滚动位置展示,支持根据滚动位置实时更新style。
|
|
6
|
+
|
|
7
|
+
======
|
|
8
|
+
|
|
9
|
+
> 属性/Props
|
|
10
|
+
|
|
11
|
+
|参数|描述|类型|默认值|
|
|
12
|
+
|----------|-------------|------|------|
|
|
13
|
+
|title|导航栏中间文字,带居中和溢出省略效果|ReactNode|-|
|
|
14
|
+
|children|自定义导航栏主内容,当导航栏内容为Tabs等非居中文字样式时可用|ReactNode|-|
|
|
15
|
+
|leftContent|导航栏左侧内容|ReactNode|返回按钮|
|
|
16
|
+
|rightContent|导航栏右侧内容|ReactNode|-|
|
|
17
|
+
|style|自定义样式,最外层元素的背景文字颜色可在此定义|CSSProperties|-|
|
|
18
|
+
|className|内层自定义类名|string|-|
|
|
19
|
+
|wrapClass|最外层元素自定义类名|string|-|
|
|
20
|
+
|fixed|是否吸顶|boolean|-|
|
|
21
|
+
|statusBarHeight|沉浸式状态栏高度|number|0|
|
|
22
|
+
|hasBottomLine|是否有底边框|boolean|true|
|
|
23
|
+
|onClickLeft|点击左侧内容回调|(e: MouseEvent\<Element, MouseEvent\>) =\> void|-|
|
|
24
|
+
|onClickRight|点击右侧内容回调|(e: MouseEvent\<Element, MouseEvent\>) =\> void|-|
|
|
25
|
+
|showOffset|展示nav\-bar的offset值,当scrollTop值小于该值时,将隐藏主内容和右侧内容,左侧内容保留|number|0|
|
|
26
|
+
|onShowChange|设置showOffset后,当内容显示状态发生变化后触发|(show: boolean) =\> void|-|
|
|
27
|
+
|placeholder|设置fixed=true时,导航栏原本的位置是否要占住|boolean|true|
|
|
28
|
+
|extra|额外渲染元素,与inner平级|ReactNode|-|
|
|
29
|
+
|getScrollContainer|自定义滚动元素,不传默认是window|() =\> HTMLElement \| Window|-|
|
|
30
|
+
|getComputedStyleByScroll|根据滚动offset值设置自定义style,设置该属性后将监听滚动容器的滚动事件|(offset: number) =\> CSSProperties|-|
|
|
31
|
+
|onScrollChange|滚动时回调,设置该属性后将监听滚动容器的滚动事件|(offset: number) =\> void|-|
|
|
32
|
+
|ariaLabel|无障碍aria\-label属性|string|""|
|
|
33
|
+
|ariaRole|无障碍role属性|string|"banner"|
|
|
34
|
+
|
|
35
|
+
> 引用/Refs
|
|
36
|
+
|
|
37
|
+
|参数|描述|类型|
|
|
38
|
+
|----------|-------------|------|
|
|
39
|
+
|navBar|@deprecated|HTMLDivElement|
|
|
40
|
+
|dom|最外层元素DOM|HTMLDivElement|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { defaultLocale } from '@arco-design/mobile-utils';
|
|
3
|
+
import { ContextLayout } from '../context-provider';
|
|
4
|
+
|
|
5
|
+
function BackArrow({ color = 'currentColor' }) {
|
|
6
|
+
return (
|
|
7
|
+
<ContextLayout>
|
|
8
|
+
{({ locale = defaultLocale }) => (
|
|
9
|
+
<div
|
|
10
|
+
role="button"
|
|
11
|
+
className="c-svg-arrow nav-bar-back"
|
|
12
|
+
aria-label={locale.NavBar.backBtnAriaLabel}
|
|
13
|
+
>
|
|
14
|
+
<svg height="100%" viewBox="0 0 16 16">
|
|
15
|
+
<path
|
|
16
|
+
id="path-1_1_"
|
|
17
|
+
d="M2.1,8l5.4,5.4c0.1,0.1,0.1,0.3,0,0.5L7,14.4c-0.1,0.1-0.3,0.1-0.5,0L0.7,8.5c-0.3-0.3-0.3-0.7,0-0.9
|
|
18
|
+
l5.9-5.9c0.1-0.1,0.3-0.1,0.5,0l0.5,0.5c0.1,0.1,0.1,0.3,0,0.5L2.1,8z"
|
|
19
|
+
fill={color}
|
|
20
|
+
/>
|
|
21
|
+
</svg>
|
|
22
|
+
</div>
|
|
23
|
+
)}
|
|
24
|
+
</ContextLayout>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default BackArrow;
|