@arco-design/mobile-react 2.27.1 → 2.27.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.en-US.md +2 -2
  3. package/README.md +2 -2
  4. package/cjs/_helpers/index.d.ts +1 -0
  5. package/cjs/_helpers/index.js +10 -0
  6. package/cjs/index-bar/type.d.ts +3 -3
  7. package/cjs/load-more/index.js +4 -1
  8. package/cjs/nav-bar/index.js +2 -2
  9. package/cjs/show-monitor/index.js +112 -38
  10. package/cjs/swipe-load/demo/style/css/mobile.css +3 -0
  11. package/cjs/swipe-load/demo/style/mobile.less +11 -0
  12. package/cjs/swipe-load/index.js +86 -32
  13. package/cjs/swipe-load/style/css/index.css +3 -0
  14. package/cjs/swipe-load/style/index.less +7 -0
  15. package/cjs/swipe-load/type.d.ts +29 -0
  16. package/cjs/tabs/index.js +1 -0
  17. package/dist/index.js +218 -81
  18. package/dist/index.min.js +4 -4
  19. package/dist/style.css +3 -0
  20. package/dist/style.min.css +1 -1
  21. package/esm/_helpers/index.d.ts +1 -0
  22. package/esm/_helpers/index.js +7 -0
  23. package/esm/index-bar/type.d.ts +3 -3
  24. package/esm/load-more/index.js +4 -1
  25. package/esm/nav-bar/index.js +2 -2
  26. package/esm/show-monitor/index.js +112 -38
  27. package/esm/swipe-load/demo/style/css/mobile.css +3 -0
  28. package/esm/swipe-load/demo/style/mobile.less +11 -0
  29. package/esm/swipe-load/index.js +85 -32
  30. package/esm/swipe-load/style/css/index.css +3 -0
  31. package/esm/swipe-load/style/index.less +7 -0
  32. package/esm/swipe-load/type.d.ts +29 -0
  33. package/esm/tabs/index.js +1 -0
  34. package/package.json +3 -3
  35. package/umd/_helpers/index.d.ts +1 -0
  36. package/umd/_helpers/index.js +10 -0
  37. package/umd/index-bar/type.d.ts +3 -3
  38. package/umd/load-more/index.js +4 -1
  39. package/umd/nav-bar/index.js +2 -2
  40. package/umd/show-monitor/index.js +112 -38
  41. package/umd/swipe-load/demo/style/css/mobile.css +3 -0
  42. package/umd/swipe-load/demo/style/mobile.less +11 -0
  43. package/umd/swipe-load/index.js +88 -36
  44. package/umd/swipe-load/style/css/index.css +3 -0
  45. package/umd/swipe-load/style/index.less +7 -0
  46. package/umd/swipe-load/type.d.ts +29 -0
  47. package/umd/tabs/index.js +1 -0
@@ -130,7 +130,7 @@ var NavBar = /*#__PURE__*/forwardRef(function (props, ref) {
130
130
  ref: navBarRef,
131
131
  className: cls(wrapClass, prefixCls + "-nav-bar", (_cls = {}, _cls[prefixCls + "-nav-bar-fixed"] = fixed, _cls[prefixCls + "-nav-bar-float"] = !placeholder, _cls[prefixCls + "-nav-bar-hide"] = scrollToggleHide, _cls)),
132
132
  style: _extends({
133
- paddingTop: fixed && statusBarHeight ? statusBarHeight + "px" : ''
133
+ paddingTop: fixed && statusBarHeight ? statusBarHeight + "px" : '0px'
134
134
  }, style || {}, relBackground ? {
135
135
  background: relBackground
136
136
  } : {}),
@@ -139,7 +139,7 @@ var NavBar = /*#__PURE__*/forwardRef(function (props, ref) {
139
139
  }, /*#__PURE__*/React.createElement("div", {
140
140
  className: cls(className, system, prefixCls + "-nav-bar-wrapper", (_cls2 = {}, _cls2[prefixCls + "-nav-bar-wrapper-fixed"] = fixed, _cls2[prefixCls + "-nav-bar-wrapper-border"] = hasBottomLine, _cls2)),
141
141
  style: _extends({
142
- paddingTop: statusBarHeight ? statusBarHeight + "px" : ''
142
+ paddingTop: statusBarHeight ? statusBarHeight + "px" : '0px'
143
143
  }, customStyle)
144
144
  }, /*#__PURE__*/React.createElement("div", {
145
145
  className: prefixCls + "-nav-bar-inner all-border-box"
@@ -16,6 +16,18 @@ var wrapperNodeList = [];
16
16
 
17
17
  var listeners = {};
18
18
  var onOnceEmittedListeners = {};
19
+ /**
20
+ * Intersection Observer 同一 root 节点下的监听队列
21
+ * @en Intersection Observer Listening queue under the same root node
22
+ */
23
+
24
+ var ioListeners = [];
25
+ /**
26
+ * Intersection Observer 监听 visible 状态队列
27
+ * @en Intersection Observer listens to the visible status queue
28
+ */
29
+
30
+ var ioVisibleList = [];
19
31
  var throttlingVisibleChange;
20
32
  /**
21
33
  * 通过滚动事件监测 children 是否进入视口或离开视口。
@@ -63,12 +75,6 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
63
75
  */
64
76
 
65
77
  var domRefParent = useRef(null);
66
- /**
67
- * 当前元素是否在可视区域内
68
- * @en Whether the current element is in the visible area
69
- */
70
-
71
- var isVisible = useRef(false);
72
78
  /**
73
79
  * 保存当前节点信息,类似于 class component 中 this
74
80
  * @en Save current node information, similar to this in class component
@@ -115,10 +121,8 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
115
121
  * @en Reset the initial visible state of the element to false, and re-detect the visibility of the element, the priority is lower than 'disabled'(Usually used to re-listen when elements inside ShowMonitor change)
116
122
  */
117
123
  flushVisibleStatus: function flushVisibleStatus() {
118
- isVisible.current = false;
119
-
120
- if (isSupportNativeApi && io.current && domRef.current) {
121
- disabled ? io.current.unobserve(domRef.current) : io.current.observe(domRef.current);
124
+ if (isSupportNativeApi) {
125
+ disabled ? ioUnobserve() : ioObserve();
122
126
  } else if (listener.current) {
123
127
  var _key = wrapperKey.current;
124
128
 
@@ -182,7 +186,7 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
182
186
  */
183
187
 
184
188
 
185
- curVisible !== preVisible.current && handleCheckChildrenExist() && onCompVisibleChange(curVisible, node);
189
+ curVisible !== preVisible && handleCheckChildrenExist() && onCompVisibleChange(curVisible, node);
186
190
  var key = wrapperKey.current;
187
191
  /**
188
192
  * 监听一次后加入 pendingList 队列,随后被 listeners 过滤掉
@@ -198,8 +202,7 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
198
202
  */
199
203
 
200
204
 
201
- curVisible && !preVisible.current && compOnce && onOnceEmittedListeners[key].push(component);
202
- preVisible.current = curVisible;
205
+ curVisible && !preVisible && compOnce && onOnceEmittedListeners[key].push(component);
203
206
  }
204
207
 
205
208
  var checkVisibleHandler = useCallback(function () {
@@ -219,22 +222,98 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
219
222
  }
220
223
 
221
224
  function handleObserverStatusChange(entries) {
222
- var _io$current;
225
+ entries.forEach(function (entry) {
226
+ var isIntersecting = entry.isIntersecting,
227
+ target = entry.target;
228
+ var visibleItem = ioVisibleList.find(function (item) {
229
+ return item.node === target;
230
+ });
223
231
 
224
- var isIntersecting = entries[0].isIntersecting;
225
- /**
226
- * 当前元素 visible 对比之前发生改变,触发回调函数
227
- * @en Callback when the visible status of current element changes before the comparison
228
- */
232
+ if (visibleItem) {
233
+ var curVisible = visibleItem.isVisible,
234
+ onCompVisibleChange = visibleItem.onVisibleChange,
235
+ onceEmit = visibleItem.once;
236
+ /**
237
+ * 当前元素 visible 对比之前发生改变,触发回调函数
238
+ * @en Callback when the visible status of current element changes before the comparison
239
+ */
240
+
241
+ isIntersecting !== curVisible && handleCheckChildrenExist() && onCompVisibleChange(isIntersecting, target);
242
+ /**
243
+ * 当前元素状态由不可见变为可见,且只触发一次
244
+ * @en The current element is invisible -> visible, and once, triggers the callback
245
+ */
246
+
247
+ isIntersecting && !curVisible && onceEmit && target && ioUnobserve(target);
248
+ visibleItem.isVisible = isIntersecting;
249
+ }
250
+ });
251
+ }
252
+ /**
253
+ * 获取 io 单例
254
+ * @en Get the io singleton
255
+ */
229
256
 
230
- isIntersecting !== isVisible.current && handleCheckChildrenExist() && onVisibleChange(isIntersecting, domRef.current);
231
- /**
232
- * 当前元素不可见 -> 可见,且 once, 触发回调函数
233
- * @en The current element is invisible -> visible, and once, triggers the callback
234
- */
235
257
 
236
- isIntersecting && !isVisible.current && once && domRef.current && ((_io$current = io.current) == null ? void 0 : _io$current.unobserve(domRef.current));
237
- isVisible.current = isIntersecting;
258
+ function getIOSingleton(ioOptions) {
259
+ var root = ioOptions.root,
260
+ rootMargin = ioOptions.rootMargin,
261
+ ioThreshold = ioOptions.threshold;
262
+ var ioKey = JSON.stringify({
263
+ rootMargin: rootMargin,
264
+ threshold: ioThreshold
265
+ });
266
+
267
+ var _ioListener = ioListeners.find(function (ioListener) {
268
+ return ioListener.root === root && ioListener.key === ioKey;
269
+ });
270
+
271
+ if (!_ioListener) {
272
+ ioListeners.push({
273
+ root: root,
274
+ key: ioKey,
275
+ listener: io.current = new IntersectionObserver(handleObserverStatusChange, ioOptions)
276
+ });
277
+ } else {
278
+ io.current = _ioListener.listener;
279
+ }
280
+ }
281
+
282
+ function ioObserve() {
283
+ if (domRef.current && io.current) {
284
+ var curIdx = ioVisibleList.findIndex(function (ioVisibleItem) {
285
+ return ioVisibleItem.node === domRef.current;
286
+ });
287
+
288
+ if (curIdx !== -1) {
289
+ ioVisibleList[curIdx].isVisible = false;
290
+ } else {
291
+ ioVisibleList.push({
292
+ node: domRef.current,
293
+ isVisible: false,
294
+ once: once,
295
+ onVisibleChange: onVisibleChange
296
+ });
297
+ }
298
+
299
+ io.current.observe(domRef.current);
300
+ }
301
+ }
302
+
303
+ function ioUnobserve(target) {
304
+ var targetNode = target || domRef.current;
305
+
306
+ if (io.current && targetNode) {
307
+ var curIdx = ioVisibleList.findIndex(function (ioVisibleItem) {
308
+ return ioVisibleItem.node === targetNode;
309
+ });
310
+
311
+ if (curIdx !== -1) {
312
+ ioVisibleList.splice(curIdx, 1);
313
+ }
314
+
315
+ io.current.unobserve(targetNode);
316
+ }
238
317
  }
239
318
  /**
240
319
  * 非首次下disabled变化时,重新监听元素
@@ -244,14 +323,11 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
244
323
 
245
324
  useEffect(function () {
246
325
  if (isSupportNativeApi) {
247
- // 非首次下
326
+ // 非首次 render 下
248
327
  // @en Not for the first time
249
- if (io.current && domRef.current) {
250
- // 禁用监听 || 监听
251
- disabled ? io.current.unobserve(domRef.current) : io.current.observe(domRef.current);
252
- }
328
+ disabled ? ioUnobserve() : ioObserve();
253
329
  } else {
254
- // 非首次下
330
+ // 非首次 render 下
255
331
  // @en Not for the first time
256
332
  if (wrapperKey.current !== -1 && listener.current && listeners[wrapperKey.current]) {
257
333
  // 禁用监听,找到对应listener并删除
@@ -315,12 +391,12 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
315
391
  rootMargin = offset + "px";
316
392
  }
317
393
 
318
- io.current = new IntersectionObserver(handleObserverStatusChange, {
394
+ getIOSingleton({
319
395
  root: root,
320
396
  rootMargin: rootMargin,
321
397
  threshold: threshold
322
398
  });
323
- !disabled && io.current.observe(domRef.current);
399
+ !disabled && ioObserve();
324
400
  }
325
401
  } else {
326
402
  // 节流后回调函数
@@ -364,7 +440,7 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
364
440
 
365
441
  listener.current = {
366
442
  node: domRef.current,
367
- isVisible: isVisible,
443
+ isVisible: false,
368
444
  overflow: overflow,
369
445
  once: once,
370
446
  offset: offset,
@@ -381,9 +457,7 @@ var ShowMonitor = /*#__PURE__*/forwardRef(function (props, ref) {
381
457
  useEffect(function () {
382
458
  return function () {
383
459
  if (isSupportNativeApi) {
384
- var _io$current2;
385
-
386
- domRef.current && ((_io$current2 = io.current) == null ? void 0 : _io$current2.unobserve(domRef.current));
460
+ ioUnobserve();
387
461
  } else {
388
462
  if (overflow) {
389
463
  var parent = domRefParent.current;
@@ -2,6 +2,9 @@
2
2
  width: 100%;
3
3
  background: #e5e6eb ;
4
4
  }
5
+ #demo-swipe-load .list-container::-webkit-scrollbar {
6
+ display: none;
7
+ }
5
8
  #demo-swipe-load .course-list {
6
9
  display: -webkit-inline-box;
7
10
  display: -webkit-inline-flex;
@@ -4,36 +4,47 @@
4
4
  .list-container {
5
5
  width: 100%;
6
6
  .use-var(background, line-color);
7
+
8
+ &::-webkit-scrollbar {
9
+ display: none;
10
+ }
7
11
  }
12
+
8
13
  .course-list {
9
14
  display: inline-flex;
10
15
  align-items: flex-start;
11
16
  padding: 12px 0;
12
17
  }
18
+
13
19
  .list-item,
14
20
  .list-item-color {
15
21
  height: 72px;
16
22
  margin-right: 10px;
17
23
  .use-var(background, background-color);
18
24
  }
25
+
19
26
  .list-item-color {
20
27
  .use-var(background, primary-disabled-color);
21
28
  }
29
+
22
30
  .mylabel-start,
23
31
  .mylabel-end {
24
32
  width: 100px;
25
33
  height: 96px;
26
34
  transition: background 0.2s;
27
35
  .use-var(background, background-color);
36
+
28
37
  &.end {
29
38
  .use-var(background, line-color);
30
39
  }
31
40
  }
41
+
32
42
  .mylabel-single {
33
43
  width: 100px;
34
44
  height: 88px;
35
45
  .use-var(background, primary-disabled-color);
36
46
  }
47
+
37
48
  .single-element {
38
49
  height: 88px;
39
50
  .use-var(background, primary-disabled-color);
@@ -1,6 +1,7 @@
1
1
  import React, { useRef, forwardRef, useImperativeHandle, useEffect, useState, useContext } from 'react';
2
2
  import { cls, fingerDisToLabelDis, defaultLocale } from '@arco-design/mobile-utils';
3
3
  import { ContextLayout, GlobalContext } from '../context-provider';
4
+ import { setStyleWithVendor } from '../_helpers';
4
5
  import { useAddListener } from '../_helpers/hooks';
5
6
  export * from './type';
6
7
  /**
@@ -36,7 +37,22 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
36
37
  _props$activeText = props.activeText,
37
38
  activeText = _props$activeText === void 0 ? '' : _props$activeText,
38
39
  _props$initPos = props.initPos,
39
- initPos = _props$initPos === void 0 ? 0 : _props$initPos;
40
+ initPos = _props$initPos === void 0 ? 0 : _props$initPos,
41
+ _props$bounceWhenBump = props.bounceWhenBumpBoundary,
42
+ bounceWhenBumpBoundary = _props$bounceWhenBump === void 0 ? false : _props$bounceWhenBump,
43
+ _props$bounceDampRate = props.bounceDampRate,
44
+ bounceDampRate = _props$bounceDampRate === void 0 ? 3 : _props$bounceDampRate,
45
+ _props$bounceAnimateD = props.bounceAnimateDuration,
46
+ bounceAnimateDuration = _props$bounceAnimateD === void 0 ? 300 : _props$bounceAnimateD,
47
+ damping = props.damping,
48
+ bounceDistanceProcessor = props.bounceDistanceProcessor,
49
+ getScrollContainer = props.getScrollContainer,
50
+ getBounceContainer = props.getBounceContainer,
51
+ onTouchStart = props.onTouchStart,
52
+ onTouchEnd = props.onTouchEnd,
53
+ onTouchCancel = props.onTouchCancel,
54
+ onTouchMove = props.onTouchMove,
55
+ renderLabel = props.renderLabel;
40
56
 
41
57
  var _useContext = useContext(GlobalContext),
42
58
  _useContext$locale = _useContext.locale,
@@ -55,13 +71,14 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
55
71
  var loadingLabelRef = useRef(null);
56
72
  var showLoadMoreRef = useRef(false);
57
73
  var ifToRightRef = useRef(false);
74
+ var bouncingRef = useRef(false);
58
75
  var offsetRef = useRef(0);
59
76
  var domRef = useRef(null);
60
77
  var wrapperEl = domRef.current;
61
- useAddListener(wrapperEl, 'touchstart', props.onTouchStart);
62
- useAddListener(wrapperEl, 'touchend', props.onTouchEnd);
63
- useAddListener(wrapperEl, 'touchcancel', props.onTouchCancel);
64
- useAddListener(wrapperEl, 'touchmove', props.onTouchMove);
78
+ useAddListener(wrapperEl, 'touchstart', onTouchStart);
79
+ useAddListener(wrapperEl, 'touchend', onTouchEnd);
80
+ useAddListener(wrapperEl, 'touchcancel', onTouchCancel);
81
+ useAddListener(wrapperEl, 'touchmove', onTouchMove);
65
82
  useEffect(function () {
66
83
  if (disabled || !containerRef.current || disableState) {
67
84
  return;
@@ -75,13 +92,11 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
75
92
  // @en If no child element is passed in, component will be disabled
76
93
  setDisableState(true);
77
94
  } else if (containerRef.current.childNodes.length === 1) {
95
+ var _getScrollContainer;
96
+
78
97
  // 传入一个子元素 滑动单个元素
79
98
  // @en Pass in a child element swipe the single element
80
- if (props.getScrollContainer) {
81
- scrollContainer = props.getScrollContainer();
82
- } else {
83
- scrollContainer = containerRef.current.firstChild;
84
- }
99
+ scrollContainer = (_getScrollContainer = getScrollContainer == null ? void 0 : getScrollContainer()) != null ? _getScrollContainer : containerRef.current.firstChild;
85
100
  } else {
86
101
  // 传入多个子元素(列表元素为例) 组件控制自行滑动 不推荐
87
102
  // @en Pass in multiple sub-elements (list elements as an example) Component control slides by itself which is not recommended
@@ -101,17 +116,20 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
101
116
 
102
117
  if (!loadingCurrent) {
103
118
  return;
104
- } // 初始不显示标签
105
- // @en Initially no labels are displayed
119
+ }
106
120
 
121
+ var bounceScrollContainer = (getBounceContainer == null ? void 0 : getBounceContainer()) || scrollContainer; // 初始不显示标签
122
+ // @en Initially no labels are displayed
107
123
 
108
124
  loadingCurrent.style.display = 'none';
109
125
  var startX = 0;
110
- var endX = 0; // 触摸页面确定X起始坐标
126
+ var endX = 0;
127
+ var bounceDistance = 0; // 触摸页面确定X起始坐标
111
128
  // @en Determine the X starting coordinate on touchstart
112
129
 
113
130
  var touchstart = function touchstart(e) {
114
- startX = e.touches[0].pageX;
131
+ var evt = e.touches[0];
132
+ startX = evt.clientX || 0;
115
133
  }; // 页面滑动确定X终止坐标,更新手指的X坐标,改变loading中的文字和大小
116
134
  // @en Determine the X end coordinate, update the X coordinate of the finger, change the text and size in the loading on touchmove
117
135
 
@@ -123,12 +141,30 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
123
141
  scrollContainer.scrollLeft = 1;
124
142
  }
125
143
 
126
- endX = e.touches[0].pageX;
144
+ endX = e.touches[0].clientX || 0;
127
145
  var diff = endX - startX;
128
146
  offsetRef.current = diff;
129
- var labelDiff = fingerDisToLabelDis(Math.abs(diff), props.damping); // 向左滑动到尽头 '更多'标签加载 根据scrollLeft判断 滚动容器到达边缘触发 非滚动容器不判断
147
+ var labelDiff = fingerDisToLabelDis(Math.abs(diff), damping); // 滑动到最左侧,处理回弹效果
148
+ // @en Swipe to the far left to handle the rebound effect
149
+
150
+ if (diff > 0 && scrollContainer.scrollLeft <= 1 && bounceWhenBumpBoundary) {
151
+ e.stopPropagation();
152
+ e.cancelBubble && e.preventDefault();
153
+ bouncingRef.current = true;
154
+
155
+ var processor = bounceDistanceProcessor || function (dis) {
156
+ return Math.min(dis, bounceScrollContainer.offsetWidth) / bounceDampRate;
157
+ };
158
+
159
+ bounceDistance = processor(diff);
160
+ setStyleWithVendor(bounceScrollContainer, {
161
+ transition: 'none',
162
+ transform: "translateX(" + bounceDistance + "px) translateZ(0)"
163
+ });
164
+ } // 向左滑动到尽头 '更多'标签加载 根据scrollLeft判断 滚动容器到达边缘触发 非滚动容器不判断
130
165
  // @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
131
166
 
167
+
132
168
  if (diff < 0 && (scrollContainer.scrollLeft + scrollContainer.clientWidth >= scrollContainer.scrollWidth - 1 || !scrollContainer.scrollLeft) && !ifToRightRef.current) {
133
169
  showLoadMoreRef.current = true;
134
170
  loadingCurrent.style.display = 'flex';
@@ -154,12 +190,14 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
154
190
  loadingLabelCurrent.innerHTML = labelDiff >= minConfirmOffset ? activeText || locale.SwipeLoad.activeText : normalText || locale.SwipeLoad.normalText;
155
191
  }
156
192
 
157
- loadingCurrent.style.transition = 'all 0.02s';
158
- loadingCurrent.style.webkitTransform = "translateX(-" + labelRightMargin + "px)";
159
- loadingCurrent.style.transform = "translateX(-" + labelRightMargin + "px)";
160
- scrollContainer.style.transition = 'all 0.03s';
161
- scrollContainer.style.webkitTransform = "translateX(-" + listRightMargin + "px)";
162
- scrollContainer.style.transform = "translateX(-" + listRightMargin + "px)";
193
+ setStyleWithVendor(loadingCurrent, {
194
+ transition: 'none',
195
+ transform: "translateX(-" + labelRightMargin + "px) translateZ(0)"
196
+ });
197
+ setStyleWithVendor(scrollContainer, {
198
+ transition: 'none',
199
+ transform: "translateX(-" + listRightMargin + "px) translateZ(0)"
200
+ });
163
201
  }
164
202
 
165
203
  if (diff > 0 && scrollContainer.scrollLeft + scrollContainer.clientWidth <= scrollContainer.scrollWidth - 1) {
@@ -184,13 +222,28 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
184
222
  var labelDiff = fingerDisToLabelDis(Math.abs(diff));
185
223
 
186
224
  var resumeAnimation = function resumeAnimation() {
187
- scrollContainer.style.transition = "all " + labelAnimationDuration + "ms " + labelAnimationFunction;
188
- scrollContainer.style.webkitTransform = 'translateX(0px)';
189
- scrollContainer.style.transform = 'translateX(0px)';
190
- loadingCurrent.style.transition = "all " + labelAnimationDuration + "ms " + labelAnimationFunction;
191
- loadingCurrent.style.webkitTransform = 'translateX(0px)';
192
- loadingCurrent.style.transform = 'translateX(0px)';
193
- showLoadMoreRef.current = false;
225
+ if (showLoadMoreRef.current) {
226
+ showLoadMoreRef.current = false;
227
+ var scrollTransitionCssStyle = "all " + labelAnimationDuration + "ms " + labelAnimationFunction;
228
+ var scrollTransformCssStyle = 'translateX(0px) translateZ(0)';
229
+ setStyleWithVendor(scrollContainer, {
230
+ transition: scrollTransitionCssStyle,
231
+ transform: scrollTransformCssStyle
232
+ });
233
+ setStyleWithVendor(loadingCurrent, {
234
+ transition: scrollTransitionCssStyle,
235
+ transform: scrollTransformCssStyle
236
+ });
237
+ }
238
+
239
+ if (bouncingRef.current) {
240
+ bouncingRef.current = false;
241
+ setStyleWithVendor(bounceScrollContainer, {
242
+ transition: "all " + bounceAnimateDuration + "ms",
243
+ transform: 'translateX(0px) translateZ(0)'
244
+ });
245
+ }
246
+
194
247
  ifToRightRef.current = false;
195
248
  setTimeout(function () {
196
249
  loadingCurrent.style.display = 'none';
@@ -220,7 +273,7 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
220
273
  scrollContainer.removeEventListener('touchmove', touchmove);
221
274
  scrollContainer.removeEventListener('touchend', touchend);
222
275
  };
223
- }, [disabled]);
276
+ }, [disabled, getScrollContainer, getBounceContainer, bounceWhenBumpBoundary, bounceDampRate, bounceAnimateDuration]);
224
277
  useImperativeHandle(ref, function () {
225
278
  return {
226
279
  dom: domRef.current
@@ -234,14 +287,14 @@ var SwipeLoad = /*#__PURE__*/forwardRef(function (props, ref) {
234
287
  }, /*#__PURE__*/React.createElement("div", {
235
288
  className: cls(prefixCls + "-list-area"),
236
289
  ref: containerRef
237
- }, children), props.renderLabel ? /*#__PURE__*/React.createElement("div", {
290
+ }, children), renderLabel ? /*#__PURE__*/React.createElement("div", {
238
291
  className: cls(prefixCls + "-custom-loading-area"),
239
292
  ref: loadingRef,
240
293
  style: {
241
294
  position: 'absolute',
242
295
  right: initPos + "px"
243
296
  }
244
- }, props.renderLabel.length ? props.renderLabel(labelOffsetState) : props.renderLabel()) : /*#__PURE__*/React.createElement("div", {
297
+ }, renderLabel.length ? renderLabel(labelOffsetState) : renderLabel()) : /*#__PURE__*/React.createElement("div", {
245
298
  className: cls(prefixCls + "-loading-area"),
246
299
  ref: loadingRef,
247
300
  style: {
@@ -9,6 +9,9 @@
9
9
  position: relative;
10
10
  width: 100%;
11
11
  }
12
+ .arco-swipe-load .arco-list-area::-webkit-scrollbar {
13
+ display: none;
14
+ }
12
15
  .arco-swipe-load .arco-loading-area {
13
16
  background-color: #f8f8f8 ;
14
17
  margin-top: 0;
@@ -4,14 +4,21 @@
4
4
  position: relative;
5
5
  display: inline-flex;
6
6
  width: 100%;
7
+
7
8
  .@{prefix}-list-area {
8
9
  position: relative;
9
10
  width: 100%;
11
+
12
+ &::-webkit-scrollbar {
13
+ display: none;
14
+ }
10
15
  }
16
+
11
17
  .@{prefix}-loading-area {
12
18
  .use-var(background-color, swipe-load-label-background);
13
19
  margin-top: 0;
14
20
  .use-var(border-radius, swipe-load-label-border-radius);
21
+
15
22
  .@{prefix}-loading-label {
16
23
  .use-var(margin-left, swipe-load-label-text-margin-left);
17
24
  .use-var(width, swipe-load-label-text-width);
@@ -77,6 +77,35 @@ export interface SwipeLoadProps {
77
77
  * @default_en "Release to view"
78
78
  */
79
79
  activeText?: string;
80
+ /**
81
+ * 触碰左侧边界时是否需要回弹效果
82
+ * @en Whether a bounce effect is required when touching the left boundary
83
+ * @default false
84
+ */
85
+ bounceWhenBumpBoundary?: boolean;
86
+ /**
87
+ * 当开启回弹效果时的阻尼系数
88
+ * @en Damping coefficient when the rebound effect is turned on
89
+ * @default 3
90
+ */
91
+ bounceDampRate?: number;
92
+ /**
93
+ * 当开启回弹效果时的动画毫秒时间
94
+ * @en Animation in milliseconds when the bounce effect is turned on
95
+ * @default 300
96
+ */
97
+ bounceAnimateDuration?: number;
98
+ /**
99
+ * 回弹效果开启时需要回弹的容器,默认为 getScrollContainer 返回的容器或容器的一个子元素
100
+ * @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
101
+ */
102
+ getBounceContainer?: () => HTMLElement | null;
103
+ /**
104
+ * 当开启回弹效果时自定义手指滑动跟手的距离计算方式,dis表示touchmove的距离
105
+ * @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
106
+ * @default (dis) => Math.min(dis, bounceScrollContainer.offsetWidth) / bounceDampRate
107
+ */
108
+ bounceDistanceProcessor?: (dis: number) => number;
80
109
  /**
81
110
  * 抛出外层touch事件,便于自定义,常用于阻止划动退出,切换tab等手势冲突
82
111
  * @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.
package/esm/tabs/index.js CHANGED
@@ -220,6 +220,7 @@ var Tabs = /*#__PURE__*/forwardRef(function (props, ref) {
220
220
  // 利用受控手动更改index时,给cell line加上动画
221
221
  // @en Animate the cell line when changeing the index
222
222
  setCellTrans(true);
223
+ changeFromRef.current = 'manual';
223
224
  }, [activeTab]);
224
225
  useUpdateEffect(function () {
225
226
  onDistanceChange && onDistanceChange(distance, wrapWidth, activeIndex);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arco-design/mobile-react",
3
- "version": "2.27.1",
3
+ "version": "2.27.2",
4
4
  "description": "",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -15,7 +15,7 @@
15
15
  "author": "taoyiyue@bytedance.com",
16
16
  "license": "ISC",
17
17
  "dependencies": {
18
- "@arco-design/mobile-utils": "2.15.1",
18
+ "@arco-design/mobile-utils": "2.15.2",
19
19
  "@arco-design/transformable": "^1.0.0",
20
20
  "lodash.throttle": "^4.1.1",
21
21
  "resize-observer-polyfill": "^1.5.1"
@@ -35,5 +35,5 @@
35
35
  "publishConfig": {
36
36
  "access": "public"
37
37
  },
38
- "gitHead": "9c06acb2cc9341ee12843d1720e9b796cbbc2ac5"
38
+ "gitHead": "e270c691a36dba4048f27ee6d10616291e11e062"
39
39
  }
@@ -7,6 +7,7 @@ export * from './hooks';
7
7
  export * from './type';
8
8
  export * from './react-dom';
9
9
  export declare function getStyleWithVendor(style: CSSProperties): CSSProperties;
10
+ export declare function setStyleWithVendor(dom: HTMLElement, style: CSSProperties): void;
10
11
  /**
11
12
  * 计算默认值,仅未定义时使用默认值
12
13
  * @desc {en} Calculate the default value, use default value only if undefined
@@ -18,10 +18,12 @@
18
18
  _exports.__esModule = true;
19
19
  var _exportNames = {
20
20
  getStyleWithVendor: true,
21
+ setStyleWithVendor: true,
21
22
  getDefaultValue: true
22
23
  };
23
24
  _exports.getDefaultValue = void 0;
24
25
  _exports.getStyleWithVendor = getStyleWithVendor;
26
+ _exports.setStyleWithVendor = setStyleWithVendor;
25
27
  _extends3 = _interopRequireDefault(_extends3);
26
28
  Object.keys(_hooks).forEach(function (key) {
27
29
  if (key === "default" || key === "__esModule") return;
@@ -58,6 +60,14 @@
58
60
  }, {});
59
61
  return newStyle;
60
62
  }
63
+
64
+ function setStyleWithVendor(dom, style) {
65
+ var vendorStyle = getStyleWithVendor(style);
66
+
67
+ for (var key in vendorStyle) {
68
+ dom.style[key] = vendorStyle[key];
69
+ }
70
+ }
61
71
  /**
62
72
  * 计算默认值,仅未定义时使用默认值
63
73
  * @desc {en} Calculate the default value, use default value only if undefined