@mpxjs/webpack-plugin 2.10.5 → 2.10.6-beta.1

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 (81) hide show
  1. package/lib/index.js +16 -6
  2. package/lib/json-compiler/helper.js +1 -4
  3. package/lib/platform/json/wx/index.js +0 -1
  4. package/lib/platform/template/wx/component-config/button.js +1 -1
  5. package/lib/platform/template/wx/component-config/index.js +5 -1
  6. package/lib/platform/template/wx/component-config/input.js +1 -1
  7. package/lib/platform/template/wx/component-config/sticky-header.js +23 -0
  8. package/lib/platform/template/wx/component-config/sticky-section.js +23 -0
  9. package/lib/platform/template/wx/index.js +21 -1
  10. package/lib/react/processJSON.js +7 -6
  11. package/lib/resolver/PackageEntryPlugin.js +3 -1
  12. package/lib/runtime/components/react/context.ts +12 -3
  13. package/lib/runtime/components/react/dist/context.js +4 -1
  14. package/lib/runtime/components/react/dist/mpx-button.jsx +9 -4
  15. package/lib/runtime/components/react/dist/mpx-canvas/Image.js +2 -4
  16. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +20 -17
  17. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +7 -2
  18. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +7 -2
  19. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +7 -2
  20. package/lib/runtime/components/react/dist/mpx-image.jsx +9 -2
  21. package/lib/runtime/components/react/dist/mpx-input.jsx +7 -2
  22. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +1 -1
  23. package/lib/runtime/components/react/dist/mpx-label.jsx +7 -2
  24. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +8 -3
  25. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +100 -62
  26. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +11 -13
  27. package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +8 -7
  28. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +26 -8
  29. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +9 -2
  30. package/lib/runtime/components/react/dist/mpx-radio.jsx +7 -2
  31. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +7 -2
  32. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +30 -10
  33. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +115 -0
  34. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +45 -0
  35. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +11 -9
  36. package/lib/runtime/components/react/dist/mpx-swiper.jsx +82 -36
  37. package/lib/runtime/components/react/dist/mpx-switch.jsx +7 -2
  38. package/lib/runtime/components/react/dist/mpx-text.jsx +7 -2
  39. package/lib/runtime/components/react/dist/mpx-video.jsx +7 -2
  40. package/lib/runtime/components/react/dist/mpx-view.jsx +2 -4
  41. package/lib/runtime/components/react/dist/mpx-web-view.jsx +13 -13
  42. package/lib/runtime/components/react/dist/utils.jsx +14 -3
  43. package/lib/runtime/components/react/mpx-button.tsx +12 -3
  44. package/lib/runtime/components/react/mpx-canvas/Image.ts +4 -4
  45. package/lib/runtime/components/react/mpx-canvas/index.tsx +24 -17
  46. package/lib/runtime/components/react/mpx-checkbox-group.tsx +9 -1
  47. package/lib/runtime/components/react/mpx-checkbox.tsx +9 -1
  48. package/lib/runtime/components/react/mpx-icon/index.tsx +9 -1
  49. package/lib/runtime/components/react/mpx-image.tsx +38 -19
  50. package/lib/runtime/components/react/mpx-input.tsx +10 -1
  51. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +1 -1
  52. package/lib/runtime/components/react/mpx-label.tsx +9 -1
  53. package/lib/runtime/components/react/mpx-movable-area.tsx +8 -2
  54. package/lib/runtime/components/react/mpx-movable-view.tsx +100 -62
  55. package/lib/runtime/components/react/mpx-picker/index.tsx +18 -16
  56. package/lib/runtime/components/react/mpx-picker-view/index.tsx +22 -8
  57. package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +34 -30
  58. package/lib/runtime/components/react/mpx-radio-group.tsx +20 -9
  59. package/lib/runtime/components/react/mpx-radio.tsx +9 -1
  60. package/lib/runtime/components/react/mpx-rich-text/index.tsx +10 -2
  61. package/lib/runtime/components/react/mpx-scroll-view.tsx +82 -53
  62. package/lib/runtime/components/react/mpx-sticky-header.tsx +179 -0
  63. package/lib/runtime/components/react/mpx-sticky-section.tsx +96 -0
  64. package/lib/runtime/components/react/mpx-swiper-item.tsx +11 -19
  65. package/lib/runtime/components/react/mpx-swiper.tsx +95 -38
  66. package/lib/runtime/components/react/mpx-switch.tsx +10 -2
  67. package/lib/runtime/components/react/mpx-text.tsx +10 -2
  68. package/lib/runtime/components/react/mpx-video.tsx +7 -2
  69. package/lib/runtime/components/react/mpx-view.tsx +8 -4
  70. package/lib/runtime/components/react/mpx-web-view.tsx +12 -12
  71. package/lib/runtime/components/react/utils.tsx +16 -5
  72. package/lib/runtime/components/web/mpx-scroll-view.vue +21 -4
  73. package/lib/runtime/components/web/mpx-sticky-header.vue +91 -0
  74. package/lib/runtime/components/web/mpx-sticky-section.vue +15 -0
  75. package/lib/runtime/components/web/mpx-web-view.vue +1 -1
  76. package/lib/runtime/mpxGlobal.js +1 -0
  77. package/lib/runtime/optionProcessor.d.ts +5 -0
  78. package/lib/template-compiler/bind-this.js +8 -7
  79. package/lib/wxs/pre-loader.js +1 -0
  80. package/package.json +4 -4
  81. package/LICENSE +0 -433
@@ -44,6 +44,7 @@ import { useUpdateEffect, useTransformStyle, useLayout, extendObject, isIOS } fr
44
44
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
45
45
  import useNodesRef from './useNodesRef';
46
46
  import { FormContext, KeyboardAvoidContext } from './context';
47
+ import Portal from './mpx-portal';
47
48
  const keyboardTypeMap = {
48
49
  text: 'default',
49
50
  number: 'numeric',
@@ -83,7 +84,7 @@ const Input = forwardRef((props, ref) => {
83
84
  const styleObj = extendObject({ padding: 0, backgroundColor: '#fff' }, style, multiline && autoHeight
84
85
  ? { height: 'auto', minHeight: Math.max(style?.minHeight || 35, contentHeight) }
85
86
  : {});
86
- const { hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
87
+ const { hasPositionFixed, hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
87
88
  const nodeRef = useRef(null);
88
89
  useNodesRef(props, ref, nodeRef, {
89
90
  style: normalStyle
@@ -289,7 +290,11 @@ const Input = forwardRef((props, ref) => {
289
290
  ], {
290
291
  layoutRef
291
292
  });
292
- return createElement(TextInput, innerProps);
293
+ const finalComponent = createElement(TextInput, innerProps);
294
+ if (hasPositionFixed) {
295
+ return createElement(Portal, null, finalComponent);
296
+ }
297
+ return finalComponent;
293
298
  });
294
299
  Input.displayName = 'MpxInput';
295
300
  export default Input;
@@ -36,7 +36,7 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
36
36
  const { ref, cursorSpacing = 0 } = keyboardAvoid.current;
37
37
  setTimeout(() => {
38
38
  ref?.current?.measure((x, y, width, height, pageX, pageY) => {
39
- const aboveOffset = pageY + height - endCoordinates.screenY;
39
+ const aboveOffset = offset.value + pageY + height - endCoordinates.screenY;
40
40
  const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing;
41
41
  const belowValue = Math.min(endCoordinates.height, aboveOffset + cursorSpacing);
42
42
  const value = aboveOffset > 0 ? belowValue : aboveValue;
@@ -8,6 +8,7 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners';
8
8
  import useNodesRef from './useNodesRef';
9
9
  import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
10
10
  import { LabelContext } from './context';
11
+ import Portal from './mpx-portal';
11
12
  const Label = forwardRef((labelProps, ref) => {
12
13
  const { textProps, innerProps: props = {} } = splitProps(labelProps);
13
14
  const propsRef = useRef({});
@@ -17,7 +18,7 @@ const Label = forwardRef((labelProps, ref) => {
17
18
  flexDirection: 'row'
18
19
  };
19
20
  const styleObj = extendObject({}, defaultStyle, style);
20
- const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
21
+ const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
21
22
  const nodeRef = useRef(null);
22
23
  useNodesRef(props, ref, nodeRef, { style: normalStyle });
23
24
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
@@ -40,12 +41,16 @@ const Label = forwardRef((labelProps, ref) => {
40
41
  }), [], {
41
42
  layoutRef
42
43
  });
43
- return createElement(View, innerProps, createElement(LabelContext.Provider, { value: contextRef }, wrapChildren(props, {
44
+ const finalComponent = createElement(View, innerProps, createElement(LabelContext.Provider, { value: contextRef }, wrapChildren(props, {
44
45
  hasVarDec,
45
46
  varContext: varContextRef.current,
46
47
  textStyle,
47
48
  textProps
48
49
  })));
50
+ if (hasPositionFixed) {
51
+ return createElement(Portal, null, finalComponent);
52
+ }
53
+ return finalComponent;
49
54
  });
50
55
  Label.displayName = 'MpxLabel';
51
56
  export default Label;
@@ -7,9 +7,10 @@ import useNodesRef from './useNodesRef';
7
7
  import useInnerProps from './getInnerListeners';
8
8
  import { MovableAreaContext } from './context';
9
9
  import { useTransformStyle, wrapChildren, useLayout, extendObject } from './utils';
10
+ import Portal from './mpx-portal';
10
11
  const _MovableArea = forwardRef((props, ref) => {
11
12
  const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
12
- const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
13
+ const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, hasPositionFixed, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
13
14
  const movableViewRef = useRef(null);
14
15
  useNodesRef(props, ref, movableViewRef, {
15
16
  style: normalStyle
@@ -20,13 +21,17 @@ const _MovableArea = forwardRef((props, ref) => {
20
21
  }), [normalStyle.width, normalStyle.height]);
21
22
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: movableViewRef });
22
23
  const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
23
- style: extendObject({ height: contextValue.height, width: contextValue.width, overflow: 'hidden' }, normalStyle, layoutStyle),
24
+ style: extendObject({ height: contextValue.height, width: contextValue.width }, normalStyle, layoutStyle),
24
25
  ref: movableViewRef
25
26
  }), [], { layoutRef });
26
- return createElement(MovableAreaContext.Provider, { value: contextValue }, createElement(View, innerProps, wrapChildren(props, {
27
+ let movableComponent = createElement(MovableAreaContext.Provider, { value: contextValue }, createElement(View, innerProps, wrapChildren(props, {
27
28
  hasVarDec,
28
29
  varContext: varContextRef.current
29
30
  })));
31
+ if (hasPositionFixed) {
32
+ movableComponent = createElement(Portal, null, movableComponent);
33
+ }
34
+ return movableComponent;
30
35
  });
31
36
  _MovableArea.displayName = 'MpxMovableArea';
32
37
  export default _MovableArea;
@@ -24,7 +24,7 @@ import useNodesRef from './useNodesRef';
24
24
  import { MovableAreaContext } from './context';
25
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, withDecay, runOnJS, runOnUI, useAnimatedReaction, withSpring } from 'react-native-reanimated';
27
+ import Animated, { useSharedValue, useAnimatedStyle, withDecay, runOnJS, runOnUI, withSpring } from 'react-native-reanimated';
28
28
  import { collectDataset, noop } from '@mpxjs/utils';
29
29
  const styles = StyleSheet.create({
30
30
  container: {
@@ -41,7 +41,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
41
41
  const hasLayoutRef = useRef(false);
42
42
  const propsRef = useRef({});
43
43
  propsRef.current = (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;
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, bindchange } = props;
45
45
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(Object.assign({}, style, styles.container), { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
46
46
  const navigation = useNavigation();
47
47
  const prevSimultaneousHandlersRef = useRef(originSimultaneousHandlers || []);
@@ -61,6 +61,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
61
61
  const yInertialMotion = useSharedValue(false);
62
62
  const isFirstTouch = useSharedValue(true);
63
63
  const touchEvent = useSharedValue('');
64
+ const initialViewPosition = useSharedValue({ x: x || 0, y: y || 0 });
64
65
  const MovableAreaLayout = useContext(MovableAreaContext);
65
66
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
66
67
  const waitForHandlers = flatGesture(waitFor);
@@ -118,11 +119,13 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
118
119
  })
119
120
  : newY;
120
121
  }
121
- runOnJS(handleTriggerChange)({
122
- x: newX,
123
- y: newY,
124
- type: 'setData'
125
- });
122
+ if (bindchange) {
123
+ runOnJS(handleTriggerChange)({
124
+ x: newX,
125
+ y: newY,
126
+ type: 'setData'
127
+ });
128
+ }
126
129
  }
127
130
  })();
128
131
  }, [x, y]);
@@ -132,16 +135,6 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
132
135
  resetBoundaryAndCheck({ width, height });
133
136
  }
134
137
  }, [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
- });
145
138
  const getTouchSource = useCallback((offsetX, offsetY) => {
146
139
  const hasOverBoundary = offsetX < draggableXRange.value[0] || offsetX > draggableXRange.value[1] ||
147
140
  offsetY < draggableYRange.value[0] || offsetY > draggableYRange.value[1];
@@ -259,11 +252,13 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
259
252
  });
260
253
  }, []);
261
254
  const triggerStartOnJS = ({ e }) => {
255
+ const { bindtouchstart, catchtouchstart } = propsRef.current;
262
256
  extendEvent(e, 'start');
263
257
  bindtouchstart && bindtouchstart(e);
264
258
  catchtouchstart && catchtouchstart(e);
265
259
  };
266
260
  const triggerMoveOnJS = ({ e, hasTouchmove, hasCatchTouchmove, touchEvent }) => {
261
+ const { bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove } = propsRef.current;
267
262
  extendEvent(e, 'move');
268
263
  if (hasTouchmove) {
269
264
  if (touchEvent === 'htouchmove') {
@@ -285,6 +280,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
285
280
  }
286
281
  };
287
282
  const triggerEndOnJS = ({ e }) => {
283
+ const { bindtouchend, catchtouchend } = propsRef.current;
288
284
  extendEvent(e, 'end');
289
285
  bindtouchend && bindtouchend(e);
290
286
  catchtouchend && catchtouchend(e);
@@ -315,6 +311,13 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
315
311
  if (bindtouchstart || catchtouchstart) {
316
312
  runOnJS(triggerStartOnJS)({ e });
317
313
  }
314
+ })
315
+ .onStart(() => {
316
+ 'worklet';
317
+ initialViewPosition.value = {
318
+ x: offsetX.value,
319
+ y: offsetY.value
320
+ };
318
321
  })
319
322
  .onTouchesMove((e) => {
320
323
  'worklet';
@@ -325,12 +328,13 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
325
328
  isFirstTouch.value = false;
326
329
  }
327
330
  handleTriggerMove(e);
331
+ })
332
+ .onUpdate((e) => {
333
+ 'worklet';
328
334
  if (disabled)
329
335
  return;
330
- const changeX = changedTouches.x - startPosition.value.x;
331
- const changeY = changedTouches.y - startPosition.value.y;
332
336
  if (direction === 'horizontal' || direction === 'all') {
333
- const newX = offsetX.value + changeX;
337
+ const newX = initialViewPosition.value.x + e.translationX;
334
338
  if (!outOfBounds) {
335
339
  const { x } = checkBoundaryPosition({ positionX: newX, positionY: offsetY.value });
336
340
  offsetX.value = x;
@@ -340,7 +344,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
340
344
  }
341
345
  }
342
346
  if (direction === 'vertical' || direction === 'all') {
343
- const newY = offsetY.value + changeY;
347
+ const newY = initialViewPosition.value.y + e.translationY;
344
348
  if (!outOfBounds) {
345
349
  const { y } = checkBoundaryPosition({ positionX: offsetX.value, positionY: newY });
346
350
  offsetY.value = y;
@@ -349,6 +353,12 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
349
353
  offsetY.value = newY;
350
354
  }
351
355
  }
356
+ if (bindchange) {
357
+ runOnJS(handleTriggerChange)({
358
+ x: offsetX.value,
359
+ y: offsetY.value
360
+ });
361
+ }
352
362
  })
353
363
  .onTouchesUp((e) => {
354
364
  'worklet';
@@ -357,55 +367,83 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
357
367
  if (bindtouchend || catchtouchend) {
358
368
  runOnJS(triggerEndOnJS)({ e });
359
369
  }
360
- if (disabled)
361
- return;
362
- if (!inertia) {
363
- const { x, y } = checkBoundaryPosition({ positionX: offsetX.value, positionY: offsetY.value });
364
- if (x !== offsetX.value) {
365
- offsetX.value = animation
366
- ? withSpring(x, {
367
- duration: 1500,
368
- dampingRatio: 0.8
369
- })
370
- : x;
371
- }
372
- if (y !== offsetY.value) {
373
- offsetY.value = animation
374
- ? withSpring(y, {
375
- duration: 1500,
376
- dampingRatio: 0.8
377
- })
378
- : y;
379
- }
380
- }
381
370
  })
382
- .onFinalize((e) => {
371
+ .onEnd((e) => {
383
372
  'worklet';
384
373
  isMoving.value = false;
385
- if (!inertia || disabled || !animation)
374
+ if (disabled)
386
375
  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
- });
376
+ // 处理没有惯性且超出边界的回弹
377
+ if (!inertia && outOfBounds) {
378
+ const { x, y } = checkBoundaryPosition({ positionX: offsetX.value, positionY: offsetY.value });
379
+ if (x !== offsetX.value || y !== offsetY.value) {
380
+ if (x !== offsetX.value) {
381
+ offsetX.value = animation
382
+ ? withSpring(x, {
383
+ duration: 1500,
384
+ dampingRatio: 0.8
385
+ })
386
+ : x;
387
+ }
388
+ if (y !== offsetY.value) {
389
+ offsetY.value = animation
390
+ ? withSpring(y, {
391
+ duration: 1500,
392
+ dampingRatio: 0.8
393
+ })
394
+ : y;
395
+ }
396
+ if (bindchange) {
397
+ runOnJS(handleTriggerChange)({
398
+ x,
399
+ y
400
+ });
401
+ }
402
+ }
396
403
  }
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
- });
404
+ else if (inertia) {
405
+ // 惯性处理
406
+ if (direction === 'horizontal' || direction === 'all') {
407
+ xInertialMotion.value = true;
408
+ offsetX.value = withDecay({
409
+ velocity: e.velocityX / 10,
410
+ rubberBandEffect: outOfBounds,
411
+ clamp: draggableXRange.value
412
+ }, () => {
413
+ xInertialMotion.value = false;
414
+ if (bindchange) {
415
+ runOnJS(handleTriggerChange)({
416
+ x: offsetX.value,
417
+ y: offsetY.value
418
+ });
419
+ }
420
+ });
421
+ }
422
+ if (direction === 'vertical' || direction === 'all') {
423
+ yInertialMotion.value = true;
424
+ offsetY.value = withDecay({
425
+ velocity: e.velocityY / 10,
426
+ rubberBandEffect: outOfBounds,
427
+ clamp: draggableYRange.value
428
+ }, () => {
429
+ yInertialMotion.value = false;
430
+ if (bindchange) {
431
+ runOnJS(handleTriggerChange)({
432
+ x: offsetX.value,
433
+ y: offsetY.value
434
+ });
435
+ }
436
+ });
437
+ }
406
438
  }
407
439
  })
408
440
  .withRef(movableGestureRef);
441
+ if (direction === 'horizontal') {
442
+ gesturePan.activeOffsetX([-5, 5]).failOffsetY([-5, 5]);
443
+ }
444
+ else if (direction === 'vertical') {
445
+ gesturePan.activeOffsetY([-5, 5]).failOffsetX([-5, 5]);
446
+ }
409
447
  if (simultaneousHandlers && simultaneousHandlers.length) {
410
448
  gesturePan.simultaneousWithExternalGesture(...simultaneousHandlers);
411
449
  }
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, useRef, useContext, useEffect } from 'react';
1
+ import React, { forwardRef, useRef, useContext, useEffect, createElement } 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 } from '../utils';
12
+ import { extendObject, useLayout } from '../utils';
13
13
  import { createPopupManager } from '../mpx-popup';
14
14
  /**
15
15
  * ✔ mode
@@ -109,17 +109,18 @@ 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({});
113
112
  const nodeRef = useRef(null);
114
113
  const pickerRef = useRef(null);
115
114
  const { open, show, hide, remove } = useRef(createPopupManager()).current;
116
115
  useNodesRef(props, ref, nodeRef);
116
+ const { layoutRef, layoutProps } = useLayout({
117
+ props,
118
+ hasSelfPercent: false,
119
+ nodeRef
120
+ });
117
121
  const innerProps = useInnerProps(extendObject({}, props, {
118
122
  ref: nodeRef
119
- }), [], { layoutRef: innerLayout });
120
- const getInnerLayout = (layout) => {
121
- innerLayout.current = layout.current;
122
- };
123
+ }, layoutProps), [], { layoutRef });
123
124
  useEffect(() => {
124
125
  if (range && pickerRef.current && mode === "multiSelector" /* PickerMode.MULTI_SELECTOR */) {
125
126
  pickerRef.current.updateRange?.(range);
@@ -162,7 +163,7 @@ const Picker = forwardRef((props, ref) => {
162
163
  if (mode !== "multiSelector" /* PickerMode.MULTI_SELECTOR */) {
163
164
  return;
164
165
  }
165
- const eventData = getCustomEvent('columnchange', {}, { detail: { column: columnIndex, value }, layoutRef: innerLayout });
166
+ const eventData = getCustomEvent('columnchange', {}, { detail: { column: columnIndex, value }, layoutRef });
166
167
  props.bindcolumnchange?.(eventData);
167
168
  };
168
169
  const onCancel = () => {
@@ -170,7 +171,7 @@ const Picker = forwardRef((props, ref) => {
170
171
  hide();
171
172
  };
172
173
  const onConfirm = () => {
173
- const eventData = getCustomEvent('change', {}, { detail: { value: pickerValue.current }, layoutRef: innerLayout });
174
+ const eventData = getCustomEvent('change', {}, { detail: { value: pickerValue.current }, layoutRef });
174
175
  bindchange?.(eventData);
175
176
  hide();
176
177
  };
@@ -179,7 +180,6 @@ const Picker = forwardRef((props, ref) => {
179
180
  children,
180
181
  bindchange: onChange,
181
182
  bindcolumnchange: onColumnChange,
182
- getInnerLayout,
183
183
  getRange: () => range
184
184
  });
185
185
  const renderPickerContent = () => {
@@ -215,9 +215,7 @@ const Picker = forwardRef((props, ref) => {
215
215
  remove();
216
216
  };
217
217
  }, []);
218
- return (<TouchableWithoutFeedback onPress={show}>
219
- {children}
220
- </TouchableWithoutFeedback>);
218
+ return createElement(TouchableWithoutFeedback, { onPress: show }, createElement(View, innerProps, children));
221
219
  });
222
220
  Picker.displayName = 'MpxPicker';
223
221
  export default Picker;
@@ -1,9 +1,10 @@
1
1
  import { View } from 'react-native';
2
- import React, { forwardRef, useRef } from 'react';
2
+ import React, { createElement, 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';
7
8
  const styles = {
8
9
  wrapper: {
9
10
  display: 'flex',
@@ -23,7 +24,7 @@ const _PickerView = forwardRef((props, ref) => {
23
24
  const activeValueRef = useRef(value);
24
25
  activeValueRef.current = value.slice();
25
26
  const snapActiveValueRef = useRef(null);
26
- const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
27
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight, hasPositionFixed } = useTransformStyle(style, { enableVar, externalVarContext });
27
28
  useNodesRef(props, ref, nodeRef, {
28
29
  style: normalStyle
29
30
  });
@@ -114,11 +115,11 @@ const _PickerView = forwardRef((props, ref) => {
114
115
  onInitialChange(isInvalid, validValue);
115
116
  return renderColumns;
116
117
  };
117
- return (<PickerViewStyleContext.Provider value={textStyle}>
118
- <View {...innerProps}>
119
- <View style={[styles.wrapper]}>{renderPickerColumns()}</View>
120
- </View>
121
- </PickerViewStyleContext.Provider>);
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;
122
123
  });
123
124
  _PickerView.displayName = 'MpxPickerView';
124
125
  export default _PickerView;
@@ -1,7 +1,7 @@
1
- import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react';
1
+ import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback, createElement } 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 } from '../utils';
4
+ import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS, isHarmony, extendObject } from '../utils';
5
5
  import useNodesRef from '../useNodesRef';
6
6
  import PickerIndicator from './pickerViewIndicator';
7
7
  import PickerMask from './pickerViewMask';
@@ -220,11 +220,28 @@ 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
- 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>);
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()));
228
245
  };
229
246
  const renderIndicator = () => (<PickerIndicator itemHeight={itemHeight} indicatorItemStyle={pickerIndicatorStyle}/>);
230
247
  const renderMask = () => (<PickerMask itemHeight={itemHeight} maskContainerStyle={pickerMaskStyle}/>);
@@ -235,7 +252,8 @@ const _PickerViewColumn = forwardRef((props, ref) => {
235
252
  </View>);
236
253
  });
237
254
  const styles = StyleSheet.create({
238
- wrapper: { display: 'flex', flex: 1 }
255
+ wrapper: { display: 'flex', flex: 1 },
256
+ scrollView: { width: '100%' }
239
257
  });
240
258
  _PickerViewColumn.displayName = 'MpxPickerViewColumn';
241
259
  export default _PickerViewColumn;
@@ -8,6 +8,7 @@ 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';
11
12
  const radioGroup = forwardRef((props, ref) => {
12
13
  const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
13
14
  const propsRef = useRef({});
@@ -23,7 +24,7 @@ const radioGroup = forwardRef((props, ref) => {
23
24
  flexWrap: 'wrap'
24
25
  };
25
26
  const styleObj = extendObject({}, defaultStyle, style);
26
- const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
27
+ const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
27
28
  const nodeRef = useRef(null);
28
29
  useNodesRef(props, ref, nodeRef, { style: normalStyle });
29
30
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
@@ -77,10 +78,16 @@ const radioGroup = forwardRef((props, ref) => {
77
78
  }), ['name'], {
78
79
  layoutRef
79
80
  });
80
- return createElement(View, innerProps, createElement(RadioGroupContext.Provider, { value: contextValue }, wrapChildren(props, {
81
+ const finalComponent = createElement(View, innerProps, createElement(RadioGroupContext.Provider, {
82
+ value: contextValue
83
+ }, wrapChildren(props, {
81
84
  hasVarDec,
82
85
  varContext: varContextRef.current
83
86
  })));
87
+ if (hasPositionFixed) {
88
+ return createElement(Portal, null, finalComponent);
89
+ }
90
+ return finalComponent;
84
91
  });
85
92
  radioGroup.displayName = 'MpxRadioGroup';
86
93
  export default radioGroup;
@@ -12,6 +12,7 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners';
12
12
  import useNodesRef from './useNodesRef';
13
13
  import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
14
14
  import Icon from './mpx-icon';
15
+ import Portal from './mpx-portal';
15
16
  const styles = StyleSheet.create({
16
17
  container: {
17
18
  flexDirection: 'row',
@@ -73,7 +74,7 @@ const Radio = forwardRef((radioProps, ref) => {
73
74
  bindtap && bindtap(getCustomEvent('tap', evt, { layoutRef }, props));
74
75
  onChange(evt);
75
76
  };
76
- const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
77
+ const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
77
78
  const { textStyle, backgroundStyle, innerStyle = {} } = splitStyle(normalStyle);
78
79
  if (backgroundStyle) {
79
80
  warn('Radio does not support background image-related styles!');
@@ -123,7 +124,7 @@ const Radio = forwardRef((radioProps, ref) => {
123
124
  }
124
125
  }
125
126
  }, [checked]);
126
- return createElement(View, innerProps, createElement(View, { style: defaultStyle }, createElement(Icon, {
127
+ const finalComponent = createElement(View, innerProps, createElement(View, { style: defaultStyle }, createElement(Icon, {
127
128
  type: 'success',
128
129
  size: 24,
129
130
  color: disabled ? '#E1E1E1' : color,
@@ -134,6 +135,10 @@ const Radio = forwardRef((radioProps, ref) => {
134
135
  textStyle,
135
136
  textProps
136
137
  }));
138
+ if (hasPositionFixed) {
139
+ return createElement(Portal, null, finalComponent);
140
+ }
141
+ return finalComponent;
137
142
  });
138
143
  Radio.displayName = 'MpxRadio';
139
144
  export default Radio;
@@ -8,6 +8,7 @@ import useNodesRef from '../useNodesRef'; // 引入辅助函数
8
8
  import { useTransformStyle, useLayout, extendObject } from '../utils';
9
9
  import { WebView } from 'react-native-webview';
10
10
  import { generateHTML } from './html';
11
+ import Portal from '../mpx-portal';
11
12
  function jsonToHtmlStr(elements) {
12
13
  let htmlStr = '';
13
14
  for (const element of elements) {
@@ -30,7 +31,7 @@ const _RichText = forwardRef((props, ref) => {
30
31
  const { style = {}, nodes, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
31
32
  const nodeRef = useRef(null);
32
33
  const [webViewHeight, setWebViewHeight] = useState(0);
33
- const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(Object.assign({
34
+ const { normalStyle, hasSelfPercent, setWidth, setHeight, hasPositionFixed } = useTransformStyle(Object.assign({
34
35
  width: '100%',
35
36
  height: webViewHeight
36
37
  }, style), {
@@ -51,12 +52,16 @@ const _RichText = forwardRef((props, ref) => {
51
52
  layoutRef
52
53
  });
53
54
  const html = typeof nodes === 'string' ? nodes : jsonToHtmlStr(nodes);
54
- return createElement(View, innerProps, createElement(WebView, {
55
+ let finalComponent = createElement(View, innerProps, createElement(WebView, {
55
56
  source: { html: generateHTML(html) },
56
57
  onMessage: (event) => {
57
58
  setWebViewHeight(+event.nativeEvent.data);
58
59
  }
59
60
  }));
61
+ if (hasPositionFixed) {
62
+ finalComponent = createElement(Portal, null, finalComponent);
63
+ }
64
+ return finalComponent;
60
65
  });
61
66
  _RichText.displayName = 'mpx-rich-text';
62
67
  export default _RichText;