@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.
Files changed (29) hide show
  1. package/LICENSE +433 -0
  2. package/lib/index.js +0 -12
  3. package/lib/runtime/components/react/dist/mpx-camera.d.ts +4 -4
  4. package/lib/runtime/components/react/dist/mpx-camera.jsx +75 -41
  5. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +92 -15
  6. package/lib/runtime/components/react/dist/mpx-swiper.d.ts +0 -1
  7. package/lib/runtime/components/react/dist/mpx-swiper.jsx +24 -43
  8. package/lib/runtime/components/react/mpx-camera.tsx +78 -47
  9. package/lib/runtime/components/react/mpx-scroll-view.tsx +106 -16
  10. package/lib/runtime/components/react/mpx-swiper.tsx +23 -43
  11. package/lib/runtime/components/web/mpx-scroll-view.vue +2 -5
  12. package/lib/template-compiler/compiler.js +3 -7
  13. package/lib/utils/const.js +0 -29
  14. package/package.json +4 -3
  15. package/lib/resolver/ExtendComponentsPlugin.js +0 -60
  16. package/lib/runtime/components/ali/mpx-section-list.mpx +0 -566
  17. package/lib/runtime/components/ali/mpx-sticky-header.mpx +0 -212
  18. package/lib/runtime/components/ali/mpx-sticky-section.mpx +0 -17
  19. package/lib/runtime/components/react/dist/mpx-section-list.d.ts +0 -48
  20. package/lib/runtime/components/react/dist/mpx-section-list.jsx +0 -292
  21. package/lib/runtime/components/react/mpx-section-list.tsx +0 -439
  22. package/lib/runtime/components/web/mpx-section-list.vue +0 -551
  23. package/lib/runtime/components/wx/mpx-section-list-default/list-footer.mpx +0 -26
  24. package/lib/runtime/components/wx/mpx-section-list-default/list-header.mpx +0 -26
  25. package/lib/runtime/components/wx/mpx-section-list-default/list-item.mpx +0 -26
  26. package/lib/runtime/components/wx/mpx-section-list-default/section-header.mpx +0 -26
  27. package/lib/runtime/components/wx/mpx-section-list.mpx +0 -209
  28. package/lib/runtime/components/wx/mpx-sticky-header.mpx +0 -40
  29. package/lib/runtime/components/wx/mpx-sticky-section.mpx +0 -31
@@ -1,8 +1,10 @@
1
- import React, { 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 { noop } from '@mpxjs/utils'
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
- devicePosition?: 'front' | 'back'
19
+ 'device-position'?: 'front' | 'back'
18
20
  flash?: 'auto' | 'on' | 'off'
19
- frameSize?: 'small' | 'medium' | 'large'
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 = mode === 'normal'
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 hasCamera = useRef(false)
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: 640, height: 480 },
114
- medium: { width: 1280, height: 720 },
115
- high: { width: 1920, height: 1080 }
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: 480, height: 360 },
119
- medium: { width: 720, height: 540 },
120
- large: { width: 1080, height: 810 }
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', 'ean-13'],
144
+ codeTypes: ['qr'],
132
145
  onCodeScanned: (codes: any[]) => {
133
- const result = codes.map(code => code.value).join(',')
134
- bindscancode && bindscancode(getCustomEvent('scancode', {}, {
135
- detail: {
136
- result: codes.map(code => code.value).join(',')
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
- let isTimeout = false
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
- if (navigation) {
256
- if (navigation && !navigation.camera) {
257
- navigation.camera = camera
258
- } else {
259
- hasCamera.current = true
260
- navigation.camera.multi = true
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 && navigation.camera) {
279
- navigation.camera = null
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: true,
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 (!hasPermission || hasCamera.current || !device) {
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
- scrollToOffset(left, top, animated)
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
- const refs = __selectRef!(`#${selector}`, 'node')
308
- if (!refs) return
309
- const { nodeRef } = refs.getNodeInstance()
310
- nodeRef.current?.measureLayout(
311
- scrollViewRef.current,
312
- (left: number, top: number) => {
313
- const adjustedLeft = scrollX ? left + offset : left
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
- }, [hasRefresher, enhanced, bounces, refreshing, refresherThreshold])
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 = (circular && children.length > 1) ? displayMultipleItems + 1 : 0
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 / displayMultipleItems
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 = (dir === 'x' ? realWidth : realHeight) / displayMultipleItems
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 frontClones = []
374
- // 计算补位序列的起始索引。例如 len=3, patch=2 -> start=1 (即从B开始)
375
- const startIndex = intLen - (patchElmNum % intLen)
376
- for (let i = 0; i < patchElmNum; i++) {
377
- const sourceIndex = (startIndex + i) % intLen
378
- frontClones.push(React.cloneElement(children[sourceIndex], { key: `clone_front_${i}` }))
379
- }
380
- // 动态生成后置补位元素
381
- const backClones = []
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 - displayMultipleItemsShared.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 || patchElmNum !== patchElmNumShared.value || displayMultipleItems !== displayMultipleItemsShared.value) {
573
+ if (circular !== circularShared.value) {
592
574
  circularShared.value = circular
593
- patchElmNumShared.value = patchElmNum
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, patchElmNum, displayMultipleItems])
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
- const maxIndex = Math.max(0, childrenLength.value - displayMultipleItemsShared.value)
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 - displayMultipleItemsShared.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 - displayMultipleItemsShared.value) * step.value : 0
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, EXTEND_COMPONENT_CONFIG } = require('../utils/const')
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] || isExtendComponentNode(el)
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 && !isExtendComponentNode(el)
2443
+ return !isComponentNode(el) && isRealNode(el) && !el.isBuiltIn
2448
2444
  }
2449
2445
 
2450
2446
  function processExternalClasses (el, options) {
@@ -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
  }