@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
|
|
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, WatchOptions } from '@mpxjs/core'
|
|
6
8
|
|
|
7
9
|
const qualityValue = {
|
|
8
10
|
high: 90,
|
|
@@ -14,9 +16,9 @@ const qualityValue = {
|
|
|
14
16
|
interface CameraProps {
|
|
15
17
|
mode?: 'normal' | 'scanCode'
|
|
16
18
|
resolution?: 'low' | 'medium' | 'high'
|
|
17
|
-
|
|
19
|
+
'device-position'?: 'front' | 'back'
|
|
18
20
|
flash?: 'auto' | 'on' | 'off'
|
|
19
|
-
|
|
21
|
+
'frame-size'?: 'small' | 'medium' | 'large'
|
|
20
22
|
style?: Record<string, any>
|
|
21
23
|
bindstop?: () => void
|
|
22
24
|
binderror?: (error: { message: string }) => void
|
|
@@ -65,14 +67,13 @@ let RecordRes: any = null
|
|
|
65
67
|
|
|
66
68
|
const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: CameraProps, ref): JSX.Element | null => {
|
|
67
69
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
68
|
-
const { Camera, useCameraDevice, useCodeScanner, useCameraFormat } = require('react-native-vision-camera')
|
|
69
70
|
const cameraRef = useRef<any>(null)
|
|
70
71
|
const {
|
|
71
72
|
mode = 'normal',
|
|
72
73
|
resolution = 'medium',
|
|
73
|
-
devicePosition = 'back',
|
|
74
|
+
'device-position': devicePosition = 'back',
|
|
74
75
|
flash = 'auto',
|
|
75
|
-
frameSize = 'medium',
|
|
76
|
+
'frame-size': frameSize = 'medium',
|
|
76
77
|
bindinitdone,
|
|
77
78
|
bindstop,
|
|
78
79
|
bindscancode,
|
|
@@ -100,24 +101,26 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
100
101
|
parentHeight
|
|
101
102
|
})
|
|
102
103
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: cameraRef })
|
|
103
|
-
const isPhoto =
|
|
104
|
+
const isPhoto = useRef<boolean>(false)
|
|
105
|
+
isPhoto.current = mode === 'normal'
|
|
104
106
|
const device = useCameraDevice(devicePosition || 'back')
|
|
105
|
-
const { navigation } = useContext(RouteContext) || {}
|
|
107
|
+
const { navigation, pageId } = useContext(RouteContext) || {}
|
|
106
108
|
const [zoomValue, setZoomValue] = useState<number>(1)
|
|
109
|
+
const [isActive, setIsActive] = useState<boolean>(true)
|
|
107
110
|
const [hasPermission, setHasPermission] = useState<boolean | null>(null)
|
|
108
|
-
const
|
|
111
|
+
const page = getCurrentPage(pageId)
|
|
109
112
|
|
|
110
113
|
// 先定义常量,避免在条件判断后使用
|
|
111
114
|
const maxZoom = device?.maxZoom || 1
|
|
112
|
-
const RESOLUTION_MAPPING: Record<string, { width: number, height: number }> = {
|
|
113
|
-
low: { width:
|
|
114
|
-
medium: { width:
|
|
115
|
-
high:
|
|
115
|
+
const RESOLUTION_MAPPING: Record<string, { width: number, height: number } | 'max'> = {
|
|
116
|
+
low: { width: 1280, height: 720 },
|
|
117
|
+
medium: { width: 1920, height: 1080 },
|
|
118
|
+
high: 'max'
|
|
116
119
|
}
|
|
117
|
-
const FRAME_SIZE_MAPPING: Record<string, { width: number, height: number }> = {
|
|
118
|
-
small: { width:
|
|
119
|
-
medium: { width:
|
|
120
|
-
large:
|
|
120
|
+
const FRAME_SIZE_MAPPING: Record<string, { width: number, height: number } | 'max'> = {
|
|
121
|
+
small: { width: 1280, height: 720 },
|
|
122
|
+
medium: { width: 1920, height: 1080 },
|
|
123
|
+
large: 'max'
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
const format = useCameraFormat(device, [
|
|
@@ -126,16 +129,31 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
126
129
|
videoResolution: FRAME_SIZE_MAPPING[frameSize] || RESOLUTION_MAPPING[resolution]
|
|
127
130
|
}
|
|
128
131
|
])
|
|
129
|
-
|
|
132
|
+
const isScancode = useCallback((fail: (res: { errMsg: string }) => void, complete: (res: { errMsg: string }) => void) => {
|
|
133
|
+
if (!isPhoto.current) {
|
|
134
|
+
const result = {
|
|
135
|
+
errMsg: 'Not allow to invoke takePhoto in \'scanCode\' mode.'
|
|
136
|
+
}
|
|
137
|
+
fail(result)
|
|
138
|
+
complete(result)
|
|
139
|
+
return true
|
|
140
|
+
}
|
|
141
|
+
return false
|
|
142
|
+
}, [])
|
|
130
143
|
const codeScanner = useCodeScanner({
|
|
131
|
-
codeTypes: ['qr'
|
|
144
|
+
codeTypes: ['qr'],
|
|
132
145
|
onCodeScanned: (codes: any[]) => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
codes.forEach(code => {
|
|
147
|
+
const type = code.type === 'qr' ? 'QR_CODE' : code.type?.toUpperCase()
|
|
148
|
+
const frame = code.frame || {}
|
|
149
|
+
bindscancode && bindscancode(getCustomEvent('scancode', {}, {
|
|
150
|
+
detail: {
|
|
151
|
+
result: code.value,
|
|
152
|
+
type,
|
|
153
|
+
scanArea: [parseInt(frame.x) || 0, parseInt(frame.y) || 0, parseInt(frame.width) || 0, parseInt(frame.height) || 0]
|
|
154
|
+
}
|
|
155
|
+
}))
|
|
156
|
+
})
|
|
139
157
|
}
|
|
140
158
|
})
|
|
141
159
|
|
|
@@ -151,14 +169,14 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
151
169
|
bindstop && bindstop()
|
|
152
170
|
}, [bindstop])
|
|
153
171
|
|
|
154
|
-
const camera: CameraRef = {
|
|
172
|
+
const camera: CameraRef = useMemo(() => ({
|
|
155
173
|
setZoom: (zoom: number) => {
|
|
156
174
|
setZoomValue(zoom)
|
|
157
175
|
},
|
|
158
176
|
takePhoto: (options: TakePhotoOptions = {}) => {
|
|
159
177
|
const { success = noop, fail = noop, complete = noop } = options
|
|
178
|
+
if (isScancode(fail, complete)) return
|
|
160
179
|
cameraRef.current?.takePhoto?.({
|
|
161
|
-
flash,
|
|
162
180
|
quality: qualityValue[options.quality || 'normal'] as number
|
|
163
181
|
} as any).then((res: { path: any }) => {
|
|
164
182
|
const result = {
|
|
@@ -179,7 +197,7 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
179
197
|
let { timeout = 30, success = noop, fail = noop, complete = noop, timeoutCallback = noop } = options
|
|
180
198
|
timeout = timeout > 300 ? 300 : timeout
|
|
181
199
|
let recordTimer: NodeJS.Timeout | null = null
|
|
182
|
-
|
|
200
|
+
if (isScancode(fail, complete)) return
|
|
183
201
|
try {
|
|
184
202
|
const result = {
|
|
185
203
|
errMsg: 'startRecord:ok'
|
|
@@ -188,7 +206,6 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
188
206
|
complete(result)
|
|
189
207
|
|
|
190
208
|
cameraRef.current?.startRecording?.({
|
|
191
|
-
flash,
|
|
192
209
|
onRecordingError: (error: any) => {
|
|
193
210
|
if (recordTimer) clearTimeout(recordTimer)
|
|
194
211
|
const errorResult = {
|
|
@@ -204,7 +221,6 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
204
221
|
})
|
|
205
222
|
|
|
206
223
|
recordTimer = setTimeout(() => { // 超时自动停止
|
|
207
|
-
isTimeout = true
|
|
208
224
|
cameraRef.current?.stopRecording().catch(() => {
|
|
209
225
|
// 忽略停止录制时的错误
|
|
210
226
|
})
|
|
@@ -220,6 +236,7 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
220
236
|
},
|
|
221
237
|
stopRecord: (options: StopRecordOptions = {}) => {
|
|
222
238
|
const { success = noop, fail = noop, complete = noop } = options
|
|
239
|
+
if (isScancode(fail, complete)) return
|
|
223
240
|
try {
|
|
224
241
|
cameraRef.current?.stopRecording().then(() => {
|
|
225
242
|
setTimeout(() => {
|
|
@@ -249,16 +266,21 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
249
266
|
complete(result)
|
|
250
267
|
}
|
|
251
268
|
}
|
|
252
|
-
}
|
|
269
|
+
}), [])
|
|
253
270
|
|
|
254
271
|
useEffect(() => {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
272
|
+
let unWatch: any
|
|
273
|
+
if (pageId && hasOwn(global.__mpxPageStatusMap, String(pageId))) {
|
|
274
|
+
unWatch = watch(() => global.__mpxPageStatusMap[pageId], (newVal: string) => {
|
|
275
|
+
if (newVal === 'show') {
|
|
276
|
+
if (page.id === pageId) {
|
|
277
|
+
setIsActive(true)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (newVal === 'hide') {
|
|
281
|
+
setIsActive(false)
|
|
282
|
+
}
|
|
283
|
+
}, { sync: true } as WatchOptions)
|
|
262
284
|
}
|
|
263
285
|
const checkCameraPermission = async () => {
|
|
264
286
|
try {
|
|
@@ -275,13 +297,14 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
275
297
|
}
|
|
276
298
|
checkCameraPermission()
|
|
277
299
|
return () => {
|
|
278
|
-
if (navigation
|
|
279
|
-
navigation.camera
|
|
300
|
+
if (navigation?.camera === camera) {
|
|
301
|
+
delete navigation.camera
|
|
280
302
|
}
|
|
303
|
+
unWatch && unWatch()
|
|
281
304
|
}
|
|
282
305
|
}, [])
|
|
283
306
|
|
|
284
|
-
const innerProps = useInnerProps(
|
|
307
|
+
const innerProps:any = useInnerProps(
|
|
285
308
|
extendObject(
|
|
286
309
|
{},
|
|
287
310
|
props,
|
|
@@ -289,15 +312,16 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
289
312
|
{
|
|
290
313
|
ref: cameraRef,
|
|
291
314
|
style: extendObject({}, normalStyle, layoutStyle),
|
|
292
|
-
isActive
|
|
315
|
+
isActive,
|
|
293
316
|
photo: true,
|
|
294
317
|
video: true,
|
|
295
318
|
onInitialized,
|
|
296
319
|
onStopped,
|
|
297
320
|
device,
|
|
298
321
|
format,
|
|
299
|
-
codeScanner: !isPhoto ? codeScanner : undefined,
|
|
300
|
-
zoom: zoomValue
|
|
322
|
+
codeScanner: !isPhoto.current ? codeScanner : undefined,
|
|
323
|
+
zoom: zoomValue,
|
|
324
|
+
torch: flash
|
|
301
325
|
}
|
|
302
326
|
),
|
|
303
327
|
[
|
|
@@ -315,7 +339,14 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
|
|
|
315
339
|
}
|
|
316
340
|
)
|
|
317
341
|
|
|
318
|
-
if (
|
|
342
|
+
if (navigation && navigation.camera && navigation.camera !== camera) {
|
|
343
|
+
warn('<camera>: 一个页面只能插入一个')
|
|
344
|
+
return null
|
|
345
|
+
} else if (navigation) {
|
|
346
|
+
navigation.camera = camera
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (!hasPermission || !device) {
|
|
319
350
|
return null
|
|
320
351
|
}
|
|
321
352
|
|
|
@@ -299,22 +299,112 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
299
299
|
}
|
|
300
300
|
}, [refresherTriggered])
|
|
301
301
|
|
|
302
|
-
function scrollTo ({ top = 0, left = 0, animated = false }: { top?: number; left?: number; animated?: boolean }) {
|
|
303
|
-
|
|
302
|
+
function scrollTo ({ top = 0, left = 0, animated = false, duration }: { top?: number; left?: number; animated?: boolean; duration?: number }) {
|
|
303
|
+
// 如果指定了 duration 且需要动画,使用自定义动画
|
|
304
|
+
if (animated && duration && duration > 0) {
|
|
305
|
+
// 获取当前滚动位置
|
|
306
|
+
const currentY = scrollOptions.current.scrollTop || 0
|
|
307
|
+
const currentX = scrollOptions.current.scrollLeft || 0
|
|
308
|
+
|
|
309
|
+
const startTime = Date.now()
|
|
310
|
+
const deltaY = top - currentY
|
|
311
|
+
const deltaX = left - currentX
|
|
312
|
+
|
|
313
|
+
// 缓动函数:easeInOutCubic
|
|
314
|
+
const easing = (t: number) => {
|
|
315
|
+
return t < 0.5
|
|
316
|
+
? 4 * t * t * t
|
|
317
|
+
: 1 - Math.pow(-2 * t + 2, 3) / 2
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// 使用 requestAnimationFrame 实现平滑动画
|
|
321
|
+
const animate = () => {
|
|
322
|
+
const elapsed = Date.now() - startTime
|
|
323
|
+
const progress = Math.min(elapsed / duration, 1) // 0 到 1
|
|
324
|
+
|
|
325
|
+
const easeProgress = easing(progress)
|
|
326
|
+
const nextY = currentY + deltaY * easeProgress
|
|
327
|
+
const nextX = currentX + deltaX * easeProgress
|
|
328
|
+
|
|
329
|
+
if (scrollViewRef.current) {
|
|
330
|
+
scrollViewRef.current.scrollTo({ y: nextY, x: nextX, animated: false })
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (progress < 1) {
|
|
334
|
+
requestAnimationFrame(animate)
|
|
335
|
+
} else {
|
|
336
|
+
// 确保最终位置准确
|
|
337
|
+
if (scrollViewRef.current) {
|
|
338
|
+
scrollViewRef.current.scrollTo({ y: top, x: left, animated: false })
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
requestAnimationFrame(animate)
|
|
344
|
+
} else {
|
|
345
|
+
// 使用原生的 scrollTo
|
|
346
|
+
scrollToOffset(left, top, animated)
|
|
347
|
+
}
|
|
304
348
|
}
|
|
305
349
|
|
|
306
|
-
function handleScrollIntoView (selector = '', { offset = 0, animated = true } = {}) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const adjustedTop = scrollY ? top + offset : top
|
|
315
|
-
scrollToOffset(adjustedLeft, adjustedTop, animated)
|
|
350
|
+
function handleScrollIntoView (selector = '', { offset = 0, animated = true, duration = undefined }: { offset?: number; animated?: boolean; duration?: number } = {}) {
|
|
351
|
+
try {
|
|
352
|
+
const currentSelectRef = propsRef.current.__selectRef
|
|
353
|
+
|
|
354
|
+
if (!currentSelectRef) {
|
|
355
|
+
const errMsg = '__selectRef is not available. Please ensure the scroll-view component is properly initialized.'
|
|
356
|
+
warn(errMsg)
|
|
357
|
+
return
|
|
316
358
|
}
|
|
317
|
-
|
|
359
|
+
|
|
360
|
+
const targetScrollView = scrollViewRef.current
|
|
361
|
+
|
|
362
|
+
if (!targetScrollView) {
|
|
363
|
+
const errMsg = 'scrollViewRef is not ready'
|
|
364
|
+
warn(errMsg)
|
|
365
|
+
return
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// scroll-into-view prop 按微信规范直传裸 id(如 "section-1"),而 __refs 注册时 key 带 # 或 . 前缀,需补齐才能命中;
|
|
369
|
+
// pageScrollTo 调用方已自带前缀(如 "#section-1")
|
|
370
|
+
const normalizedSelector = selector.startsWith('#') || selector.startsWith('.') ? selector : `#${selector}`
|
|
371
|
+
|
|
372
|
+
// 调用 __selectRef 查找元素
|
|
373
|
+
const refs = currentSelectRef(normalizedSelector, 'node')
|
|
374
|
+
if (!refs) {
|
|
375
|
+
const errMsg = `Element not found for selector: ${normalizedSelector}`
|
|
376
|
+
warn(errMsg)
|
|
377
|
+
return
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const { nodeRef } = refs.getNodeInstance()
|
|
381
|
+
if (!nodeRef?.current) {
|
|
382
|
+
const errMsg = `Node ref not available for selector: ${normalizedSelector}`
|
|
383
|
+
warn(errMsg)
|
|
384
|
+
return
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
nodeRef.current.measureLayout(
|
|
388
|
+
targetScrollView,
|
|
389
|
+
(left: number, top: number) => {
|
|
390
|
+
const adjustedLeft = scrollX ? left + offset : left
|
|
391
|
+
const adjustedTop = scrollY ? top + offset : top
|
|
392
|
+
|
|
393
|
+
// 使用 scrollTo 方法,支持 duration 参数
|
|
394
|
+
if (duration !== undefined) {
|
|
395
|
+
scrollTo({ left: adjustedLeft, top: adjustedTop, animated, duration })
|
|
396
|
+
} else {
|
|
397
|
+
scrollToOffset(adjustedLeft, adjustedTop, animated)
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
(error: any) => {
|
|
401
|
+
warn(`Failed to measure layout for selector ${normalizedSelector}: ${error}`)
|
|
402
|
+
}
|
|
403
|
+
)
|
|
404
|
+
} catch (error: any) {
|
|
405
|
+
const errMsg = `handleScrollIntoView error for selector ${selector}: ${error?.message || error}`
|
|
406
|
+
warn(errMsg)
|
|
407
|
+
}
|
|
318
408
|
}
|
|
319
409
|
|
|
320
410
|
function selectLength (size: { height: number; width: number }) {
|
|
@@ -641,9 +731,9 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
641
731
|
|
|
642
732
|
// 处理下拉刷新的手势 - 使用 useMemo 避免每次渲染都创建
|
|
643
733
|
const panGesture = useMemo(() => {
|
|
644
|
-
if (!hasRefresher) return Gesture.Pan() // 返回空手势
|
|
645
|
-
|
|
646
734
|
return Gesture.Pan()
|
|
735
|
+
.activeOffsetY([-5, 5])
|
|
736
|
+
.failOffsetX([-5, 5])
|
|
647
737
|
.onUpdate((event) => {
|
|
648
738
|
'worklet'
|
|
649
739
|
if (enhanced && !!bounces) {
|
|
@@ -703,7 +793,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
703
793
|
}
|
|
704
794
|
})
|
|
705
795
|
.simultaneousWithExternalGesture(scrollViewRef)
|
|
706
|
-
}, [
|
|
796
|
+
}, [enhanced, bounces, refreshing, refresherThreshold])
|
|
707
797
|
|
|
708
798
|
const scrollAdditionalProps: ScrollAdditionalProps = extendObject(
|
|
709
799
|
{
|
|
@@ -77,7 +77,6 @@ interface SwiperProps {
|
|
|
77
77
|
'wait-for'?: Array<GestureHandler>
|
|
78
78
|
'simultaneous-handlers'?: Array<GestureHandler>
|
|
79
79
|
disableGesture?: boolean
|
|
80
|
-
'display-multiple-items'?: number
|
|
81
80
|
bindchange?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void
|
|
82
81
|
}
|
|
83
82
|
|
|
@@ -172,7 +171,6 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
172
171
|
marginBottom: dotSpacing,
|
|
173
172
|
zIndex: 98
|
|
174
173
|
}
|
|
175
|
-
const displayMultipleItems = props['display-multiple-items'] || 1
|
|
176
174
|
const easeingFunc = props['easing-function'] || 'default'
|
|
177
175
|
const easeDuration = props.duration || 500
|
|
178
176
|
const horizontal = props.vertical !== undefined ? !props.vertical : true
|
|
@@ -206,19 +204,19 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
206
204
|
const preMarginShared = useSharedValue(preMargin)
|
|
207
205
|
const nextMarginShared = useSharedValue(nextMargin)
|
|
208
206
|
const autoplayShared = useSharedValue(autoplay)
|
|
209
|
-
const children = Array.isArray(props.children) ? props.children.filter(child => child) : (props.children ? [props.children] : [])
|
|
210
207
|
// 默认前后补位的元素个数
|
|
211
|
-
const patchElmNum =
|
|
208
|
+
const patchElmNum = circular ? (preMargin ? 2 : 1) : 0
|
|
212
209
|
const patchElmNumShared = useSharedValue(patchElmNum)
|
|
213
|
-
const displayMultipleItemsShared = useSharedValue(displayMultipleItems)
|
|
214
210
|
const circularShared = useSharedValue(circular)
|
|
211
|
+
// 支持swiper-item 同时存在<swiper-item wx:for/>和<swiper-item>并列的情况
|
|
212
|
+
const children = React.Children.toArray(props.children) as ReactElement[]
|
|
215
213
|
// 对有变化的变量,在worklet中只能使用sharedValue变量,useRef不能更新
|
|
216
214
|
const childrenLength = useSharedValue(children.length)
|
|
217
215
|
const initWidth = typeof normalStyle?.width === 'number' ? normalStyle.width - preMargin - nextMargin : normalStyle.width
|
|
218
216
|
const initHeight = typeof normalStyle?.height === 'number' ? normalStyle.height - preMargin - nextMargin : normalStyle.height
|
|
219
217
|
const dir = horizontal === false ? 'y' : 'x'
|
|
220
218
|
const pstep = dir === 'x' ? initWidth : initHeight
|
|
221
|
-
const initStep: number = isNaN(pstep) ? 0 : pstep
|
|
219
|
+
const initStep: number = isNaN(pstep) ? 0 : pstep
|
|
222
220
|
// 每个元素的宽度 or 高度,有固定值直接初始化无则0
|
|
223
221
|
const step = useSharedValue(initStep)
|
|
224
222
|
// 记录选中元素的索引值
|
|
@@ -296,7 +294,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
296
294
|
const { width, height } = e.nativeEvent.layout
|
|
297
295
|
const realWidth = dir === 'x' ? width - preMargin - nextMargin : width
|
|
298
296
|
const realHeight = dir === 'y' ? height - preMargin - nextMargin : height
|
|
299
|
-
const iStep =
|
|
297
|
+
const iStep = dir === 'x' ? realWidth : realHeight
|
|
300
298
|
if (iStep !== step.value) {
|
|
301
299
|
step.value = iStep
|
|
302
300
|
updateCurrent(propCurrent, iStep)
|
|
@@ -355,35 +353,18 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
355
353
|
function renderItems () {
|
|
356
354
|
const intLen = children.length
|
|
357
355
|
let renderChild = children.slice()
|
|
358
|
-
// if (circular && intLen > 1) {
|
|
359
|
-
// // 最前面加最后一个元素
|
|
360
|
-
// const lastChild = React.cloneElement(children[intLen - 1] as ReactElement, { key: 'clone0' })
|
|
361
|
-
// // 最后面加第一个元素
|
|
362
|
-
// const firstChild = React.cloneElement(children[0] as ReactElement, { key: 'clone1' })
|
|
363
|
-
// if (preMargin) {
|
|
364
|
-
// const lastChild1 = React.cloneElement(children[intLen - 2] as ReactElement, { key: 'clone2' })
|
|
365
|
-
// const firstChild1 = React.cloneElement(children[1] as ReactElement, { key: 'clone3' })
|
|
366
|
-
// renderChild = [lastChild1, lastChild].concat(renderChild).concat([firstChild, firstChild1])
|
|
367
|
-
// } else {
|
|
368
|
-
// renderChild = [lastChild].concat(renderChild).concat([firstChild])
|
|
369
|
-
// }
|
|
370
|
-
// }
|
|
371
356
|
if (circular && intLen > 1) {
|
|
372
|
-
//
|
|
373
|
-
const
|
|
374
|
-
//
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
for (let i = 0; i < patchElmNum; i++) {
|
|
383
|
-
const sourceIndex = i % intLen
|
|
384
|
-
backClones.push(React.cloneElement(children[sourceIndex], { key: `clone_back_${i}` }))
|
|
357
|
+
// 最前面加最后一个元素
|
|
358
|
+
const lastChild = React.cloneElement(children[intLen - 1] as ReactElement, { key: 'clone0' })
|
|
359
|
+
// 最后面加第一个元素
|
|
360
|
+
const firstChild = React.cloneElement(children[0] as ReactElement, { key: 'clone1' })
|
|
361
|
+
if (preMargin) {
|
|
362
|
+
const lastChild1 = React.cloneElement(children[intLen - 2] as ReactElement, { key: 'clone2' })
|
|
363
|
+
const firstChild1 = React.cloneElement(children[1] as ReactElement, { key: 'clone3' })
|
|
364
|
+
renderChild = [lastChild1, lastChild].concat(renderChild).concat([firstChild, firstChild1])
|
|
365
|
+
} else {
|
|
366
|
+
renderChild = [lastChild].concat(renderChild).concat([firstChild])
|
|
385
367
|
}
|
|
386
|
-
renderChild = [...frontClones, ...renderChild, ...backClones]
|
|
387
368
|
}
|
|
388
369
|
const arrChildren = renderChild.map((child, index) => {
|
|
389
370
|
const extraStyle = {} as { [key: string]: any }
|
|
@@ -418,7 +399,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
418
399
|
let nextIndex = currentIndex.value
|
|
419
400
|
if (!circularShared.value) {
|
|
420
401
|
// 获取下一个位置的坐标, 循环到最后一个元素,直接停止, 取消定时器
|
|
421
|
-
if (currentIndex.value === childrenLength.value -
|
|
402
|
+
if (currentIndex.value === childrenLength.value - 1) {
|
|
422
403
|
pauseLoop()
|
|
423
404
|
return
|
|
424
405
|
}
|
|
@@ -587,14 +568,14 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
587
568
|
}
|
|
588
569
|
}
|
|
589
570
|
}, [autoplay])
|
|
571
|
+
|
|
590
572
|
useEffect(() => {
|
|
591
|
-
if (circular !== circularShared.value
|
|
573
|
+
if (circular !== circularShared.value) {
|
|
592
574
|
circularShared.value = circular
|
|
593
|
-
patchElmNumShared.value =
|
|
594
|
-
displayMultipleItemsShared.value = displayMultipleItems
|
|
575
|
+
patchElmNumShared.value = circular ? (preMargin ? 2 : 1) : 0
|
|
595
576
|
offset.value = getOffset(currentIndex.value, step.value)
|
|
596
577
|
}
|
|
597
|
-
}, [circular,
|
|
578
|
+
}, [circular, preMargin])
|
|
598
579
|
const { gestureHandler } = useMemo(() => {
|
|
599
580
|
// 基于transdir + 当前offset计算索引
|
|
600
581
|
function getTargetPosition (eventData: EventEndType) {
|
|
@@ -613,8 +594,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
613
594
|
const moveToIndex = transdir < 0 ? Math.ceil(computedIndex) : Math.floor(computedIndex)
|
|
614
595
|
// 实际应该定位的索引值
|
|
615
596
|
if (!circularShared.value) {
|
|
616
|
-
|
|
617
|
-
selectedIndex = Math.min(Math.max(moveToIndex, 0), maxIndex)
|
|
597
|
+
selectedIndex = moveToIndex
|
|
618
598
|
moveToTargetPos = selectedIndex * step.value
|
|
619
599
|
} else {
|
|
620
600
|
if (moveToIndex >= childrenLength.value + patchElmNumShared.value) {
|
|
@@ -647,7 +627,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
647
627
|
const gestureMovePos = offset.value + translation
|
|
648
628
|
if (!circularShared.value) {
|
|
649
629
|
// 如果只判断区间,中间非滑动状态(handleResistanceMove)向左滑动,突然改为向右滑动,但是还在非滑动态,本应该可滑动判断为了不可滑动
|
|
650
|
-
const posEnd = -step.value * (childrenLength.value -
|
|
630
|
+
const posEnd = -step.value * (childrenLength.value - 1)
|
|
651
631
|
if (transdir < 0) {
|
|
652
632
|
return gestureMovePos > posEnd
|
|
653
633
|
} else {
|
|
@@ -751,7 +731,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
751
731
|
const { translation, transdir } = eventData
|
|
752
732
|
const moveToOffset = offset.value + translation
|
|
753
733
|
const maxOverDrag = Math.floor(step.value / 2)
|
|
754
|
-
const maxOffset = translation < 0 ? -(childrenLength.value -
|
|
734
|
+
const maxOffset = translation < 0 ? -(childrenLength.value - 1) * step.value : 0
|
|
755
735
|
let resistance = 0.1
|
|
756
736
|
let overDrag = 0
|
|
757
737
|
let finalOffset = 0
|
|
@@ -380,7 +380,7 @@
|
|
|
380
380
|
const top = item.offsetTop
|
|
381
381
|
const width = item.offsetWidth
|
|
382
382
|
const height = item.offsetHeight
|
|
383
|
-
|
|
383
|
+
|
|
384
384
|
minLeft = getMinLength(minLeft, left)
|
|
385
385
|
minTop = getMinLength(minTop, top)
|
|
386
386
|
maxRight = getMaxLength(maxRight, left + width)
|
|
@@ -414,9 +414,6 @@
|
|
|
414
414
|
if (this.bs) this.bs.refresh()
|
|
415
415
|
}
|
|
416
416
|
},
|
|
417
|
-
forceUpdateRefreshVersion () {
|
|
418
|
-
this.refreshVersion++
|
|
419
|
-
},
|
|
420
417
|
compare(num1, num2, scale = 1) {
|
|
421
418
|
return Math.abs(num1 - num2) < scale
|
|
422
419
|
},
|
|
@@ -591,4 +588,4 @@
|
|
|
591
588
|
background: rgba(255, 255, 255, .7)
|
|
592
589
|
100%
|
|
593
590
|
background: rgba(255, 255, 255, .3)
|
|
594
|
-
</style>
|
|
591
|
+
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const JSON5 = require('json5')
|
|
2
2
|
const he = require('he')
|
|
3
3
|
const config = require('../config')
|
|
4
|
-
const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID, PARENT_MODULE_ID, MPX_TAG_PAGE_SELECTOR
|
|
4
|
+
const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID, PARENT_MODULE_ID, MPX_TAG_PAGE_SELECTOR } = require('../utils/const')
|
|
5
5
|
const normalize = require('../utils/normalize')
|
|
6
6
|
const { normalizeCondition } = require('../utils/match-condition')
|
|
7
7
|
const isValidIdentifierStr = require('../utils/is-valid-identifier-str')
|
|
@@ -2432,11 +2432,7 @@ function isRealNode (el) {
|
|
|
2432
2432
|
}
|
|
2433
2433
|
|
|
2434
2434
|
function isComponentNode (el) {
|
|
2435
|
-
return usingComponents.indexOf(el.tag) !== -1 || el.tag === 'component' || componentGenerics[el.tag]
|
|
2436
|
-
}
|
|
2437
|
-
|
|
2438
|
-
function isExtendComponentNode (el) {
|
|
2439
|
-
return EXTEND_COMPONENT_CONFIG[el.tag]?.[mode]
|
|
2435
|
+
return usingComponents.indexOf(el.tag) !== -1 || el.tag === 'component' || componentGenerics[el.tag]
|
|
2440
2436
|
}
|
|
2441
2437
|
|
|
2442
2438
|
function getComponentInfo (el) {
|
|
@@ -2444,7 +2440,7 @@ function getComponentInfo (el) {
|
|
|
2444
2440
|
}
|
|
2445
2441
|
|
|
2446
2442
|
function isReactComponent (el) {
|
|
2447
|
-
return !isComponentNode(el) && isRealNode(el) && !el.isBuiltIn
|
|
2443
|
+
return !isComponentNode(el) && isRealNode(el) && !el.isBuiltIn
|
|
2448
2444
|
}
|
|
2449
2445
|
|
|
2450
2446
|
function processExternalClasses (el, options) {
|
package/lib/utils/const.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const componentPrefixPath = '@mpxjs/webpack-plugin/lib/runtime/components'
|
|
2
|
-
|
|
3
1
|
module.exports = {
|
|
4
2
|
MPX_PROCESSED_FLAG: 'mpx_processed',
|
|
5
3
|
MPX_DISABLE_EXTRACTOR_CACHE: 'mpx_disable_extractor_cache',
|
|
@@ -9,32 +7,5 @@ module.exports = {
|
|
|
9
7
|
MPX_ROOT_VIEW: 'mpx-root-view', // 根节点类名
|
|
10
8
|
MPX_APP_MODULE_ID: 'mpx-app-scope', // app文件moduleId
|
|
11
9
|
PARENT_MODULE_ID: '__pid',
|
|
12
|
-
// 扩展组件的平台配置:声明哪些组件在哪些平台有专用实现,哪些使用公共组件
|
|
13
|
-
EXTEND_COMPONENT_CONFIG: {
|
|
14
|
-
'section-list': {
|
|
15
|
-
wx: `${componentPrefixPath}/wx/mpx-section-list.mpx`,
|
|
16
|
-
ali: `${componentPrefixPath}/ali/mpx-section-list.mpx`,
|
|
17
|
-
web: `${componentPrefixPath}/web/mpx-section-list.vue`,
|
|
18
|
-
ios: `${componentPrefixPath}/react/dist/mpx-section-list.jsx`,
|
|
19
|
-
android: `${componentPrefixPath}/react/dist/mpx-section-list.jsx`,
|
|
20
|
-
harmony: `${componentPrefixPath}/react/dist/mpx-section-list.jsx`
|
|
21
|
-
},
|
|
22
|
-
'sticky-header': {
|
|
23
|
-
wx: `${componentPrefixPath}/wx/mpx-sticky-header.mpx`,
|
|
24
|
-
ali: `${componentPrefixPath}/ali/mpx-sticky-header.mpx`,
|
|
25
|
-
web: `${componentPrefixPath}/web/mpx-sticky-header.vue`,
|
|
26
|
-
ios: `${componentPrefixPath}/react/dist/mpx-sticky-header.jsx`,
|
|
27
|
-
android: `${componentPrefixPath}/react/dist/mpx-sticky-header.jsx`,
|
|
28
|
-
harmony: `${componentPrefixPath}/react/dist/mpx-sticky-header.jsx`
|
|
29
|
-
},
|
|
30
|
-
'sticky-section': {
|
|
31
|
-
wx: `${componentPrefixPath}/wx/mpx-sticky-section.mpx`,
|
|
32
|
-
ali: `${componentPrefixPath}/ali/mpx-sticky-section.mpx`,
|
|
33
|
-
web: `${componentPrefixPath}/web/mpx-sticky-section.vue`,
|
|
34
|
-
ios: `${componentPrefixPath}/react/dist/mpx-sticky-section.jsx`,
|
|
35
|
-
android: `${componentPrefixPath}/react/dist/mpx-sticky-section.jsx`,
|
|
36
|
-
harmony: `${componentPrefixPath}/react/dist/mpx-sticky-section.jsx`
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
10
|
MPX_TAG_PAGE_SELECTOR: 'mpx-page'
|
|
40
11
|
}
|