@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.
Files changed (191) hide show
  1. package/README.md +85 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +244 -0
  4. package/metaData/components/action-sheet/doc.md +102 -0
  5. package/metaData/components/action-sheet/example/index.tsx +199 -0
  6. package/metaData/components/action-sheet/example/methods.tsx +6 -0
  7. package/metaData/components/avatar/doc.md +57 -0
  8. package/metaData/components/avatar/example/group.tsx +69 -0
  9. package/metaData/components/avatar/example/index.tsx +196 -0
  10. package/metaData/components/badge/doc.md +28 -0
  11. package/metaData/components/badge/example/index.tsx +128 -0
  12. package/metaData/components/button/doc.md +45 -0
  13. package/metaData/components/button/example/index.tsx +264 -0
  14. package/metaData/components/carousel/doc.md +89 -0
  15. package/metaData/components/carousel/example/index.tsx +1481 -0
  16. package/metaData/components/cell/doc.md +68 -0
  17. package/metaData/components/cell/example/arrow.tsx +13 -0
  18. package/metaData/components/cell/example/cell.tsx +71 -0
  19. package/metaData/components/cell/example/group.tsx +63 -0
  20. package/metaData/components/cell/example/index.tsx +19 -0
  21. package/metaData/components/checkbox/doc.md +91 -0
  22. package/metaData/components/checkbox/example/checkbox.tsx +158 -0
  23. package/metaData/components/checkbox/example/group.tsx +103 -0
  24. package/metaData/components/checkbox/example/index.tsx +25 -0
  25. package/metaData/components/circle-progress/doc.md +40 -0
  26. package/metaData/components/circle-progress/example/index.tsx +323 -0
  27. package/metaData/components/collapse/doc.md +74 -0
  28. package/metaData/components/collapse/example/collapse.tsx +183 -0
  29. package/metaData/components/collapse/example/group.tsx +136 -0
  30. package/metaData/components/collapse/example/index.tsx +16 -0
  31. package/metaData/components/collapse/example/utils.tsx +20 -0
  32. package/metaData/components/context-provider/doc.md +44 -0
  33. package/metaData/components/context-provider/example/index.tsx +208 -0
  34. package/metaData/components/count-down/doc.md +40 -0
  35. package/metaData/components/count-down/example/hooks.tsx +118 -0
  36. package/metaData/components/count-down/example/index.tsx +63 -0
  37. package/metaData/components/date-picker/doc.md +102 -0
  38. package/metaData/components/date-picker/example/index.tsx +545 -0
  39. package/metaData/components/dialog/doc.md +200 -0
  40. package/metaData/components/dialog/example/index.tsx +328 -0
  41. package/metaData/components/dialog/example/methods.tsx +56 -0
  42. package/metaData/components/divider/doc.md +25 -0
  43. package/metaData/components/divider/example/index.tsx +87 -0
  44. package/metaData/components/dropdown/doc.md +80 -0
  45. package/metaData/components/dropdown/example/dropdown.tsx +308 -0
  46. package/metaData/components/dropdown/example/index.tsx +19 -0
  47. package/metaData/components/dropdown/example/options.tsx +103 -0
  48. package/metaData/components/dropdown-menu/doc.md +91 -0
  49. package/metaData/components/dropdown-menu/example/dropdown-menu.tsx +270 -0
  50. package/metaData/components/dropdown-menu/example/index.tsx +16 -0
  51. package/metaData/components/ellipsis/doc.md +33 -0
  52. package/metaData/components/ellipsis/example/index.tsx +93 -0
  53. package/metaData/components/ellipsis/example/js-ellipsis.tsx +229 -0
  54. package/metaData/components/ellipsis/example/native-ellipsis.tsx +48 -0
  55. package/metaData/components/form/doc.md +90 -0
  56. package/metaData/components/form/example/form-item-context.tsx +8 -0
  57. package/metaData/components/form/example/form-item.tsx +378 -0
  58. package/metaData/components/form/example/index.tsx +87 -0
  59. package/metaData/components/form/example/linked-container.tsx +66 -0
  60. package/metaData/components/grid/doc.md +39 -0
  61. package/metaData/components/grid/example/index.tsx +252 -0
  62. package/metaData/components/icon/doc.md +15 -0
  63. package/metaData/components/icon/example/index.tsx +32 -0
  64. package/metaData/components/image/doc.md +62 -0
  65. package/metaData/components/image/example/index.tsx +528 -0
  66. package/metaData/components/image-picker/doc.md +116 -0
  67. package/metaData/components/image-picker/example/add-icon.tsx +14 -0
  68. package/metaData/components/image-picker/example/index.tsx +175 -0
  69. package/metaData/components/image-preview/doc.md +119 -0
  70. package/metaData/components/image-preview/example/index.tsx +1290 -0
  71. package/metaData/components/image-preview/example/methods.tsx +72 -0
  72. package/metaData/components/index-bar/doc.md +83 -0
  73. package/metaData/components/index-bar/example/group.tsx +93 -0
  74. package/metaData/components/index-bar/example/index.tsx +271 -0
  75. package/metaData/components/index-bar/example/side-bar.tsx +82 -0
  76. package/metaData/components/input/doc.md +60 -0
  77. package/metaData/components/input/example/hooks.tsx +259 -0
  78. package/metaData/components/input/example/index.tsx +134 -0
  79. package/metaData/components/input/example/props.tsx +183 -0
  80. package/metaData/components/keyboard/doc.md +73 -0
  81. package/metaData/components/keyboard/example/index.tsx +238 -0
  82. package/metaData/components/load-more/doc.md +48 -0
  83. package/metaData/components/load-more/example/index.tsx +395 -0
  84. package/metaData/components/loading/doc.md +34 -0
  85. package/metaData/components/loading/example/index.tsx +312 -0
  86. package/metaData/components/masking/doc.md +93 -0
  87. package/metaData/components/masking/example/index.tsx +410 -0
  88. package/metaData/components/masking/example/methods.tsx +88 -0
  89. package/metaData/components/nav-bar/doc.md +40 -0
  90. package/metaData/components/nav-bar/example/back-icon.tsx +28 -0
  91. package/metaData/components/nav-bar/example/index.tsx +305 -0
  92. package/metaData/components/notice-bar/doc.md +34 -0
  93. package/metaData/components/notice-bar/example/index.tsx +294 -0
  94. package/metaData/components/notify/doc.md +81 -0
  95. package/metaData/components/notify/example/index.tsx +171 -0
  96. package/metaData/components/notify/example/methods.tsx +83 -0
  97. package/metaData/components/pagination/doc.md +41 -0
  98. package/metaData/components/pagination/example/arrow.tsx +14 -0
  99. package/metaData/components/pagination/example/index.tsx +292 -0
  100. package/metaData/components/picker/doc.md +89 -0
  101. package/metaData/components/picker/example/index.tsx +217 -0
  102. package/metaData/components/picker-view/doc.md +57 -0
  103. package/metaData/components/picker-view/example/cascader.tsx +141 -0
  104. package/metaData/components/picker-view/example/index.tsx +297 -0
  105. package/metaData/components/picker-view/example/multi-picker.tsx +66 -0
  106. package/metaData/components/picker-view/example/picker-cell.tsx +416 -0
  107. package/metaData/components/popover/doc.md +144 -0
  108. package/metaData/components/popover/example/index.tsx +23 -0
  109. package/metaData/components/popover/example/menu.tsx +145 -0
  110. package/metaData/components/popover/example/popover-inner.tsx +147 -0
  111. package/metaData/components/popover/example/popover.tsx +268 -0
  112. package/metaData/components/popup/doc.md +101 -0
  113. package/metaData/components/popup/example/index.tsx +125 -0
  114. package/metaData/components/popup/example/methods.tsx +6 -0
  115. package/metaData/components/popup-swiper/doc.md +108 -0
  116. package/metaData/components/popup-swiper/example/index.tsx +332 -0
  117. package/metaData/components/popup-swiper/example/methods.tsx +6 -0
  118. package/metaData/components/portal/doc.md +14 -0
  119. package/metaData/components/portal/example/index.tsx +35 -0
  120. package/metaData/components/progress/doc.md +42 -0
  121. package/metaData/components/progress/example/index.tsx +256 -0
  122. package/metaData/components/pull-refresh/doc.md +37 -0
  123. package/metaData/components/pull-refresh/example/android-pull-refresh.tsx +260 -0
  124. package/metaData/components/pull-refresh/example/index.tsx +44 -0
  125. package/metaData/components/pull-refresh/example/ios-pull-refresh.tsx +216 -0
  126. package/metaData/components/radio/doc.md +89 -0
  127. package/metaData/components/radio/example/group.tsx +92 -0
  128. package/metaData/components/radio/example/index.tsx +25 -0
  129. package/metaData/components/radio/example/radio.tsx +22 -0
  130. package/metaData/components/rate/doc.md +33 -0
  131. package/metaData/components/rate/example/index.tsx +281 -0
  132. package/metaData/components/search-bar/doc.md +97 -0
  133. package/metaData/components/search-bar/example/association.tsx +89 -0
  134. package/metaData/components/search-bar/example/cancel-button.tsx +34 -0
  135. package/metaData/components/search-bar/example/highlight.tsx +66 -0
  136. package/metaData/components/search-bar/example/index.tsx +251 -0
  137. package/metaData/components/show-monitor/doc.md +34 -0
  138. package/metaData/components/show-monitor/example/index.tsx +646 -0
  139. package/metaData/components/skeleton/doc.md +101 -0
  140. package/metaData/components/skeleton/example/elements.tsx +290 -0
  141. package/metaData/components/skeleton/example/index.tsx +96 -0
  142. package/metaData/components/skeleton/example/skeleton-context.tsx +7 -0
  143. package/metaData/components/slider/doc.md +42 -0
  144. package/metaData/components/slider/example/index.tsx +326 -0
  145. package/metaData/components/slider/example/marks.tsx +50 -0
  146. package/metaData/components/slider/example/popover.tsx +38 -0
  147. package/metaData/components/slider/example/thumb.tsx +48 -0
  148. package/metaData/components/slider/example/useSliderIcon.tsx +38 -0
  149. package/metaData/components/slider/example/useSliderInit.tsx +170 -0
  150. package/metaData/components/stepper/doc.md +46 -0
  151. package/metaData/components/stepper/example/index.tsx +166 -0
  152. package/metaData/components/stepper/example/useButtonClick.tsx +74 -0
  153. package/metaData/components/stepper/example/useInputEvent.tsx +65 -0
  154. package/metaData/components/stepper/example/useValue.tsx +43 -0
  155. package/metaData/components/steps/doc.md +57 -0
  156. package/metaData/components/steps/example/index.tsx +123 -0
  157. package/metaData/components/steps/example/step.tsx +126 -0
  158. package/metaData/components/sticky/doc.md +45 -0
  159. package/metaData/components/sticky/example/index.tsx +430 -0
  160. package/metaData/components/swipe-action/doc.md +44 -0
  161. package/metaData/components/swipe-action/example/index.tsx +338 -0
  162. package/metaData/components/swipe-action/example/item.tsx +40 -0
  163. package/metaData/components/swipe-load/doc.md +43 -0
  164. package/metaData/components/swipe-load/example/index.tsx +339 -0
  165. package/metaData/components/swipe-load/example/type.tsx +153 -0
  166. package/metaData/components/switch/doc.md +38 -0
  167. package/metaData/components/switch/example/index.tsx +237 -0
  168. package/metaData/components/tab-bar/doc.md +57 -0
  169. package/metaData/components/tab-bar/example/index.tsx +18 -0
  170. package/metaData/components/tab-bar/example/item.tsx +74 -0
  171. package/metaData/components/tab-bar/example/tab-bar.tsx +105 -0
  172. package/metaData/components/tabs/doc.md +187 -0
  173. package/metaData/components/tabs/example/index.tsx +514 -0
  174. package/metaData/components/tabs/example/tab-cell-underline.tsx +320 -0
  175. package/metaData/components/tabs/example/tab-cell.tsx +433 -0
  176. package/metaData/components/tabs/example/tab-pane.tsx +349 -0
  177. package/metaData/components/tag/doc.md +80 -0
  178. package/metaData/components/tag/example/index.tsx +23 -0
  179. package/metaData/components/tag/example/list.tsx +97 -0
  180. package/metaData/components/tag/example/tag.tsx +85 -0
  181. package/metaData/components/textarea/doc.md +67 -0
  182. package/metaData/components/textarea/example/index.tsx +258 -0
  183. package/metaData/components/toast/doc.md +90 -0
  184. package/metaData/components/toast/example/index.tsx +335 -0
  185. package/metaData/components/toast/example/methods.tsx +87 -0
  186. package/metaData/components/transition/doc.md +19 -0
  187. package/metaData/components/transition/example/index.tsx +113 -0
  188. package/metaData/components/uploader/doc.md +82 -0
  189. package/metaData/components/uploader/example/index.tsx +208 -0
  190. package/metaData/components-index.json +242 -0
  191. package/package.json +56 -0
@@ -0,0 +1,514 @@
1
+ import React, {
2
+ useRef,
3
+ forwardRef,
4
+ Ref,
5
+ useImperativeHandle,
6
+ ReactNode,
7
+ useState,
8
+ useEffect,
9
+ useCallback,
10
+ useContext,
11
+ } from 'react';
12
+ import { cls, nextTick, getOffset } from '@arco-design/mobile-utils';
13
+ import { ContextLayout, GlobalContext } from '../context-provider';
14
+ import TabCell from './tab-cell';
15
+ import TabPane from './tab-pane';
16
+ import {
17
+ useRefState,
18
+ useListenResize,
19
+ useUpdateEffect,
20
+ useSwiperInnerScroll,
21
+ useSystem,
22
+ } from '../_helpers';
23
+ import { TabCellRef, TabPaneRef, TabsProps, TabsRef } from './type';
24
+
25
+ export * from './type';
26
+
27
+ /**
28
+ * 用于让用户在不同的视图中进行切换。为优化移动端渲染性能,如有替换DOM、发请求更新数据等操作,请在`onAfterChange`而非`onChange`回调中进行。
29
+ * @en Used to let the user switch between different views. In order to optimize the rendering performance of the mobile terminal, if you need to replace the DOM, send a request to update data, etc., please do it in the `onAfterChange` instead of the `onChange` callback.
30
+ * @type 导航
31
+ * @type_en Navigation
32
+ * @name 选项卡
33
+ * @name_en Tabs
34
+ */
35
+ const Tabs = forwardRef((props: TabsProps, ref: Ref<TabsRef>) => {
36
+ const {
37
+ className,
38
+ style,
39
+ tabs = [],
40
+ tabBarPosition = 'top',
41
+ activeTab,
42
+ defaultActiveTab = 0,
43
+ children,
44
+ onChange,
45
+ onAfterChange,
46
+ onTabClick,
47
+ onTabBarOverflowChange,
48
+ onTouchStart,
49
+ onTouchMove,
50
+ onTouchEnd,
51
+ onTabBarScroll,
52
+ onDistanceChange,
53
+ onScroll,
54
+ type = 'line',
55
+ swipeable = true,
56
+ disabled,
57
+ tabBarArrange = 'center',
58
+ tabBarScroll = true,
59
+ tabBarFixed,
60
+ tabBarExtra,
61
+ tabBarScrollBezier,
62
+ tabBarScrollDuration,
63
+ tabBarScrollChance = 'jump',
64
+ tabBarHasDivider,
65
+ tabBarResetWhenScroll = 'touchmove',
66
+ stopPropagation = true,
67
+ getInnerScrollContainer,
68
+ mode = 'swipe',
69
+ getScrollContainer,
70
+ scrollThrottle = 300,
71
+ scrollOffset = 0,
72
+ scrollWhenMounted,
73
+ goLastWhenScrollBottom = true,
74
+ scrollVertical = true,
75
+ renderUnderline,
76
+ renderTabBar,
77
+ renderTabBarItem,
78
+ renderTabBarInner,
79
+ duration = 240,
80
+ transitionDuration = 300,
81
+ useCaterpillar = false,
82
+ distanceToChangeTab = 10,
83
+ percentToChangeTab = 0.3,
84
+ speedToChangeTab = 200,
85
+ disableClickTransition = true,
86
+ lazyloadCount,
87
+ hideContentStyle = null,
88
+ renderHideContent,
89
+ hideTabBarBeforeMounted,
90
+ overflowThreshold = 5,
91
+ tabBarGutter,
92
+ tabBarPadding,
93
+ underlineSize,
94
+ underlineThick,
95
+ underlineInnerStyle,
96
+ caterpillarMaxScale,
97
+ caterpillarProperty = 'scale',
98
+ showUnderline = true,
99
+ underlineAdaptive = false,
100
+ stopTouchThreshold = 0,
101
+ touchSideDisableThreshold = 0,
102
+ onTouchStopped,
103
+ tabBarStyle,
104
+ tabPaneStyle,
105
+ tabBarClass,
106
+ tabPaneClass,
107
+ tabPaneExtra,
108
+ translateZ = true,
109
+ fullScreen,
110
+ autoHeight,
111
+ tabBarStopPropagation = true,
112
+ swipeEnergySaving = false,
113
+ } = props;
114
+ const { useRtl } = useContext(GlobalContext);
115
+ const domRef = useRef<HTMLDivElement | null>(null);
116
+ const cellRef = useRef<TabCellRef | null>(null);
117
+ const paneRef = useRef<TabPaneRef | null>(null);
118
+ const [innerIndex, setInnerIndex] = useState(defaultActiveTab);
119
+ const [jumpingDis, setJumpingDis] = useState(0);
120
+ const [wrapWidth, setWrapWidth] = useState(0);
121
+ const [wrapHeight, setWrapHeight] = useState(0);
122
+ const [cellTrans, setCellTrans] = useState(false);
123
+ const [paneTrans, setPaneTrans] = useState(false);
124
+ const [activeIndex, activeIndexRef, setActiveIndex] = useRefState(
125
+ activeTab === void 0 ? innerIndex : activeTab,
126
+ );
127
+ const [distance, distanceRef, setDistance] = useRefState(0);
128
+ const posAdjustingRef = useRef(false);
129
+ const touchStartedRef = useRef(false);
130
+ const touchStartXRef = useRef(0);
131
+ const touchStartYRef = useRef(0);
132
+ const touchStartTimeRef = useRef(0);
133
+ const touchMovedRef = useRef(false);
134
+ const scrollingRef = useRef<boolean | null>(null);
135
+ const touchStoppedRef = useRef(false);
136
+ const changeFromRef = useRef('');
137
+ const touchMoveBarScrollRef = useRef(false);
138
+ const system = useSystem();
139
+ const allPanes = getAllPanes();
140
+ const tabDirection =
141
+ ['top', 'bottom'].indexOf(tabBarPosition) !== -1 ? 'vertical' : 'horizontal';
142
+ const canSwipe =
143
+ mode === 'swipe' &&
144
+ !disabled &&
145
+ swipeable &&
146
+ tabDirection === 'vertical' &&
147
+ tabs.length > 1;
148
+ const horizontalUseRtl = tabDirection === 'vertical' && useRtl;
149
+ const rtlRatio = horizontalUseRtl ? -1 : 1;
150
+
151
+ useImperativeHandle(ref, () => ({
152
+ dom: domRef.current,
153
+ bar: cellRef.current,
154
+ pane: paneRef.current,
155
+ barOverflow: cellRef.current ? cellRef.current.hasOverflow : false,
156
+ updateLayout,
157
+ changeIndex: (newIndex: number, rightNow?: boolean) =>
158
+ changeIndex(newIndex, 'manual', rightNow),
159
+ scrollToIndex: paneRef.current ? paneRef.current.scrollToIndex : () => {},
160
+ }));
161
+
162
+ useListenResize(updateLayout);
163
+
164
+ useSwiperInnerScroll(getInnerScrollContainer);
165
+
166
+ useEffect(() => {
167
+ if (distanceToChangeTab > 0 && distanceToChangeTab < 1) {
168
+ console.warn(
169
+ `[Tabs Props Warning] The value of the prop \`distanceToChangeTab\` is too small(${distanceToChangeTab}). Do you meant to use the prop \`percentToChangeTab\`?`,
170
+ );
171
+ }
172
+ }, [distanceToChangeTab]);
173
+
174
+ useEffect(() => {
175
+ updateLayout();
176
+ if (mode === 'scroll') {
177
+ // 判断初始是否滚动时,如果指定了scrollWhenMounted则看它的值,否则看是否默认选中第一个
178
+ // @en When judging whether to scroll initially, if scrollWhenMounted is specified, see its value, otherwise, see if the first one is selected by default
179
+ const needScroll = scrollWhenMounted === void 0 ? activeIndex !== 0 : scrollWhenMounted;
180
+ if (needScroll) {
181
+ paneRef.current?.scrollToIndex(activeIndex, true);
182
+ }
183
+ }
184
+ }, []);
185
+
186
+ useEffect(() => {
187
+ paneRef.current && paneRef.current.setCurrentHeight();
188
+ }, [children, activeIndex, autoHeight]);
189
+
190
+ useEffect(() => {
191
+ // 受控时用受控值,否则用内部值
192
+ // @en When controlled, use the controlled value, otherwise use the internal value
193
+ setActiveIndex(activeTab === void 0 ? innerIndex : activeTab);
194
+ }, [activeTab, innerIndex]);
195
+
196
+ useUpdateEffect(() => {
197
+ // 利用受控手动更改index时,给cell line加上动画
198
+ // @en Animate the cell line when changeing the index
199
+ setCellTrans(true);
200
+ if (!changeFromRef.current) {
201
+ changeFromRef.current = 'manual';
202
+ }
203
+ }, [activeTab]);
204
+
205
+ useUpdateEffect(() => {
206
+ onDistanceChange && onDistanceChange(distance, wrapWidth, activeIndex);
207
+ }, [distance, wrapWidth, activeIndex]);
208
+
209
+ useUpdateEffect(() => {
210
+ if (changeFromRef.current !== 'scroll' && mode === 'scroll') {
211
+ paneRef.current?.scrollToIndex(activeIndex);
212
+ }
213
+ if (changeFromRef.current === 'click' && useCaterpillar) {
214
+ cellRef.current?.setCaterpillarAnimate();
215
+ }
216
+ const changeFrom = changeFromRef.current;
217
+ changeFromRef.current = '';
218
+ nextTick(() => {
219
+ setTimeout(
220
+ () => {
221
+ onAfterChange && onAfterChange(tabs[activeIndex], activeIndex, changeFrom);
222
+ },
223
+ paneRef.current ? paneRef.current.getTransition() : 0,
224
+ );
225
+ });
226
+ }, [activeIndex]);
227
+
228
+ const handlePaneTouchStart = useCallback(
229
+ (e: TouchEvent) => {
230
+ if (onTouchStart && onTouchStart(e, activeIndexRef.current)) {
231
+ return;
232
+ }
233
+ if (posAdjustingRef.current) {
234
+ return;
235
+ }
236
+ touchStartedRef.current = true;
237
+ touchMovedRef.current = false;
238
+ setCellTrans(false);
239
+ setPaneTrans(false);
240
+ const evt = e.touches[0];
241
+ touchStartXRef.current = evt.clientX || 0;
242
+ touchStartYRef.current = evt.clientY || 0;
243
+ scrollingRef.current = null;
244
+ posAdjustingRef.current = false;
245
+ touchStartTimeRef.current = new Date().getTime();
246
+ touchStoppedRef.current = false;
247
+ },
248
+ [onTouchStart],
249
+ );
250
+
251
+ const handlePaneTouchMove = useCallback(
252
+ (e: TouchEvent) => {
253
+ if (onTouchMove && onTouchMove(e, activeIndexRef.current)) {
254
+ return;
255
+ }
256
+ // 从屏幕边缘开始滑动时,屏蔽tabs滑动事件
257
+ if (touchStartXRef.current < touchSideDisableThreshold) {
258
+ return;
259
+ }
260
+ stopPropagation && e.stopPropagation();
261
+ if (!touchStartedRef.current || posAdjustingRef.current) {
262
+ e.cancelable && e.preventDefault();
263
+ return;
264
+ }
265
+ touchMovedRef.current = true;
266
+ const evt = e.changedTouches[0];
267
+ const touchMoveX = evt.clientX || 0;
268
+ const touchMoveY = evt.clientY || 0;
269
+ // bugfix: 兼容safari在右滑返回上一页时clientX为负值的情况,安卓有折叠屏,触点会有超出屏幕(clientX < 0)的情况,因此这里限定ios系统
270
+ // @en bugfix: bugfix: Compatible with the case in safari where clientX is negative when swiping right back to the previous page
271
+ const posDisX =
272
+ system === 'ios' && touchMoveX < 0 ? 0 : touchMoveX - touchStartXRef.current;
273
+ const posDisY = touchMoveY - touchStartYRef.current;
274
+ const absDisX = Math.abs(posDisX);
275
+ const absDisY = Math.abs(posDisY);
276
+ const comparedDis = posDisX * rtlRatio;
277
+ if (scrollingRef.current === null) {
278
+ scrollingRef.current = absDisX < absDisY;
279
+ }
280
+ // 如果是在上下滚动页面则禁用滑动手势
281
+ // @en Disable swipe gestures if scrolling up and down
282
+ if (scrollingRef.current) {
283
+ if (tabBarResetWhenScroll === 'touchmove' && !touchMoveBarScrollRef.current) {
284
+ cellRef.current && cellRef.current.scrollToCenter();
285
+ touchMoveBarScrollRef.current = true;
286
+ }
287
+ setDistance(0);
288
+ return;
289
+ }
290
+ if (
291
+ (activeIndexRef.current === 0 && comparedDis > 0) ||
292
+ (activeIndexRef.current === tabs.length - 1 && comparedDis < 0)
293
+ ) {
294
+ if (!touchStoppedRef.current && absDisX > stopTouchThreshold) {
295
+ touchStoppedRef.current = true;
296
+ onTouchStopped && onTouchStopped(comparedDis >= 0 ? -1 : 1);
297
+ }
298
+ setDistance(0);
299
+ return;
300
+ }
301
+ e.cancelable && e.preventDefault();
302
+ setDistance(posDisX);
303
+ },
304
+ [
305
+ onTouchMove,
306
+ onTouchStopped,
307
+ stopTouchThreshold,
308
+ tabs.length,
309
+ touchSideDisableThreshold,
310
+ tabBarResetWhenScroll,
311
+ stopPropagation,
312
+ ],
313
+ );
314
+
315
+ useEffect(() => {
316
+ if (paneRef.current && paneRef.current.dom && canSwipe) {
317
+ paneRef.current.dom.addEventListener('touchstart', handlePaneTouchStart);
318
+ paneRef.current.dom.addEventListener('touchmove', handlePaneTouchMove);
319
+ }
320
+ return () => {
321
+ if (paneRef.current && paneRef.current.dom && canSwipe) {
322
+ paneRef.current.dom.removeEventListener('touchstart', handlePaneTouchStart);
323
+ paneRef.current.dom.removeEventListener('touchmove', handlePaneTouchMove);
324
+ }
325
+ };
326
+ }, [handlePaneTouchStart, handlePaneTouchMove, canSwipe]);
327
+
328
+ function handlePaneTouchEnd(e: React.TouchEvent<HTMLDivElement>) {
329
+ if (onTouchEnd && onTouchEnd(e.nativeEvent, activeIndexRef.current)) {
330
+ return;
331
+ }
332
+ stopPropagation && e.stopPropagation();
333
+ touchMoveBarScrollRef.current = false;
334
+ if (scrollingRef.current && tabBarResetWhenScroll === 'touchend') {
335
+ cellRef.current && cellRef.current.scrollToCenter();
336
+ }
337
+ setCellTrans(true);
338
+ setPaneTrans(true);
339
+ if (
340
+ !touchStartedRef.current ||
341
+ posAdjustingRef.current ||
342
+ scrollingRef.current ||
343
+ !touchMovedRef.current
344
+ ) {
345
+ return;
346
+ }
347
+ touchStartedRef.current = false;
348
+ const touchEndTime = new Date().getTime();
349
+ const dis = distanceRef.current;
350
+ const speed = (dis / (touchEndTime - touchStartTimeRef.current)) * 1000;
351
+ const maxSlice = wrapWidth * percentToChangeTab;
352
+ const index = activeIndexRef.current;
353
+ const needJump =
354
+ (Math.abs(dis) > maxSlice && Math.abs(dis) > distanceToChangeTab) ||
355
+ Math.abs(speed) > speedToChangeTab;
356
+ let newIndex = index;
357
+ const comparedDis = dis * rtlRatio;
358
+ if (comparedDis > 0 && needJump) {
359
+ newIndex = index - 1;
360
+ } else if (comparedDis < 0 && needJump) {
361
+ newIndex = index + 1;
362
+ }
363
+ nextTick(() => {
364
+ jumpTo(newIndex);
365
+ });
366
+ }
367
+
368
+ function jumpTo(newIndex: number) {
369
+ posAdjustingRef.current = true;
370
+ if (newIndex !== activeIndexRef.current) {
371
+ setJumpingDis(distanceRef.current);
372
+ }
373
+ changeIndex(newIndex, 'swipe');
374
+ touchStartTimeRef.current = 0;
375
+ setTimeout(() => {
376
+ posAdjustingRef.current = false;
377
+ setJumpingDis(0);
378
+ }, transitionDuration);
379
+ }
380
+
381
+ function updateLayout() {
382
+ const { width, height } = getOffset(domRef.current);
383
+ cellRef.current && cellRef.current.updateLayout();
384
+ setWrapWidth(width || domRef.current?.offsetWidth || 0);
385
+ setWrapHeight(height || domRef.current?.offsetHeight || 0);
386
+ paneRef.current && paneRef.current.setCurrentHeight();
387
+ }
388
+
389
+ function getAllPanes(): ReactNode[] {
390
+ let panes: ReactNode[] = children ? [children] : [];
391
+ if (children && Object.prototype.toString.call(children) === '[object Array]') {
392
+ panes = children as ReactNode[];
393
+ }
394
+ // panes不可超过tabs.length
395
+ return panes.slice(0, tabs.length);
396
+ }
397
+
398
+ function changeIndex(newIndex: number, changeFrom?: string, rightNow?: boolean) {
399
+ if (rightNow || (changeFrom === 'click' && disableClickTransition)) {
400
+ setPaneTrans(false);
401
+ } else {
402
+ setPaneTrans(true);
403
+ }
404
+ changeFromRef.current = changeFrom || '';
405
+ setCellTrans(true);
406
+ setInnerIndex(newIndex);
407
+ if (newIndex !== activeIndexRef.current) {
408
+ onChange && onChange(tabs[newIndex], newIndex, changeFrom);
409
+ }
410
+ setDistance(0);
411
+ }
412
+
413
+ return (
414
+ <ContextLayout>
415
+ {({ prefixCls }) => {
416
+ const prefix = `${prefixCls}-tabs`;
417
+ const commonProps = {
418
+ prefixCls,
419
+ activeIndex,
420
+ activeIndexRef,
421
+ tabDirection: tabDirection as 'horizontal' | 'vertical',
422
+ changeIndex,
423
+ duration,
424
+ transitionDuration,
425
+ wrapWidth,
426
+ wrapHeight,
427
+ distance,
428
+ mode,
429
+ translateZ,
430
+ fullScreen,
431
+ };
432
+ const cellProps = {
433
+ ref: cellRef,
434
+ tabs,
435
+ onTabClick,
436
+ type,
437
+ tabBarPosition,
438
+ tabBarArrange,
439
+ tabBarScroll,
440
+ renderUnderline,
441
+ useCaterpillar,
442
+ cellTrans,
443
+ jumpingDis,
444
+ tabBarExtra,
445
+ onTabBarOverflowChange,
446
+ tabBarGutter,
447
+ tabBarPadding,
448
+ tabBarFixed,
449
+ tabBarScrollBezier,
450
+ tabBarScrollDuration,
451
+ tabBarScrollChance,
452
+ tabBarHasDivider,
453
+ underlineSize,
454
+ underlineThick,
455
+ underlineInnerStyle,
456
+ caterpillarMaxScale,
457
+ caterpillarProperty,
458
+ onTabBarScroll,
459
+ hideTabBarBeforeMounted,
460
+ overflowThreshold,
461
+ showUnderline,
462
+ underlineAdaptive,
463
+ disabled,
464
+ renderTabBarItem,
465
+ renderTabBarInner,
466
+ tabBarStyle,
467
+ tabBarClass,
468
+ tabBarStopPropagation,
469
+ onUnderlineFirstShow: () => setCellTrans(true),
470
+ ...commonProps,
471
+ };
472
+ const CellComp = <TabCell {...cellProps} />;
473
+ return (
474
+ <div
475
+ className={cls(
476
+ `${prefix} ${prefix}-${tabBarPosition} ${prefix}-${tabDirection} all-border-box`,
477
+ { 'full-screen': fullScreen },
478
+ className || '',
479
+ )}
480
+ style={style}
481
+ ref={domRef}
482
+ >
483
+ {renderTabBar ? renderTabBar(CellComp, cellProps) : CellComp}
484
+ <TabPane
485
+ ref={paneRef}
486
+ panes={allPanes}
487
+ handlePaneTouchEnd={handlePaneTouchEnd}
488
+ paneTrans={paneTrans}
489
+ swipeable={canSwipe}
490
+ lazyloadCount={lazyloadCount}
491
+ hideContentStyle={hideContentStyle}
492
+ renderHideContent={renderHideContent}
493
+ tabPaneStyle={tabPaneStyle}
494
+ getScrollContainer={getScrollContainer}
495
+ scrollThrottle={scrollThrottle}
496
+ scrollOffset={scrollOffset}
497
+ goLastWhenScrollBottom={goLastWhenScrollBottom}
498
+ scrollVertical={scrollVertical}
499
+ tabPaneClass={tabPaneClass}
500
+ tabPaneExtra={tabPaneExtra}
501
+ autoHeight={autoHeight}
502
+ onScroll={onScroll}
503
+ swipeEnergySaving={swipeEnergySaving}
504
+ rtlRatio={rtlRatio}
505
+ {...commonProps}
506
+ />
507
+ </div>
508
+ );
509
+ }}
510
+ </ContextLayout>
511
+ );
512
+ });
513
+
514
+ export default Tabs;