@mpxjs/webpack-plugin 2.10.4-beta.18 → 2.10.4-beta.19-input
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/lib/runtime/components/react/dist/getInnerListeners.js +36 -22
- package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +145 -0
- package/lib/runtime/components/react/dist/mpx-button.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-canvas/Image.js +2 -4
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +20 -17
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-icon/index.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-image.jsx +33 -20
- package/lib/runtime/components/react/dist/mpx-input.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-label.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +8 -3
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +205 -79
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +11 -13
- package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +8 -7
- package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +29 -11
- package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +3 -5
- package/lib/runtime/components/react/dist/mpx-progress.jsx +163 -0
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +9 -2
- package/lib/runtime/components/react/dist/mpx-radio.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -2
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +104 -51
- package/lib/runtime/components/react/dist/mpx-slider.jsx +321 -0
- package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +3 -1
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +11 -9
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +203 -141
- package/lib/runtime/components/react/dist/mpx-switch.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-text.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-video.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-view.jsx +28 -26
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +34 -29
- package/lib/runtime/components/react/dist/useAnimationHooks.js +12 -89
- package/lib/runtime/components/react/dist/utils.jsx +199 -114
- package/lib/runtime/components/react/mpx-input.tsx +6 -6
- package/lib/template-compiler/compiler.js +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { View } from 'react-native';
|
|
2
2
|
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
|
|
3
3
|
import Animated, { useAnimatedStyle, useSharedValue, withTiming, Easing, runOnJS, useAnimatedReaction, cancelAnimation } from 'react-native-reanimated';
|
|
4
|
-
import React, { forwardRef, useRef, useEffect, useMemo } from 'react';
|
|
4
|
+
import React, { forwardRef, useRef, useEffect, useMemo, createElement } from 'react';
|
|
5
5
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
6
6
|
import useNodesRef from './useNodesRef'; // 引入辅助函数
|
|
7
|
-
import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren, extendObject, flatGesture } from './utils';
|
|
7
|
+
import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren, extendObject, flatGesture, useRunOnJSCallback } from './utils';
|
|
8
8
|
import { SwiperContext } from './context';
|
|
9
|
+
import Portal from './mpx-portal';
|
|
9
10
|
/**
|
|
10
11
|
* 默认的Style类型
|
|
11
12
|
*/
|
|
@@ -70,16 +71,19 @@ const easeMap = {
|
|
|
70
71
|
easeInOutCubic: Easing.inOut(Easing.cubic)
|
|
71
72
|
};
|
|
72
73
|
const SwiperWrapper = forwardRef((props, ref) => {
|
|
73
|
-
const { 'indicator-dots':
|
|
74
|
+
const { 'indicator-dots': showPagination, 'indicator-color': dotColor = 'rgba(0, 0, 0, .3)', 'indicator-active-color': activeDotColor = '#000000', 'enable-var': enableVar = false, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'external-var-context': externalVarContext, 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, autoplay = false, circular = false, disableGesture = false, current: propCurrent = 0, bindchange } = props;
|
|
74
75
|
const easeingFunc = props['easing-function'] || 'default';
|
|
75
76
|
const easeDuration = props.duration || 500;
|
|
76
77
|
const horizontal = props.vertical !== undefined ? !props.vertical : true;
|
|
77
78
|
const nodeRef = useRef(null);
|
|
78
79
|
// 手势协同gesture 1.0
|
|
79
80
|
const swiperGestureRef = useRef();
|
|
80
|
-
useNodesRef(props, ref, nodeRef, {
|
|
81
|
+
useNodesRef(props, ref, nodeRef, {
|
|
82
|
+
// scrollView内部会过滤是否绑定了gestureRef,withRef(swiperGestureRef)给gesture对象设置一个ref(2.0版本)
|
|
83
|
+
gestureRef: swiperGestureRef
|
|
84
|
+
});
|
|
81
85
|
// 计算transfrom之类的
|
|
82
|
-
const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, {
|
|
86
|
+
const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, hasPositionFixed, setWidth, setHeight } = useTransformStyle(style, {
|
|
83
87
|
enableVar,
|
|
84
88
|
externalVarContext,
|
|
85
89
|
parentFontSize,
|
|
@@ -108,23 +112,18 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
108
112
|
// 每个元素的宽度 or 高度,有固定值直接初始化无则0
|
|
109
113
|
const step = useSharedValue(initStep);
|
|
110
114
|
// 记录选中元素的索引值
|
|
111
|
-
const currentIndex = useSharedValue(
|
|
115
|
+
const currentIndex = useSharedValue(propCurrent);
|
|
112
116
|
// const initOffset = getOffset(props.current || 0, initStep)
|
|
113
117
|
// 记录元素的偏移量
|
|
114
|
-
const offset = useSharedValue(getOffset(
|
|
118
|
+
const offset = useSharedValue(getOffset(propCurrent, initStep));
|
|
115
119
|
const strAbso = 'absolute' + dir.toUpperCase();
|
|
120
|
+
const strVelocity = 'velocity' + dir.toUpperCase();
|
|
116
121
|
// 标识手指触摸和抬起, 起点在onBegin
|
|
117
122
|
const touchfinish = useSharedValue(true);
|
|
118
123
|
// 记录上一帧的绝对定位坐标
|
|
119
124
|
const preAbsolutePos = useSharedValue(0);
|
|
120
125
|
// 记录从onBegin 到 onTouchesUp 时移动的距离
|
|
121
126
|
const moveTranstion = useSharedValue(0);
|
|
122
|
-
// 记录从onBegin 到 onTouchesUp 的时间
|
|
123
|
-
const moveTime = useSharedValue(0);
|
|
124
|
-
// 记录从onBegin 到 onTouchesCancelled 另外一个方向移动的距离
|
|
125
|
-
const anotherDirectionMove = useSharedValue(0);
|
|
126
|
-
// 另一个方向的
|
|
127
|
-
const anotherAbso = 'absolute' + (dir === 'x' ? 'y' : 'x').toUpperCase();
|
|
128
127
|
const timerId = useRef(0);
|
|
129
128
|
const intervalTimer = props.interval || 500;
|
|
130
129
|
const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
|
|
@@ -171,7 +170,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
171
170
|
const iStep = dir === 'x' ? realWidth : realHeight;
|
|
172
171
|
if (iStep !== step.value) {
|
|
173
172
|
step.value = iStep;
|
|
174
|
-
updateCurrent(
|
|
173
|
+
updateCurrent(propCurrent, iStep);
|
|
175
174
|
updateAutoplay();
|
|
176
175
|
}
|
|
177
176
|
}
|
|
@@ -187,8 +186,6 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
187
186
|
}
|
|
188
187
|
});
|
|
189
188
|
function renderPagination() {
|
|
190
|
-
if (children.length <= 1)
|
|
191
|
-
return null;
|
|
192
189
|
const activeColor = activeDotColor || '#007aff';
|
|
193
190
|
const unActionColor = dotColor || 'rgba(0,0,0,.2)';
|
|
194
191
|
// 正常渲染所有dots
|
|
@@ -275,7 +272,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
275
272
|
easing: easeMap[easeingFunc]
|
|
276
273
|
}, () => {
|
|
277
274
|
currentIndex.value = nextIndex;
|
|
278
|
-
runOnJS(
|
|
275
|
+
runOnJS(runOnJSCallback)('loop');
|
|
279
276
|
});
|
|
280
277
|
}
|
|
281
278
|
else {
|
|
@@ -291,7 +288,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
291
288
|
// 将开始位置设置为真正的位置
|
|
292
289
|
offset.value = initOffset;
|
|
293
290
|
currentIndex.value = nextIndex;
|
|
294
|
-
runOnJS(
|
|
291
|
+
runOnJS(runOnJSCallback)('loop');
|
|
295
292
|
});
|
|
296
293
|
}
|
|
297
294
|
else {
|
|
@@ -303,7 +300,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
303
300
|
easing: easeMap[easeingFunc]
|
|
304
301
|
}, () => {
|
|
305
302
|
currentIndex.value = nextIndex;
|
|
306
|
-
runOnJS(
|
|
303
|
+
runOnJS(runOnJSCallback)('loop');
|
|
307
304
|
});
|
|
308
305
|
}
|
|
309
306
|
}
|
|
@@ -328,12 +325,19 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
328
325
|
resumeLoop
|
|
329
326
|
};
|
|
330
327
|
}, []);
|
|
331
|
-
function handleSwiperChange(current) {
|
|
332
|
-
if (
|
|
328
|
+
function handleSwiperChange(current, pCurrent) {
|
|
329
|
+
if (pCurrent !== currentIndex.value) {
|
|
333
330
|
const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef });
|
|
334
|
-
|
|
331
|
+
bindchange && bindchange(eventData);
|
|
335
332
|
}
|
|
336
333
|
}
|
|
334
|
+
const runOnJSCallbackRef = useRef({
|
|
335
|
+
loop,
|
|
336
|
+
pauseLoop,
|
|
337
|
+
resumeLoop,
|
|
338
|
+
handleSwiperChange
|
|
339
|
+
});
|
|
340
|
+
const runOnJSCallback = useRunOnJSCallback(runOnJSCallbackRef);
|
|
337
341
|
function getOffset(index, stepValue) {
|
|
338
342
|
if (!stepValue)
|
|
339
343
|
return 0;
|
|
@@ -351,12 +355,12 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
351
355
|
const targetOffset = getOffset(index || 0, stepValue);
|
|
352
356
|
if (targetOffset !== offset.value) {
|
|
353
357
|
// 内部基于props.current!==currentIndex.value决定是否使用动画及更新currentIndex.value
|
|
354
|
-
if (
|
|
358
|
+
if (propCurrent !== undefined && propCurrent !== currentIndex.value) {
|
|
355
359
|
offset.value = withTiming(targetOffset, {
|
|
356
360
|
duration: easeDuration,
|
|
357
361
|
easing: easeMap[easeingFunc]
|
|
358
362
|
}, () => {
|
|
359
|
-
currentIndex.value =
|
|
363
|
+
currentIndex.value = propCurrent;
|
|
360
364
|
});
|
|
361
365
|
}
|
|
362
366
|
else {
|
|
@@ -375,8 +379,8 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
375
379
|
// 1. 用户在当前页切换选中项,动画;用户携带选中index打开到swiper页直接选中不走动画
|
|
376
380
|
useAnimatedReaction(() => currentIndex.value, (newIndex, preIndex) => {
|
|
377
381
|
// 这里必须传递函数名, 直接写()=> {}形式会报 访问了未sharedValue信息
|
|
378
|
-
if (newIndex !== preIndex &&
|
|
379
|
-
runOnJS(
|
|
382
|
+
if (newIndex !== preIndex && bindchange) {
|
|
383
|
+
runOnJS(runOnJSCallback)('handleSwiperChange', newIndex, propCurrent);
|
|
380
384
|
}
|
|
381
385
|
});
|
|
382
386
|
useEffect(() => {
|
|
@@ -408,11 +412,11 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
408
412
|
}, [children.length]);
|
|
409
413
|
useEffect(() => {
|
|
410
414
|
// 1. 如果用户在touch的过程中, 外部更新了current以外部为准(小程序表现)
|
|
411
|
-
// 2. 手指滑动过程中更新索引,外部会把current
|
|
412
|
-
if (
|
|
413
|
-
updateCurrent(
|
|
415
|
+
// 2. 手指滑动过程中更新索引,外部会把current再传入进来,导致offset直接更新,增加判断不同才更新
|
|
416
|
+
if (propCurrent !== currentIndex.value) {
|
|
417
|
+
updateCurrent(propCurrent, step.value);
|
|
414
418
|
}
|
|
415
|
-
}, [
|
|
419
|
+
}, [propCurrent]);
|
|
416
420
|
useEffect(() => {
|
|
417
421
|
autoplayShared.value = autoplay;
|
|
418
422
|
updateAutoplay();
|
|
@@ -433,7 +437,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
433
437
|
function getTargetPosition(eventData) {
|
|
434
438
|
'worklet';
|
|
435
439
|
// 移动的距离
|
|
436
|
-
const {
|
|
440
|
+
const { transdir } = eventData;
|
|
437
441
|
let resetOffsetPos = 0;
|
|
438
442
|
let selectedIndex = currentIndex.value;
|
|
439
443
|
// 是否临界点
|
|
@@ -441,9 +445,9 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
441
445
|
// 真实滚动到的偏移量坐标
|
|
442
446
|
let moveToTargetPos = 0;
|
|
443
447
|
const tmp = !circularShared.value ? 0 : preMarginShared.value;
|
|
444
|
-
const currentOffset =
|
|
448
|
+
const currentOffset = transdir < 0 ? offset.value - tmp : offset.value + tmp;
|
|
445
449
|
const computedIndex = Math.abs(currentOffset) / step.value;
|
|
446
|
-
const moveToIndex =
|
|
450
|
+
const moveToIndex = transdir < 0 ? Math.ceil(computedIndex) : Math.floor(computedIndex);
|
|
447
451
|
// 实际应该定位的索引值
|
|
448
452
|
if (!circularShared.value) {
|
|
449
453
|
selectedIndex = moveToIndex;
|
|
@@ -474,26 +478,24 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
474
478
|
targetOffset: -moveToTargetPos
|
|
475
479
|
};
|
|
476
480
|
}
|
|
477
|
-
function
|
|
481
|
+
function canMove(eventData) {
|
|
478
482
|
'worklet';
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
483
|
+
// 旧版:如果在快速多次滑动时,只根据当前的offset判断,会出现offset没超出,加上translation后越界的场景(如在倒数第二个元素快速滑动)
|
|
484
|
+
// 新版:会加上translation
|
|
485
|
+
const { translation, transdir } = eventData;
|
|
486
|
+
const gestureMovePos = offset.value + translation;
|
|
487
|
+
if (!circularShared.value) {
|
|
488
|
+
// 如果只判断区间,中间非滑动状态(handleResistanceMove)向左滑动,突然改为向右滑动,但是还在非滑动态,本应该可滑动判断为了不可滑动
|
|
489
|
+
const posEnd = -step.value * (childrenLength.value - 1);
|
|
490
|
+
if (transdir < 0) {
|
|
491
|
+
return gestureMovePos > posEnd;
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
return gestureMovePos < 0;
|
|
495
|
+
}
|
|
490
496
|
}
|
|
491
497
|
else {
|
|
492
|
-
|
|
493
|
-
return {
|
|
494
|
-
targetOffset: gestureMovePos < 0 ? 0 : offset.value + translation,
|
|
495
|
-
canMove: currentOffset > 0
|
|
496
|
-
};
|
|
498
|
+
return true;
|
|
497
499
|
}
|
|
498
500
|
}
|
|
499
501
|
function handleEnd(eventData) {
|
|
@@ -507,7 +509,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
507
509
|
if (touchfinish.value !== false) {
|
|
508
510
|
currentIndex.value = selectedIndex;
|
|
509
511
|
offset.value = resetOffset;
|
|
510
|
-
runOnJS(
|
|
512
|
+
runOnJS(runOnJSCallback)('resumeLoop');
|
|
511
513
|
}
|
|
512
514
|
});
|
|
513
515
|
}
|
|
@@ -518,21 +520,21 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
518
520
|
}, () => {
|
|
519
521
|
if (touchfinish.value !== false) {
|
|
520
522
|
currentIndex.value = selectedIndex;
|
|
521
|
-
runOnJS(
|
|
523
|
+
runOnJS(runOnJSCallback)('resumeLoop');
|
|
522
524
|
}
|
|
523
525
|
});
|
|
524
526
|
}
|
|
525
527
|
}
|
|
526
528
|
function handleBack(eventData) {
|
|
527
529
|
'worklet';
|
|
528
|
-
const {
|
|
530
|
+
const { transdir } = eventData;
|
|
529
531
|
// 向右滑动的back:trans < 0, 向左滑动的back: trans < 0
|
|
530
532
|
let currentOffset = Math.abs(offset.value);
|
|
531
533
|
if (circularShared.value) {
|
|
532
|
-
currentOffset +=
|
|
534
|
+
currentOffset += transdir < 0 ? preMarginShared.value : -preMarginShared.value;
|
|
533
535
|
}
|
|
534
536
|
const curIndex = currentOffset / step.value;
|
|
535
|
-
const moveToIndex = (
|
|
537
|
+
const moveToIndex = (transdir < 0 ? Math.floor(curIndex) : Math.ceil(curIndex)) - patchElmNumShared.value;
|
|
536
538
|
const targetOffset = -(moveToIndex + patchElmNumShared.value) * step.value + (circularShared.value ? preMarginShared.value : 0);
|
|
537
539
|
offset.value = withTiming(targetOffset, {
|
|
538
540
|
duration: easeDuration,
|
|
@@ -540,77 +542,106 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
540
542
|
}, () => {
|
|
541
543
|
if (touchfinish.value !== false) {
|
|
542
544
|
currentIndex.value = moveToIndex;
|
|
543
|
-
runOnJS(
|
|
545
|
+
runOnJS(runOnJSCallback)('resumeLoop');
|
|
544
546
|
}
|
|
545
547
|
});
|
|
546
548
|
}
|
|
547
|
-
|
|
549
|
+
// 当前的offset和index多对应的offset进行对比,判断是否超过一半
|
|
550
|
+
function computeHalf(eventData) {
|
|
548
551
|
'worklet';
|
|
552
|
+
const { transdir } = eventData;
|
|
549
553
|
const currentOffset = Math.abs(offset.value);
|
|
550
554
|
let preOffset = (currentIndex.value + patchElmNumShared.value) * step.value;
|
|
551
555
|
if (circularShared.value) {
|
|
552
556
|
preOffset -= preMarginShared.value;
|
|
553
557
|
}
|
|
554
|
-
// 正常事件中拿到的
|
|
558
|
+
// 正常事件中拿到的translation值(正向滑动<0,倒着滑>0)
|
|
555
559
|
const diffOffset = preOffset - currentOffset;
|
|
556
560
|
const half = Math.abs(diffOffset) > step.value / 2;
|
|
561
|
+
const isTriggerUpdateHalf = (transdir < 0 && currentOffset < preOffset) || (transdir > 0 && currentOffset > preOffset);
|
|
557
562
|
return {
|
|
558
563
|
diffOffset,
|
|
559
|
-
half
|
|
564
|
+
half,
|
|
565
|
+
isTriggerUpdateHalf
|
|
560
566
|
};
|
|
561
567
|
}
|
|
562
|
-
function handleLongPress() {
|
|
568
|
+
function handleLongPress(eventData) {
|
|
563
569
|
'worklet';
|
|
564
|
-
const { diffOffset, half } = computeHalf();
|
|
570
|
+
const { diffOffset, half, isTriggerUpdateHalf } = computeHalf(eventData);
|
|
565
571
|
if (+diffOffset === 0) {
|
|
566
|
-
runOnJS(
|
|
572
|
+
runOnJS(runOnJSCallback)('resumeLoop');
|
|
573
|
+
}
|
|
574
|
+
else if (isTriggerUpdateHalf) {
|
|
575
|
+
// 如果触发了onUpdate时的索引变更
|
|
576
|
+
handleEnd(eventData);
|
|
567
577
|
}
|
|
568
578
|
else if (half) {
|
|
569
|
-
handleEnd(
|
|
579
|
+
handleEnd(eventData);
|
|
570
580
|
}
|
|
571
581
|
else {
|
|
572
|
-
handleBack(
|
|
582
|
+
handleBack(eventData);
|
|
573
583
|
}
|
|
574
584
|
}
|
|
575
585
|
function reachBoundary(eventData) {
|
|
576
586
|
'worklet';
|
|
577
|
-
//
|
|
587
|
+
// 1. 基于当前的offset和translation判断是否超过当前边界值
|
|
578
588
|
const { translation } = eventData;
|
|
579
|
-
const
|
|
589
|
+
const boundaryStart = -patchElmNumShared.value * step.value;
|
|
590
|
+
const boundaryEnd = -(childrenLength.value + patchElmNumShared.value) * step.value;
|
|
591
|
+
const moveToOffset = offset.value + translation;
|
|
580
592
|
let isBoundary = false;
|
|
581
593
|
let resetOffset = 0;
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
if (currentOffset < -posEnd + step.value) {
|
|
589
|
-
isBoundary = true;
|
|
590
|
-
resetOffset = Math.abs(moveStep) === 0 ? patchElmNumShared.value * step.value + translation : moveStep * elementsLength;
|
|
591
|
-
}
|
|
592
|
-
if (currentOffset > -posReverseEnd) {
|
|
593
|
-
isBoundary = true;
|
|
594
|
-
resetOffset = moveStep * elementsLength;
|
|
595
|
-
}
|
|
594
|
+
if (moveToOffset < boundaryEnd) {
|
|
595
|
+
isBoundary = true;
|
|
596
|
+
// 超过边界的距离
|
|
597
|
+
const exceedLength = Math.abs(moveToOffset) - Math.abs(boundaryEnd);
|
|
598
|
+
// 计算对标正常元素所在的offset
|
|
599
|
+
resetOffset = patchElmNumShared.value * step.value + exceedLength;
|
|
596
600
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
}
|
|
604
|
-
if (currentOffset < -posReverseEnd) {
|
|
605
|
-
isBoundary = true;
|
|
606
|
-
resetOffset = moveStep * elementsLength + patchElmNumShared.value * step.value;
|
|
607
|
-
}
|
|
601
|
+
if (moveToOffset > boundaryStart) {
|
|
602
|
+
isBoundary = true;
|
|
603
|
+
// 超过边界的距离
|
|
604
|
+
const exceedLength = Math.abs(boundaryStart) - Math.abs(moveToOffset);
|
|
605
|
+
// 计算对标正常元素所在的offset
|
|
606
|
+
resetOffset = (patchElmNumShared.value + childrenLength.value - 1) * step.value + (step.value - exceedLength);
|
|
608
607
|
}
|
|
609
608
|
return {
|
|
610
609
|
isBoundary,
|
|
611
610
|
resetOffset: -resetOffset
|
|
612
611
|
};
|
|
613
612
|
}
|
|
613
|
+
// 非循环超出边界,应用阻力; 开始滑动少阻力小,滑动越长阻力越大
|
|
614
|
+
function handleResistanceMove(eventData) {
|
|
615
|
+
'worklet';
|
|
616
|
+
const { translation, transdir } = eventData;
|
|
617
|
+
const moveToOffset = offset.value + translation;
|
|
618
|
+
const maxOverDrag = Math.floor(step.value / 2);
|
|
619
|
+
const maxOffset = translation < 0 ? -(childrenLength.value - 1) * step.value : 0;
|
|
620
|
+
let resistance = 0.1;
|
|
621
|
+
let overDrag = 0;
|
|
622
|
+
let finalOffset = 0;
|
|
623
|
+
// 向右向下小于0, 向左向上大于0;
|
|
624
|
+
if (transdir < 0) {
|
|
625
|
+
overDrag = Math.abs(moveToOffset - maxOffset);
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
overDrag = Math.abs(moveToOffset);
|
|
629
|
+
}
|
|
630
|
+
// 滑动越多resistance越小
|
|
631
|
+
resistance = 1 - overDrag / maxOverDrag;
|
|
632
|
+
// 确保阻力在合理范围内
|
|
633
|
+
resistance = Math.min(0.5, resistance);
|
|
634
|
+
// 限制在最大拖拽范围内
|
|
635
|
+
if (transdir < 0) {
|
|
636
|
+
const adjustOffset = offset.value + translation * resistance;
|
|
637
|
+
finalOffset = Math.max(adjustOffset, maxOffset - maxOverDrag);
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
const adjustOffset = offset.value + translation * resistance;
|
|
641
|
+
finalOffset = Math.min(adjustOffset, maxOverDrag);
|
|
642
|
+
}
|
|
643
|
+
return finalOffset;
|
|
644
|
+
}
|
|
614
645
|
const gesturePan = Gesture.Pan()
|
|
615
646
|
.onBegin((e) => {
|
|
616
647
|
'worklet';
|
|
@@ -618,37 +649,47 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
618
649
|
return;
|
|
619
650
|
touchfinish.value = false;
|
|
620
651
|
cancelAnimation(offset);
|
|
621
|
-
runOnJS(
|
|
652
|
+
runOnJS(runOnJSCallback)('pauseLoop');
|
|
622
653
|
preAbsolutePos.value = e[strAbso];
|
|
623
654
|
moveTranstion.value = e[strAbso];
|
|
624
|
-
anotherDirectionMove.value = e[anotherAbso];
|
|
625
|
-
moveTime.value = new Date().getTime();
|
|
626
655
|
})
|
|
627
656
|
.onUpdate((e) => {
|
|
628
657
|
'worklet';
|
|
629
|
-
if (touchfinish.value)
|
|
630
|
-
return;
|
|
631
658
|
const moveDistance = e[strAbso] - preAbsolutePos.value;
|
|
659
|
+
if (touchfinish.value || moveDistance === 0)
|
|
660
|
+
return;
|
|
632
661
|
const eventData = {
|
|
633
|
-
translation: moveDistance
|
|
662
|
+
translation: moveDistance,
|
|
663
|
+
transdir: moveDistance
|
|
634
664
|
};
|
|
635
|
-
// 1.
|
|
636
|
-
const { half } = computeHalf();
|
|
637
|
-
if (half) {
|
|
665
|
+
// 1. 支持滑动中超出一半更新索引的能力:只更新索引并不会影响onFinalize依据当前offset计算的索引
|
|
666
|
+
const { half } = computeHalf(eventData);
|
|
667
|
+
if (childrenLength.value > 1 && half) {
|
|
638
668
|
const { selectedIndex } = getTargetPosition(eventData);
|
|
639
669
|
currentIndex.value = selectedIndex;
|
|
640
670
|
}
|
|
641
|
-
// 2.
|
|
642
|
-
const { canMove, targetOffset } = checkUnCircular(eventData);
|
|
671
|
+
// 2. 非循环: 处理用户一直拖拽到临界点的场景,如果放到onFinalize无法阻止offset.value更新为越界的值
|
|
643
672
|
if (!circularShared.value) {
|
|
644
|
-
if (canMove) {
|
|
645
|
-
offset.value =
|
|
646
|
-
preAbsolutePos.value = e[strAbso];
|
|
673
|
+
if (canMove(eventData)) {
|
|
674
|
+
offset.value = moveDistance + offset.value;
|
|
647
675
|
}
|
|
676
|
+
else {
|
|
677
|
+
const finalOffset = handleResistanceMove(eventData);
|
|
678
|
+
offset.value = finalOffset;
|
|
679
|
+
}
|
|
680
|
+
preAbsolutePos.value = e[strAbso];
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
// 3. 循环更新: 只有一个元素时可滑动,加入阻力
|
|
684
|
+
if (circularShared.value && childrenLength.value === 1) {
|
|
685
|
+
const finalOffset = handleResistanceMove(eventData);
|
|
686
|
+
offset.value = finalOffset;
|
|
687
|
+
preAbsolutePos.value = e[strAbso];
|
|
648
688
|
return;
|
|
649
689
|
}
|
|
690
|
+
// 4. 循环更新:正常
|
|
650
691
|
const { isBoundary, resetOffset } = reachBoundary(eventData);
|
|
651
|
-
if (isBoundary && circularShared.value) {
|
|
692
|
+
if (childrenLength.value > 1 && isBoundary && circularShared.value) {
|
|
652
693
|
offset.value = resetOffset;
|
|
653
694
|
}
|
|
654
695
|
else {
|
|
@@ -660,26 +701,49 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
660
701
|
'worklet';
|
|
661
702
|
if (touchfinish.value)
|
|
662
703
|
return;
|
|
663
|
-
const moveDistance = e[strAbso] - moveTranstion.value;
|
|
664
704
|
touchfinish.value = true;
|
|
705
|
+
// 触发过onUpdate正常情况下e[strAbso] - preAbsolutePos.value=0; 未触发过onUpdate的情况下e[strAbso] - preAbsolutePos.value 不为0
|
|
706
|
+
const moveDistance = e[strAbso] - preAbsolutePos.value;
|
|
665
707
|
const eventData = {
|
|
666
|
-
translation: moveDistance
|
|
708
|
+
translation: moveDistance,
|
|
709
|
+
transdir: moveDistance !== 0 ? moveDistance : e[strAbso] - moveTranstion.value
|
|
667
710
|
};
|
|
668
|
-
|
|
669
|
-
if (
|
|
670
|
-
|
|
711
|
+
// 1. 只有一个元素:循环 和 非循环状态,都走回弹效果
|
|
712
|
+
if (childrenLength.value === 1) {
|
|
713
|
+
offset.value = withTiming(0, {
|
|
714
|
+
duration: easeDuration,
|
|
715
|
+
easing: easeMap[easeingFunc]
|
|
716
|
+
});
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
// 2.非循环状态不可移动态:最后一个元素 和 第一个元素
|
|
720
|
+
// 非循环支持最后元素可滑动能力后,向左快速移动未超过最大可移动范围一半,因为offset为正值,向左滑动handleBack,默认向上取整
|
|
721
|
+
// 但是在offset大于0时,取0。[-100, 0](back取0), [0, 100](back取1), 所以handleLongPress里的处理逻辑需要兼容支持,因此这里直接单独处理,不耦合下方公共的判断逻辑。
|
|
722
|
+
if (!circularShared.value && !canMove(eventData)) {
|
|
723
|
+
if (eventData.transdir < 0) {
|
|
724
|
+
handleBack(eventData);
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
handleEnd(eventData);
|
|
728
|
+
}
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
// 3. 非循环状态可移动态、循环状态, 正常逻辑处理
|
|
732
|
+
const velocity = e[strVelocity];
|
|
733
|
+
if (Math.abs(velocity) < longPressRatio) {
|
|
734
|
+
handleLongPress(eventData);
|
|
671
735
|
}
|
|
672
736
|
else {
|
|
673
|
-
// 如果触发了onTouchesCancelled,不会触发onUpdate不会更新offset值, 索引不会变更
|
|
674
737
|
handleEnd(eventData);
|
|
675
738
|
}
|
|
676
|
-
})
|
|
739
|
+
})
|
|
740
|
+
.withRef(swiperGestureRef);
|
|
677
741
|
// swiper横向,当y轴滑动5像素手势失效;swiper纵向只响应swiper的滑动事件
|
|
678
742
|
if (dir === 'x') {
|
|
679
|
-
gesturePan.activeOffsetX([-
|
|
743
|
+
gesturePan.activeOffsetX([-2, 2]).failOffsetY([-5, 5]);
|
|
680
744
|
}
|
|
681
745
|
else {
|
|
682
|
-
gesturePan.activeOffsetY([-
|
|
746
|
+
gesturePan.activeOffsetY([-2, 2]).failOffsetX([-5, 5]);
|
|
683
747
|
}
|
|
684
748
|
// 手势协同2.0
|
|
685
749
|
if (simultaneousHandlers && simultaneousHandlers.length) {
|
|
@@ -700,34 +764,32 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
700
764
|
return { transform: [{ translateY: offset.value }], opacity: step.value > 0 ? 1 : 0 };
|
|
701
765
|
}
|
|
702
766
|
});
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
return renderSwiper();
|
|
767
|
+
let finalComponent;
|
|
768
|
+
const arrPages = renderItems();
|
|
769
|
+
const mergeProps = Object.assign({
|
|
770
|
+
style: [normalStyle, layoutStyle, styles.swiper]
|
|
771
|
+
}, layoutProps, innerProps);
|
|
772
|
+
const animateComponent = createElement(Animated.View, {
|
|
773
|
+
style: [{ flexDirection: dir === 'x' ? 'row' : 'column', width: '100%', height: '100%' }, animatedStyles]
|
|
774
|
+
}, wrapChildren({
|
|
775
|
+
children: arrPages
|
|
776
|
+
}, {
|
|
777
|
+
hasVarDec,
|
|
778
|
+
varContext: varContextRef.current,
|
|
779
|
+
textStyle,
|
|
780
|
+
textProps
|
|
781
|
+
}));
|
|
782
|
+
const renderChildrens = showPagination ? [animateComponent, renderPagination()] : animateComponent;
|
|
783
|
+
finalComponent = createElement(View, mergeProps, renderChildrens);
|
|
784
|
+
if (!disableGesture) {
|
|
785
|
+
finalComponent = createElement(GestureDetector, {
|
|
786
|
+
gesture: gestureHandler
|
|
787
|
+
}, finalComponent);
|
|
725
788
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
{renderSwiper()}
|
|
729
|
-
</GestureDetector>);
|
|
789
|
+
if (hasPositionFixed) {
|
|
790
|
+
finalComponent = createElement(Portal, null, finalComponent);
|
|
730
791
|
}
|
|
792
|
+
return finalComponent;
|
|
731
793
|
});
|
|
732
794
|
SwiperWrapper.displayName = 'MpxSwiperWrapper';
|
|
733
795
|
export default SwiperWrapper;
|
|
@@ -10,6 +10,7 @@ import { warn } from '@mpxjs/utils';
|
|
|
10
10
|
import useNodesRef from './useNodesRef'; // 引入辅助函数
|
|
11
11
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
12
12
|
import CheckBox from './mpx-checkbox';
|
|
13
|
+
import Portal from './mpx-portal';
|
|
13
14
|
import { FormContext } from './context';
|
|
14
15
|
import { useTransformStyle, useLayout, extendObject } from './utils';
|
|
15
16
|
const _Switch = forwardRef((props, ref) => {
|
|
@@ -21,7 +22,7 @@ const _Switch = forwardRef((props, ref) => {
|
|
|
21
22
|
if (formContext) {
|
|
22
23
|
formValuesMap = formContext.formValuesMap;
|
|
23
24
|
}
|
|
24
|
-
const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, {
|
|
25
|
+
const { normalStyle, hasSelfPercent, setWidth, setHeight, hasPositionFixed } = useTransformStyle(style, {
|
|
25
26
|
enableVar,
|
|
26
27
|
externalVarContext,
|
|
27
28
|
parentFontSize,
|
|
@@ -83,13 +84,17 @@ const _Switch = forwardRef((props, ref) => {
|
|
|
83
84
|
checked: isChecked
|
|
84
85
|
}));
|
|
85
86
|
}
|
|
86
|
-
|
|
87
|
+
let finalComponent = createElement(Switch, extendObject({}, innerProps, {
|
|
87
88
|
style: normalStyle,
|
|
88
89
|
value: isChecked,
|
|
89
90
|
trackColor: { false: '#FFF', true: color },
|
|
90
91
|
thumbColor: isChecked ? '#FFF' : '#f4f3f4',
|
|
91
92
|
ios_backgroundColor: '#FFF'
|
|
92
93
|
}));
|
|
94
|
+
if (hasPositionFixed) {
|
|
95
|
+
finalComponent = createElement(Portal, null, finalComponent);
|
|
96
|
+
}
|
|
97
|
+
return finalComponent;
|
|
93
98
|
});
|
|
94
99
|
_Switch.displayName = 'MpxSwitch';
|
|
95
100
|
export default _Switch;
|
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Text } from 'react-native';
|
|
7
7
|
import { useRef, forwardRef, createElement } from 'react';
|
|
8
|
+
import Portal from './mpx-portal';
|
|
8
9
|
import useInnerProps from './getInnerListeners';
|
|
9
10
|
import useNodesRef from './useNodesRef'; // 引入辅助函数
|
|
10
11
|
import { useTransformStyle, wrapChildren, extendObject } from './utils';
|
|
11
12
|
const _Text = forwardRef((props, ref) => {
|
|
12
13
|
const { style = {}, allowFontScaling = false, selectable, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'user-select': userSelect, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
|
|
13
|
-
const { normalStyle, hasVarDec, varContextRef } = useTransformStyle(style, {
|
|
14
|
+
const { normalStyle, hasVarDec, varContextRef, hasPositionFixed } = useTransformStyle(style, {
|
|
14
15
|
enableVar,
|
|
15
16
|
externalVarContext,
|
|
16
17
|
parentFontSize,
|
|
@@ -29,10 +30,14 @@ const _Text = forwardRef((props, ref) => {
|
|
|
29
30
|
}), [
|
|
30
31
|
'user-select'
|
|
31
32
|
]);
|
|
32
|
-
|
|
33
|
+
let finalComponent = createElement(Text, innerProps, wrapChildren(props, {
|
|
33
34
|
hasVarDec,
|
|
34
35
|
varContext: varContextRef.current
|
|
35
36
|
}));
|
|
37
|
+
if (hasPositionFixed) {
|
|
38
|
+
finalComponent = createElement(Portal, null, finalComponent);
|
|
39
|
+
}
|
|
40
|
+
return finalComponent;
|
|
36
41
|
});
|
|
37
42
|
_Text.displayName = 'MpxText';
|
|
38
43
|
export default _Text;
|