@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,339 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useRef,
|
|
3
|
+
forwardRef,
|
|
4
|
+
Ref,
|
|
5
|
+
useImperativeHandle,
|
|
6
|
+
useEffect,
|
|
7
|
+
useState,
|
|
8
|
+
useContext,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import { cls, fingerDisToLabelDis, defaultLocale } from '@arco-design/mobile-utils';
|
|
11
|
+
import { ContextLayout, GlobalContext } from '../context-provider';
|
|
12
|
+
import { SwipeLoadProps, SwipeLoadRef } from './type';
|
|
13
|
+
import { setStyleWithVendor } from '../_helpers';
|
|
14
|
+
import { useAddListener } from '../_helpers/hooks';
|
|
15
|
+
|
|
16
|
+
export * from './type';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 向左滑动到达屏幕边缘后,超过一定距离时触发加载,常用于横划展示少量的元素,滑动到底后跳转至另外界面的场景
|
|
20
|
+
* @en After swiping to the left to reach the edge of the screen, the loading is triggered when the distance exceeds a certain distance. It is often used to display a small number of elements horizontally, and then jump to another interface after swiping to the end.
|
|
21
|
+
* @type 反馈
|
|
22
|
+
* @type_en FeedBack
|
|
23
|
+
* @name 左滑加载
|
|
24
|
+
* @name_en SwipeLoad
|
|
25
|
+
*/
|
|
26
|
+
const SwipeLoad = forwardRef((props: SwipeLoadProps, ref: Ref<SwipeLoadRef>) => {
|
|
27
|
+
const {
|
|
28
|
+
className = '',
|
|
29
|
+
maxElementOffset = 56,
|
|
30
|
+
maxLabelOffset = 40,
|
|
31
|
+
onConfirm,
|
|
32
|
+
disabled = false,
|
|
33
|
+
circleSize = 80,
|
|
34
|
+
minConfirmOffset = 30,
|
|
35
|
+
labelAnimationFunction = 'cubic-bezier(0.14, 1, 0.34, 1)',
|
|
36
|
+
labelAnimationDuration = 250,
|
|
37
|
+
children,
|
|
38
|
+
normalText = '',
|
|
39
|
+
activeText = '',
|
|
40
|
+
initPos = 0,
|
|
41
|
+
bounceWhenBumpBoundary = false,
|
|
42
|
+
bounceDampRate = 3,
|
|
43
|
+
bounceAnimateDuration = 300,
|
|
44
|
+
damping,
|
|
45
|
+
bounceDistanceProcessor,
|
|
46
|
+
getScrollContainer,
|
|
47
|
+
getBounceContainer,
|
|
48
|
+
onTouchStart,
|
|
49
|
+
onTouchEnd,
|
|
50
|
+
onTouchCancel,
|
|
51
|
+
onTouchMove,
|
|
52
|
+
renderLabel,
|
|
53
|
+
} = props;
|
|
54
|
+
const { locale = defaultLocale, useRtl } = useContext(GlobalContext);
|
|
55
|
+
const [disableState, setDisableState] = useState(disabled);
|
|
56
|
+
const [labelOffsetState, setLabelOffsetState] = useState(0);
|
|
57
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
58
|
+
const loadingRef = useRef<HTMLDivElement>(null);
|
|
59
|
+
const loadingLabelRef = useRef<HTMLDivElement>(null);
|
|
60
|
+
const showLoadMoreRef = useRef(false);
|
|
61
|
+
const ifToRightRef = useRef(false);
|
|
62
|
+
const bouncingRef = useRef(false);
|
|
63
|
+
const offsetRef = useRef(0);
|
|
64
|
+
const domRef = useRef<HTMLDivElement | null>(null);
|
|
65
|
+
const { current: wrapperEl } = domRef;
|
|
66
|
+
useAddListener(wrapperEl, 'touchstart', onTouchStart);
|
|
67
|
+
useAddListener(wrapperEl, 'touchend', onTouchEnd);
|
|
68
|
+
useAddListener(wrapperEl, 'touchcancel', onTouchCancel);
|
|
69
|
+
useAddListener(wrapperEl, 'touchmove', onTouchMove);
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (disabled || !containerRef.current || disableState) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
let scrollContainer;
|
|
76
|
+
// 对children类型进行判断
|
|
77
|
+
// @en Judging the type of children
|
|
78
|
+
if (containerRef.current.childNodes.length === 0) {
|
|
79
|
+
// 未传入子元素 不启用组件
|
|
80
|
+
// @en If no child element is passed in, component will be disabled
|
|
81
|
+
setDisableState(true);
|
|
82
|
+
} else if (containerRef.current.childNodes.length === 1) {
|
|
83
|
+
// 传入一个子元素 滑动单个元素
|
|
84
|
+
// @en Pass in a child element swipe the single element
|
|
85
|
+
scrollContainer = getScrollContainer?.() ?? containerRef.current.firstChild;
|
|
86
|
+
} else {
|
|
87
|
+
// 传入多个子元素(列表元素为例) 组件控制自行滑动 不推荐
|
|
88
|
+
// @en Pass in multiple sub-elements (list elements as an example) Component control slides by itself which is not recommended
|
|
89
|
+
scrollContainer = containerRef.current;
|
|
90
|
+
scrollContainer.style.width = '100%';
|
|
91
|
+
scrollContainer.style.overflowX = 'scroll';
|
|
92
|
+
scrollContainer.style.display = 'inline-flex';
|
|
93
|
+
scrollContainer.style.webkitOverflowScrolling = 'touch';
|
|
94
|
+
}
|
|
95
|
+
if (!scrollContainer) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const { current: loadingCurrent } = loadingRef;
|
|
99
|
+
const { current: loadingLabelCurrent } = loadingLabelRef;
|
|
100
|
+
if (!loadingCurrent) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const bounceScrollContainer: HTMLElement = getBounceContainer?.() || scrollContainer;
|
|
104
|
+
// 初始不显示标签
|
|
105
|
+
// @en Initially no labels are displayed
|
|
106
|
+
loadingCurrent.style.display = 'none';
|
|
107
|
+
let startX = 0;
|
|
108
|
+
let endX = 0;
|
|
109
|
+
let bounceDistance = 0;
|
|
110
|
+
// 触摸页面确定X起始坐标
|
|
111
|
+
// @en Determine the X starting coordinate on touchstart
|
|
112
|
+
const touchstart = (e: TouchEvent) => {
|
|
113
|
+
const evt = e.touches[0];
|
|
114
|
+
startX = evt.clientX || 0;
|
|
115
|
+
};
|
|
116
|
+
// 页面滑动确定X终止坐标,更新手指的X坐标,改变loading中的文字和大小
|
|
117
|
+
// @en Determine the X end coordinate, update the X coordinate of the finger, change the text and size in the loading on touchmove
|
|
118
|
+
const touchmove = (e: TouchEvent) => {
|
|
119
|
+
// 判断元素是否属于滚动元素 先置为1 之后变成0表示非滚动容器
|
|
120
|
+
// @en Determine whether the element belongs to a scrolling element. Set it to 1 and then change to 0 to indicate a non-scrolling container
|
|
121
|
+
if (!scrollContainer.scrollLeft) {
|
|
122
|
+
scrollContainer.scrollLeft = useRtl ? -1 : 1;
|
|
123
|
+
}
|
|
124
|
+
endX = e.touches[0].clientX || 0;
|
|
125
|
+
const diff = endX - startX;
|
|
126
|
+
offsetRef.current = diff;
|
|
127
|
+
const labelDiff = fingerDisToLabelDis(Math.abs(diff), damping);
|
|
128
|
+
|
|
129
|
+
// 判断是否是滚动到列表开始方向,ltr模式下是向左滚动,rtl模式下是向右滚动
|
|
130
|
+
const isScrollToLeft = useRtl ? diff < 0 : diff > 0;
|
|
131
|
+
// 判断是否是滚动到列表结束方向,ltr模式下是向右滚动,rtl模式下是向左滚动
|
|
132
|
+
const isScrollToRight = useRtl ? diff > 0 : diff < 0;
|
|
133
|
+
// 滑动到最左侧,处理回弹效果
|
|
134
|
+
// @en Swipe to the far left to handle the rebound effect
|
|
135
|
+
if (
|
|
136
|
+
isScrollToLeft &&
|
|
137
|
+
Math.abs(scrollContainer.scrollLeft) <= 1 &&
|
|
138
|
+
bounceWhenBumpBoundary
|
|
139
|
+
) {
|
|
140
|
+
e.stopPropagation();
|
|
141
|
+
e.cancelBubble && e.preventDefault();
|
|
142
|
+
bouncingRef.current = true;
|
|
143
|
+
const processor =
|
|
144
|
+
bounceDistanceProcessor ||
|
|
145
|
+
(dis => Math.min(dis, bounceScrollContainer.offsetWidth) / bounceDampRate);
|
|
146
|
+
bounceDistance = processor(diff);
|
|
147
|
+
setStyleWithVendor(bounceScrollContainer, {
|
|
148
|
+
transition: 'none',
|
|
149
|
+
transform: `translateX(${bounceDistance}px) translateZ(0)`,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
// 向左滑动到尽头 '更多'标签加载 根据scrollLeft判断 滚动容器到达边缘触发 非滚动容器不判断
|
|
153
|
+
// @en Swipe left to the end and the 'more' label is loaded. Judging by scrollLeft, the scroll container reaches the edge and the non-scroll container does not judge
|
|
154
|
+
if (
|
|
155
|
+
isScrollToRight &&
|
|
156
|
+
(Math.abs(scrollContainer.scrollLeft) + scrollContainer.clientWidth >=
|
|
157
|
+
scrollContainer.scrollWidth - 1 ||
|
|
158
|
+
!scrollContainer.scrollLeft) &&
|
|
159
|
+
!ifToRightRef.current
|
|
160
|
+
) {
|
|
161
|
+
showLoadMoreRef.current = true;
|
|
162
|
+
loadingCurrent.style.display = 'flex';
|
|
163
|
+
}
|
|
164
|
+
// 继续滑动露出标签
|
|
165
|
+
// @en Continue swiping to reveal labels
|
|
166
|
+
if (showLoadMoreRef.current && isScrollToRight) {
|
|
167
|
+
// 此时禁止list原生滚动
|
|
168
|
+
// @en Disable list native scrolling at this time
|
|
169
|
+
e.stopPropagation();
|
|
170
|
+
e.cancelable && e.preventDefault();
|
|
171
|
+
// list元素平移最大 maxElementOffset
|
|
172
|
+
// @en Maximum list element translation, maxElementOffset
|
|
173
|
+
const listRightMargin = labelDiff > maxElementOffset ? maxElementOffset : labelDiff;
|
|
174
|
+
// 标签的平移最大为40px(半圆)
|
|
175
|
+
// @en The translation of the label is up to 40px (semi-circle)
|
|
176
|
+
const labelRightMargin = labelDiff > maxLabelOffset ? maxLabelOffset : labelDiff;
|
|
177
|
+
setLabelOffsetState(labelRightMargin);
|
|
178
|
+
// 标签全部展示 字样改变
|
|
179
|
+
// @en All labels are displayed and the text style is changed
|
|
180
|
+
if (loadingLabelCurrent) {
|
|
181
|
+
loadingLabelCurrent.innerHTML =
|
|
182
|
+
labelDiff >= minConfirmOffset
|
|
183
|
+
? activeText || locale.SwipeLoad.activeText
|
|
184
|
+
: normalText || locale.SwipeLoad.normalText;
|
|
185
|
+
}
|
|
186
|
+
setStyleWithVendor(loadingCurrent, {
|
|
187
|
+
transition: 'none',
|
|
188
|
+
transform: useRtl
|
|
189
|
+
? `translateX(${labelRightMargin}px) translateZ(0)`
|
|
190
|
+
: `translateX(-${labelRightMargin}px) translateZ(0)`,
|
|
191
|
+
});
|
|
192
|
+
setStyleWithVendor(scrollContainer, {
|
|
193
|
+
transition: 'none',
|
|
194
|
+
transform: useRtl
|
|
195
|
+
? `translateX(${listRightMargin}px) translateZ(0)`
|
|
196
|
+
: `translateX(-${listRightMargin}px) translateZ(0)`,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (
|
|
200
|
+
isScrollToLeft &&
|
|
201
|
+
Math.abs(scrollContainer.scrollLeft) + scrollContainer.clientWidth <=
|
|
202
|
+
scrollContainer.scrollWidth - 1
|
|
203
|
+
) {
|
|
204
|
+
showLoadMoreRef.current = false;
|
|
205
|
+
loadingCurrent.style.display = 'none';
|
|
206
|
+
}
|
|
207
|
+
// 针对ios惯性滚动处理
|
|
208
|
+
// @en Handling inertial scrolling for ios
|
|
209
|
+
if (
|
|
210
|
+
isScrollToRight &&
|
|
211
|
+
Math.abs(scrollContainer.scrollLeft) + scrollContainer.clientWidth <=
|
|
212
|
+
scrollContainer.scrollWidth - 1
|
|
213
|
+
) {
|
|
214
|
+
ifToRightRef.current = false;
|
|
215
|
+
} else {
|
|
216
|
+
ifToRightRef.current = true;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// 露出标签 反方向滑动隐藏'更多'标签
|
|
221
|
+
// @en Reveal the label, swipe in opposite direction to hide 'more' tab
|
|
222
|
+
const touchend = () => {
|
|
223
|
+
const diff = endX - startX;
|
|
224
|
+
offsetRef.current = diff;
|
|
225
|
+
const labelDiff = fingerDisToLabelDis(Math.abs(diff));
|
|
226
|
+
const resumeAnimation = () => {
|
|
227
|
+
if (showLoadMoreRef.current) {
|
|
228
|
+
showLoadMoreRef.current = false;
|
|
229
|
+
const scrollTransitionCssStyle = `all ${labelAnimationDuration}ms ${labelAnimationFunction}`;
|
|
230
|
+
const scrollTransformCssStyle = 'translateX(0px) translateZ(0)';
|
|
231
|
+
setStyleWithVendor(scrollContainer, {
|
|
232
|
+
transition: scrollTransitionCssStyle,
|
|
233
|
+
transform: scrollTransformCssStyle,
|
|
234
|
+
});
|
|
235
|
+
setStyleWithVendor(loadingCurrent, {
|
|
236
|
+
transition: scrollTransitionCssStyle,
|
|
237
|
+
transform: scrollTransformCssStyle,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (bouncingRef.current) {
|
|
241
|
+
bouncingRef.current = false;
|
|
242
|
+
setStyleWithVendor(bounceScrollContainer, {
|
|
243
|
+
transition: `all ${bounceAnimateDuration}ms`,
|
|
244
|
+
transform: 'translateX(0px) translateZ(0)',
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
ifToRightRef.current = false;
|
|
248
|
+
setTimeout(() => {
|
|
249
|
+
loadingCurrent.style.display = 'none';
|
|
250
|
+
}, labelAnimationDuration);
|
|
251
|
+
};
|
|
252
|
+
// 向左滑动 标签已经全部展示
|
|
253
|
+
// @em Swipe left, labels are all displayed
|
|
254
|
+
if (
|
|
255
|
+
labelDiff >= minConfirmOffset &&
|
|
256
|
+
(Math.abs(scrollContainer.scrollLeft) + scrollContainer.clientWidth >=
|
|
257
|
+
scrollContainer.scrollWidth - 1 ||
|
|
258
|
+
!scrollContainer.scrollLeft) &&
|
|
259
|
+
showLoadMoreRef.current
|
|
260
|
+
) {
|
|
261
|
+
onConfirm();
|
|
262
|
+
// 安卓机型返回动画优化
|
|
263
|
+
// @en Return animation optimization on Android
|
|
264
|
+
setTimeout(() => {
|
|
265
|
+
resumeAnimation();
|
|
266
|
+
}, 250);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
resumeAnimation();
|
|
270
|
+
};
|
|
271
|
+
scrollContainer.addEventListener('touchstart', touchstart);
|
|
272
|
+
scrollContainer.addEventListener('touchmove', touchmove);
|
|
273
|
+
scrollContainer.addEventListener('touchend', touchend);
|
|
274
|
+
return () => {
|
|
275
|
+
scrollContainer.removeEventListener('touchstart', touchstart);
|
|
276
|
+
scrollContainer.removeEventListener('touchmove', touchmove);
|
|
277
|
+
scrollContainer.removeEventListener('touchend', touchend);
|
|
278
|
+
};
|
|
279
|
+
}, [
|
|
280
|
+
disabled,
|
|
281
|
+
getScrollContainer,
|
|
282
|
+
getBounceContainer,
|
|
283
|
+
bounceWhenBumpBoundary,
|
|
284
|
+
bounceDampRate,
|
|
285
|
+
bounceAnimateDuration,
|
|
286
|
+
]);
|
|
287
|
+
useImperativeHandle(ref, () => ({
|
|
288
|
+
dom: domRef.current,
|
|
289
|
+
}));
|
|
290
|
+
return (
|
|
291
|
+
<ContextLayout>
|
|
292
|
+
{({ prefixCls }) => (
|
|
293
|
+
<div className={`${prefixCls}-swipe-load ${className}`} ref={domRef}>
|
|
294
|
+
<div className={cls(`${prefixCls}-list-area`)} ref={containerRef}>
|
|
295
|
+
{children}
|
|
296
|
+
</div>
|
|
297
|
+
{/*
|
|
298
|
+
* 用户可以自行渲染label样式
|
|
299
|
+
* @en Users can render the label style by themselves
|
|
300
|
+
*/}
|
|
301
|
+
{renderLabel ? (
|
|
302
|
+
<div
|
|
303
|
+
className={cls(`${prefixCls}-custom-loading-area`)}
|
|
304
|
+
ref={loadingRef}
|
|
305
|
+
style={{
|
|
306
|
+
position: 'absolute',
|
|
307
|
+
[useRtl ? 'left' : 'right']: `${initPos}px`,
|
|
308
|
+
}}
|
|
309
|
+
>
|
|
310
|
+
{/*
|
|
311
|
+
* 判断自定义渲染label函数的参数个数 传入offset则根据位置渲染
|
|
312
|
+
* @en Determine the number of parameters of the custom rendering label function, and pass in the offset to render according to the position
|
|
313
|
+
*/}
|
|
314
|
+
{renderLabel.length ? renderLabel(labelOffsetState) : renderLabel()}
|
|
315
|
+
</div>
|
|
316
|
+
) : (
|
|
317
|
+
<div
|
|
318
|
+
className={cls(`${prefixCls}-loading-area`)}
|
|
319
|
+
ref={loadingRef}
|
|
320
|
+
style={{
|
|
321
|
+
width: `${circleSize}px`,
|
|
322
|
+
height: `${circleSize}px`,
|
|
323
|
+
position: 'absolute',
|
|
324
|
+
[useRtl ? 'left' : 'right']: `-${circleSize}px`,
|
|
325
|
+
}}
|
|
326
|
+
>
|
|
327
|
+
<div
|
|
328
|
+
className={cls(`${prefixCls}-loading-label`)}
|
|
329
|
+
ref={loadingLabelRef}
|
|
330
|
+
/>
|
|
331
|
+
</div>
|
|
332
|
+
)}
|
|
333
|
+
</div>
|
|
334
|
+
)}
|
|
335
|
+
</ContextLayout>
|
|
336
|
+
);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
export default SwipeLoad;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface SwipeLoadProps {
|
|
4
|
+
/**
|
|
5
|
+
* 自定义类名
|
|
6
|
+
* @en Custom classname
|
|
7
|
+
*/
|
|
8
|
+
className?: string;
|
|
9
|
+
/**
|
|
10
|
+
* 是否禁用组件
|
|
11
|
+
* @en whether to be disabled
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* 页面元素允许划动的最大距离
|
|
17
|
+
* @en The maximum distance the page element is allowed to swipe
|
|
18
|
+
* @default 56
|
|
19
|
+
*/
|
|
20
|
+
maxElementOffset?: number;
|
|
21
|
+
/**
|
|
22
|
+
* label移动的最大距离
|
|
23
|
+
* @en The maximum distance the label moves
|
|
24
|
+
* @default 40
|
|
25
|
+
*/
|
|
26
|
+
maxLabelOffset?: number;
|
|
27
|
+
/**
|
|
28
|
+
* 页面允许触发的临界值(通常小于maxLabelOffset)
|
|
29
|
+
* @en The threshold value at which the page is allowed to trigger (usually less than maxLabelOffset)
|
|
30
|
+
* @default 30
|
|
31
|
+
*/
|
|
32
|
+
minConfirmOffset?: number;
|
|
33
|
+
/**
|
|
34
|
+
* 释放触发的函数(跳转,加载等)
|
|
35
|
+
* @en Callback when releasing(jump, load, etc.)
|
|
36
|
+
*/
|
|
37
|
+
onConfirm: () => void;
|
|
38
|
+
/**
|
|
39
|
+
* 圆形的直径
|
|
40
|
+
* @en Diameter of circle
|
|
41
|
+
* @default 80
|
|
42
|
+
*/
|
|
43
|
+
circleSize?: number;
|
|
44
|
+
/**
|
|
45
|
+
* 恢复动效时长(ms)
|
|
46
|
+
* @en Resume animation duration (ms)
|
|
47
|
+
* @default 250
|
|
48
|
+
*/
|
|
49
|
+
labelAnimationDuration?: number;
|
|
50
|
+
/**
|
|
51
|
+
* 恢复动效函数
|
|
52
|
+
* @en Resume animation function (ms)
|
|
53
|
+
* @default "cubic-bezier(0.14, 1, 0.34, 1)"
|
|
54
|
+
*/
|
|
55
|
+
labelAnimationFunction?: string;
|
|
56
|
+
/**
|
|
57
|
+
* 阻尼动效参数,使用函数x = X/(aX+b),其中X代表当前滑动距离,传入的值代表[a, b]
|
|
58
|
+
* @en Damping animation parameter, use the function x = X/(aX+b), where X represents the current sliding distance, and the incoming value represents [a, b]
|
|
59
|
+
* @default [0.013312, 1.636345]
|
|
60
|
+
*/
|
|
61
|
+
damping?: [number, number];
|
|
62
|
+
/**
|
|
63
|
+
* 得到滚动容器
|
|
64
|
+
* @en Scroll container
|
|
65
|
+
*/
|
|
66
|
+
getScrollContainer?: () => HTMLElement | null;
|
|
67
|
+
/**
|
|
68
|
+
* 标签初始文案
|
|
69
|
+
* @en Label initial text
|
|
70
|
+
* @default "更多"
|
|
71
|
+
* @default_en "More"
|
|
72
|
+
*/
|
|
73
|
+
normalText?: string;
|
|
74
|
+
/**
|
|
75
|
+
* 触发跳转文案
|
|
76
|
+
* @en Text when triggering jump
|
|
77
|
+
* @default "释放查看"
|
|
78
|
+
* @default_en "Release to view"
|
|
79
|
+
*/
|
|
80
|
+
activeText?: string;
|
|
81
|
+
/**
|
|
82
|
+
* 触碰左侧边界时是否需要回弹效果
|
|
83
|
+
* @en Whether a bounce effect is required when touching the left boundary
|
|
84
|
+
* @default false
|
|
85
|
+
*/
|
|
86
|
+
bounceWhenBumpBoundary?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* 当开启回弹效果时的阻尼系数
|
|
89
|
+
* @en Damping coefficient when the rebound effect is turned on
|
|
90
|
+
* @default 3
|
|
91
|
+
*/
|
|
92
|
+
bounceDampRate?: number;
|
|
93
|
+
/**
|
|
94
|
+
* 当开启回弹效果时的动画毫秒时间
|
|
95
|
+
* @en Animation in milliseconds when the bounce effect is turned on
|
|
96
|
+
* @default 300
|
|
97
|
+
*/
|
|
98
|
+
bounceAnimateDuration?: number;
|
|
99
|
+
/**
|
|
100
|
+
* 回弹效果开启时需要回弹的容器,默认为 getScrollContainer 返回的容器或容器的一个子元素
|
|
101
|
+
* @en The container that needs to be rebounded when the rebound effect is enabled, the default is the container returned by getScrollContainer or a child element of the container
|
|
102
|
+
*/
|
|
103
|
+
getBounceContainer?: () => HTMLElement | null;
|
|
104
|
+
/**
|
|
105
|
+
* 当开启回弹效果时自定义手指滑动跟手的距离计算方式,dis表示touchmove的距离
|
|
106
|
+
* @en When the rebound effect is turned on, customize the calculation method of the distance between the finger sliding and the hand, and dis indicates the distance of touchmove
|
|
107
|
+
* @default (dis) => Math.min(dis, bounceScrollContainer.offsetWidth) / bounceDampRate
|
|
108
|
+
*/
|
|
109
|
+
bounceDistanceProcessor?: (dis: number) => number;
|
|
110
|
+
/**
|
|
111
|
+
* 抛出外层touch事件,便于自定义,常用于阻止划动退出,切换tab等手势冲突
|
|
112
|
+
* @en Throw the outer touchstart event, which is easy to customize. It is often used to prevent gesture conflicts such as swiping to exit, switching tabs, etc.
|
|
113
|
+
*/
|
|
114
|
+
onTouchStart?: (e?: TouchEvent) => void;
|
|
115
|
+
/**
|
|
116
|
+
* 抛出外层touch事件,便于自定义,常用于阻止划动退出,切换tab等手势冲突
|
|
117
|
+
* @en Throws the outer touchmove event, which is easy to customize. It is often used to prevent gesture conflicts such as swiping to exit, switching tabs, etc.
|
|
118
|
+
*/
|
|
119
|
+
onTouchMove?: (e?: TouchEvent) => void;
|
|
120
|
+
/**
|
|
121
|
+
* 抛出外层touch事件,便于自定义,常用于阻止划动退出,切换tab等手势冲突
|
|
122
|
+
* @en Throws the outer touchend event, which is easy to customize. It is often used to prevent gesture conflicts such as swiping to exit, switching tabs, etc.
|
|
123
|
+
*/
|
|
124
|
+
onTouchEnd?: (e?: TouchEvent) => void;
|
|
125
|
+
/**
|
|
126
|
+
* 抛出外层touch事件,便于自定义,常用于阻止划动退出,切换tab等手势冲突
|
|
127
|
+
* @en Throws the outer touchcancel event, which is easy to customize. It is often used to prevent gesture conflicts such as swiping to exit, switching tabs, etc.
|
|
128
|
+
*/
|
|
129
|
+
onTouchCancel?: (e?: TouchEvent) => void;
|
|
130
|
+
/**
|
|
131
|
+
* 用户自定义标签样式
|
|
132
|
+
* @en User-defined label style
|
|
133
|
+
*/
|
|
134
|
+
renderLabel?: (offset?: number) => ReactNode;
|
|
135
|
+
/**
|
|
136
|
+
* 标签的初始位置 自定义必传
|
|
137
|
+
* @en The initial position of the label, required when customized
|
|
138
|
+
* @default 0
|
|
139
|
+
*/
|
|
140
|
+
initPos?: number;
|
|
141
|
+
/**
|
|
142
|
+
* 子元素
|
|
143
|
+
* @en Children elements
|
|
144
|
+
*/
|
|
145
|
+
children: ReactNode;
|
|
146
|
+
}
|
|
147
|
+
export interface SwipeLoadRef {
|
|
148
|
+
/**
|
|
149
|
+
* 最外层元素 DOM
|
|
150
|
+
* @en The outermost element DOM
|
|
151
|
+
*/
|
|
152
|
+
dom: HTMLDivElement | null;
|
|
153
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
### 数据录入
|
|
2
|
+
|
|
3
|
+
# 开关 Switch
|
|
4
|
+
|
|
5
|
+
开关组件,支持点击和滑动触发开关动作。
|
|
6
|
+
|
|
7
|
+
======
|
|
8
|
+
|
|
9
|
+
> 属性/Props
|
|
10
|
+
|
|
11
|
+
|参数|描述|类型|默认值|
|
|
12
|
+
|----------|-------------|------|------|
|
|
13
|
+
|className|自定义类名|string|-|
|
|
14
|
+
|style|自定义样式|CSSProperties|-|
|
|
15
|
+
|platform|组件的平台特有样式, 可选值为 android, ios|string|跟随当前所在系统|
|
|
16
|
+
|checked|是否设置为打开状态 有checked时defaultChecked不会使用|boolean|-|
|
|
17
|
+
|defaultChecked|默认的初始状态|boolean|false|
|
|
18
|
+
|text|开关文案|SwitchText|-|
|
|
19
|
+
|shape|圆角样式, fully \- 全圆角,semi \- 直角|"fully" \| "semi"|"fully"|
|
|
20
|
+
|innerArea|内部区域元素|ReactNode|-|
|
|
21
|
+
|disabled|是否设置为禁用状态|boolean|false|
|
|
22
|
+
|onChange|状态改变时触发的回调函数|(checked: boolean) =\> void|-|
|
|
23
|
+
|onTouchStart|touchStart事件回调|(e: TouchEvent\<HTMLDivElement\>) =\> void|-|
|
|
24
|
+
|onTouchEnd|touchEnd事件回调|(e: TouchEvent\<HTMLDivElement\>) =\> void|-|
|
|
25
|
+
|onClick|click事件回调|(e: MouseEvent\<HTMLDivElement, MouseEvent\>) =\> void|-|
|
|
26
|
+
|
|
27
|
+
> 引用/Refs
|
|
28
|
+
|
|
29
|
+
|参数|描述|类型|
|
|
30
|
+
|----------|-------------|------|
|
|
31
|
+
|dom|最外层元素 DOM|HTMLDivElement|
|
|
32
|
+
|
|
33
|
+
> SwitchText
|
|
34
|
+
|
|
35
|
+
|参数|描述|类型|
|
|
36
|
+
|----------|-------------|------|
|
|
37
|
+
|on|打开时的展示文案|string|
|
|
38
|
+
|off|关闭时的展示文案|string|
|