@mpxjs/webpack-plugin 2.10.7-beta.8 → 2.10.7-beta.9

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.
@@ -44,7 +44,7 @@ import Portal from './mpx-portal';
44
44
  const AnimatedScrollView = RNAnimated.createAnimatedComponent(ScrollView);
45
45
  const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
46
46
  const { textProps, innerProps: props = {} } = splitProps(scrollViewProps);
47
- const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchstart, bindtouchmove, bindtouchend, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation = false, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'refresher-threshold': refresherThreshold = 45, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor, 'enable-sticky': enableSticky, 'scroll-event-throttle': scrollEventThrottle = 0, __selectRef } = props;
47
+ const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchstart, bindtouchmove, bindtouchend, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation = false, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'refresher-threshold': refresherThreshold = 45, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor, 'enable-sticky': enableSticky, 'scroll-event-throttle': scrollEventThrottle = 0, 'scroll-into-view-offset': scrollIntoViewOffset = 0, __selectRef } = props;
48
48
  const scrollOffset = useRef(new RNAnimated.Value(0)).current;
49
49
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
50
50
  const waitForHandlers = flatGesture(waitFor);
@@ -69,7 +69,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
69
69
  const hasCallScrollToLower = useRef(false);
70
70
  const initialTimeout = useRef(null);
71
71
  const intersectionObservers = useContext(IntersectionObserverContext);
72
- const firstScrollIntoViewChange = useRef(false);
72
+ const firstScrollIntoViewChange = useRef(true);
73
73
  const refreshColor = {
74
74
  black: ['#000'],
75
75
  white: ['#fff']
@@ -89,7 +89,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
89
89
  pagingEnabled,
90
90
  fastDeceleration: false,
91
91
  decelerationDisabled: false,
92
- scrollTo
92
+ scrollTo,
93
+ scrollIntoView: handleScrollIntoView
93
94
  },
94
95
  gestureRef: scrollViewRef
95
96
  });
@@ -119,14 +120,16 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
119
120
  }, [scrollTop, scrollLeft]);
120
121
  useEffect(() => {
121
122
  if (scrollIntoView && __selectRef) {
122
- if (!firstScrollIntoViewChange.current) {
123
- setTimeout(handleScrollIntoView);
123
+ if (firstScrollIntoViewChange.current) {
124
+ setTimeout(() => {
125
+ handleScrollIntoView(scrollIntoView, { offset: scrollIntoViewOffset, animated: scrollWithAnimation });
126
+ });
124
127
  }
125
128
  else {
126
- handleScrollIntoView();
129
+ handleScrollIntoView(scrollIntoView, { offset: scrollIntoViewOffset, animated: scrollWithAnimation });
127
130
  }
128
131
  }
129
- firstScrollIntoViewChange.current = true;
132
+ firstScrollIntoViewChange.current = false;
130
133
  }, [scrollIntoView]);
131
134
  useEffect(() => {
132
135
  if (refresherEnabled) {
@@ -146,13 +149,15 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
146
149
  function scrollTo({ top = 0, left = 0, animated = false }) {
147
150
  scrollToOffset(left, top, animated);
148
151
  }
149
- function handleScrollIntoView() {
150
- const refs = __selectRef(`#${scrollIntoView}`, 'node');
152
+ function handleScrollIntoView(selector = '', { offset = 0, animated = true } = {}) {
153
+ const refs = __selectRef(`#${selector}`, 'node');
151
154
  if (!refs)
152
155
  return;
153
156
  const { nodeRef } = refs.getNodeInstance();
154
157
  nodeRef.current?.measureLayout(scrollViewRef.current, (left, top) => {
155
- scrollToOffset(left, top);
158
+ const adjustedLeft = scrollX ? left + offset : left;
159
+ const adjustedTop = scrollY ? top + offset : top;
160
+ scrollToOffset(adjustedLeft, adjustedTop, animated);
156
161
  });
157
162
  }
158
163
  function selectLength(size) {
@@ -108,7 +108,9 @@ const _StickyHeader = forwardRef((stickyHeaderProps = {}, ref) => {
108
108
  const styles = StyleSheet.create({
109
109
  content: {
110
110
  width: '100%',
111
- zIndex: 10
111
+ zIndex: 10,
112
+ // harmony 需要手动设置 relative, zIndex 才生效
113
+ position: 'relative'
112
114
  }
113
115
  });
114
116
  _StickyHeader.displayName = 'MpxStickyHeader';
@@ -1,12 +1,14 @@
1
1
  /**
2
- * scale-area
2
+ * scale-area
3
3
  */
4
4
 
5
5
  import { View } from 'react-native'
6
- import { JSX, forwardRef, ReactNode, useRef, useMemo, createElement } from 'react'
6
+ import { JSX, forwardRef, ReactNode, useRef, useMemo, useCallback, createElement } from 'react'
7
+ import { GestureDetector, Gesture } from 'react-native-gesture-handler'
8
+ import { useSharedValue } from 'react-native-reanimated'
7
9
  import useNodesRef, { HandlerRef } from './useNodesRef'
8
10
  import useInnerProps from './getInnerListeners'
9
- import { MovableAreaContext } from './context'
11
+ import { MovableAreaContext, MovableAreaContextValue } from './context'
10
12
  import { useTransformStyle, wrapChildren, useLayout, extendObject } from './utils'
11
13
  import Portal from './mpx-portal'
12
14
 
@@ -15,6 +17,7 @@ interface MovableAreaProps {
15
17
  children: ReactNode
16
18
  width?: number
17
19
  height?: number
20
+ 'scale-area'?: boolean
18
21
  'enable-offset'?: boolean
19
22
  'enable-var'?: boolean
20
23
  'external-var-context'?: Record<string, any>
@@ -23,8 +26,21 @@ interface MovableAreaProps {
23
26
  'parent-height'?: number
24
27
  }
25
28
 
29
+ interface MovableViewCallbacks {
30
+ onScale: (scaleInfo: {scale: number}) => void
31
+ onScaleEnd?: () => void
32
+ }
33
+
26
34
  const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaProps>((props: MovableAreaProps, ref): JSX.Element => {
27
- const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props
35
+ const {
36
+ style = {},
37
+ 'scale-area': scaleArea = false,
38
+ 'enable-var': enableVar,
39
+ 'external-var-context': externalVarContext,
40
+ 'parent-font-size': parentFontSize,
41
+ 'parent-width': parentWidth,
42
+ 'parent-height': parentHeight
43
+ } = props
28
44
 
29
45
  const {
30
46
  hasSelfPercent,
@@ -36,17 +52,67 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
36
52
  setHeight
37
53
  } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
38
54
 
39
- const movableViewRef = useRef(null)
40
- useNodesRef(props, ref, movableViewRef, {
55
+ const movableAreaRef = useRef(null)
56
+ const movableViewsValue = useSharedValue<Record<string, MovableViewCallbacks>>({})
57
+ useNodesRef(props, ref, movableAreaRef, {
41
58
  style: normalStyle
42
59
  })
43
60
 
44
- const contextValue = useMemo(() => ({
61
+ // 注册/注销 MovableView 的回调
62
+ const registerMovableView = useCallback((id: string, callbacks: { onScale?: (scaleInfo: { scale: number }) => void; onScaleEnd?: () => void }) => {
63
+ movableViewsValue.value = extendObject(movableViewsValue.value, { [id]: callbacks })
64
+ }, [])
65
+
66
+ const unregisterMovableView = useCallback((id: string) => {
67
+ delete movableViewsValue.value[id]
68
+ }, [])
69
+
70
+ // 处理区域缩放手势
71
+ const handleAreaScale = useCallback((scaleInfo: { scale: number }) => {
72
+ 'worklet'
73
+ if (scaleArea) {
74
+ // 将缩放信息广播给所有注册的 MovableView
75
+ Object.values(movableViewsValue.value).forEach((callbacks) => {
76
+ callbacks.onScale && callbacks.onScale(scaleInfo)
77
+ })
78
+ }
79
+ }, [scaleArea])
80
+
81
+ // 处理区域缩放结束
82
+ const handleAreaScaleEnd = useCallback(() => {
83
+ 'worklet'
84
+ if (scaleArea) {
85
+ // 通知所有注册的 MovableView 缩放结束
86
+ Object.values(movableViewsValue.value).forEach((callbacks) => {
87
+ callbacks.onScaleEnd && callbacks.onScaleEnd()
88
+ })
89
+ }
90
+ }, [scaleArea])
91
+
92
+ const contextValue: MovableAreaContextValue = useMemo(() => ({
45
93
  height: normalStyle.height || 10,
46
- width: normalStyle.width || 10
47
- }), [normalStyle.width, normalStyle.height])
94
+ width: normalStyle.width || 10,
95
+ scaleArea,
96
+ registerMovableView,
97
+ unregisterMovableView
98
+ }), [normalStyle.width, normalStyle.height, scaleArea])
48
99
 
49
- const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: movableViewRef })
100
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: movableAreaRef })
101
+
102
+ // 创建缩放手势
103
+ const scaleGesture = useMemo(() => {
104
+ if (!scaleArea) return null
105
+
106
+ return Gesture.Pinch()
107
+ .onUpdate((e) => {
108
+ 'worklet'
109
+ handleAreaScale(e)
110
+ })
111
+ .onEnd(() => {
112
+ 'worklet'
113
+ handleAreaScaleEnd()
114
+ })
115
+ }, [scaleArea])
50
116
 
51
117
  const innerProps = useInnerProps(
52
118
  extendObject(
@@ -55,7 +121,7 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
55
121
  layoutProps,
56
122
  {
57
123
  style: extendObject({ height: contextValue.height, width: contextValue.width }, normalStyle, layoutStyle),
58
- ref: movableViewRef
124
+ ref: movableAreaRef
59
125
  }
60
126
  ),
61
127
  [],
@@ -73,9 +139,30 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
73
139
  }
74
140
  )
75
141
  ))
142
+
143
+ // 如果启用了 scale-area,包装一个 GestureDetector
144
+ if (scaleArea && scaleGesture) {
145
+ movableComponent = createElement(MovableAreaContext.Provider, { value: contextValue }, createElement(
146
+ GestureDetector,
147
+ { gesture: scaleGesture },
148
+ createElement(
149
+ View,
150
+ innerProps,
151
+ wrapChildren(
152
+ props,
153
+ {
154
+ hasVarDec,
155
+ varContext: varContextRef.current
156
+ }
157
+ )
158
+ )
159
+ ))
160
+ }
161
+
76
162
  if (hasPositionFixed) {
77
163
  movableComponent = createElement(Portal, null, movableComponent)
78
164
  }
165
+
79
166
  return movableComponent
80
167
  })
81
168