@mpxjs/webpack-plugin 2.10.7 → 2.10.8

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 (43) hide show
  1. package/lib/dependencies/RecordPageConfigsMapDependency.js +1 -1
  2. package/lib/dependencies/RequireExternalDependency.js +61 -0
  3. package/lib/file-loader.js +3 -2
  4. package/lib/index.js +55 -9
  5. package/lib/json-compiler/index.js +1 -0
  6. package/lib/parser.js +1 -1
  7. package/lib/platform/json/wx/index.js +43 -25
  8. package/lib/platform/style/wx/index.js +7 -0
  9. package/lib/platform/template/wx/component-config/fix-component-name.js +2 -2
  10. package/lib/platform/template/wx/component-config/index.js +5 -1
  11. package/lib/platform/template/wx/component-config/sticky-header.js +23 -0
  12. package/lib/platform/template/wx/component-config/sticky-section.js +23 -0
  13. package/lib/react/LoadAsyncChunkModule.js +74 -0
  14. package/lib/react/index.js +3 -1
  15. package/lib/react/processJSON.js +74 -13
  16. package/lib/react/processScript.js +6 -6
  17. package/lib/react/script-helper.js +100 -41
  18. package/lib/runtime/components/react/context.ts +12 -3
  19. package/lib/runtime/components/react/dist/context.js +4 -1
  20. package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +135 -0
  21. package/lib/runtime/components/react/dist/mpx-button.jsx +2 -2
  22. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +8 -6
  23. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +31 -15
  24. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +117 -0
  25. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +45 -0
  26. package/lib/runtime/components/react/mpx-async-suspense.tsx +180 -0
  27. package/lib/runtime/components/react/mpx-button.tsx +3 -2
  28. package/lib/runtime/components/react/mpx-movable-view.tsx +8 -4
  29. package/lib/runtime/components/react/mpx-scroll-view.tsx +84 -59
  30. package/lib/runtime/components/react/mpx-sticky-header.tsx +181 -0
  31. package/lib/runtime/components/react/mpx-sticky-section.tsx +96 -0
  32. package/lib/runtime/components/web/mpx-scroll-view.vue +18 -4
  33. package/lib/runtime/components/web/mpx-sticky-header.vue +99 -0
  34. package/lib/runtime/components/web/mpx-sticky-section.vue +15 -0
  35. package/lib/runtime/optionProcessorReact.d.ts +18 -0
  36. package/lib/runtime/optionProcessorReact.js +30 -0
  37. package/lib/script-setup-compiler/index.js +27 -5
  38. package/lib/template-compiler/bind-this.js +2 -1
  39. package/lib/template-compiler/compiler.js +4 -3
  40. package/lib/utils/dom-tag-config.js +17 -3
  41. package/lib/utils/trans-async-sub-rules.js +19 -0
  42. package/lib/web/script-helper.js +1 -1
  43. package/package.json +4 -4
@@ -32,6 +32,7 @@
32
32
  * ✔ bindscroll
33
33
  */
34
34
  import { ScrollView, RefreshControl, Gesture, GestureDetector } from 'react-native-gesture-handler';
35
+ import { Animated as RNAnimated } from 'react-native';
35
36
  import { isValidElement, Children, useRef, useState, useEffect, forwardRef, useContext, useMemo, createElement } from 'react';
36
37
  import Animated, { useAnimatedRef, useSharedValue, withTiming, useAnimatedStyle, runOnJS } from 'react-native-reanimated';
37
38
  import { warn, hasOwn } from '@mpxjs/utils';
@@ -40,9 +41,11 @@ import useNodesRef from './useNodesRef';
40
41
  import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, HIDDEN_STYLE } from './utils';
41
42
  import { IntersectionObserverContext, ScrollViewContext } from './context';
42
43
  import Portal from './mpx-portal';
44
+ const AnimatedScrollView = RNAnimated.createAnimatedComponent(ScrollView);
43
45
  const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
44
46
  const { textProps, innerProps: props = {} } = splitProps(scrollViewProps);
45
- 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, '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
+ const scrollOffset = useRef(new RNAnimated.Value(0)).current;
46
49
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
47
50
  const waitForHandlers = flatGesture(waitFor);
48
51
  const snapScrollTop = useRef(0);
@@ -66,7 +69,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
66
69
  const hasCallScrollToLower = useRef(false);
67
70
  const initialTimeout = useRef(null);
68
71
  const intersectionObservers = useContext(IntersectionObserverContext);
69
- const firstScrollIntoViewChange = useRef(false);
72
+ const firstScrollIntoViewChange = useRef(true);
70
73
  const refreshColor = {
71
74
  black: ['#000'],
72
75
  white: ['#fff']
@@ -86,16 +89,18 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
86
89
  pagingEnabled,
87
90
  fastDeceleration: false,
88
91
  decelerationDisabled: false,
89
- scrollTo
92
+ scrollTo,
93
+ scrollIntoView: handleScrollIntoView
90
94
  },
91
95
  gestureRef: scrollViewRef
92
96
  });
97
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout });
93
98
  const contextValue = useMemo(() => {
94
99
  return {
95
- gestureRef: scrollViewRef
100
+ gestureRef: scrollViewRef,
101
+ scrollOffset
96
102
  };
97
103
  }, []);
98
- const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout });
99
104
  const hasRefresherLayoutRef = useRef(false);
100
105
  // layout 完成前先隐藏,避免安卓闪烁问题
101
106
  const refresherLayoutStyle = useMemo(() => { return !hasRefresherLayoutRef.current ? HIDDEN_STYLE : {}; }, [hasRefresherLayoutRef.current]);
@@ -115,14 +120,16 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
115
120
  }, [scrollTop, scrollLeft]);
116
121
  useEffect(() => {
117
122
  if (scrollIntoView && __selectRef) {
118
- if (!firstScrollIntoViewChange.current) {
119
- setTimeout(handleScrollIntoView);
123
+ if (firstScrollIntoViewChange.current) {
124
+ setTimeout(() => {
125
+ handleScrollIntoView(scrollIntoView, { offset: scrollIntoViewOffset, animated: scrollWithAnimation });
126
+ });
120
127
  }
121
128
  else {
122
- handleScrollIntoView();
129
+ handleScrollIntoView(scrollIntoView, { offset: scrollIntoViewOffset, animated: scrollWithAnimation });
123
130
  }
124
131
  }
125
- firstScrollIntoViewChange.current = true;
132
+ firstScrollIntoViewChange.current = false;
126
133
  }, [scrollIntoView]);
127
134
  useEffect(() => {
128
135
  if (refresherEnabled) {
@@ -142,13 +149,15 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
142
149
  function scrollTo({ top = 0, left = 0, animated = false }) {
143
150
  scrollToOffset(left, top, animated);
144
151
  }
145
- function handleScrollIntoView() {
146
- const refs = __selectRef(`#${scrollIntoView}`, 'node');
152
+ function handleScrollIntoView(selector = '', { offset = 0, animated = true } = {}) {
153
+ const refs = __selectRef(`#${selector}`, 'node');
147
154
  if (!refs)
148
155
  return;
149
156
  const { nodeRef } = refs.getNodeInstance();
150
157
  nodeRef.current?.measureLayout(scrollViewRef.current, (left, top) => {
151
- scrollToOffset(left, top);
158
+ const adjustedLeft = scrollX ? left + offset : left;
159
+ const adjustedTop = scrollY ? top + offset : top;
160
+ scrollToOffset(adjustedLeft, adjustedTop, animated);
152
161
  });
153
162
  }
154
163
  function selectLength(size) {
@@ -321,6 +330,12 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
321
330
  updateScrollOptions(e, { scrollLeft, scrollTop });
322
331
  updateIntersection();
323
332
  }
333
+ const scrollHandler = RNAnimated.event([{ nativeEvent: { contentOffset: { y: scrollOffset } } }], {
334
+ useNativeDriver: true,
335
+ listener: (event) => {
336
+ onScroll(event);
337
+ }
338
+ });
324
339
  function onScrollDragStart(e) {
325
340
  hasCallScrollToLower.current = false;
326
341
  hasCallScrollToUpper.current = false;
@@ -481,7 +496,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
481
496
  scrollEnabled: !enableScroll ? false : !!(scrollX || scrollY),
482
497
  bounces: false,
483
498
  ref: scrollViewRef,
484
- onScroll: onScroll,
499
+ onScroll: enableSticky ? scrollHandler : onScroll,
485
500
  onContentSizeChange: onContentSizeChange,
486
501
  bindtouchstart: ((enhanced && binddragstart) || bindtouchstart) && onScrollTouchStart,
487
502
  bindtouchmove: ((enhanced && binddragging) || bindtouchmove) && onScrollTouchMove,
@@ -523,13 +538,14 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
523
538
  'bindscrolltolower',
524
539
  'bindrefresherrefresh'
525
540
  ], { layoutRef });
526
- const withRefresherScrollView = createElement(GestureDetector, { gesture: panGesture }, createElement(ScrollView, innerProps, createElement(Animated.View, { style: [refresherAnimatedStyle, refresherLayoutStyle], onLayout: onRefresherLayout }, refresherContent), createElement(Animated.View, { style: contentAnimatedStyle }, createElement(ScrollViewContext.Provider, { value: contextValue }, wrapChildren(extendObject({}, props, { children: otherContent }), {
541
+ const ScrollViewComponent = enableSticky ? AnimatedScrollView : ScrollView;
542
+ const withRefresherScrollView = createElement(GestureDetector, { gesture: panGesture }, createElement(ScrollViewComponent, innerProps, createElement(Animated.View, { style: [refresherAnimatedStyle, refresherLayoutStyle], onLayout: onRefresherLayout }, refresherContent), createElement(Animated.View, { style: contentAnimatedStyle }, createElement(ScrollViewContext.Provider, { value: contextValue }, wrapChildren(extendObject({}, props, { children: otherContent }), {
527
543
  hasVarDec,
528
544
  varContext: varContextRef.current,
529
545
  textStyle,
530
546
  textProps
531
547
  })))));
532
- const commonScrollView = createElement(ScrollView, extendObject(innerProps, {
548
+ const commonScrollView = createElement(ScrollViewComponent, extendObject({}, innerProps, {
533
549
  refreshControl: refresherEnabled
534
550
  ? createElement(RefreshControl, extendObject({
535
551
  progressBackgroundColor: refresherBackground,
@@ -0,0 +1,117 @@
1
+ import { useEffect, useRef, useContext, forwardRef, useMemo, createElement, useId } from 'react';
2
+ import { Animated, StyleSheet, useAnimatedValue } from 'react-native';
3
+ import { ScrollViewContext, StickyContext } from './context';
4
+ import useNodesRef from './useNodesRef';
5
+ import { splitProps, splitStyle, useTransformStyle, wrapChildren, useLayout, extendObject } from './utils';
6
+ import { error } from '@mpxjs/utils';
7
+ import useInnerProps, { getCustomEvent } from './getInnerListeners';
8
+ const _StickyHeader = forwardRef((stickyHeaderProps = {}, ref) => {
9
+ const { textProps, innerProps: props = {} } = splitProps(stickyHeaderProps);
10
+ const { style, bindstickontopchange, padding = [0, 0, 0, 0], 'offset-top': offsetTop = 0, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
11
+ const scrollViewContext = useContext(ScrollViewContext);
12
+ const stickyContext = useContext(StickyContext);
13
+ const { scrollOffset } = scrollViewContext;
14
+ const { registerStickyHeader, unregisterStickyHeader } = stickyContext;
15
+ const headerRef = useRef(null);
16
+ const isStickOnTopRef = useRef(false);
17
+ const id = useId();
18
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
19
+ const { layoutRef, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: headerRef, onLayout });
20
+ const { textStyle, innerStyle = {} } = splitStyle(normalStyle);
21
+ const headerTopAnimated = useAnimatedValue(0);
22
+ // harmony animatedValue 不支持通过 _value 访问
23
+ const headerTopRef = useRef(0);
24
+ useEffect(() => {
25
+ registerStickyHeader({ key: id, updatePosition });
26
+ return () => {
27
+ unregisterStickyHeader(id);
28
+ };
29
+ }, []);
30
+ function updatePosition() {
31
+ if (headerRef.current) {
32
+ const scrollViewRef = scrollViewContext.gestureRef;
33
+ if (scrollViewRef && scrollViewRef.current) {
34
+ headerRef.current.measureLayout(scrollViewRef.current, (left, top) => {
35
+ Animated.timing(headerTopAnimated, {
36
+ toValue: top,
37
+ duration: 0,
38
+ useNativeDriver: true
39
+ }).start();
40
+ headerTopRef.current = top;
41
+ });
42
+ }
43
+ else {
44
+ error('StickyHeader measureLayout error: scrollViewRef is not a valid native component reference');
45
+ }
46
+ }
47
+ }
48
+ function onLayout(e) {
49
+ updatePosition();
50
+ }
51
+ useNodesRef(props, ref, headerRef, {
52
+ style: normalStyle
53
+ });
54
+ useEffect(() => {
55
+ if (!bindstickontopchange)
56
+ return;
57
+ const listener = scrollOffset.addListener((state) => {
58
+ const currentScrollValue = state.value;
59
+ const newIsStickOnTop = currentScrollValue > headerTopRef.current;
60
+ if (newIsStickOnTop !== isStickOnTopRef.current) {
61
+ isStickOnTopRef.current = newIsStickOnTop;
62
+ bindstickontopchange(getCustomEvent('stickontopchange', {}, {
63
+ detail: {
64
+ isStickOnTop: newIsStickOnTop
65
+ },
66
+ layoutRef
67
+ }, props));
68
+ }
69
+ });
70
+ return () => {
71
+ scrollOffset.removeListener(listener);
72
+ };
73
+ }, []);
74
+ const animatedStyle = useMemo(() => {
75
+ const translateY = Animated.subtract(scrollOffset, headerTopAnimated).interpolate({
76
+ inputRange: [0, 1],
77
+ outputRange: [0, 1],
78
+ extrapolateLeft: 'clamp',
79
+ extrapolateRight: 'extend'
80
+ });
81
+ const finalTranslateY = offsetTop === 0
82
+ ? translateY
83
+ : Animated.add(translateY, Animated.subtract(scrollOffset, headerTopAnimated).interpolate({
84
+ inputRange: [0, 1],
85
+ outputRange: [0, offsetTop],
86
+ extrapolate: 'clamp'
87
+ }));
88
+ return {
89
+ transform: [{ translateY: finalTranslateY }]
90
+ };
91
+ }, [scrollOffset, headerTopAnimated, offsetTop]);
92
+ const innerProps = useInnerProps(extendObject({}, props, {
93
+ ref: headerRef,
94
+ style: extendObject({}, styles.content, innerStyle, animatedStyle, {
95
+ paddingTop: padding[0] || 0,
96
+ paddingRight: padding[1] || 0,
97
+ paddingBottom: padding[2] || 0,
98
+ paddingLeft: padding[3] || 0
99
+ })
100
+ }, layoutProps), [], { layoutRef });
101
+ return (createElement(Animated.View, innerProps, wrapChildren(props, {
102
+ hasVarDec,
103
+ varContext: varContextRef.current,
104
+ textStyle,
105
+ textProps
106
+ })));
107
+ });
108
+ const styles = StyleSheet.create({
109
+ content: {
110
+ width: '100%',
111
+ zIndex: 10,
112
+ // harmony 需要手动设置 relative, zIndex 才生效
113
+ position: 'relative'
114
+ }
115
+ });
116
+ _StickyHeader.displayName = 'MpxStickyHeader';
117
+ export default _StickyHeader;
@@ -0,0 +1,45 @@
1
+ import { useRef, forwardRef, createElement, useCallback, useMemo } from 'react';
2
+ import { View } from 'react-native';
3
+ import useNodesRef from './useNodesRef';
4
+ import { splitProps, splitStyle, useTransformStyle, wrapChildren, useLayout, extendObject } from './utils';
5
+ import { StickyContext } from './context';
6
+ import useInnerProps from './getInnerListeners';
7
+ const _StickySection = forwardRef((stickySectionProps = {}, ref) => {
8
+ const { textProps, innerProps: props = {} } = splitProps(stickySectionProps);
9
+ const { style, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
10
+ const sectionRef = useRef(null);
11
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
12
+ const { layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: sectionRef, onLayout });
13
+ const { textStyle, innerStyle = {} } = splitStyle(normalStyle);
14
+ const stickyHeaders = useRef(new Map());
15
+ const registerStickyHeader = useCallback((item) => {
16
+ stickyHeaders.current.set(item.id, item);
17
+ }, []);
18
+ const unregisterStickyHeader = useCallback((id) => {
19
+ stickyHeaders.current.delete(id);
20
+ }, []);
21
+ const contextValue = useMemo(() => ({
22
+ registerStickyHeader,
23
+ unregisterStickyHeader
24
+ }), []);
25
+ useNodesRef(props, ref, sectionRef, {
26
+ style: normalStyle
27
+ });
28
+ function onLayout() {
29
+ stickyHeaders.current.forEach(item => {
30
+ item.updatePosition();
31
+ });
32
+ }
33
+ const innerProps = useInnerProps(extendObject({}, props, {
34
+ style: extendObject(innerStyle, layoutStyle),
35
+ ref: sectionRef
36
+ }, layoutProps), [], { layoutRef });
37
+ return (createElement(View, innerProps, createElement(StickyContext.Provider, { value: contextValue }, wrapChildren(props, {
38
+ hasVarDec,
39
+ varContext: varContextRef.current,
40
+ textStyle,
41
+ textProps
42
+ }))));
43
+ });
44
+ _StickySection.displayName = 'MpxStickySection';
45
+ export default _StickySection;
@@ -0,0 +1,180 @@
1
+ import { useState, ComponentType, useEffect, useCallback, useRef, ReactNode, createElement } from 'react'
2
+ import { View, Image, StyleSheet, Text, TouchableOpacity } from 'react-native'
3
+ import FastImage from '@d11/react-native-fast-image'
4
+
5
+ const asyncChunkMap = new Map()
6
+
7
+ const styles = StyleSheet.create({
8
+ container: {
9
+ flex: 1,
10
+ padding: 20,
11
+ backgroundColor: '#fff'
12
+ },
13
+ loadingImage: {
14
+ width: 100,
15
+ height: 100,
16
+ marginTop: 220,
17
+ alignSelf: 'center'
18
+ },
19
+ buttonText: {
20
+ color: '#fff',
21
+ fontSize: 16,
22
+ fontWeight: '500',
23
+ textAlign: 'center'
24
+ },
25
+ errorImage: {
26
+ marginTop: 80,
27
+ width: 220,
28
+ aspectRatio: 1,
29
+ alignSelf: 'center'
30
+ },
31
+ errorText: {
32
+ fontSize: 16,
33
+ textAlign: 'center',
34
+ color: '#333',
35
+ marginBottom: 20
36
+ },
37
+ retryButton: {
38
+ position: 'absolute',
39
+ bottom: 54,
40
+ left: 20,
41
+ right: 20,
42
+ backgroundColor: '#fff',
43
+ paddingVertical: 15,
44
+ borderRadius: 30,
45
+ marginTop: 40,
46
+ borderWidth: 1,
47
+ borderColor: '#FF5F00'
48
+ },
49
+ retryButtonText: {
50
+ color: '#FF5F00',
51
+ fontSize: 16,
52
+ fontWeight: '500',
53
+ textAlign: 'center'
54
+ }
55
+ })
56
+
57
+ interface DefaultFallbackProps {
58
+ onReload: () => void
59
+ }
60
+
61
+ const DefaultFallback = ({ onReload }: DefaultFallbackProps) => {
62
+ return (
63
+ <View style={styles.container}>
64
+ <Image
65
+ source={{
66
+ uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png'
67
+ }}
68
+ style={styles.errorImage}
69
+ resizeMode="contain"
70
+ />
71
+ <Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
72
+ <TouchableOpacity
73
+ style={styles.retryButton}
74
+ onPress={onReload}
75
+ activeOpacity={0.7}
76
+ >
77
+ <Text style={styles.retryButtonText}>点击重试</Text>
78
+ </TouchableOpacity>
79
+ </View>
80
+ )
81
+ }
82
+
83
+ const DefaultLoading = () => {
84
+ return (
85
+ <View style={styles.container}>
86
+ <FastImage
87
+ style={styles.loadingImage}
88
+ source={{
89
+ uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif'
90
+ }}
91
+ resizeMode={FastImage.resizeMode.contain}
92
+ ></FastImage>
93
+ </View>
94
+ )
95
+ }
96
+
97
+ interface AsyncSuspenseProps {
98
+ type: 'component' | 'page'
99
+ chunkName: string
100
+ moduleId: string
101
+ innerProps: any,
102
+ loading?: ComponentType<unknown>
103
+ fallback?: ComponentType<unknown>
104
+ getChildren: () => Promise<ReactNode>
105
+ }
106
+
107
+ type ComponentStauts = 'pending' | 'error' | 'loaded'
108
+
109
+ const AsyncSuspense: React.FC<AsyncSuspenseProps> = ({
110
+ type,
111
+ innerProps,
112
+ chunkName,
113
+ moduleId,
114
+ loading,
115
+ fallback,
116
+ getChildren
117
+ }) => {
118
+ const [status, setStatus] = useState<ComponentStauts>('pending')
119
+ const chunkLoaded = asyncChunkMap.has(moduleId)
120
+ const loadChunkPromise = useRef<null | Promise<ReactNode>>(null)
121
+
122
+ const reloadPage = useCallback(() => {
123
+ setStatus('pending')
124
+ }, [])
125
+
126
+ useEffect(() => {
127
+ let cancelled = false
128
+ if (!chunkLoaded && status === 'pending') {
129
+ if (loadChunkPromise.current) {
130
+ loadChunkPromise
131
+ .current.then((res: ReactNode) => {
132
+ if (cancelled) return
133
+ asyncChunkMap.set(moduleId, res)
134
+ setStatus('loaded')
135
+ })
136
+ .catch((e) => {
137
+ if (cancelled) return
138
+ if (type === 'component') {
139
+ global.onLazyLoadError({
140
+ type: 'subpackage',
141
+ subpackage: [chunkName],
142
+ errMsg: `loadSubpackage: ${e.type}`
143
+ })
144
+ }
145
+ loadChunkPromise.current = null
146
+ setStatus('error')
147
+ })
148
+ }
149
+ }
150
+
151
+ return () => {
152
+ cancelled = true
153
+ }
154
+ }, [status])
155
+
156
+ if (chunkLoaded) {
157
+ const Comp = asyncChunkMap.get(moduleId)
158
+ return createElement(Comp, innerProps)
159
+ } else if (status === 'error') {
160
+ if (type === 'page') {
161
+ fallback = fallback || DefaultFallback
162
+ return createElement(fallback as ComponentType<DefaultFallbackProps>, { onReload: reloadPage })
163
+ } else {
164
+ return fallback ? createElement(fallback, innerProps) : null
165
+ }
166
+ } else {
167
+ if (!loadChunkPromise.current) {
168
+ loadChunkPromise.current = getChildren()
169
+ }
170
+ if (type === 'page') {
171
+ return createElement(loading || DefaultLoading)
172
+ } else {
173
+ return fallback ? createElement(fallback, innerProps) : null
174
+ }
175
+ }
176
+ }
177
+
178
+ AsyncSuspense.displayName = 'MpxAsyncSuspense'
179
+
180
+ export default AsyncSuspense
@@ -42,7 +42,8 @@ import {
42
42
  TextStyle,
43
43
  Animated,
44
44
  Easing,
45
- NativeSyntheticEvent
45
+ NativeSyntheticEvent,
46
+ useAnimatedValue
46
47
  } from 'react-native'
47
48
  import { warn } from '@mpxjs/utils'
48
49
  import { GestureDetector, PanGesture } from 'react-native-gesture-handler'
@@ -157,7 +158,7 @@ const timer = (data: any, time = 3000) => new Promise((resolve) => {
157
158
  })
158
159
 
159
160
  const Loading = ({ alone = false }: { alone: boolean }): JSX.Element => {
160
- const image = useRef(new Animated.Value(0)).current
161
+ const image = useAnimatedValue(0)
161
162
 
162
163
  const rotate = image.interpolate({
163
164
  inputRange: [0, 1],
@@ -70,6 +70,7 @@ interface MovableViewProps {
70
70
  'parent-font-size'?: number
71
71
  'parent-width'?: number
72
72
  'parent-height'?: number
73
+ 'disable-event-passthrough'?: boolean
73
74
  }
74
75
 
75
76
  const styles = StyleSheet.create({
@@ -103,6 +104,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
103
104
  'parent-width': parentWidth,
104
105
  'parent-height': parentHeight,
105
106
  direction = 'none',
107
+ 'disable-event-passthrough': disableEventPassthrough = false,
106
108
  'simultaneous-handlers': originSimultaneousHandlers = [],
107
109
  'wait-for': waitFor = [],
108
110
  style = {},
@@ -557,10 +559,12 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
557
559
  })
558
560
  .withRef(movableGestureRef)
559
561
 
560
- if (direction === 'horizontal') {
561
- gesturePan.activeOffsetX([-5, 5]).failOffsetY([-5, 5])
562
- } else if (direction === 'vertical') {
563
- gesturePan.activeOffsetY([-5, 5]).failOffsetX([-5, 5])
562
+ if (!disableEventPassthrough) {
563
+ if (direction === 'horizontal') {
564
+ gesturePan.activeOffsetX([-5, 5]).failOffsetY([-5, 5])
565
+ } else if (direction === 'vertical') {
566
+ gesturePan.activeOffsetY([-5, 5]).failOffsetX([-5, 5])
567
+ }
564
568
  }
565
569
 
566
570
  if (simultaneousHandlers && simultaneousHandlers.length) {