@mpxjs/webpack-plugin 2.10.18-beta.1 → 2.10.19
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/LICENSE +433 -0
- package/lib/index.js +0 -12
- package/lib/runtime/components/react/dist/mpx-camera.d.ts +4 -4
- package/lib/runtime/components/react/dist/mpx-camera.jsx +75 -41
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +92 -15
- package/lib/runtime/components/react/dist/mpx-swiper.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +24 -43
- package/lib/runtime/components/react/mpx-camera.tsx +78 -47
- package/lib/runtime/components/react/mpx-scroll-view.tsx +106 -16
- package/lib/runtime/components/react/mpx-swiper.tsx +23 -43
- package/lib/runtime/components/web/mpx-scroll-view.vue +2 -5
- package/lib/template-compiler/compiler.js +3 -7
- package/lib/utils/const.js +0 -29
- package/package.json +4 -3
- package/lib/resolver/ExtendComponentsPlugin.js +0 -60
- package/lib/runtime/components/ali/mpx-section-list.mpx +0 -566
- package/lib/runtime/components/ali/mpx-sticky-header.mpx +0 -212
- package/lib/runtime/components/ali/mpx-sticky-section.mpx +0 -17
- package/lib/runtime/components/react/dist/mpx-section-list.d.ts +0 -48
- package/lib/runtime/components/react/dist/mpx-section-list.jsx +0 -292
- package/lib/runtime/components/react/mpx-section-list.tsx +0 -439
- package/lib/runtime/components/web/mpx-section-list.vue +0 -551
- package/lib/runtime/components/wx/mpx-section-list-default/list-footer.mpx +0 -26
- package/lib/runtime/components/wx/mpx-section-list-default/list-header.mpx +0 -26
- package/lib/runtime/components/wx/mpx-section-list-default/list-item.mpx +0 -26
- package/lib/runtime/components/wx/mpx-section-list-default/section-header.mpx +0 -26
- package/lib/runtime/components/wx/mpx-section-list.mpx +0 -209
- package/lib/runtime/components/wx/mpx-sticky-header.mpx +0 -40
- package/lib/runtime/components/wx/mpx-sticky-section.mpx +0 -31
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { createElement, forwardRef, useRef, useCallback, useContext, useState, useEffect } from 'react';
|
|
2
|
-
import { useTransformStyle, useLayout, extendObject } from './utils';
|
|
1
|
+
import { createElement, forwardRef, useRef, useCallback, useContext, useState, useEffect, useMemo } from 'react';
|
|
2
|
+
import { getCurrentPage, useTransformStyle, useLayout, extendObject } from './utils';
|
|
3
3
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
4
|
-
import {
|
|
4
|
+
import { Camera, useCameraDevice, useCodeScanner, useCameraFormat } from 'react-native-vision-camera';
|
|
5
|
+
import { noop, warn, hasOwn } from '@mpxjs/utils';
|
|
5
6
|
import { RouteContext } from './context';
|
|
7
|
+
import { watch } from '@mpxjs/core';
|
|
6
8
|
const qualityValue = {
|
|
7
9
|
high: 90,
|
|
8
10
|
normal: 75,
|
|
@@ -12,9 +14,8 @@ const qualityValue = {
|
|
|
12
14
|
let RecordRes = null;
|
|
13
15
|
const _camera = forwardRef((props, ref) => {
|
|
14
16
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
15
|
-
const { Camera, useCameraDevice, useCodeScanner, useCameraFormat } = require('react-native-vision-camera');
|
|
16
17
|
const cameraRef = useRef(null);
|
|
17
|
-
const { mode = 'normal', resolution = 'medium', devicePosition = 'back', flash = 'auto', frameSize = 'medium', bindinitdone, bindstop, bindscancode, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'enable-var': enableVar, 'external-var-context': externalVarContext, style = {} } = props;
|
|
18
|
+
const { mode = 'normal', resolution = 'medium', 'device-position': devicePosition = 'back', flash = 'auto', 'frame-size': frameSize = 'medium', bindinitdone, bindstop, bindscancode, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'enable-var': enableVar, 'external-var-context': externalVarContext, style = {} } = props;
|
|
18
19
|
const styleObj = extendObject({}, style);
|
|
19
20
|
const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(styleObj, {
|
|
20
21
|
enableVar,
|
|
@@ -24,23 +25,25 @@ const _camera = forwardRef((props, ref) => {
|
|
|
24
25
|
parentHeight
|
|
25
26
|
});
|
|
26
27
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: cameraRef });
|
|
27
|
-
const isPhoto =
|
|
28
|
+
const isPhoto = useRef(false);
|
|
29
|
+
isPhoto.current = mode === 'normal';
|
|
28
30
|
const device = useCameraDevice(devicePosition || 'back');
|
|
29
|
-
const { navigation } = useContext(RouteContext) || {};
|
|
31
|
+
const { navigation, pageId } = useContext(RouteContext) || {};
|
|
30
32
|
const [zoomValue, setZoomValue] = useState(1);
|
|
33
|
+
const [isActive, setIsActive] = useState(true);
|
|
31
34
|
const [hasPermission, setHasPermission] = useState(null);
|
|
32
|
-
const
|
|
35
|
+
const page = getCurrentPage(pageId);
|
|
33
36
|
// 先定义常量,避免在条件判断后使用
|
|
34
37
|
const maxZoom = device?.maxZoom || 1;
|
|
35
38
|
const RESOLUTION_MAPPING = {
|
|
36
|
-
low: { width:
|
|
37
|
-
medium: { width:
|
|
38
|
-
high:
|
|
39
|
+
low: { width: 1280, height: 720 },
|
|
40
|
+
medium: { width: 1920, height: 1080 },
|
|
41
|
+
high: 'max'
|
|
39
42
|
};
|
|
40
43
|
const FRAME_SIZE_MAPPING = {
|
|
41
|
-
small: { width:
|
|
42
|
-
medium: { width:
|
|
43
|
-
large:
|
|
44
|
+
small: { width: 1280, height: 720 },
|
|
45
|
+
medium: { width: 1920, height: 1080 },
|
|
46
|
+
large: 'max'
|
|
44
47
|
};
|
|
45
48
|
const format = useCameraFormat(device, [
|
|
46
49
|
{
|
|
@@ -48,15 +51,31 @@ const _camera = forwardRef((props, ref) => {
|
|
|
48
51
|
videoResolution: FRAME_SIZE_MAPPING[frameSize] || RESOLUTION_MAPPING[resolution]
|
|
49
52
|
}
|
|
50
53
|
]);
|
|
54
|
+
const isScancode = useCallback((fail, complete) => {
|
|
55
|
+
if (!isPhoto.current) {
|
|
56
|
+
const result = {
|
|
57
|
+
errMsg: 'Not allow to invoke takePhoto in \'scanCode\' mode.'
|
|
58
|
+
};
|
|
59
|
+
fail(result);
|
|
60
|
+
complete(result);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}, []);
|
|
51
65
|
const codeScanner = useCodeScanner({
|
|
52
|
-
codeTypes: ['qr'
|
|
66
|
+
codeTypes: ['qr'],
|
|
53
67
|
onCodeScanned: (codes) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
codes.forEach(code => {
|
|
69
|
+
const type = code.type === 'qr' ? 'QR_CODE' : code.type?.toUpperCase();
|
|
70
|
+
const frame = code.frame || {};
|
|
71
|
+
bindscancode && bindscancode(getCustomEvent('scancode', {}, {
|
|
72
|
+
detail: {
|
|
73
|
+
result: code.value,
|
|
74
|
+
type,
|
|
75
|
+
scanArea: [parseInt(frame.x) || 0, parseInt(frame.y) || 0, parseInt(frame.width) || 0, parseInt(frame.height) || 0]
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
78
|
+
});
|
|
60
79
|
}
|
|
61
80
|
});
|
|
62
81
|
const onInitialized = useCallback(() => {
|
|
@@ -69,14 +88,15 @@ const _camera = forwardRef((props, ref) => {
|
|
|
69
88
|
const onStopped = useCallback(() => {
|
|
70
89
|
bindstop && bindstop();
|
|
71
90
|
}, [bindstop]);
|
|
72
|
-
const camera = {
|
|
91
|
+
const camera = useMemo(() => ({
|
|
73
92
|
setZoom: (zoom) => {
|
|
74
93
|
setZoomValue(zoom);
|
|
75
94
|
},
|
|
76
95
|
takePhoto: (options = {}) => {
|
|
77
96
|
const { success = noop, fail = noop, complete = noop } = options;
|
|
97
|
+
if (isScancode(fail, complete))
|
|
98
|
+
return;
|
|
78
99
|
cameraRef.current?.takePhoto?.({
|
|
79
|
-
flash,
|
|
80
100
|
quality: qualityValue[options.quality || 'normal']
|
|
81
101
|
}).then((res) => {
|
|
82
102
|
const result = {
|
|
@@ -97,7 +117,8 @@ const _camera = forwardRef((props, ref) => {
|
|
|
97
117
|
let { timeout = 30, success = noop, fail = noop, complete = noop, timeoutCallback = noop } = options;
|
|
98
118
|
timeout = timeout > 300 ? 300 : timeout;
|
|
99
119
|
let recordTimer = null;
|
|
100
|
-
|
|
120
|
+
if (isScancode(fail, complete))
|
|
121
|
+
return;
|
|
101
122
|
try {
|
|
102
123
|
const result = {
|
|
103
124
|
errMsg: 'startRecord:ok'
|
|
@@ -105,7 +126,6 @@ const _camera = forwardRef((props, ref) => {
|
|
|
105
126
|
success(result);
|
|
106
127
|
complete(result);
|
|
107
128
|
cameraRef.current?.startRecording?.({
|
|
108
|
-
flash,
|
|
109
129
|
onRecordingError: (error) => {
|
|
110
130
|
if (recordTimer)
|
|
111
131
|
clearTimeout(recordTimer);
|
|
@@ -122,7 +142,6 @@ const _camera = forwardRef((props, ref) => {
|
|
|
122
142
|
}
|
|
123
143
|
});
|
|
124
144
|
recordTimer = setTimeout(() => {
|
|
125
|
-
isTimeout = true;
|
|
126
145
|
cameraRef.current?.stopRecording().catch(() => {
|
|
127
146
|
// 忽略停止录制时的错误
|
|
128
147
|
});
|
|
@@ -140,6 +159,8 @@ const _camera = forwardRef((props, ref) => {
|
|
|
140
159
|
},
|
|
141
160
|
stopRecord: (options = {}) => {
|
|
142
161
|
const { success = noop, fail = noop, complete = noop } = options;
|
|
162
|
+
if (isScancode(fail, complete))
|
|
163
|
+
return;
|
|
143
164
|
try {
|
|
144
165
|
cameraRef.current?.stopRecording().then(() => {
|
|
145
166
|
setTimeout(() => {
|
|
@@ -170,16 +191,20 @@ const _camera = forwardRef((props, ref) => {
|
|
|
170
191
|
complete(result);
|
|
171
192
|
}
|
|
172
193
|
}
|
|
173
|
-
};
|
|
194
|
+
}), []);
|
|
174
195
|
useEffect(() => {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
196
|
+
let unWatch;
|
|
197
|
+
if (pageId && hasOwn(global.__mpxPageStatusMap, String(pageId))) {
|
|
198
|
+
unWatch = watch(() => global.__mpxPageStatusMap[pageId], (newVal) => {
|
|
199
|
+
if (newVal === 'show') {
|
|
200
|
+
if (page.id === pageId) {
|
|
201
|
+
setIsActive(true);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (newVal === 'hide') {
|
|
205
|
+
setIsActive(false);
|
|
206
|
+
}
|
|
207
|
+
}, { sync: true });
|
|
183
208
|
}
|
|
184
209
|
const checkCameraPermission = async () => {
|
|
185
210
|
try {
|
|
@@ -198,23 +223,25 @@ const _camera = forwardRef((props, ref) => {
|
|
|
198
223
|
};
|
|
199
224
|
checkCameraPermission();
|
|
200
225
|
return () => {
|
|
201
|
-
if (navigation
|
|
202
|
-
navigation.camera
|
|
226
|
+
if (navigation?.camera === camera) {
|
|
227
|
+
delete navigation.camera;
|
|
203
228
|
}
|
|
229
|
+
unWatch && unWatch();
|
|
204
230
|
};
|
|
205
231
|
}, []);
|
|
206
232
|
const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
|
|
207
233
|
ref: cameraRef,
|
|
208
234
|
style: extendObject({}, normalStyle, layoutStyle),
|
|
209
|
-
isActive
|
|
235
|
+
isActive,
|
|
210
236
|
photo: true,
|
|
211
237
|
video: true,
|
|
212
238
|
onInitialized,
|
|
213
239
|
onStopped,
|
|
214
240
|
device,
|
|
215
241
|
format,
|
|
216
|
-
codeScanner: !isPhoto ? codeScanner : undefined,
|
|
217
|
-
zoom: zoomValue
|
|
242
|
+
codeScanner: !isPhoto.current ? codeScanner : undefined,
|
|
243
|
+
zoom: zoomValue,
|
|
244
|
+
torch: flash
|
|
218
245
|
}), [
|
|
219
246
|
'mode',
|
|
220
247
|
'resolution',
|
|
@@ -227,7 +254,14 @@ const _camera = forwardRef((props, ref) => {
|
|
|
227
254
|
], {
|
|
228
255
|
layoutRef
|
|
229
256
|
});
|
|
230
|
-
if (
|
|
257
|
+
if (navigation && navigation.camera && navigation.camera !== camera) {
|
|
258
|
+
warn('<camera>: 一个页面只能插入一个');
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
else if (navigation) {
|
|
262
|
+
navigation.camera = camera;
|
|
263
|
+
}
|
|
264
|
+
if (!hasPermission || !device) {
|
|
231
265
|
return null;
|
|
232
266
|
}
|
|
233
267
|
return createElement(Camera, innerProps);
|
|
@@ -160,19 +160,96 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
}, [refresherTriggered]);
|
|
163
|
-
function scrollTo({ top = 0, left = 0, animated = false }) {
|
|
164
|
-
|
|
163
|
+
function scrollTo({ top = 0, left = 0, animated = false, duration }) {
|
|
164
|
+
// 如果指定了 duration 且需要动画,使用自定义动画
|
|
165
|
+
if (animated && duration && duration > 0) {
|
|
166
|
+
// 获取当前滚动位置
|
|
167
|
+
const currentY = scrollOptions.current.scrollTop || 0;
|
|
168
|
+
const currentX = scrollOptions.current.scrollLeft || 0;
|
|
169
|
+
const startTime = Date.now();
|
|
170
|
+
const deltaY = top - currentY;
|
|
171
|
+
const deltaX = left - currentX;
|
|
172
|
+
// 缓动函数:easeInOutCubic
|
|
173
|
+
const easing = (t) => {
|
|
174
|
+
return t < 0.5
|
|
175
|
+
? 4 * t * t * t
|
|
176
|
+
: 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
177
|
+
};
|
|
178
|
+
// 使用 requestAnimationFrame 实现平滑动画
|
|
179
|
+
const animate = () => {
|
|
180
|
+
const elapsed = Date.now() - startTime;
|
|
181
|
+
const progress = Math.min(elapsed / duration, 1); // 0 到 1
|
|
182
|
+
const easeProgress = easing(progress);
|
|
183
|
+
const nextY = currentY + deltaY * easeProgress;
|
|
184
|
+
const nextX = currentX + deltaX * easeProgress;
|
|
185
|
+
if (scrollViewRef.current) {
|
|
186
|
+
scrollViewRef.current.scrollTo({ y: nextY, x: nextX, animated: false });
|
|
187
|
+
}
|
|
188
|
+
if (progress < 1) {
|
|
189
|
+
requestAnimationFrame(animate);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// 确保最终位置准确
|
|
193
|
+
if (scrollViewRef.current) {
|
|
194
|
+
scrollViewRef.current.scrollTo({ y: top, x: left, animated: false });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
requestAnimationFrame(animate);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// 使用原生的 scrollTo
|
|
202
|
+
scrollToOffset(left, top, animated);
|
|
203
|
+
}
|
|
165
204
|
}
|
|
166
|
-
function handleScrollIntoView(selector = '', { offset = 0, animated = true } = {}) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
205
|
+
function handleScrollIntoView(selector = '', { offset = 0, animated = true, duration = undefined } = {}) {
|
|
206
|
+
try {
|
|
207
|
+
const currentSelectRef = propsRef.current.__selectRef;
|
|
208
|
+
if (!currentSelectRef) {
|
|
209
|
+
const errMsg = '__selectRef is not available. Please ensure the scroll-view component is properly initialized.';
|
|
210
|
+
warn(errMsg);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const targetScrollView = scrollViewRef.current;
|
|
214
|
+
if (!targetScrollView) {
|
|
215
|
+
const errMsg = 'scrollViewRef is not ready';
|
|
216
|
+
warn(errMsg);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
// scroll-into-view prop 按微信规范直传裸 id(如 "section-1"),而 __refs 注册时 key 带 # 或 . 前缀,需补齐才能命中;
|
|
220
|
+
// pageScrollTo 调用方已自带前缀(如 "#section-1")
|
|
221
|
+
const normalizedSelector = selector.startsWith('#') || selector.startsWith('.') ? selector : `#${selector}`;
|
|
222
|
+
// 调用 __selectRef 查找元素
|
|
223
|
+
const refs = currentSelectRef(normalizedSelector, 'node');
|
|
224
|
+
if (!refs) {
|
|
225
|
+
const errMsg = `Element not found for selector: ${normalizedSelector}`;
|
|
226
|
+
warn(errMsg);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const { nodeRef } = refs.getNodeInstance();
|
|
230
|
+
if (!nodeRef?.current) {
|
|
231
|
+
const errMsg = `Node ref not available for selector: ${normalizedSelector}`;
|
|
232
|
+
warn(errMsg);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
nodeRef.current.measureLayout(targetScrollView, (left, top) => {
|
|
236
|
+
const adjustedLeft = scrollX ? left + offset : left;
|
|
237
|
+
const adjustedTop = scrollY ? top + offset : top;
|
|
238
|
+
// 使用 scrollTo 方法,支持 duration 参数
|
|
239
|
+
if (duration !== undefined) {
|
|
240
|
+
scrollTo({ left: adjustedLeft, top: adjustedTop, animated, duration });
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
scrollToOffset(adjustedLeft, adjustedTop, animated);
|
|
244
|
+
}
|
|
245
|
+
}, (error) => {
|
|
246
|
+
warn(`Failed to measure layout for selector ${normalizedSelector}: ${error}`);
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
const errMsg = `handleScrollIntoView error for selector ${selector}: ${error?.message || error}`;
|
|
251
|
+
warn(errMsg);
|
|
252
|
+
}
|
|
176
253
|
}
|
|
177
254
|
function selectLength(size) {
|
|
178
255
|
return !scrollX ? size.height : size.width;
|
|
@@ -457,9 +534,9 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
457
534
|
}
|
|
458
535
|
// 处理下拉刷新的手势 - 使用 useMemo 避免每次渲染都创建
|
|
459
536
|
const panGesture = useMemo(() => {
|
|
460
|
-
if (!hasRefresher)
|
|
461
|
-
return Gesture.Pan(); // 返回空手势
|
|
462
537
|
return Gesture.Pan()
|
|
538
|
+
.activeOffsetY([-5, 5])
|
|
539
|
+
.failOffsetX([-5, 5])
|
|
463
540
|
.onUpdate((event) => {
|
|
464
541
|
'worklet';
|
|
465
542
|
if (enhanced && !!bounces) {
|
|
@@ -519,7 +596,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
519
596
|
}
|
|
520
597
|
})
|
|
521
598
|
.simultaneousWithExternalGesture(scrollViewRef);
|
|
522
|
-
}, [
|
|
599
|
+
}, [enhanced, bounces, refreshing, refresherThreshold]);
|
|
523
600
|
const scrollAdditionalProps = extendObject({
|
|
524
601
|
style: extendObject(hasOwn(innerStyle, 'flex') || hasOwn(innerStyle, 'flexGrow')
|
|
525
602
|
? {}
|
|
@@ -56,7 +56,6 @@ interface SwiperProps {
|
|
|
56
56
|
'wait-for'?: Array<GestureHandler>;
|
|
57
57
|
'simultaneous-handlers'?: Array<GestureHandler>;
|
|
58
58
|
disableGesture?: boolean;
|
|
59
|
-
'display-multiple-items'?: number;
|
|
60
59
|
bindchange?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void;
|
|
61
60
|
}
|
|
62
61
|
declare const SwiperWrapper: React.ForwardRefExoticComponent<SwiperProps & React.RefAttributes<HandlerRef<View, SwiperProps>>>;
|
|
@@ -72,7 +72,6 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
72
72
|
marginBottom: dotSpacing,
|
|
73
73
|
zIndex: 98
|
|
74
74
|
};
|
|
75
|
-
const displayMultipleItems = props['display-multiple-items'] || 1;
|
|
76
75
|
const easeingFunc = props['easing-function'] || 'default';
|
|
77
76
|
const easeDuration = props.duration || 500;
|
|
78
77
|
const horizontal = props.vertical !== undefined ? !props.vertical : true;
|
|
@@ -98,19 +97,19 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
98
97
|
const preMarginShared = useSharedValue(preMargin);
|
|
99
98
|
const nextMarginShared = useSharedValue(nextMargin);
|
|
100
99
|
const autoplayShared = useSharedValue(autoplay);
|
|
101
|
-
const children = Array.isArray(props.children) ? props.children.filter(child => child) : (props.children ? [props.children] : []);
|
|
102
100
|
// 默认前后补位的元素个数
|
|
103
|
-
const patchElmNum =
|
|
101
|
+
const patchElmNum = circular ? (preMargin ? 2 : 1) : 0;
|
|
104
102
|
const patchElmNumShared = useSharedValue(patchElmNum);
|
|
105
|
-
const displayMultipleItemsShared = useSharedValue(displayMultipleItems);
|
|
106
103
|
const circularShared = useSharedValue(circular);
|
|
104
|
+
// 支持swiper-item 同时存在<swiper-item wx:for/>和<swiper-item>并列的情况
|
|
105
|
+
const children = React.Children.toArray(props.children);
|
|
107
106
|
// 对有变化的变量,在worklet中只能使用sharedValue变量,useRef不能更新
|
|
108
107
|
const childrenLength = useSharedValue(children.length);
|
|
109
108
|
const initWidth = typeof normalStyle?.width === 'number' ? normalStyle.width - preMargin - nextMargin : normalStyle.width;
|
|
110
109
|
const initHeight = typeof normalStyle?.height === 'number' ? normalStyle.height - preMargin - nextMargin : normalStyle.height;
|
|
111
110
|
const dir = horizontal === false ? 'y' : 'x';
|
|
112
111
|
const pstep = dir === 'x' ? initWidth : initHeight;
|
|
113
|
-
const initStep = isNaN(pstep) ? 0 : pstep
|
|
112
|
+
const initStep = isNaN(pstep) ? 0 : pstep;
|
|
114
113
|
// 每个元素的宽度 or 高度,有固定值直接初始化无则0
|
|
115
114
|
const step = useSharedValue(initStep);
|
|
116
115
|
// 记录选中元素的索引值
|
|
@@ -174,7 +173,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
174
173
|
const { width, height } = e.nativeEvent.layout;
|
|
175
174
|
const realWidth = dir === 'x' ? width - preMargin - nextMargin : width;
|
|
176
175
|
const realHeight = dir === 'y' ? height - preMargin - nextMargin : height;
|
|
177
|
-
const iStep =
|
|
176
|
+
const iStep = dir === 'x' ? realWidth : realHeight;
|
|
178
177
|
if (iStep !== step.value) {
|
|
179
178
|
step.value = iStep;
|
|
180
179
|
updateCurrent(propCurrent, iStep);
|
|
@@ -230,35 +229,19 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
230
229
|
function renderItems() {
|
|
231
230
|
const intLen = children.length;
|
|
232
231
|
let renderChild = children.slice();
|
|
233
|
-
// if (circular && intLen > 1) {
|
|
234
|
-
// // 最前面加最后一个元素
|
|
235
|
-
// const lastChild = React.cloneElement(children[intLen - 1] as ReactElement, { key: 'clone0' })
|
|
236
|
-
// // 最后面加第一个元素
|
|
237
|
-
// const firstChild = React.cloneElement(children[0] as ReactElement, { key: 'clone1' })
|
|
238
|
-
// if (preMargin) {
|
|
239
|
-
// const lastChild1 = React.cloneElement(children[intLen - 2] as ReactElement, { key: 'clone2' })
|
|
240
|
-
// const firstChild1 = React.cloneElement(children[1] as ReactElement, { key: 'clone3' })
|
|
241
|
-
// renderChild = [lastChild1, lastChild].concat(renderChild).concat([firstChild, firstChild1])
|
|
242
|
-
// } else {
|
|
243
|
-
// renderChild = [lastChild].concat(renderChild).concat([firstChild])
|
|
244
|
-
// }
|
|
245
|
-
// }
|
|
246
232
|
if (circular && intLen > 1) {
|
|
247
|
-
//
|
|
248
|
-
const
|
|
249
|
-
//
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
backClones.push(React.cloneElement(children[sourceIndex], { key: `clone_back_${i}` }));
|
|
260
|
-
}
|
|
261
|
-
renderChild = [...frontClones, ...renderChild, ...backClones];
|
|
233
|
+
// 最前面加最后一个元素
|
|
234
|
+
const lastChild = React.cloneElement(children[intLen - 1], { key: 'clone0' });
|
|
235
|
+
// 最后面加第一个元素
|
|
236
|
+
const firstChild = React.cloneElement(children[0], { key: 'clone1' });
|
|
237
|
+
if (preMargin) {
|
|
238
|
+
const lastChild1 = React.cloneElement(children[intLen - 2], { key: 'clone2' });
|
|
239
|
+
const firstChild1 = React.cloneElement(children[1], { key: 'clone3' });
|
|
240
|
+
renderChild = [lastChild1, lastChild].concat(renderChild).concat([firstChild, firstChild1]);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
renderChild = [lastChild].concat(renderChild).concat([firstChild]);
|
|
244
|
+
}
|
|
262
245
|
}
|
|
263
246
|
const arrChildren = renderChild.map((child, index) => {
|
|
264
247
|
const extraStyle = {};
|
|
@@ -293,7 +276,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
293
276
|
let nextIndex = currentIndex.value;
|
|
294
277
|
if (!circularShared.value) {
|
|
295
278
|
// 获取下一个位置的坐标, 循环到最后一个元素,直接停止, 取消定时器
|
|
296
|
-
if (currentIndex.value === childrenLength.value -
|
|
279
|
+
if (currentIndex.value === childrenLength.value - 1) {
|
|
297
280
|
pauseLoop();
|
|
298
281
|
return;
|
|
299
282
|
}
|
|
@@ -459,13 +442,12 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
459
442
|
};
|
|
460
443
|
}, [autoplay]);
|
|
461
444
|
useEffect(() => {
|
|
462
|
-
if (circular !== circularShared.value
|
|
445
|
+
if (circular !== circularShared.value) {
|
|
463
446
|
circularShared.value = circular;
|
|
464
|
-
patchElmNumShared.value =
|
|
465
|
-
displayMultipleItemsShared.value = displayMultipleItems;
|
|
447
|
+
patchElmNumShared.value = circular ? (preMargin ? 2 : 1) : 0;
|
|
466
448
|
offset.value = getOffset(currentIndex.value, step.value);
|
|
467
449
|
}
|
|
468
|
-
}, [circular,
|
|
450
|
+
}, [circular, preMargin]);
|
|
469
451
|
const { gestureHandler } = useMemo(() => {
|
|
470
452
|
// 基于transdir + 当前offset计算索引
|
|
471
453
|
function getTargetPosition(eventData) {
|
|
@@ -484,8 +466,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
484
466
|
const moveToIndex = transdir < 0 ? Math.ceil(computedIndex) : Math.floor(computedIndex);
|
|
485
467
|
// 实际应该定位的索引值
|
|
486
468
|
if (!circularShared.value) {
|
|
487
|
-
|
|
488
|
-
selectedIndex = Math.min(Math.max(moveToIndex, 0), maxIndex);
|
|
469
|
+
selectedIndex = moveToIndex;
|
|
489
470
|
moveToTargetPos = selectedIndex * step.value;
|
|
490
471
|
}
|
|
491
472
|
else {
|
|
@@ -521,7 +502,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
521
502
|
const gestureMovePos = offset.value + translation;
|
|
522
503
|
if (!circularShared.value) {
|
|
523
504
|
// 如果只判断区间,中间非滑动状态(handleResistanceMove)向左滑动,突然改为向右滑动,但是还在非滑动态,本应该可滑动判断为了不可滑动
|
|
524
|
-
const posEnd = -step.value * (childrenLength.value -
|
|
505
|
+
const posEnd = -step.value * (childrenLength.value - 1);
|
|
525
506
|
if (transdir < 0) {
|
|
526
507
|
return gestureMovePos > posEnd;
|
|
527
508
|
}
|
|
@@ -628,7 +609,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
628
609
|
const { translation, transdir } = eventData;
|
|
629
610
|
const moveToOffset = offset.value + translation;
|
|
630
611
|
const maxOverDrag = Math.floor(step.value / 2);
|
|
631
|
-
const maxOffset = translation < 0 ? -(childrenLength.value -
|
|
612
|
+
const maxOffset = translation < 0 ? -(childrenLength.value - 1) * step.value : 0;
|
|
632
613
|
let resistance = 0.1;
|
|
633
614
|
let overDrag = 0;
|
|
634
615
|
let finalOffset = 0;
|