@mpxjs/webpack-plugin 2.10.4-beta.19-input → 2.10.4-beta.19-input1

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 (34) hide show
  1. package/lib/runtime/components/react/dist/getInnerListeners.js +22 -36
  2. package/lib/runtime/components/react/dist/mpx-button.jsx +2 -7
  3. package/lib/runtime/components/react/dist/mpx-canvas/Image.js +4 -2
  4. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +17 -20
  5. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -7
  6. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +2 -7
  7. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +2 -7
  8. package/lib/runtime/components/react/dist/mpx-image.jsx +20 -33
  9. package/lib/runtime/components/react/dist/mpx-input.jsx +9 -14
  10. package/lib/runtime/components/react/dist/mpx-label.jsx +2 -7
  11. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +3 -8
  12. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +79 -205
  13. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +13 -11
  14. package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +7 -8
  15. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +11 -29
  16. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +5 -3
  17. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +2 -9
  18. package/lib/runtime/components/react/dist/mpx-radio.jsx +2 -7
  19. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +2 -10
  20. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +51 -104
  21. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +1 -3
  22. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +9 -11
  23. package/lib/runtime/components/react/dist/mpx-swiper.jsx +141 -203
  24. package/lib/runtime/components/react/dist/mpx-switch.jsx +2 -7
  25. package/lib/runtime/components/react/dist/mpx-text.jsx +2 -7
  26. package/lib/runtime/components/react/dist/mpx-video.jsx +2 -7
  27. package/lib/runtime/components/react/dist/mpx-view.jsx +26 -28
  28. package/lib/runtime/components/react/dist/mpx-web-view.jsx +29 -34
  29. package/lib/runtime/components/react/dist/useAnimationHooks.js +89 -12
  30. package/lib/runtime/components/react/dist/utils.jsx +114 -199
  31. package/package.json +1 -1
  32. package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +0 -145
  33. package/lib/runtime/components/react/dist/mpx-progress.jsx +0 -163
  34. package/lib/runtime/components/react/dist/mpx-slider.jsx +0 -321
@@ -4,8 +4,8 @@
4
4
  * ✔ out-of-bounds
5
5
  * ✔ x
6
6
  * ✔ y
7
- * damping
8
- * friction
7
+ * damping
8
+ * friction
9
9
  * ✔ disabled
10
10
  * ✘ scale
11
11
  * ✘ scale-min
@@ -22,98 +22,10 @@ import { StyleSheet } from 'react-native';
22
22
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
23
23
  import useNodesRef from './useNodesRef';
24
24
  import { MovableAreaContext } from './context';
25
- import { useTransformStyle, splitProps, splitStyle, HIDDEN_STYLE, wrapChildren, flatGesture, extendObject, omit, useNavigation, useRunOnJSCallback } from './utils';
25
+ import { useTransformStyle, splitProps, splitStyle, HIDDEN_STYLE, wrapChildren, flatGesture, extendObject, omit, useNavigation } from './utils';
26
26
  import { GestureDetector, Gesture } from 'react-native-gesture-handler';
27
- import Animated, { useSharedValue, useAnimatedStyle, runOnJS, runOnUI, withTiming, Easing } from 'react-native-reanimated';
27
+ import Animated, { useSharedValue, useAnimatedStyle, withDecay, runOnJS, runOnUI, useAnimatedReaction, withSpring } from 'react-native-reanimated';
28
28
  import { collectDataset, noop } from '@mpxjs/utils';
29
- // 超出边界处理函数,参考微信小程序的超出边界衰减效果
30
- const applyBoundaryDecline = (newValue, range) => {
31
- 'worklet';
32
- const decline = (distance) => {
33
- 'worklet';
34
- return Math.sqrt(Math.abs(distance));
35
- };
36
- if (newValue < range[0]) {
37
- const overDistance = range[0] - newValue;
38
- return range[0] - decline(overDistance);
39
- }
40
- else if (newValue > range[1]) {
41
- const overDistance = newValue - range[1];
42
- return range[1] + decline(overDistance);
43
- }
44
- return newValue;
45
- };
46
- // 参考微信小程序的弹簧阻尼系统实现
47
- const withWechatSpring = (toValue, dampingParam = 20, callback) => {
48
- 'worklet';
49
- // 弹簧参数计算
50
- const m = 1; // 质量
51
- const k = 9 * Math.pow(dampingParam, 2) / 40; // 弹簧系数
52
- const c = dampingParam; // 阻尼系数
53
- // 判别式:r = c² - 4mk
54
- const discriminant = c * c - 4 * m * k;
55
- // 计算动画持续时间和缓动函数
56
- let duration;
57
- let easingFunction;
58
- if (Math.abs(discriminant) < 0.01) {
59
- // 临界阻尼 (discriminant ≈ 0)
60
- // 使用cubic-out模拟临界阻尼的平滑过渡
61
- duration = Math.max(350, Math.min(800, 2000 / dampingParam));
62
- easingFunction = Easing.out(Easing.cubic);
63
- }
64
- else if (discriminant > 0) {
65
- // 过阻尼 (discriminant > 0)
66
- // 使用指数缓动模拟过阻尼的缓慢收敛
67
- duration = Math.max(450, Math.min(1000, 2500 / dampingParam));
68
- easingFunction = Easing.out(Easing.exp);
69
- }
70
- else {
71
- // 欠阻尼 (discriminant < 0) - 会产生振荡
72
- // 计算振荡频率和衰减率
73
- const dampingRatio = c / (2 * Math.sqrt(m * k)); // 阻尼比
74
- // 根据阻尼比调整动画参数
75
- if (dampingRatio < 0.7) {
76
- // 明显振荡
77
- duration = Math.max(600, Math.min(1200, 3000 / dampingParam));
78
- // 创建带振荡的贝塞尔曲线
79
- easingFunction = Easing.bezier(0.175, 0.885, 0.32, 1.275);
80
- }
81
- else {
82
- // 轻微振荡
83
- duration = Math.max(400, Math.min(800, 2000 / dampingParam));
84
- easingFunction = Easing.bezier(0.25, 0.46, 0.45, 0.94);
85
- }
86
- }
87
- return withTiming(toValue, {
88
- duration,
89
- easing: easingFunction
90
- }, callback);
91
- };
92
- // 参考微信小程序friction的惯性动画
93
- const withWechatDecay = (velocity, currentPosition, clampRange, frictionValue = 2, callback) => {
94
- 'worklet';
95
- // 微信小程序friction算法: delta = -1.5 * v² / a, 其中 a = -f * v / |v|
96
- // 如果friction小于等于0,设置为默认值2
97
- const validFriction = frictionValue <= 0 ? 2 : frictionValue;
98
- const f = 1000 * validFriction;
99
- const acceleration = velocity !== 0 ? -f * velocity / Math.abs(velocity) : 0;
100
- const delta = acceleration !== 0 ? (-1.5 * velocity * velocity) / acceleration : 0;
101
- let finalPosition = currentPosition + delta;
102
- // 边界限制
103
- if (finalPosition < clampRange[0]) {
104
- finalPosition = clampRange[0];
105
- }
106
- else if (finalPosition > clampRange[1]) {
107
- finalPosition = clampRange[1];
108
- }
109
- // 计算动画时长
110
- const distance = Math.abs(finalPosition - currentPosition);
111
- const duration = Math.min(1500, Math.max(200, distance * 8));
112
- return withTiming(finalPosition, {
113
- duration,
114
- easing: Easing.out(Easing.cubic)
115
- }, callback);
116
- };
117
29
  const styles = StyleSheet.create({
118
30
  container: {
119
31
  position: 'absolute',
@@ -129,7 +41,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
129
41
  const hasLayoutRef = useRef(false);
130
42
  const propsRef = useRef({});
131
43
  propsRef.current = (props || {});
132
- const { x = 0, y = 0, inertia = false, disabled = false, animation = true, damping = 20, friction = 2, 'out-of-bounds': outOfBounds = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, direction = 'none', 'disable-event-passthrough': disableEventPassthrough = false, 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, changeThrottleTime = 60, bindtouchstart, catchtouchstart, bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove, bindtouchend, catchtouchend, bindchange } = props;
44
+ const { x = 0, y = 0, inertia = false, disabled = false, animation = true, 'out-of-bounds': outOfBounds = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, direction = 'none', 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, bindtouchstart, catchtouchstart, bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove, bindtouchend, catchtouchend } = props;
133
45
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(Object.assign({}, style, styles.container), { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
134
46
  const navigation = useNavigation();
135
47
  const prevSimultaneousHandlersRef = useRef(originSimultaneousHandlers || []);
@@ -149,8 +61,6 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
149
61
  const yInertialMotion = useSharedValue(false);
150
62
  const isFirstTouch = useSharedValue(true);
151
63
  const touchEvent = useSharedValue('');
152
- const initialViewPosition = useSharedValue({ x: x || 0, y: y || 0 });
153
- const lastChangeTime = useSharedValue(0);
154
64
  const MovableAreaLayout = useContext(MovableAreaContext);
155
65
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
156
66
  const waitForHandlers = flatGesture(waitFor);
@@ -194,21 +104,25 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
194
104
  const { x: newX, y: newY } = checkBoundaryPosition({ positionX: Number(x), positionY: Number(y) });
195
105
  if (direction === 'horizontal' || direction === 'all') {
196
106
  offsetX.value = animation
197
- ? withWechatSpring(newX, damping)
107
+ ? withSpring(newX, {
108
+ duration: 1500,
109
+ dampingRatio: 0.8
110
+ })
198
111
  : newX;
199
112
  }
200
113
  if (direction === 'vertical' || direction === 'all') {
201
114
  offsetY.value = animation
202
- ? withWechatSpring(newY, damping)
115
+ ? withSpring(newY, {
116
+ duration: 1500,
117
+ dampingRatio: 0.8
118
+ })
203
119
  : newY;
204
120
  }
205
- if (bindchange) {
206
- runOnJS(runOnJSCallback)('handleTriggerChange', {
207
- x: newX,
208
- y: newY,
209
- type: 'setData'
210
- });
211
- }
121
+ runOnJS(handleTriggerChange)({
122
+ x: newX,
123
+ y: newY,
124
+ type: 'setData'
125
+ });
212
126
  }
213
127
  })();
214
128
  }, [x, y]);
@@ -218,6 +132,16 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
218
132
  resetBoundaryAndCheck({ width, height });
219
133
  }
220
134
  }, [MovableAreaLayout.height, MovableAreaLayout.width]);
135
+ useAnimatedReaction(() => ({
136
+ offsetX: offsetX.value,
137
+ offsetY: offsetY.value
138
+ }), (currentValue) => {
139
+ const { offsetX, offsetY } = currentValue;
140
+ runOnJS(handleTriggerChange)({
141
+ x: offsetX,
142
+ y: offsetY
143
+ });
144
+ });
221
145
  const getTouchSource = useCallback((offsetX, offsetY) => {
222
146
  const hasOverBoundary = offsetX < draggableXRange.value[0] || offsetX > draggableXRange.value[1] ||
223
147
  offsetY < draggableYRange.value[0] || offsetY > draggableYRange.value[1];
@@ -306,14 +230,14 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
306
230
  setHeight(height || 0);
307
231
  }
308
232
  nodeRef.current?.measure((x, y, width, height) => {
309
- const { top: navigationY = 0 } = navigation?.layout || {};
233
+ const { y: navigationY = 0 } = navigation?.layout || {};
310
234
  layoutRef.current = { x, y: y - navigationY, width, height, offsetLeft: 0, offsetTop: 0 };
311
235
  resetBoundaryAndCheck({ width, height });
312
236
  });
313
237
  props.onLayout && props.onLayout(e);
314
238
  };
315
239
  const extendEvent = useCallback((e, type) => {
316
- const { top: navigationY = 0 } = navigation?.layout || {};
240
+ const { y: navigationY = 0 } = navigation?.layout || {};
317
241
  const touchArr = [e.changedTouches, e.allTouches];
318
242
  touchArr.forEach(touches => {
319
243
  touches && touches.forEach((item) => {
@@ -335,13 +259,11 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
335
259
  });
336
260
  }, []);
337
261
  const triggerStartOnJS = ({ e }) => {
338
- const { bindtouchstart, catchtouchstart } = propsRef.current;
339
262
  extendEvent(e, 'start');
340
263
  bindtouchstart && bindtouchstart(e);
341
264
  catchtouchstart && catchtouchstart(e);
342
265
  };
343
266
  const triggerMoveOnJS = ({ e, hasTouchmove, hasCatchTouchmove, touchEvent }) => {
344
- const { bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove } = propsRef.current;
345
267
  extendEvent(e, 'move');
346
268
  if (hasTouchmove) {
347
269
  if (touchEvent === 'htouchmove') {
@@ -363,34 +285,17 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
363
285
  }
364
286
  };
365
287
  const triggerEndOnJS = ({ e }) => {
366
- const { bindtouchend, catchtouchend } = propsRef.current;
367
288
  extendEvent(e, 'end');
368
289
  bindtouchend && bindtouchend(e);
369
290
  catchtouchend && catchtouchend(e);
370
291
  };
371
- const runOnJSCallbackRef = useRef({
372
- handleTriggerChange,
373
- triggerStartOnJS,
374
- triggerMoveOnJS,
375
- triggerEndOnJS
376
- });
377
- const runOnJSCallback = useRunOnJSCallback(runOnJSCallbackRef);
378
- // 节流版本的change事件触发
379
- const handleTriggerChangeThrottled = useCallback(({ x, y, type }) => {
380
- 'worklet';
381
- const now = Date.now();
382
- if (now - lastChangeTime.value >= changeThrottleTime) {
383
- lastChangeTime.value = now;
384
- runOnJS(runOnJSCallback)('handleTriggerChange', { x, y, type });
385
- }
386
- }, [changeThrottleTime]);
387
292
  const gesture = useMemo(() => {
388
293
  const handleTriggerMove = (e) => {
389
294
  'worklet';
390
295
  const hasTouchmove = !!bindhtouchmove || !!bindvtouchmove || !!bindtouchmove;
391
296
  const hasCatchTouchmove = !!catchhtouchmove || !!catchvtouchmove || !!catchtouchmove;
392
297
  if (hasTouchmove || hasCatchTouchmove) {
393
- runOnJS(runOnJSCallback)('triggerMoveOnJS', {
298
+ runOnJS(triggerMoveOnJS)({
394
299
  e,
395
300
  touchEvent: touchEvent.value,
396
301
  hasTouchmove,
@@ -408,15 +313,8 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
408
313
  y: changedTouches.y
409
314
  };
410
315
  if (bindtouchstart || catchtouchstart) {
411
- runOnJS(runOnJSCallback)('triggerStartOnJS', { e });
316
+ runOnJS(triggerStartOnJS)({ e });
412
317
  }
413
- })
414
- .onStart(() => {
415
- 'worklet';
416
- initialViewPosition.value = {
417
- x: offsetX.value,
418
- y: offsetY.value
419
- };
420
318
  })
421
319
  .onTouchesMove((e) => {
422
320
  'worklet';
@@ -427,111 +325,87 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
427
325
  isFirstTouch.value = false;
428
326
  }
429
327
  handleTriggerMove(e);
430
- })
431
- .onUpdate((e) => {
432
- 'worklet';
433
328
  if (disabled)
434
329
  return;
330
+ const changeX = changedTouches.x - startPosition.value.x;
331
+ const changeY = changedTouches.y - startPosition.value.y;
435
332
  if (direction === 'horizontal' || direction === 'all') {
436
- const newX = initialViewPosition.value.x + e.translationX;
333
+ const newX = offsetX.value + changeX;
437
334
  if (!outOfBounds) {
438
335
  const { x } = checkBoundaryPosition({ positionX: newX, positionY: offsetY.value });
439
336
  offsetX.value = x;
440
337
  }
441
338
  else {
442
- offsetX.value = applyBoundaryDecline(newX, draggableXRange.value);
339
+ offsetX.value = newX;
443
340
  }
444
341
  }
445
342
  if (direction === 'vertical' || direction === 'all') {
446
- const newY = initialViewPosition.value.y + e.translationY;
343
+ const newY = offsetY.value + changeY;
447
344
  if (!outOfBounds) {
448
345
  const { y } = checkBoundaryPosition({ positionX: offsetX.value, positionY: newY });
449
346
  offsetY.value = y;
450
347
  }
451
348
  else {
452
- offsetY.value = applyBoundaryDecline(newY, draggableYRange.value);
349
+ offsetY.value = newY;
453
350
  }
454
351
  }
455
- if (bindchange) {
456
- // 使用节流版本减少 runOnJS 调用
457
- handleTriggerChangeThrottled({
458
- x: offsetX.value,
459
- y: offsetY.value
460
- });
461
- }
462
352
  })
463
353
  .onTouchesUp((e) => {
464
354
  'worklet';
465
355
  isFirstTouch.value = true;
466
356
  isMoving.value = false;
467
357
  if (bindtouchend || catchtouchend) {
468
- runOnJS(runOnJSCallback)('triggerEndOnJS', { e });
358
+ runOnJS(triggerEndOnJS)({ e });
469
359
  }
470
- })
471
- .onEnd((e) => {
472
- 'worklet';
473
- isMoving.value = false;
474
360
  if (disabled)
475
361
  return;
476
- // 处理没有惯性且超出边界的回弹
477
- if (!inertia && outOfBounds) {
362
+ if (!inertia) {
478
363
  const { x, y } = checkBoundaryPosition({ positionX: offsetX.value, positionY: offsetY.value });
479
- if (x !== offsetX.value || y !== offsetY.value) {
480
- if (x !== offsetX.value) {
481
- offsetX.value = animation
482
- ? withWechatSpring(x, damping)
483
- : x;
484
- }
485
- if (y !== offsetY.value) {
486
- offsetY.value = animation
487
- ? withWechatSpring(y, damping)
488
- : y;
489
- }
490
- if (bindchange) {
491
- runOnJS(runOnJSCallback)('handleTriggerChange', {
492
- x,
493
- y
494
- });
495
- }
496
- }
497
- }
498
- else if (inertia) {
499
- // 惯性处理 - 使用微信小程序friction算法
500
- if (direction === 'horizontal' || direction === 'all') {
501
- xInertialMotion.value = true;
502
- offsetX.value = withWechatDecay(e.velocityX / 10, offsetX.value, draggableXRange.value, friction, () => {
503
- xInertialMotion.value = false;
504
- if (bindchange) {
505
- runOnJS(runOnJSCallback)('handleTriggerChange', {
506
- x: offsetX.value,
507
- y: offsetY.value
508
- });
509
- }
510
- });
364
+ if (x !== offsetX.value) {
365
+ offsetX.value = animation
366
+ ? withSpring(x, {
367
+ duration: 1500,
368
+ dampingRatio: 0.8
369
+ })
370
+ : x;
511
371
  }
512
- if (direction === 'vertical' || direction === 'all') {
513
- yInertialMotion.value = true;
514
- offsetY.value = withWechatDecay(e.velocityY / 10, offsetY.value, draggableYRange.value, friction, () => {
515
- yInertialMotion.value = false;
516
- if (bindchange) {
517
- runOnJS(runOnJSCallback)('handleTriggerChange', {
518
- x: offsetX.value,
519
- y: offsetY.value
520
- });
521
- }
522
- });
372
+ if (y !== offsetY.value) {
373
+ offsetY.value = animation
374
+ ? withSpring(y, {
375
+ duration: 1500,
376
+ dampingRatio: 0.8
377
+ })
378
+ : y;
523
379
  }
524
380
  }
525
381
  })
526
- .withRef(movableGestureRef);
527
- if (!disableEventPassthrough) {
528
- if (direction === 'horizontal') {
529
- gesturePan.activeOffsetX([-5, 5]).failOffsetY([-5, 5]);
382
+ .onFinalize((e) => {
383
+ 'worklet';
384
+ isMoving.value = false;
385
+ if (!inertia || disabled || !animation)
386
+ return;
387
+ if (direction === 'horizontal' || direction === 'all') {
388
+ xInertialMotion.value = true;
389
+ offsetX.value = withDecay({
390
+ velocity: e.velocityX / 10,
391
+ rubberBandEffect: outOfBounds,
392
+ clamp: draggableXRange.value
393
+ }, () => {
394
+ xInertialMotion.value = false;
395
+ });
530
396
  }
531
- else if (direction === 'vertical') {
532
- gesturePan.activeOffsetY([-5, 5]).failOffsetX([-5, 5]);
397
+ if (direction === 'vertical' || direction === 'all') {
398
+ yInertialMotion.value = true;
399
+ offsetY.value = withDecay({
400
+ velocity: e.velocityY / 10,
401
+ rubberBandEffect: outOfBounds,
402
+ clamp: draggableYRange.value
403
+ }, () => {
404
+ yInertialMotion.value = false;
405
+ });
533
406
  }
534
- }
407
+ })
408
+ .withRef(movableGestureRef);
535
409
  if (simultaneousHandlers && simultaneousHandlers.length) {
536
410
  gesturePan.simultaneousWithExternalGesture(...simultaneousHandlers);
537
411
  }
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, useRef, useContext, useEffect, createElement } from 'react';
1
+ import React, { forwardRef, useRef, useContext, useEffect } from 'react';
2
2
  import { StyleSheet, Text, TouchableWithoutFeedback, View } from 'react-native';
3
3
  import { warn } from '@mpxjs/utils';
4
4
  import PickerSelector from './selector';
@@ -9,7 +9,7 @@ import PickerRegion from './region';
9
9
  import { FormContext, RouteContext } from '../context';
10
10
  import useNodesRef from '../useNodesRef';
11
11
  import useInnerProps, { getCustomEvent } from '../getInnerListeners';
12
- import { extendObject, useLayout } from '../utils';
12
+ import { extendObject } from '../utils';
13
13
  import { createPopupManager } from '../mpx-popup';
14
14
  /**
15
15
  * ✔ mode
@@ -109,18 +109,17 @@ const Picker = forwardRef((props, ref) => {
109
109
  const buttonText = buttonTextMap[global.__mpx?.i18n?.locale || 'zh-CN'];
110
110
  const pickerValue = useRef(value);
111
111
  pickerValue.current = Array.isArray(value) ? value.slice() : value;
112
+ const innerLayout = useRef({});
112
113
  const nodeRef = useRef(null);
113
114
  const pickerRef = useRef(null);
114
115
  const { open, show, hide, remove } = useRef(createPopupManager()).current;
115
116
  useNodesRef(props, ref, nodeRef);
116
- const { layoutRef, layoutProps } = useLayout({
117
- props,
118
- hasSelfPercent: false,
119
- nodeRef
120
- });
121
117
  const innerProps = useInnerProps(extendObject({}, props, {
122
118
  ref: nodeRef
123
- }, layoutProps), [], { layoutRef });
119
+ }), [], { layoutRef: innerLayout });
120
+ const getInnerLayout = (layout) => {
121
+ innerLayout.current = layout.current;
122
+ };
124
123
  useEffect(() => {
125
124
  if (range && pickerRef.current && mode === "multiSelector" /* PickerMode.MULTI_SELECTOR */) {
126
125
  pickerRef.current.updateRange?.(range);
@@ -163,7 +162,7 @@ const Picker = forwardRef((props, ref) => {
163
162
  if (mode !== "multiSelector" /* PickerMode.MULTI_SELECTOR */) {
164
163
  return;
165
164
  }
166
- const eventData = getCustomEvent('columnchange', {}, { detail: { column: columnIndex, value }, layoutRef });
165
+ const eventData = getCustomEvent('columnchange', {}, { detail: { column: columnIndex, value }, layoutRef: innerLayout });
167
166
  props.bindcolumnchange?.(eventData);
168
167
  };
169
168
  const onCancel = () => {
@@ -171,7 +170,7 @@ const Picker = forwardRef((props, ref) => {
171
170
  hide();
172
171
  };
173
172
  const onConfirm = () => {
174
- const eventData = getCustomEvent('change', {}, { detail: { value: pickerValue.current }, layoutRef });
173
+ const eventData = getCustomEvent('change', {}, { detail: { value: pickerValue.current }, layoutRef: innerLayout });
175
174
  bindchange?.(eventData);
176
175
  hide();
177
176
  };
@@ -180,6 +179,7 @@ const Picker = forwardRef((props, ref) => {
180
179
  children,
181
180
  bindchange: onChange,
182
181
  bindcolumnchange: onColumnChange,
182
+ getInnerLayout,
183
183
  getRange: () => range
184
184
  });
185
185
  const renderPickerContent = () => {
@@ -215,7 +215,9 @@ const Picker = forwardRef((props, ref) => {
215
215
  remove();
216
216
  };
217
217
  }, []);
218
- return createElement(TouchableWithoutFeedback, { onPress: show }, createElement(View, innerProps, children));
218
+ return (<TouchableWithoutFeedback onPress={show}>
219
+ {children}
220
+ </TouchableWithoutFeedback>);
219
221
  });
220
222
  Picker.displayName = 'MpxPicker';
221
223
  export default Picker;
@@ -1,10 +1,9 @@
1
1
  import { View } from 'react-native';
2
- import React, { createElement, forwardRef, useRef } from 'react';
2
+ import React, { forwardRef, useRef } from 'react';
3
3
  import useInnerProps, { getCustomEvent } from '../getInnerListeners';
4
4
  import useNodesRef from '../useNodesRef';
5
5
  import { useLayout, splitProps, splitStyle, wrapChildren, useTransformStyle, extendObject } from '../utils';
6
6
  import { PickerViewStyleContext } from './pickerVIewContext';
7
- import Portal from '../mpx-portal';
8
7
  const styles = {
9
8
  wrapper: {
10
9
  display: 'flex',
@@ -24,7 +23,7 @@ const _PickerView = forwardRef((props, ref) => {
24
23
  const activeValueRef = useRef(value);
25
24
  activeValueRef.current = value.slice();
26
25
  const snapActiveValueRef = useRef(null);
27
- const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight, hasPositionFixed } = useTransformStyle(style, { enableVar, externalVarContext });
26
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
28
27
  useNodesRef(props, ref, nodeRef, {
29
28
  style: normalStyle
30
29
  });
@@ -115,11 +114,11 @@ const _PickerView = forwardRef((props, ref) => {
115
114
  onInitialChange(isInvalid, validValue);
116
115
  return renderColumns;
117
116
  };
118
- const finalComponent = createElement(PickerViewStyleContext.Provider, { value: textStyle }, createElement(View, innerProps, createElement(View, { style: [styles.wrapper] }, renderPickerColumns())));
119
- if (hasPositionFixed) {
120
- return createElement(Portal, null, finalComponent);
121
- }
122
- return finalComponent;
117
+ return (<PickerViewStyleContext.Provider value={textStyle}>
118
+ <View {...innerProps}>
119
+ <View style={[styles.wrapper]}>{renderPickerColumns()}</View>
120
+ </View>
121
+ </PickerViewStyleContext.Provider>);
123
122
  });
124
123
  _PickerView.displayName = 'MpxPickerView';
125
124
  export default _PickerView;
@@ -1,7 +1,7 @@
1
- import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback, createElement } from 'react';
1
+ import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
3
  import Reanimated, { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
4
- import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS, isHarmony, extendObject } from '../utils';
4
+ import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS, isHarmony } from '../utils';
5
5
  import useNodesRef from '../useNodesRef';
6
6
  import PickerIndicator from './pickerViewIndicator';
7
7
  import PickerMask from './pickerViewMask';
@@ -157,8 +157,8 @@ const _PickerViewColumn = forwardRef((props, ref) => {
157
157
  }, [itemRawH, maxIndex, snapToOffsets, onMomentumScrollEnd, resetScrollPosition]);
158
158
  const onScroll = useCallback((e) => {
159
159
  // 全局注册的振动触感 hook
160
- const onPickerVibrate = global.__mpx?.config?.rnConfig?.onPickerVibrate;
161
- if (typeof onPickerVibrate !== 'function') {
160
+ const pickerVibrate = global.__mpx?.config?.rnConfig?.pickerVibrate;
161
+ if (typeof pickerVibrate !== 'function') {
162
162
  return;
163
163
  }
164
164
  const { y } = e.nativeEvent.contentOffset;
@@ -172,7 +172,7 @@ const _PickerViewColumn = forwardRef((props, ref) => {
172
172
  y: currentId * itemRawH
173
173
  };
174
174
  // vibrateShort({ type: 'selection' })
175
- onPickerVibrate();
175
+ pickerVibrate();
176
176
  }
177
177
  }
178
178
  }
@@ -220,28 +220,11 @@ const _PickerViewColumn = forwardRef((props, ref) => {
220
220
  return (<MpxPickerVIewColumnItem key={index} item={item} index={index} itemHeight={itemHeight} textStyle={textStyle} textProps={textProps} visibleCount={visibleCount} onItemLayout={onItemLayout}/>);
221
221
  });
222
222
  const renderScollView = () => {
223
- const innerProps = extendObject({}, layoutProps, {
224
- ref: scrollViewRef,
225
- bounces: true,
226
- horizontal: false,
227
- nestedScrollEnabled: true,
228
- removeClippedSubviews: false,
229
- showsVerticalScrollIndicator: false,
230
- showsHorizontalScrollIndicator: false,
231
- scrollEventThrottle: 16,
232
- style: styles.scrollView,
233
- decelerationRate: 'fast',
234
- snapToOffsets: snapToOffsets,
235
- onTouchEnd: onClickOnceItem,
236
- onScroll,
237
- onScrollBeginDrag,
238
- onScrollEndDrag,
239
- onMomentumScrollBegin,
240
- onMomentumScrollEnd,
241
- onContentSizeChange,
242
- contentContainerStyle
243
- });
244
- return createElement(PickerViewColumnAnimationContext.Provider, { value: offsetYShared }, createElement(Reanimated.ScrollView, innerProps, renderInnerchild()));
223
+ return (<PickerViewColumnAnimationContext.Provider value={offsetYShared}>
224
+ <Reanimated.ScrollView ref={scrollViewRef} bounces={true} horizontal={false} nestedScrollEnabled={true} removeClippedSubviews={false} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} scrollEventThrottle={16} {...layoutProps} onTouchEnd={onClickOnceItem} style={[{ width: '100%' }]} decelerationRate="fast" snapToOffsets={snapToOffsets} onScroll={onScroll} onScrollBeginDrag={onScrollBeginDrag} onScrollEndDrag={onScrollEndDrag} onMomentumScrollBegin={onMomentumScrollBegin} onMomentumScrollEnd={onMomentumScrollEnd} onContentSizeChange={onContentSizeChange} contentContainerStyle={contentContainerStyle}>
225
+ {renderInnerchild()}
226
+ </Reanimated.ScrollView>
227
+ </PickerViewColumnAnimationContext.Provider>);
245
228
  };
246
229
  const renderIndicator = () => (<PickerIndicator itemHeight={itemHeight} indicatorItemStyle={pickerIndicatorStyle}/>);
247
230
  const renderMask = () => (<PickerMask itemHeight={itemHeight} maskContainerStyle={pickerMaskStyle}/>);
@@ -252,8 +235,7 @@ const _PickerViewColumn = forwardRef((props, ref) => {
252
235
  </View>);
253
236
  });
254
237
  const styles = StyleSheet.create({
255
- wrapper: { display: 'flex', flex: 1 },
256
- scrollView: { width: '100%' }
238
+ wrapper: { display: 'flex', flex: 1 }
257
239
  });
258
240
  _PickerViewColumn.displayName = 'MpxPickerViewColumn';
259
241
  export default _PickerViewColumn;
@@ -1,4 +1,5 @@
1
- import { useState, useCallback, forwardRef, useImperativeHandle, Fragment } from 'react';
1
+ import { useState, useCallback, forwardRef, useImperativeHandle } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
2
3
  const _PortalManager = forwardRef((props, ref) => {
3
4
  const [state, setState] = useState({
4
5
  portals: []
@@ -30,9 +31,10 @@ const _PortalManager = forwardRef((props, ref) => {
30
31
  portals: state.portals
31
32
  }));
32
33
  return (<>
33
- {state.portals.map(({ key, children }) => (<Fragment key={key}>
34
+ {state.portals.map(({ key, children }, i) => (<View key={key} collapsable={false} // Need collapsable=false here to clip the elevations
35
+ style={[StyleSheet.absoluteFill, { zIndex: 1000 + i, pointerEvents: 'box-none' }]}>
34
36
  {children}
35
- </Fragment>))}
37
+ </View>))}
36
38
  </>);
37
39
  });
38
40
  export default _PortalManager;
@@ -8,7 +8,6 @@ import { FormContext, RadioGroupContext } from './context';
8
8
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
9
9
  import useNodesRef from './useNodesRef';
10
10
  import { useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
11
- import Portal from './mpx-portal';
12
11
  const radioGroup = forwardRef((props, ref) => {
13
12
  const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
14
13
  const propsRef = useRef({});
@@ -24,7 +23,7 @@ const radioGroup = forwardRef((props, ref) => {
24
23
  flexWrap: 'wrap'
25
24
  };
26
25
  const styleObj = extendObject({}, defaultStyle, style);
27
- const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
26
+ const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
28
27
  const nodeRef = useRef(null);
29
28
  useNodesRef(props, ref, nodeRef, { style: normalStyle });
30
29
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
@@ -78,16 +77,10 @@ const radioGroup = forwardRef((props, ref) => {
78
77
  }), ['name'], {
79
78
  layoutRef
80
79
  });
81
- const finalComponent = createElement(View, innerProps, createElement(RadioGroupContext.Provider, {
82
- value: contextValue
83
- }, wrapChildren(props, {
80
+ return createElement(View, innerProps, createElement(RadioGroupContext.Provider, { value: contextValue }, wrapChildren(props, {
84
81
  hasVarDec,
85
82
  varContext: varContextRef.current
86
83
  })));
87
- if (hasPositionFixed) {
88
- return createElement(Portal, null, finalComponent);
89
- }
90
- return finalComponent;
91
84
  });
92
85
  radioGroup.displayName = 'MpxRadioGroup';
93
86
  export default radioGroup;