@mpxjs/webpack-plugin 2.10.7 → 2.10.8-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 (50) 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 +7 -1
  11. package/lib/platform/template/wx/component-config/page-container.js +19 -0
  12. package/lib/platform/template/wx/component-config/sticky-header.js +23 -0
  13. package/lib/platform/template/wx/component-config/sticky-section.js +23 -0
  14. package/lib/platform/template/wx/component-config/unsupported.js +1 -1
  15. package/lib/react/LoadAsyncChunkModule.js +74 -0
  16. package/lib/react/index.js +3 -1
  17. package/lib/react/processJSON.js +74 -13
  18. package/lib/react/processScript.js +6 -6
  19. package/lib/react/script-helper.js +100 -41
  20. package/lib/runtime/components/react/context.ts +12 -3
  21. package/lib/runtime/components/react/dist/context.js +4 -1
  22. package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +135 -0
  23. package/lib/runtime/components/react/dist/mpx-button.jsx +2 -2
  24. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +8 -6
  25. package/lib/runtime/components/react/dist/mpx-page-container.jsx +255 -0
  26. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +31 -15
  27. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +117 -0
  28. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +45 -0
  29. package/lib/runtime/components/react/dist/mpx-swiper.jsx +3 -2
  30. package/lib/runtime/components/react/mpx-async-suspense.tsx +180 -0
  31. package/lib/runtime/components/react/mpx-button.tsx +3 -2
  32. package/lib/runtime/components/react/mpx-movable-view.tsx +8 -4
  33. package/lib/runtime/components/react/mpx-page-container.tsx +394 -0
  34. package/lib/runtime/components/react/mpx-scroll-view.tsx +84 -59
  35. package/lib/runtime/components/react/mpx-sticky-header.tsx +181 -0
  36. package/lib/runtime/components/react/mpx-sticky-section.tsx +96 -0
  37. package/lib/runtime/components/react/mpx-swiper.tsx +4 -2
  38. package/lib/runtime/components/web/mpx-scroll-view.vue +18 -4
  39. package/lib/runtime/components/web/mpx-sticky-header.vue +99 -0
  40. package/lib/runtime/components/web/mpx-sticky-section.vue +15 -0
  41. package/lib/runtime/optionProcessorReact.d.ts +18 -0
  42. package/lib/runtime/optionProcessorReact.js +30 -0
  43. package/lib/script-setup-compiler/index.js +27 -5
  44. package/lib/template-compiler/bind-this.js +2 -1
  45. package/lib/template-compiler/compiler.js +27 -6
  46. package/lib/utils/dom-tag-config.js +18 -4
  47. package/lib/utils/trans-async-sub-rules.js +19 -0
  48. package/lib/web/script-helper.js +1 -1
  49. package/package.json +4 -4
  50. package/LICENSE +0 -433
@@ -32,7 +32,7 @@
32
32
  * ✔ bindscroll
33
33
  */
34
34
  import { ScrollView, RefreshControl, Gesture, GestureDetector } from 'react-native-gesture-handler'
35
- import { View, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle } from 'react-native'
35
+ import { View, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle, Animated as RNAnimated } from 'react-native'
36
36
  import { isValidElement, Children, JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef, useContext, useMemo, createElement } from 'react'
37
37
  import Animated, { useAnimatedRef, useSharedValue, withTiming, useAnimatedStyle, runOnJS } from 'react-native-reanimated'
38
38
  import { warn, hasOwn } from '@mpxjs/utils'
@@ -43,48 +43,49 @@ import { IntersectionObserverContext, ScrollViewContext } from './context'
43
43
  import Portal from './mpx-portal'
44
44
 
45
45
  interface ScrollViewProps {
46
- children?: ReactNode
47
- enhanced?: boolean
48
- bounces?: boolean
49
- style?: ViewStyle
50
- scrollEventThrottle?: number
51
- 'scroll-x'?: boolean
52
- 'scroll-y'?: boolean
53
- 'enable-back-to-top'?: boolean
54
- 'show-scrollbar'?: boolean
55
- 'paging-enabled'?: boolean
56
- 'upper-threshold'?: number
57
- 'lower-threshold'?: number
58
- 'scroll-with-animation'?: boolean
59
- 'refresher-triggered'?: boolean
60
- 'refresher-enabled'?: boolean
61
- 'refresher-default-style'?: 'black' | 'white' | 'none'
62
- 'refresher-background'?: string
63
- 'refresher-threshold'?: number
64
- 'scroll-top'?: number
65
- 'scroll-left'?: number
66
- 'enable-offset'?: boolean
67
- 'scroll-into-view'?: string
68
- 'enable-trigger-intersection-observer'?: boolean
69
- 'enable-var'?: boolean
70
- 'external-var-context'?: Record<string, any>
71
- 'parent-font-size'?: number
72
- 'parent-width'?: number
73
- 'parent-height'?: number
74
- 'wait-for'?: Array<GestureHandler>
75
- 'simultaneous-handlers'?: Array<GestureHandler>
76
- 'scroll-event-throttle'?: number
77
- bindscrolltoupper?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
78
- bindscrolltolower?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
79
- bindscroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
80
- bindrefresherrefresh?: (event: NativeSyntheticEvent<unknown>) => void
81
- binddragstart?: (event: NativeSyntheticEvent<DragEvent>) => void
82
- binddragging?: (event: NativeSyntheticEvent<DragEvent>) => void
83
- binddragend?: (event: NativeSyntheticEvent<DragEvent>) => void
84
- bindtouchstart?: (event: NativeSyntheticEvent<TouchEvent>) => void
85
- bindtouchmove?: (event: NativeSyntheticEvent<TouchEvent>) => void
86
- bindtouchend?: (event: NativeSyntheticEvent<TouchEvent>) => void
87
- bindscrollend?: (event: NativeSyntheticEvent<TouchEvent>) => void
46
+ children?: ReactNode;
47
+ enhanced?: boolean;
48
+ bounces?: boolean;
49
+ style?: ViewStyle;
50
+ 'scroll-x'?: boolean;
51
+ 'scroll-y'?: boolean;
52
+ 'enable-back-to-top'?: boolean;
53
+ 'show-scrollbar'?: boolean;
54
+ 'paging-enabled'?: boolean;
55
+ 'upper-threshold'?: number;
56
+ 'lower-threshold'?: number;
57
+ 'scroll-with-animation'?: boolean;
58
+ 'refresher-triggered'?: boolean;
59
+ 'refresher-enabled'?: boolean;
60
+ 'refresher-default-style'?: 'black' | 'white' | 'none';
61
+ 'refresher-background'?: string;
62
+ 'refresher-threshold'?: number;
63
+ 'scroll-top'?: number;
64
+ 'scroll-left'?: number;
65
+ 'enable-offset'?: boolean;
66
+ 'scroll-into-view'?: string;
67
+ 'enable-trigger-intersection-observer'?: boolean;
68
+ 'enable-var'?: boolean;
69
+ 'external-var-context'?: Record<string, any>;
70
+ 'parent-font-size'?: number;
71
+ 'parent-width'?: number;
72
+ 'parent-height'?: number;
73
+ 'enable-sticky'?: boolean;
74
+ 'wait-for'?: Array<GestureHandler>;
75
+ 'simultaneous-handlers'?: Array<GestureHandler>;
76
+ 'scroll-event-throttle'?:number;
77
+ 'scroll-into-view-offset'?: number;
78
+ bindscrolltoupper?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
79
+ bindscrolltolower?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
80
+ bindscroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
81
+ bindrefresherrefresh?: (event: NativeSyntheticEvent<unknown>) => void;
82
+ binddragstart?: (event: NativeSyntheticEvent<DragEvent>) => void;
83
+ binddragging?: (event: NativeSyntheticEvent<DragEvent>) => void;
84
+ binddragend?: (event: NativeSyntheticEvent<DragEvent>) => void;
85
+ bindtouchstart?: (event: NativeSyntheticEvent<TouchEvent>) => void;
86
+ bindtouchmove?: (event: NativeSyntheticEvent<TouchEvent>) => void;
87
+ bindtouchend?: (event: NativeSyntheticEvent<TouchEvent>) => void;
88
+ bindscrollend?: (event: NativeSyntheticEvent<TouchEvent>) => void;
88
89
  __selectRef?: (selector: string, nodeType: 'node' | 'component', all?: boolean) => HandlerRef<any, any>
89
90
  }
90
91
  type ScrollAdditionalProps = {
@@ -109,6 +110,8 @@ type ScrollAdditionalProps = {
109
110
  onMomentumScrollEnd?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
110
111
  }
111
112
 
113
+ const AnimatedScrollView = RNAnimated.createAnimatedComponent(ScrollView) as React.ComponentType<any>
114
+
112
115
  const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, ScrollViewProps>((scrollViewProps: ScrollViewProps = {}, ref): JSX.Element => {
113
116
  const { textProps, innerProps: props = {} } = splitProps(scrollViewProps)
114
117
  const {
@@ -145,10 +148,14 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
145
148
  'parent-height': parentHeight,
146
149
  'simultaneous-handlers': originSimultaneousHandlers,
147
150
  'wait-for': waitFor,
151
+ 'enable-sticky': enableSticky,
148
152
  'scroll-event-throttle': scrollEventThrottle = 0,
153
+ 'scroll-into-view-offset': scrollIntoViewOffset = 0,
149
154
  __selectRef
150
155
  } = props
151
156
 
157
+ const scrollOffset = useRef(new RNAnimated.Value(0)).current
158
+
152
159
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers)
153
160
  const waitForHandlers = flatGesture(waitFor)
154
161
 
@@ -180,7 +187,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
180
187
  const initialTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
181
188
  const intersectionObservers = useContext(IntersectionObserverContext)
182
189
 
183
- const firstScrollIntoViewChange = useRef<boolean>(false)
190
+ const firstScrollIntoViewChange = useRef<boolean>(true)
184
191
 
185
192
  const refreshColor = {
186
193
  black: ['#000'],
@@ -213,19 +220,21 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
213
220
  pagingEnabled,
214
221
  fastDeceleration: false,
215
222
  decelerationDisabled: false,
216
- scrollTo
223
+ scrollTo,
224
+ scrollIntoView: handleScrollIntoView
217
225
  },
218
226
  gestureRef: scrollViewRef
219
227
  })
220
228
 
229
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
230
+
221
231
  const contextValue = useMemo(() => {
222
232
  return {
223
- gestureRef: scrollViewRef
233
+ gestureRef: scrollViewRef,
234
+ scrollOffset
224
235
  }
225
236
  }, [])
226
237
 
227
- const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
228
-
229
238
  const hasRefresherLayoutRef = useRef(false)
230
239
 
231
240
  // layout 完成前先隐藏,避免安卓闪烁问题
@@ -251,13 +260,15 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
251
260
 
252
261
  useEffect(() => {
253
262
  if (scrollIntoView && __selectRef) {
254
- if (!firstScrollIntoViewChange.current) {
255
- setTimeout(handleScrollIntoView)
263
+ if (firstScrollIntoViewChange.current) {
264
+ setTimeout(() => {
265
+ handleScrollIntoView(scrollIntoView, { offset: scrollIntoViewOffset, animated: scrollWithAnimation })
266
+ })
256
267
  } else {
257
- handleScrollIntoView()
268
+ handleScrollIntoView(scrollIntoView, { offset: scrollIntoViewOffset, animated: scrollWithAnimation })
258
269
  }
259
270
  }
260
- firstScrollIntoViewChange.current = true
271
+ firstScrollIntoViewChange.current = false
261
272
  }, [scrollIntoView])
262
273
 
263
274
  useEffect(() => {
@@ -280,14 +291,16 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
280
291
  scrollToOffset(left, top, animated)
281
292
  }
282
293
 
283
- function handleScrollIntoView () {
284
- const refs = __selectRef!(`#${scrollIntoView}`, 'node')
294
+ function handleScrollIntoView (selector = '', { offset = 0, animated = true } = {}) {
295
+ const refs = __selectRef!(`#${selector}`, 'node')
285
296
  if (!refs) return
286
297
  const { nodeRef } = refs.getNodeInstance()
287
298
  nodeRef.current?.measureLayout(
288
299
  scrollViewRef.current,
289
300
  (left: number, top: number) => {
290
- scrollToOffset(left, top)
301
+ const adjustedLeft = scrollX ? left + offset : left
302
+ const adjustedTop = scrollY ? top + offset : top
303
+ scrollToOffset(adjustedLeft, adjustedTop, animated)
291
304
  }
292
305
  )
293
306
  }
@@ -487,6 +500,16 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
487
500
  updateIntersection()
488
501
  }
489
502
 
503
+ const scrollHandler = RNAnimated.event(
504
+ [{ nativeEvent: { contentOffset: { y: scrollOffset } } }],
505
+ {
506
+ useNativeDriver: true,
507
+ listener: (event: NativeSyntheticEvent<NativeScrollEvent>) => {
508
+ onScroll(event)
509
+ }
510
+ }
511
+ )
512
+
490
513
  function onScrollDragStart (e: NativeSyntheticEvent<NativeScrollEvent>) {
491
514
  hasCallScrollToLower.current = false
492
515
  hasCallScrollToUpper.current = false
@@ -661,7 +684,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
661
684
  scrollEnabled: !enableScroll ? false : !!(scrollX || scrollY),
662
685
  bounces: false,
663
686
  ref: scrollViewRef,
664
- onScroll: onScroll,
687
+ onScroll: enableSticky ? scrollHandler : onScroll,
665
688
  onContentSizeChange: onContentSizeChange,
666
689
  bindtouchstart: ((enhanced && binddragstart) || bindtouchstart) && onScrollTouchStart,
667
690
  bindtouchmove: ((enhanced && binddragging) || bindtouchmove) && onScrollTouchMove,
@@ -716,11 +739,13 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
716
739
  'bindrefresherrefresh'
717
740
  ], { layoutRef })
718
741
 
742
+ const ScrollViewComponent = enableSticky ? AnimatedScrollView : ScrollView
743
+
719
744
  const withRefresherScrollView = createElement(
720
745
  GestureDetector,
721
746
  { gesture: panGesture },
722
747
  createElement(
723
- ScrollView,
748
+ ScrollViewComponent,
724
749
  innerProps,
725
750
  createElement(
726
751
  Animated.View,
@@ -748,8 +773,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
748
773
  )
749
774
 
750
775
  const commonScrollView = createElement(
751
- ScrollView,
752
- extendObject(innerProps, {
776
+ ScrollViewComponent,
777
+ extendObject({}, innerProps, {
753
778
  refreshControl: refresherEnabled
754
779
  ? createElement(RefreshControl, extendObject({
755
780
  progressBackgroundColor: refresherBackground,
@@ -0,0 +1,181 @@
1
+ import { useEffect, useRef, useContext, forwardRef, useMemo, createElement, ReactNode, useId } from 'react'
2
+ import { Animated, StyleSheet, View, NativeSyntheticEvent, ViewStyle, LayoutChangeEvent, useAnimatedValue } from 'react-native'
3
+ import { ScrollViewContext, StickyContext } from './context'
4
+ import useNodesRef, { HandlerRef } 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
+
9
+ interface StickyHeaderProps {
10
+ children?: ReactNode;
11
+ style?: ViewStyle;
12
+ padding?: [number, number, number, number];
13
+ 'offset-top'?: number;
14
+ 'enable-var'?: boolean;
15
+ 'external-var-context'?: Record<string, any>;
16
+ 'parent-font-size'?: number;
17
+ 'parent-width'?: number;
18
+ 'parent-height'?: number;
19
+ bindstickontopchange?: (e: NativeSyntheticEvent<unknown>) => void;
20
+ }
21
+
22
+ const _StickyHeader = forwardRef<HandlerRef<View, StickyHeaderProps>, StickyHeaderProps>((stickyHeaderProps: StickyHeaderProps = {}, ref): JSX.Element => {
23
+ const { textProps, innerProps: props = {} } = splitProps(stickyHeaderProps)
24
+ const {
25
+ style,
26
+ bindstickontopchange,
27
+ padding = [0, 0, 0, 0],
28
+ 'offset-top': offsetTop = 0,
29
+ 'enable-var': enableVar,
30
+ 'external-var-context': externalVarContext,
31
+ 'parent-font-size': parentFontSize,
32
+ 'parent-width': parentWidth,
33
+ 'parent-height': parentHeight
34
+ } = props
35
+
36
+ const scrollViewContext = useContext(ScrollViewContext)
37
+ const stickyContext = useContext(StickyContext)
38
+ const { scrollOffset } = scrollViewContext
39
+ const { registerStickyHeader, unregisterStickyHeader } = stickyContext
40
+ const headerRef = useRef<View>(null)
41
+ const isStickOnTopRef = useRef(false)
42
+ const id = useId()
43
+
44
+ const {
45
+ normalStyle,
46
+ hasVarDec,
47
+ varContextRef,
48
+ hasSelfPercent,
49
+ setWidth,
50
+ setHeight
51
+ } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
52
+
53
+ const { layoutRef, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: headerRef, onLayout })
54
+
55
+ const { textStyle, innerStyle = {} } = splitStyle(normalStyle)
56
+
57
+ const headerTopAnimated = useAnimatedValue(0)
58
+ // harmony animatedValue 不支持通过 _value 访问
59
+ const headerTopRef = useRef(0)
60
+
61
+ useEffect(() => {
62
+ registerStickyHeader({ key: id, updatePosition })
63
+ return () => {
64
+ unregisterStickyHeader(id)
65
+ }
66
+ }, [])
67
+
68
+ function updatePosition () {
69
+ if (headerRef.current) {
70
+ const scrollViewRef = scrollViewContext.gestureRef
71
+ if (scrollViewRef && scrollViewRef.current) {
72
+ headerRef.current.measureLayout(
73
+ scrollViewRef.current,
74
+ (left: number, top: number) => {
75
+ Animated.timing(headerTopAnimated, {
76
+ toValue: top,
77
+ duration: 0,
78
+ useNativeDriver: true
79
+ }).start()
80
+ headerTopRef.current = top
81
+ }
82
+ )
83
+ } else {
84
+ error('StickyHeader measureLayout error: scrollViewRef is not a valid native component reference')
85
+ }
86
+ }
87
+ }
88
+
89
+ function onLayout (e: LayoutChangeEvent) {
90
+ updatePosition()
91
+ }
92
+
93
+ useNodesRef(props, ref, headerRef, {
94
+ style: normalStyle
95
+ })
96
+
97
+ useEffect(() => {
98
+ if (!bindstickontopchange) return
99
+
100
+ const listener = scrollOffset.addListener((state: { value: number }) => {
101
+ const currentScrollValue = state.value
102
+ const newIsStickOnTop = currentScrollValue > headerTopRef.current
103
+ if (newIsStickOnTop !== isStickOnTopRef.current) {
104
+ isStickOnTopRef.current = newIsStickOnTop
105
+ bindstickontopchange(
106
+ getCustomEvent('stickontopchange', {}, {
107
+ detail: {
108
+ isStickOnTop: newIsStickOnTop
109
+ },
110
+ layoutRef
111
+ }, props))
112
+ }
113
+ })
114
+
115
+ return () => {
116
+ scrollOffset.removeListener(listener)
117
+ }
118
+ }, [])
119
+
120
+ const animatedStyle = useMemo(() => {
121
+ const translateY = Animated.subtract(scrollOffset, headerTopAnimated).interpolate({
122
+ inputRange: [0, 1],
123
+ outputRange: [0, 1],
124
+ extrapolateLeft: 'clamp',
125
+ extrapolateRight: 'extend'
126
+ })
127
+
128
+ const finalTranslateY = offsetTop === 0
129
+ ? translateY
130
+ : Animated.add(
131
+ translateY,
132
+ Animated.subtract(scrollOffset, headerTopAnimated).interpolate({
133
+ inputRange: [0, 1],
134
+ outputRange: [0, offsetTop],
135
+ extrapolate: 'clamp'
136
+ })
137
+ )
138
+
139
+ return {
140
+ transform: [{ translateY: finalTranslateY }]
141
+ }
142
+ }, [scrollOffset, headerTopAnimated, offsetTop])
143
+
144
+ const innerProps = useInnerProps(extendObject({}, props, {
145
+ ref: headerRef,
146
+ style: extendObject({}, styles.content, innerStyle, animatedStyle, {
147
+ paddingTop: padding[0] || 0,
148
+ paddingRight: padding[1] || 0,
149
+ paddingBottom: padding[2] || 0,
150
+ paddingLeft: padding[3] || 0
151
+ })
152
+ }, layoutProps), [], { layoutRef })
153
+
154
+ return (
155
+ createElement(
156
+ Animated.View,
157
+ innerProps,
158
+ wrapChildren(
159
+ props,
160
+ {
161
+ hasVarDec,
162
+ varContext: varContextRef.current,
163
+ textStyle,
164
+ textProps
165
+ }
166
+ )
167
+ )
168
+ )
169
+ })
170
+
171
+ const styles = StyleSheet.create({
172
+ content: {
173
+ width: '100%',
174
+ zIndex: 10,
175
+ // harmony 需要手动设置 relative, zIndex 才生效
176
+ position: 'relative'
177
+ }
178
+ })
179
+
180
+ _StickyHeader.displayName = 'MpxStickyHeader'
181
+ export default _StickyHeader
@@ -0,0 +1,96 @@
1
+
2
+ import { useRef, forwardRef, createElement, ReactNode, useCallback, useMemo } from 'react'
3
+ import { View, ViewStyle } from 'react-native'
4
+ import useNodesRef, { HandlerRef } from './useNodesRef'
5
+ import { splitProps, splitStyle, useTransformStyle, wrapChildren, useLayout, extendObject } from './utils'
6
+ import { StickyContext } from './context'
7
+ import useInnerProps from './getInnerListeners'
8
+
9
+ interface StickySectionProps {
10
+ children?: ReactNode;
11
+ style?: ViewStyle;
12
+ 'offset-top'?: number;
13
+ 'enable-var'?: boolean;
14
+ 'external-var-context'?: Record<string, any>;
15
+ 'parent-font-size'?: number;
16
+ 'parent-width'?: number;
17
+ 'parent-height'?: number;
18
+ }
19
+
20
+ const _StickySection = forwardRef<HandlerRef<View, StickySectionProps>, StickySectionProps>((stickySectionProps: StickySectionProps = {}, ref): JSX.Element => {
21
+ const { textProps, innerProps: props = {} } = splitProps(stickySectionProps)
22
+ const {
23
+ style,
24
+ 'enable-var': enableVar,
25
+ 'external-var-context': externalVarContext,
26
+ 'parent-font-size': parentFontSize,
27
+ 'parent-width': parentWidth,
28
+ 'parent-height': parentHeight
29
+ } = props
30
+ const sectionRef = useRef<View>(null)
31
+
32
+ const {
33
+ normalStyle,
34
+ hasVarDec,
35
+ varContextRef,
36
+ hasSelfPercent,
37
+ setWidth,
38
+ setHeight
39
+ } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
40
+
41
+ const { layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: sectionRef, onLayout })
42
+
43
+ const { textStyle, innerStyle = {} } = splitStyle(normalStyle)
44
+
45
+ const stickyHeaders = useRef<Map<string, any>>(new Map())
46
+
47
+ const registerStickyHeader = useCallback((item: { id: string, updatePosition: Function }) => {
48
+ stickyHeaders.current.set(item.id, item)
49
+ }, [])
50
+
51
+ const unregisterStickyHeader = useCallback((id: string) => {
52
+ stickyHeaders.current.delete(id)
53
+ }, [])
54
+
55
+ const contextValue = useMemo(() => ({
56
+ registerStickyHeader,
57
+ unregisterStickyHeader
58
+ }), [])
59
+
60
+ useNodesRef(props, ref, sectionRef, {
61
+ style: normalStyle
62
+ })
63
+
64
+ function onLayout () {
65
+ stickyHeaders.current.forEach(item => {
66
+ item.updatePosition()
67
+ })
68
+ }
69
+
70
+ const innerProps = useInnerProps(extendObject({}, props, {
71
+ style: extendObject(innerStyle, layoutStyle),
72
+ ref: sectionRef
73
+ }, layoutProps), [], { layoutRef })
74
+
75
+ return (
76
+ createElement(
77
+ View,
78
+ innerProps,
79
+ createElement(
80
+ StickyContext.Provider,
81
+ { value: contextValue },
82
+ wrapChildren(
83
+ props,
84
+ {
85
+ hasVarDec,
86
+ varContext: varContextRef.current,
87
+ textStyle,
88
+ textProps
89
+ }
90
+ )
91
+ ))
92
+ )
93
+ })
94
+
95
+ _StickySection.displayName = 'MpxStickySection'
96
+ export default _StickySection
@@ -143,7 +143,8 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
143
143
  style = {},
144
144
  autoplay = false,
145
145
  circular = false,
146
- disableGesture = false
146
+ disableGesture = false,
147
+ bindchange
147
148
  } = props
148
149
  const easeingFunc = props['easing-function'] || 'default'
149
150
  const easeDuration = props.duration || 500
@@ -428,6 +429,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
428
429
  if (props.current !== currentIndex.value) {
429
430
  const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef })
430
431
  props.bindchange && props.bindchange(eventData)
432
+ bindchange && bindchange(eventData)
431
433
  }
432
434
  }
433
435
 
@@ -469,7 +471,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
469
471
  // 1. 用户在当前页切换选中项,动画;用户携带选中index打开到swiper页直接选中不走动画
470
472
  useAnimatedReaction(() => currentIndex.value, (newIndex: number, preIndex: number) => {
471
473
  // 这里必须传递函数名, 直接写()=> {}形式会报 访问了未sharedValue信息
472
- if (newIndex !== preIndex && props.bindchange) {
474
+ if (newIndex !== preIndex && bindchange) {
473
475
  runOnJS(handleSwiperChange)(newIndex)
474
476
  }
475
477
  })
@@ -1,4 +1,5 @@
1
1
  <script>
2
+ import { computed } from 'vue'
2
3
  import getInnerListeners, { getCustomEvent } from './getInnerListeners'
3
4
  import { processSize } from '../../utils'
4
5
  import BScroll from '@better-scroll/core'
@@ -44,6 +45,7 @@
44
45
  enhanced: Boolean,
45
46
  refresherEnabled: Boolean,
46
47
  refresherTriggered: Boolean,
48
+ enableSticky: Boolean,
47
49
  refresherThreshold: {
48
50
  type: Number,
49
51
  default: 45
@@ -57,6 +59,12 @@
57
59
  default: ''
58
60
  }
59
61
  },
62
+ provide () {
63
+ return {
64
+ scrollOffset: computed(() => -this.lastY || 0),
65
+ refreshVersion: computed(() => this.refreshVersion || 0)
66
+ }
67
+ },
60
68
  data () {
61
69
  return {
62
70
  isLoading: false,
@@ -68,7 +76,8 @@
68
76
  lastContentWidth: 0,
69
77
  lastContentHeight: 0,
70
78
  lastWrapperWidth: 0,
71
- lastWrapperHeight: 0
79
+ lastWrapperHeight: 0,
80
+ refreshVersion: 0
72
81
  }
73
82
  },
74
83
  computed: {
@@ -222,6 +231,9 @@
222
231
  stop: 56
223
232
  }
224
233
  }
234
+ if(this.enableSticky) {
235
+ originBsOptions.useTransition = false
236
+ }
225
237
  const bsOptions = Object.assign({}, originBsOptions, this.scrollOptions, { observeDOM: false })
226
238
  this.bs = new BScroll(this.$refs.wrapper, bsOptions)
227
239
  this.lastX = -this.currentX
@@ -251,7 +263,7 @@
251
263
  }
252
264
  this.lastX = x
253
265
  this.lastY = y
254
- }, 30, {
266
+ }, this.enableSticky ? 0 : 30, {
255
267
  leading: true,
256
268
  trailing: true
257
269
  }))
@@ -392,6 +404,7 @@
392
404
  this.lastContentHeight = scrollContentHeight
393
405
  this.lastWrapperWidth = scrollWrapperWidth
394
406
  this.lastWrapperHeight = scrollWrapperHeight
407
+ this.refreshVersion++
395
408
  if (this.bs) this.bs.refresh()
396
409
  }
397
410
  },
@@ -458,7 +471,8 @@
458
471
  }
459
472
 
460
473
  const innerWrapper = createElement('div', {
461
- ref: 'innerWrapper'
474
+ ref: 'innerWrapper',
475
+ class: 'mpx-inner-wrapper'
462
476
  }, this.$slots.default)
463
477
 
464
478
  const pullDownContent = this.refresherDefaultStyle !== 'none' ? createElement('div', {
@@ -568,4 +582,4 @@
568
582
  background: rgba(255, 255, 255, .7)
569
583
  100%
570
584
  background: rgba(255, 255, 255, .3)
571
- </style>
585
+ </style>