@arco-design/mobile-react 2.27.1 → 2.27.3

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 (59) hide show
  1. package/CHANGELOG.md +26 -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 +6 -2
  17. package/cjs/tabs/style/css/index.css +4 -0
  18. package/cjs/tabs/style/index.less +5 -0
  19. package/cjs/tabs/tab-pane.js +49 -12
  20. package/cjs/tabs/type.d.ts +7 -1
  21. package/dist/index.js +297 -119
  22. package/dist/index.min.js +5 -5
  23. package/dist/style.css +7 -0
  24. package/dist/style.min.css +1 -1
  25. package/esm/_helpers/index.d.ts +1 -0
  26. package/esm/_helpers/index.js +7 -0
  27. package/esm/index-bar/type.d.ts +3 -3
  28. package/esm/load-more/index.js +4 -1
  29. package/esm/nav-bar/index.js +2 -2
  30. package/esm/show-monitor/index.js +112 -38
  31. package/esm/swipe-load/demo/style/css/mobile.css +3 -0
  32. package/esm/swipe-load/demo/style/mobile.less +11 -0
  33. package/esm/swipe-load/index.js +85 -32
  34. package/esm/swipe-load/style/css/index.css +3 -0
  35. package/esm/swipe-load/style/index.less +7 -0
  36. package/esm/swipe-load/type.d.ts +29 -0
  37. package/esm/tabs/index.js +6 -2
  38. package/esm/tabs/style/css/index.css +4 -0
  39. package/esm/tabs/style/index.less +5 -0
  40. package/esm/tabs/tab-pane.js +49 -11
  41. package/esm/tabs/type.d.ts +7 -1
  42. package/package.json +3 -3
  43. package/umd/_helpers/index.d.ts +1 -0
  44. package/umd/_helpers/index.js +10 -0
  45. package/umd/index-bar/type.d.ts +3 -3
  46. package/umd/load-more/index.js +4 -1
  47. package/umd/nav-bar/index.js +2 -2
  48. package/umd/show-monitor/index.js +112 -38
  49. package/umd/swipe-load/demo/style/css/mobile.css +3 -0
  50. package/umd/swipe-load/demo/style/mobile.less +11 -0
  51. package/umd/swipe-load/index.js +88 -36
  52. package/umd/swipe-load/style/css/index.css +3 -0
  53. package/umd/swipe-load/style/index.less +7 -0
  54. package/umd/swipe-load/type.d.ts +29 -0
  55. package/umd/tabs/index.js +6 -2
  56. package/umd/tabs/style/css/index.css +4 -0
  57. package/umd/tabs/style/index.less +5 -0
  58. package/umd/tabs/tab-pane.js +49 -12
  59. package/umd/tabs/type.d.ts +7 -1
@@ -1,16 +1,16 @@
1
1
  (function (global, factory) {
2
2
  if (typeof define === "function" && define.amd) {
3
- define(["exports", "react", "@arco-design/mobile-utils", "../context-provider", "../_helpers/hooks", "./type"], factory);
3
+ define(["exports", "react", "@arco-design/mobile-utils", "../context-provider", "../_helpers", "../_helpers/hooks", "./type"], factory);
4
4
  } else if (typeof exports !== "undefined") {
5
- factory(exports, require("react"), require("@arco-design/mobile-utils"), require("../context-provider"), require("../_helpers/hooks"), require("./type"));
5
+ factory(exports, require("react"), require("@arco-design/mobile-utils"), require("../context-provider"), require("../_helpers"), require("../_helpers/hooks"), require("./type"));
6
6
  } else {
7
7
  var mod = {
8
8
  exports: {}
9
9
  };
10
- factory(mod.exports, global.react, global.mobileUtils, global.contextProvider, global.hooks, global.type);
10
+ factory(mod.exports, global.react, global.mobileUtils, global.contextProvider, global._helpers, global.hooks, global.type);
11
11
  global.index = mod.exports;
12
12
  }
13
- })(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _react, _mobileUtils, _contextProvider, _hooks, _type) {
13
+ })(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _react, _mobileUtils, _contextProvider, _helpers, _hooks, _type) {
14
14
  "use strict";
15
15
 
16
16
  _exports.__esModule = true;
@@ -60,7 +60,22 @@
60
60
  _props$activeText = props.activeText,
61
61
  activeText = _props$activeText === void 0 ? '' : _props$activeText,
62
62
  _props$initPos = props.initPos,
63
- initPos = _props$initPos === void 0 ? 0 : _props$initPos;
63
+ initPos = _props$initPos === void 0 ? 0 : _props$initPos,
64
+ _props$bounceWhenBump = props.bounceWhenBumpBoundary,
65
+ bounceWhenBumpBoundary = _props$bounceWhenBump === void 0 ? false : _props$bounceWhenBump,
66
+ _props$bounceDampRate = props.bounceDampRate,
67
+ bounceDampRate = _props$bounceDampRate === void 0 ? 3 : _props$bounceDampRate,
68
+ _props$bounceAnimateD = props.bounceAnimateDuration,
69
+ bounceAnimateDuration = _props$bounceAnimateD === void 0 ? 300 : _props$bounceAnimateD,
70
+ damping = props.damping,
71
+ bounceDistanceProcessor = props.bounceDistanceProcessor,
72
+ getScrollContainer = props.getScrollContainer,
73
+ getBounceContainer = props.getBounceContainer,
74
+ onTouchStart = props.onTouchStart,
75
+ onTouchEnd = props.onTouchEnd,
76
+ onTouchCancel = props.onTouchCancel,
77
+ onTouchMove = props.onTouchMove,
78
+ renderLabel = props.renderLabel;
64
79
 
65
80
  var _useContext = (0, _react.useContext)(_contextProvider.GlobalContext),
66
81
  _useContext$locale = _useContext.locale,
@@ -79,13 +94,14 @@
79
94
  var loadingLabelRef = (0, _react.useRef)(null);
80
95
  var showLoadMoreRef = (0, _react.useRef)(false);
81
96
  var ifToRightRef = (0, _react.useRef)(false);
97
+ var bouncingRef = (0, _react.useRef)(false);
82
98
  var offsetRef = (0, _react.useRef)(0);
83
99
  var domRef = (0, _react.useRef)(null);
84
100
  var wrapperEl = domRef.current;
85
- (0, _hooks.useAddListener)(wrapperEl, 'touchstart', props.onTouchStart);
86
- (0, _hooks.useAddListener)(wrapperEl, 'touchend', props.onTouchEnd);
87
- (0, _hooks.useAddListener)(wrapperEl, 'touchcancel', props.onTouchCancel);
88
- (0, _hooks.useAddListener)(wrapperEl, 'touchmove', props.onTouchMove);
101
+ (0, _hooks.useAddListener)(wrapperEl, 'touchstart', onTouchStart);
102
+ (0, _hooks.useAddListener)(wrapperEl, 'touchend', onTouchEnd);
103
+ (0, _hooks.useAddListener)(wrapperEl, 'touchcancel', onTouchCancel);
104
+ (0, _hooks.useAddListener)(wrapperEl, 'touchmove', onTouchMove);
89
105
  (0, _react.useEffect)(function () {
90
106
  if (disabled || !containerRef.current || disableState) {
91
107
  return;
@@ -99,13 +115,11 @@
99
115
  // @en If no child element is passed in, component will be disabled
100
116
  setDisableState(true);
101
117
  } else if (containerRef.current.childNodes.length === 1) {
118
+ var _getScrollContainer;
119
+
102
120
  // 传入一个子元素 滑动单个元素
103
121
  // @en Pass in a child element swipe the single element
104
- if (props.getScrollContainer) {
105
- scrollContainer = props.getScrollContainer();
106
- } else {
107
- scrollContainer = containerRef.current.firstChild;
108
- }
122
+ scrollContainer = (_getScrollContainer = getScrollContainer == null ? void 0 : getScrollContainer()) != null ? _getScrollContainer : containerRef.current.firstChild;
109
123
  } else {
110
124
  // 传入多个子元素(列表元素为例) 组件控制自行滑动 不推荐
111
125
  // @en Pass in multiple sub-elements (list elements as an example) Component control slides by itself which is not recommended
@@ -125,17 +139,20 @@
125
139
 
126
140
  if (!loadingCurrent) {
127
141
  return;
128
- } // 初始不显示标签
129
- // @en Initially no labels are displayed
142
+ }
130
143
 
144
+ var bounceScrollContainer = (getBounceContainer == null ? void 0 : getBounceContainer()) || scrollContainer; // 初始不显示标签
145
+ // @en Initially no labels are displayed
131
146
 
132
147
  loadingCurrent.style.display = 'none';
133
148
  var startX = 0;
134
- var endX = 0; // 触摸页面确定X起始坐标
149
+ var endX = 0;
150
+ var bounceDistance = 0; // 触摸页面确定X起始坐标
135
151
  // @en Determine the X starting coordinate on touchstart
136
152
 
137
153
  var touchstart = function touchstart(e) {
138
- startX = e.touches[0].pageX;
154
+ var evt = e.touches[0];
155
+ startX = evt.clientX || 0;
139
156
  }; // 页面滑动确定X终止坐标,更新手指的X坐标,改变loading中的文字和大小
140
157
  // @en Determine the X end coordinate, update the X coordinate of the finger, change the text and size in the loading on touchmove
141
158
 
@@ -147,12 +164,30 @@
147
164
  scrollContainer.scrollLeft = 1;
148
165
  }
149
166
 
150
- endX = e.touches[0].pageX;
167
+ endX = e.touches[0].clientX || 0;
151
168
  var diff = endX - startX;
152
169
  offsetRef.current = diff;
153
- var labelDiff = (0, _mobileUtils.fingerDisToLabelDis)(Math.abs(diff), props.damping); // 向左滑动到尽头 '更多'标签加载 根据scrollLeft判断 滚动容器到达边缘触发 非滚动容器不判断
170
+ var labelDiff = (0, _mobileUtils.fingerDisToLabelDis)(Math.abs(diff), damping); // 滑动到最左侧,处理回弹效果
171
+ // @en Swipe to the far left to handle the rebound effect
172
+
173
+ if (diff > 0 && scrollContainer.scrollLeft <= 1 && bounceWhenBumpBoundary) {
174
+ e.stopPropagation();
175
+ e.cancelBubble && e.preventDefault();
176
+ bouncingRef.current = true;
177
+
178
+ var processor = bounceDistanceProcessor || function (dis) {
179
+ return Math.min(dis, bounceScrollContainer.offsetWidth) / bounceDampRate;
180
+ };
181
+
182
+ bounceDistance = processor(diff);
183
+ (0, _helpers.setStyleWithVendor)(bounceScrollContainer, {
184
+ transition: 'none',
185
+ transform: "translateX(" + bounceDistance + "px) translateZ(0)"
186
+ });
187
+ } // 向左滑动到尽头 '更多'标签加载 根据scrollLeft判断 滚动容器到达边缘触发 非滚动容器不判断
154
188
  // @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
155
189
 
190
+
156
191
  if (diff < 0 && (scrollContainer.scrollLeft + scrollContainer.clientWidth >= scrollContainer.scrollWidth - 1 || !scrollContainer.scrollLeft) && !ifToRightRef.current) {
157
192
  showLoadMoreRef.current = true;
158
193
  loadingCurrent.style.display = 'flex';
@@ -178,12 +213,14 @@
178
213
  loadingLabelCurrent.innerHTML = labelDiff >= minConfirmOffset ? activeText || locale.SwipeLoad.activeText : normalText || locale.SwipeLoad.normalText;
179
214
  }
180
215
 
181
- loadingCurrent.style.transition = 'all 0.02s';
182
- loadingCurrent.style.webkitTransform = "translateX(-" + labelRightMargin + "px)";
183
- loadingCurrent.style.transform = "translateX(-" + labelRightMargin + "px)";
184
- scrollContainer.style.transition = 'all 0.03s';
185
- scrollContainer.style.webkitTransform = "translateX(-" + listRightMargin + "px)";
186
- scrollContainer.style.transform = "translateX(-" + listRightMargin + "px)";
216
+ (0, _helpers.setStyleWithVendor)(loadingCurrent, {
217
+ transition: 'none',
218
+ transform: "translateX(-" + labelRightMargin + "px) translateZ(0)"
219
+ });
220
+ (0, _helpers.setStyleWithVendor)(scrollContainer, {
221
+ transition: 'none',
222
+ transform: "translateX(-" + listRightMargin + "px) translateZ(0)"
223
+ });
187
224
  }
188
225
 
189
226
  if (diff > 0 && scrollContainer.scrollLeft + scrollContainer.clientWidth <= scrollContainer.scrollWidth - 1) {
@@ -208,13 +245,28 @@
208
245
  var labelDiff = (0, _mobileUtils.fingerDisToLabelDis)(Math.abs(diff));
209
246
 
210
247
  var resumeAnimation = function resumeAnimation() {
211
- scrollContainer.style.transition = "all " + labelAnimationDuration + "ms " + labelAnimationFunction;
212
- scrollContainer.style.webkitTransform = 'translateX(0px)';
213
- scrollContainer.style.transform = 'translateX(0px)';
214
- loadingCurrent.style.transition = "all " + labelAnimationDuration + "ms " + labelAnimationFunction;
215
- loadingCurrent.style.webkitTransform = 'translateX(0px)';
216
- loadingCurrent.style.transform = 'translateX(0px)';
217
- showLoadMoreRef.current = false;
248
+ if (showLoadMoreRef.current) {
249
+ showLoadMoreRef.current = false;
250
+ var scrollTransitionCssStyle = "all " + labelAnimationDuration + "ms " + labelAnimationFunction;
251
+ var scrollTransformCssStyle = 'translateX(0px) translateZ(0)';
252
+ (0, _helpers.setStyleWithVendor)(scrollContainer, {
253
+ transition: scrollTransitionCssStyle,
254
+ transform: scrollTransformCssStyle
255
+ });
256
+ (0, _helpers.setStyleWithVendor)(loadingCurrent, {
257
+ transition: scrollTransitionCssStyle,
258
+ transform: scrollTransformCssStyle
259
+ });
260
+ }
261
+
262
+ if (bouncingRef.current) {
263
+ bouncingRef.current = false;
264
+ (0, _helpers.setStyleWithVendor)(bounceScrollContainer, {
265
+ transition: "all " + bounceAnimateDuration + "ms",
266
+ transform: 'translateX(0px) translateZ(0)'
267
+ });
268
+ }
269
+
218
270
  ifToRightRef.current = false;
219
271
  setTimeout(function () {
220
272
  loadingCurrent.style.display = 'none';
@@ -244,7 +296,7 @@
244
296
  scrollContainer.removeEventListener('touchmove', touchmove);
245
297
  scrollContainer.removeEventListener('touchend', touchend);
246
298
  };
247
- }, [disabled]);
299
+ }, [disabled, getScrollContainer, getBounceContainer, bounceWhenBumpBoundary, bounceDampRate, bounceAnimateDuration]);
248
300
  (0, _react.useImperativeHandle)(ref, function () {
249
301
  return {
250
302
  dom: domRef.current
@@ -258,14 +310,14 @@
258
310
  }, /*#__PURE__*/_react.default.createElement("div", {
259
311
  className: (0, _mobileUtils.cls)(prefixCls + "-list-area"),
260
312
  ref: containerRef
261
- }, children), props.renderLabel ? /*#__PURE__*/_react.default.createElement("div", {
313
+ }, children), renderLabel ? /*#__PURE__*/_react.default.createElement("div", {
262
314
  className: (0, _mobileUtils.cls)(prefixCls + "-custom-loading-area"),
263
315
  ref: loadingRef,
264
316
  style: {
265
317
  position: 'absolute',
266
318
  right: initPos + "px"
267
319
  }
268
- }, props.renderLabel.length ? props.renderLabel(labelOffsetState) : props.renderLabel()) : /*#__PURE__*/_react.default.createElement("div", {
320
+ }, renderLabel.length ? renderLabel(labelOffsetState) : renderLabel()) : /*#__PURE__*/_react.default.createElement("div", {
269
321
  className: (0, _mobileUtils.cls)(prefixCls + "-loading-area"),
270
322
  ref: loadingRef,
271
323
  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/umd/tabs/index.js CHANGED
@@ -147,7 +147,9 @@
147
147
  fullScreen = props.fullScreen,
148
148
  autoHeight = props.autoHeight,
149
149
  _props$tabBarStopProp = props.tabBarStopPropagation,
150
- tabBarStopPropagation = _props$tabBarStopProp === void 0 ? true : _props$tabBarStopProp;
150
+ tabBarStopPropagation = _props$tabBarStopProp === void 0 ? true : _props$tabBarStopProp,
151
+ _props$swipeEnergySav = props.swipeEnergySaving,
152
+ swipeEnergySaving = _props$swipeEnergySav === void 0 ? false : _props$swipeEnergySav;
151
153
  var domRef = (0, _react.useRef)(null);
152
154
  var cellRef = (0, _react.useRef)(null);
153
155
  var paneRef = (0, _react.useRef)(null);
@@ -246,6 +248,7 @@
246
248
  // 利用受控手动更改index时,给cell line加上动画
247
249
  // @en Animate the cell line when changeing the index
248
250
  setCellTrans(true);
251
+ changeFromRef.current = 'manual';
249
252
  }, [activeTab]);
250
253
  (0, _helpers.useUpdateEffect)(function () {
251
254
  onDistanceChange && onDistanceChange(distance, wrapWidth, activeIndex);
@@ -533,7 +536,8 @@
533
536
  tabPaneClass: tabPaneClass,
534
537
  tabPaneExtra: tabPaneExtra,
535
538
  autoHeight: autoHeight,
536
- onScroll: onScroll
539
+ onScroll: onScroll,
540
+ swipeEnergySaving: swipeEnergySaving
537
541
  }, commonProps)));
538
542
  });
539
543
  });
@@ -473,6 +473,10 @@
473
473
  -webkit-transition-timing-function: ease-out;
474
474
  transition-timing-function: ease-out;
475
475
  }
476
+ .arco-tab-pane-container.mode-swipe-energy-saving {
477
+ position: relative;
478
+ overflow: hidden;
479
+ }
476
480
  .arco-tab-pane-container.full-screen {
477
481
  -webkit-box-flex: 1;
478
482
  -webkit-flex: 1;
@@ -399,6 +399,11 @@
399
399
  transition-timing-function: ease-out;
400
400
  }
401
401
 
402
+ &.mode-swipe-energy-saving {
403
+ position: relative;
404
+ overflow: hidden;
405
+ }
406
+
402
407
  &.full-screen {
403
408
  flex: 1;
404
409
  overflow: hidden;
@@ -56,6 +56,7 @@
56
56
  translateZ = props.translateZ,
57
57
  fullScreen = props.fullScreen,
58
58
  autoHeight = props.autoHeight,
59
+ swipeEnergySaving = props.swipeEnergySaving,
59
60
  changeIndex = props.changeIndex,
60
61
  onScroll = props.onScroll;
61
62
  var domRef = (0, _react.useRef)(null);
@@ -67,12 +68,16 @@
67
68
  shownIndexes = _useState[0],
68
69
  setShownIndexes = _useState[1];
69
70
 
71
+ var _useState2 = (0, _react.useState)(activeIndex),
72
+ shownActiveIndex = _useState2[0],
73
+ setShownActiveIndex = _useState2[1];
74
+
70
75
  var prefix = prefixCls + "-tab-pane";
71
76
  var handleTouchEnd = swipeable ? handlePaneTouchEnd : void 0;
72
77
 
73
- var _useState2 = (0, _react.useState)('auto'),
74
- currentPaneHeight = _useState2[0],
75
- setCurrentPaneHeight = _useState2[1];
78
+ var _useState3 = (0, _react.useState)('auto'),
79
+ currentPaneHeight = _useState3[0],
80
+ setCurrentPaneHeight = _useState3[1];
76
81
 
77
82
  (0, _react.useImperativeHandle)(ref, function () {
78
83
  return {
@@ -158,6 +163,8 @@
158
163
  }
159
164
 
160
165
  function calcShownIndexes() {
166
+ setShownActiveIndex(activeIndex);
167
+
161
168
  if (typeof lazyloadCount === 'number') {
162
169
  setShownIndexes([activeIndex - lazyloadCount, activeIndex + lazyloadCount]);
163
170
  return;
@@ -258,11 +265,35 @@
258
265
  var heightStyle = currentPaneHeight && currentPaneHeight !== 'auto' ? {
259
266
  height: currentPaneHeight
260
267
  } : {};
261
- return (0, _helpers.getStyleWithVendor)((0, _extends2.default)({}, sizeStyle, {
268
+ return (0, _helpers.getStyleWithVendor)((0, _extends2.default)({}, swipeEnergySaving ? {} : sizeStyle, {
262
269
  transitionDuration: getTransition() + "ms"
263
270
  }, heightStyle, commonStyle));
264
271
  }
265
272
 
273
+ function getEnergySavingPaneStyle(index) {
274
+ if (mode === 'scroll' || !swipeEnergySaving) {
275
+ return undefined;
276
+ }
277
+
278
+ if (index !== shownActiveIndex) {
279
+ return {
280
+ position: 'absolute',
281
+ left: '-100%',
282
+ top: '-100%'
283
+ };
284
+ }
285
+
286
+ var translateStr = translateZ ? ' translateZ(0)' : '';
287
+ var sizeStyle = tabDirection === 'vertical' ? {
288
+ transform: "translateX(" + (distance - wrapWidth * (activeIndex - index)) + "px)" + translateStr
289
+ } : {
290
+ transform: "translateY(" + (distance - wrapHeight * (activeIndex - index)) + "px)" + translateStr
291
+ };
292
+ return (0, _helpers.getStyleWithVendor)((0, _extends2.default)({}, sizeStyle, {
293
+ transitionDuration: getTransition() + "ms"
294
+ }));
295
+ }
296
+
266
297
  function renderContent(pane, index) {
267
298
  var contentProps = {
268
299
  key: index,
@@ -272,32 +303,38 @@
272
303
  ref: function ref(r) {
273
304
  return panesRef.current[index] = r;
274
305
  }
275
- }; // 是滚动模式或在加载范围内,直接渲染
306
+ };
307
+ var energySavingStyle = getEnergySavingPaneStyle(index); // 是滚动模式或在加载范围内,直接渲染
276
308
  // @en Render directly when in scroll mode or in loading scope
277
309
 
278
310
  if (mode === 'scroll' || index >= shownIndexes[0] && index <= shownIndexes[1]) {
279
- return /*#__PURE__*/_react.default.createElement("div", contentProps, pane);
280
- } // 不在加载范围内,视renderHideContent和hideContentStyle情况而定
281
- // @en Not in the loading range, depending on renderHideContent and hideContentStyle
311
+ return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, contentProps, {
312
+ style: energySavingStyle
313
+ }), pane);
314
+ }
282
315
 
316
+ var energySavingHideStyle = (0, _extends2.default)({}, energySavingStyle, hideContentStyle || {}); // 不在加载范围内,视renderHideContent和hideContentStyle情况而定
317
+ // @en Not in the loading range, depending on renderHideContent and hideContentStyle
283
318
 
284
319
  if (renderHideContent) {
285
320
  return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, contentProps, {
286
- style: hideContentStyle || {}
321
+ style: energySavingHideStyle
287
322
  }), renderHideContent(index, pane));
288
323
  }
289
324
 
290
325
  if (hideContentStyle === null) {
291
- return /*#__PURE__*/_react.default.createElement("div", contentProps);
326
+ return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, contentProps, {
327
+ style: energySavingStyle
328
+ }));
292
329
  }
293
330
 
294
331
  return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, contentProps, {
295
- style: hideContentStyle
332
+ style: energySavingHideStyle
296
333
  }), pane);
297
334
  }
298
335
 
299
336
  return /*#__PURE__*/_react.default.createElement("div", {
300
- className: (0, _mobileUtils.cls)(prefix + "-container", tabDirection, "mode-" + mode, tabPaneClass, {
337
+ className: (0, _mobileUtils.cls)(prefix + "-container", tabDirection, swipeEnergySaving ? "mode-" + mode + "-energy-saving" : "mode-" + mode, tabPaneClass, {
301
338
  'full-screen': fullScreen
302
339
  }, (_cls = {}, _cls["mode-scroll-" + (scrollVertical ? 'vertical' : 'horizontal')] = mode === 'scroll', _cls)),
303
340
  style: getPaneStyle(),
@@ -322,6 +322,12 @@ export interface TabsProps {
322
322
  * @default true
323
323
  */
324
324
  translateZ?: boolean;
325
+ /**
326
+ * 是否启用滑动节能模式,开启后TabPane外层容器不会随panes数量撑开并提升为合成层,仅滑动当前选中的pane,其他pane在选中前将被隐藏
327
+ * @en Whether to enable the energy-saving sliding mode. After opening, the outer container of the TabPane will not expand with the number of panes and be promoted to a composite layer. Only the currently selected pane will be slid, and other panes will be hidden before being selected.
328
+ * @default false
329
+ */
330
+ swipeEnergySaving?: boolean;
325
331
  /**
326
332
  * 当滑到第一页或最后一页,还想再滑动时触发
327
333
  * @en Triggered when swiping to the first or last page and want to swipe again
@@ -560,7 +566,7 @@ export interface TabCellRef {
560
566
  */
561
567
  resetUnderlineStyle: () => void;
562
568
  }
563
- export interface TabPaneProps extends Pick<TabsProps, 'duration' | 'transitionDuration' | 'lazyloadCount' | 'hideContentStyle' | 'renderHideContent' | 'mode' | 'tabPaneClass' | 'tabPaneStyle' | 'tabPaneExtra' | 'getScrollContainer' | 'scrollThrottle' | 'scrollOffset' | 'goLastWhenScrollBottom' | 'scrollVertical' | 'translateZ' | 'fullScreen' | 'autoHeight' | 'onScroll'> {
569
+ export interface TabPaneProps extends Pick<TabsProps, 'duration' | 'transitionDuration' | 'lazyloadCount' | 'hideContentStyle' | 'renderHideContent' | 'mode' | 'tabPaneClass' | 'tabPaneStyle' | 'tabPaneExtra' | 'getScrollContainer' | 'scrollThrottle' | 'scrollOffset' | 'goLastWhenScrollBottom' | 'scrollVertical' | 'translateZ' | 'fullScreen' | 'autoHeight' | 'onScroll' | 'swipeEnergySaving'> {
564
570
  prefixCls?: string;
565
571
  panes: ReactNodeArray;
566
572
  activeIndex: number;