@mpxjs/webpack-plugin 2.10.4-beta.2 → 2.10.4-beta.20
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.
- package/lib/parser.js +1 -1
- package/lib/platform/json/wx/index.js +0 -1
- package/lib/platform/style/wx/index.js +22 -21
- package/lib/platform/template/wx/component-config/button.js +1 -1
- package/lib/platform/template/wx/component-config/index.js +5 -1
- package/lib/platform/template/wx/component-config/input.js +1 -1
- package/lib/platform/template/wx/component-config/sticky-header.js +23 -0
- package/lib/platform/template/wx/component-config/sticky-section.js +23 -0
- package/lib/react/processJSON.js +7 -6
- package/lib/runtime/components/react/context.ts +12 -3
- package/lib/runtime/components/react/dist/context.js +4 -1
- package/lib/runtime/components/react/dist/event.config.js +0 -2
- package/lib/runtime/components/react/dist/getInnerListeners.js +127 -153
- package/lib/runtime/components/react/dist/mpx-button.jsx +4 -5
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +3 -4
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +2 -3
- package/lib/runtime/components/react/dist/mpx-form.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-icon/index.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-input.jsx +8 -5
- package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +23 -30
- package/lib/runtime/components/react/dist/mpx-label.jsx +2 -3
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-navigator.jsx +11 -3
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +2 -3
- package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +3 -3
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-radio.jsx +2 -3
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +32 -16
- package/lib/runtime/components/react/dist/mpx-simple-text.jsx +3 -2
- package/lib/runtime/components/react/dist/mpx-simple-view.jsx +3 -3
- package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +115 -0
- package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +45 -0
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +5 -6
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +99 -37
- package/lib/runtime/components/react/dist/mpx-switch.jsx +3 -5
- package/lib/runtime/components/react/dist/mpx-text.jsx +4 -7
- package/lib/runtime/components/react/dist/mpx-video.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-view.jsx +23 -9
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +13 -13
- package/lib/runtime/components/react/dist/useAnimationHooks.js +26 -4
- package/lib/runtime/components/react/dist/utils.jsx +12 -1
- package/lib/runtime/components/react/event.config.ts +1 -8
- package/lib/runtime/components/react/getInnerListeners.ts +146 -192
- package/lib/runtime/components/react/mpx-button.tsx +7 -7
- package/lib/runtime/components/react/mpx-canvas/index.tsx +23 -15
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +4 -3
- package/lib/runtime/components/react/mpx-checkbox.tsx +8 -9
- package/lib/runtime/components/react/mpx-form.tsx +25 -19
- package/lib/runtime/components/react/mpx-icon/index.tsx +4 -3
- package/lib/runtime/components/react/mpx-image.tsx +4 -3
- package/lib/runtime/components/react/mpx-input.tsx +14 -9
- package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +31 -42
- package/lib/runtime/components/react/mpx-label.tsx +4 -5
- package/lib/runtime/components/react/mpx-movable-area.tsx +22 -13
- package/lib/runtime/components/react/mpx-movable-view.tsx +47 -40
- package/lib/runtime/components/react/mpx-navigator.tsx +4 -6
- package/lib/runtime/components/react/mpx-picker/index.tsx +7 -4
- package/lib/runtime/components/react/mpx-picker-view/index.tsx +17 -14
- package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +3 -3
- package/lib/runtime/components/react/mpx-radio-group.tsx +4 -3
- package/lib/runtime/components/react/mpx-radio.tsx +8 -9
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +15 -6
- package/lib/runtime/components/react/mpx-scroll-view.tsx +97 -66
- package/lib/runtime/components/react/mpx-simple-text.tsx +10 -3
- package/lib/runtime/components/react/mpx-simple-view.tsx +10 -4
- package/lib/runtime/components/react/mpx-sticky-header.tsx +179 -0
- package/lib/runtime/components/react/mpx-sticky-section.tsx +96 -0
- package/lib/runtime/components/react/mpx-swiper-item.tsx +32 -25
- package/lib/runtime/components/react/mpx-swiper.tsx +166 -88
- package/lib/runtime/components/react/mpx-switch.tsx +19 -14
- package/lib/runtime/components/react/mpx-text.tsx +16 -13
- package/lib/runtime/components/react/mpx-video.tsx +34 -33
- package/lib/runtime/components/react/mpx-view.tsx +41 -17
- package/lib/runtime/components/react/mpx-web-view.tsx +12 -12
- package/lib/runtime/components/react/types/getInnerListeners.d.ts +65 -35
- package/lib/runtime/components/react/useAnimationHooks.ts +29 -9
- package/lib/runtime/components/react/utils.tsx +12 -1
- package/lib/runtime/components/web/mpx-scroll-view.vue +21 -4
- package/lib/runtime/components/web/mpx-sticky-header.vue +91 -0
- package/lib/runtime/components/web/mpx-sticky-section.vue +15 -0
- package/lib/script-setup-compiler/index.js +27 -5
- package/lib/template-compiler/compiler.js +3 -2
- package/package.json +1 -1
|
@@ -22,9 +22,9 @@ export interface RadioProps {
|
|
|
22
22
|
'enable-offset'?: boolean
|
|
23
23
|
'enable-var'?: boolean
|
|
24
24
|
'external-var-context'?: Record<string, any>
|
|
25
|
-
'parent-font-size'?: number
|
|
26
|
-
'parent-width'?: number
|
|
27
|
-
'parent-height'?: number
|
|
25
|
+
'parent-font-size'?: number
|
|
26
|
+
'parent-width'?: number
|
|
27
|
+
'parent-height'?: number
|
|
28
28
|
children: ReactNode
|
|
29
29
|
bindtap?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
|
|
30
30
|
}
|
|
@@ -84,7 +84,7 @@ const Radio = forwardRef<HandlerRef<View, RadioProps>, RadioProps>(
|
|
|
84
84
|
const [isChecked, setIsChecked] = useState<boolean>(!!checked)
|
|
85
85
|
|
|
86
86
|
const groupContext = useContext(RadioGroupContext)
|
|
87
|
-
let groupValue: { [key: string]: { checked: boolean; setValue: Dispatch<SetStateAction<boolean
|
|
87
|
+
let groupValue: { [key: string]: { checked: boolean; setValue: Dispatch<SetStateAction<boolean>> } } | undefined
|
|
88
88
|
let notifyChange: (evt: NativeSyntheticEvent<TouchEvent>) => void | undefined
|
|
89
89
|
|
|
90
90
|
const labelContext = useContext(LabelContext)
|
|
@@ -149,14 +149,13 @@ const Radio = forwardRef<HandlerRef<View, RadioProps>, RadioProps>(
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
const innerProps = useInnerProps(
|
|
152
|
-
props,
|
|
153
152
|
extendObject(
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
style: extendObject({}, innerStyle, layoutStyle)
|
|
157
|
-
},
|
|
153
|
+
{},
|
|
154
|
+
props,
|
|
158
155
|
layoutProps,
|
|
159
156
|
{
|
|
157
|
+
ref: nodeRef,
|
|
158
|
+
style: extendObject({}, innerStyle, layoutStyle),
|
|
160
159
|
bindtap: !disabled && onTap
|
|
161
160
|
}
|
|
162
161
|
),
|
|
@@ -91,12 +91,21 @@ const _RichText = forwardRef<HandlerRef<View, _RichTextProps>, _RichTextProps>((
|
|
|
91
91
|
layoutRef
|
|
92
92
|
})
|
|
93
93
|
|
|
94
|
-
const innerProps = useInnerProps(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
const innerProps = useInnerProps(
|
|
95
|
+
extendObject(
|
|
96
|
+
{},
|
|
97
|
+
props,
|
|
98
|
+
layoutProps,
|
|
99
|
+
{
|
|
100
|
+
ref: nodeRef,
|
|
101
|
+
style: extendObject(normalStyle, layoutStyle)
|
|
102
|
+
}
|
|
103
|
+
),
|
|
104
|
+
[],
|
|
105
|
+
{
|
|
106
|
+
layoutRef
|
|
107
|
+
}
|
|
108
|
+
)
|
|
100
109
|
|
|
101
110
|
const html: string = typeof nodes === 'string' ? nodes : jsonToHtmlStr(nodes)
|
|
102
111
|
|
|
@@ -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 } from '@mpxjs/utils'
|
|
@@ -46,7 +46,6 @@ interface ScrollViewProps {
|
|
|
46
46
|
enhanced?: boolean;
|
|
47
47
|
bounces?: boolean;
|
|
48
48
|
style?: ViewStyle;
|
|
49
|
-
scrollEventThrottle?: number;
|
|
50
49
|
'scroll-x'?: boolean;
|
|
51
50
|
'scroll-y'?: boolean;
|
|
52
51
|
'enable-back-to-top'?: boolean;
|
|
@@ -70,9 +69,11 @@ interface ScrollViewProps {
|
|
|
70
69
|
'parent-font-size'?: number;
|
|
71
70
|
'parent-width'?: number;
|
|
72
71
|
'parent-height'?: number;
|
|
72
|
+
'enable-sticky'?: boolean;
|
|
73
73
|
'wait-for'?: Array<GestureHandler>;
|
|
74
74
|
'simultaneous-handlers'?: Array<GestureHandler>;
|
|
75
75
|
'scroll-event-throttle'?:number;
|
|
76
|
+
'scroll-into-view-offset'?: number;
|
|
76
77
|
bindscrolltoupper?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
77
78
|
bindscrolltolower?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
78
79
|
bindscroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
@@ -87,26 +88,28 @@ interface ScrollViewProps {
|
|
|
87
88
|
__selectRef?: (selector: string, nodeType: 'node' | 'component', all?: boolean) => HandlerRef<any, any>
|
|
88
89
|
}
|
|
89
90
|
type ScrollAdditionalProps = {
|
|
90
|
-
pinchGestureEnabled: boolean
|
|
91
|
-
horizontal: boolean
|
|
92
|
-
onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
|
93
|
-
onContentSizeChange: (width: number, height: number) => void
|
|
94
|
-
onLayout?: (event: LayoutChangeEvent) => void
|
|
95
|
-
scrollsToTop: boolean
|
|
96
|
-
showsHorizontalScrollIndicator: boolean
|
|
97
|
-
showsVerticalScrollIndicator: boolean
|
|
98
|
-
scrollEnabled: boolean
|
|
99
|
-
ref: RefObject<ScrollView
|
|
100
|
-
bounces?: boolean
|
|
101
|
-
pagingEnabled?: boolean
|
|
102
|
-
style?: ViewStyle
|
|
103
|
-
bindtouchstart?: (event: NativeSyntheticEvent<TouchEvent>) => void
|
|
104
|
-
bindtouchmove?: (event: NativeSyntheticEvent<TouchEvent>) => void
|
|
105
|
-
bindtouchend?: (event: NativeSyntheticEvent<TouchEvent>) => void
|
|
106
|
-
onScrollBeginDrag?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
|
107
|
-
onScrollEndDrag?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
|
108
|
-
onMomentumScrollEnd?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
|
109
|
-
}
|
|
91
|
+
pinchGestureEnabled: boolean
|
|
92
|
+
horizontal: boolean
|
|
93
|
+
onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
|
94
|
+
onContentSizeChange: (width: number, height: number) => void
|
|
95
|
+
onLayout?: (event: LayoutChangeEvent) => void
|
|
96
|
+
scrollsToTop: boolean
|
|
97
|
+
showsHorizontalScrollIndicator: boolean
|
|
98
|
+
showsVerticalScrollIndicator: boolean
|
|
99
|
+
scrollEnabled: boolean
|
|
100
|
+
ref: RefObject<ScrollView>
|
|
101
|
+
bounces?: boolean
|
|
102
|
+
pagingEnabled?: boolean
|
|
103
|
+
style?: ViewStyle
|
|
104
|
+
bindtouchstart?: (event: NativeSyntheticEvent<TouchEvent>) => void
|
|
105
|
+
bindtouchmove?: (event: NativeSyntheticEvent<TouchEvent>) => void
|
|
106
|
+
bindtouchend?: (event: NativeSyntheticEvent<TouchEvent>) => void
|
|
107
|
+
onScrollBeginDrag?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
|
108
|
+
onScrollEndDrag?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
|
109
|
+
onMomentumScrollEnd?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const AnimatedScrollView = RNAnimated.createAnimatedComponent(ScrollView) as React.ComponentType<any>
|
|
110
113
|
|
|
111
114
|
const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, ScrollViewProps>((scrollViewProps: ScrollViewProps = {}, ref): JSX.Element => {
|
|
112
115
|
const { textProps, innerProps: props = {} } = splitProps(scrollViewProps)
|
|
@@ -144,10 +147,14 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
144
147
|
'parent-height': parentHeight,
|
|
145
148
|
'simultaneous-handlers': originSimultaneousHandlers,
|
|
146
149
|
'wait-for': waitFor,
|
|
150
|
+
'enable-sticky': enableSticky,
|
|
147
151
|
'scroll-event-throttle': scrollEventThrottle = 0,
|
|
152
|
+
'scroll-into-view-offset': scrollIntoViewOffset = 0,
|
|
148
153
|
__selectRef
|
|
149
154
|
} = props
|
|
150
155
|
|
|
156
|
+
const scrollOffset = useRef(new RNAnimated.Value(0)).current
|
|
157
|
+
|
|
151
158
|
const simultaneousHandlers = flatGesture(originSimultaneousHandlers)
|
|
152
159
|
const waitForHandlers = flatGesture(waitFor)
|
|
153
160
|
|
|
@@ -179,7 +186,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
179
186
|
const initialTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
180
187
|
const intersectionObservers = useContext(IntersectionObserverContext)
|
|
181
188
|
|
|
182
|
-
const firstScrollIntoViewChange = useRef<boolean>(
|
|
189
|
+
const firstScrollIntoViewChange = useRef<boolean>(true)
|
|
183
190
|
|
|
184
191
|
const refreshColor = {
|
|
185
192
|
black: ['#000'],
|
|
@@ -211,19 +218,21 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
211
218
|
pagingEnabled,
|
|
212
219
|
fastDeceleration: false,
|
|
213
220
|
decelerationDisabled: false,
|
|
214
|
-
scrollTo
|
|
221
|
+
scrollTo,
|
|
222
|
+
scrollIntoView: handleScrollIntoView
|
|
215
223
|
},
|
|
216
224
|
gestureRef: scrollViewRef
|
|
217
225
|
})
|
|
218
226
|
|
|
227
|
+
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
|
|
228
|
+
|
|
219
229
|
const contextValue = useMemo(() => {
|
|
220
230
|
return {
|
|
221
|
-
gestureRef: scrollViewRef
|
|
231
|
+
gestureRef: scrollViewRef,
|
|
232
|
+
scrollOffset
|
|
222
233
|
}
|
|
223
234
|
}, [])
|
|
224
235
|
|
|
225
|
-
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
|
|
226
|
-
|
|
227
236
|
const hasRefresherLayoutRef = useRef(false)
|
|
228
237
|
|
|
229
238
|
// layout 完成前先隐藏,避免安卓闪烁问题
|
|
@@ -249,13 +258,15 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
249
258
|
|
|
250
259
|
useEffect(() => {
|
|
251
260
|
if (scrollIntoView && __selectRef) {
|
|
252
|
-
if (
|
|
253
|
-
setTimeout(
|
|
261
|
+
if (firstScrollIntoViewChange.current) {
|
|
262
|
+
setTimeout(() => {
|
|
263
|
+
handleScrollIntoView(scrollIntoView, { offset: scrollIntoViewOffset, animated: scrollWithAnimation })
|
|
264
|
+
})
|
|
254
265
|
} else {
|
|
255
|
-
handleScrollIntoView()
|
|
266
|
+
handleScrollIntoView(scrollIntoView, { offset: scrollIntoViewOffset, animated: scrollWithAnimation })
|
|
256
267
|
}
|
|
257
268
|
}
|
|
258
|
-
firstScrollIntoViewChange.current =
|
|
269
|
+
firstScrollIntoViewChange.current = false
|
|
259
270
|
}, [scrollIntoView])
|
|
260
271
|
|
|
261
272
|
useEffect(() => {
|
|
@@ -274,18 +285,20 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
274
285
|
}
|
|
275
286
|
}, [refresherTriggered])
|
|
276
287
|
|
|
277
|
-
function scrollTo ({ top = 0, left = 0, animated = false }
|
|
288
|
+
function scrollTo ({ top = 0, left = 0, animated = false }: { top?: number; left?: number; animated?: boolean }) {
|
|
278
289
|
scrollToOffset(left, top, animated)
|
|
279
290
|
}
|
|
280
291
|
|
|
281
|
-
function handleScrollIntoView () {
|
|
282
|
-
const refs = __selectRef!(`#${
|
|
292
|
+
function handleScrollIntoView (selector = '', { offset = 0, animated = true } = {}) {
|
|
293
|
+
const refs = __selectRef!(`#${selector}`, 'node')
|
|
283
294
|
if (!refs) return
|
|
284
295
|
const { nodeRef } = refs.getNodeInstance()
|
|
285
296
|
nodeRef.current?.measureLayout(
|
|
286
297
|
scrollViewRef.current,
|
|
287
298
|
(left: number, top: number) => {
|
|
288
|
-
|
|
299
|
+
const adjustedLeft = scrollX ? left + offset : left
|
|
300
|
+
const adjustedTop = scrollY ? top + offset : top
|
|
301
|
+
scrollToOffset(adjustedLeft, adjustedTop, animated)
|
|
289
302
|
}
|
|
290
303
|
)
|
|
291
304
|
}
|
|
@@ -485,6 +498,16 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
485
498
|
updateIntersection()
|
|
486
499
|
}
|
|
487
500
|
|
|
501
|
+
const scrollHandler = RNAnimated.event(
|
|
502
|
+
[{ nativeEvent: { contentOffset: { y: scrollOffset } } }],
|
|
503
|
+
{
|
|
504
|
+
useNativeDriver: true,
|
|
505
|
+
listener: (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
506
|
+
onScroll(event)
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
)
|
|
510
|
+
|
|
488
511
|
function onScrollDragStart (e: NativeSyntheticEvent<NativeScrollEvent>) {
|
|
489
512
|
hasCallScrollToLower.current = false
|
|
490
513
|
hasCallScrollToUpper.current = false
|
|
@@ -655,7 +678,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
655
678
|
scrollEnabled: !enableScroll ? false : !!(scrollX || scrollY),
|
|
656
679
|
bounces: false,
|
|
657
680
|
ref: scrollViewRef,
|
|
658
|
-
onScroll: onScroll,
|
|
681
|
+
onScroll: enableSticky ? scrollHandler : onScroll,
|
|
659
682
|
onContentSizeChange: onContentSizeChange,
|
|
660
683
|
bindtouchstart: ((enhanced && binddragstart) || bindtouchstart) && onScrollTouchStart,
|
|
661
684
|
bindtouchmove: ((enhanced && binddragging) || bindtouchmove) && onScrollTouchMove,
|
|
@@ -676,39 +699,47 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
676
699
|
})
|
|
677
700
|
}
|
|
678
701
|
|
|
679
|
-
const innerProps = useInnerProps(
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
702
|
+
const innerProps = useInnerProps(
|
|
703
|
+
extendObject(
|
|
704
|
+
{},
|
|
705
|
+
props,
|
|
706
|
+
scrollAdditionalProps
|
|
707
|
+
),
|
|
708
|
+
[
|
|
709
|
+
'id',
|
|
710
|
+
'scroll-x',
|
|
711
|
+
'scroll-y',
|
|
712
|
+
'enable-back-to-top',
|
|
713
|
+
'enable-trigger-intersection-observer',
|
|
714
|
+
'paging-enabled',
|
|
715
|
+
'show-scrollbar',
|
|
716
|
+
'upper-threshold',
|
|
717
|
+
'lower-threshold',
|
|
718
|
+
'scroll-top',
|
|
719
|
+
'scroll-left',
|
|
720
|
+
'scroll-with-animation',
|
|
721
|
+
'refresher-triggered',
|
|
722
|
+
'refresher-enabled',
|
|
723
|
+
'refresher-default-style',
|
|
724
|
+
'refresher-background',
|
|
725
|
+
'children',
|
|
726
|
+
'enhanced',
|
|
727
|
+
'binddragstart',
|
|
728
|
+
'binddragging',
|
|
729
|
+
'binddragend',
|
|
730
|
+
'bindscroll',
|
|
731
|
+
'bindscrolltoupper',
|
|
732
|
+
'bindscrolltolower',
|
|
733
|
+
'bindrefresherrefresh'
|
|
734
|
+
], { layoutRef })
|
|
735
|
+
|
|
736
|
+
const ScrollViewComponent = enableSticky ? AnimatedScrollView : ScrollView
|
|
706
737
|
|
|
707
738
|
const withRefresherScrollView = createElement(
|
|
708
739
|
GestureDetector,
|
|
709
740
|
{ gesture: panGesture },
|
|
710
741
|
createElement(
|
|
711
|
-
|
|
742
|
+
ScrollViewComponent,
|
|
712
743
|
innerProps,
|
|
713
744
|
createElement(
|
|
714
745
|
Animated.View,
|
|
@@ -736,8 +767,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
736
767
|
)
|
|
737
768
|
|
|
738
769
|
const commonScrollView = createElement(
|
|
739
|
-
|
|
740
|
-
extendObject(innerProps, {
|
|
770
|
+
ScrollViewComponent,
|
|
771
|
+
extendObject({}, innerProps, {
|
|
741
772
|
refreshControl: refresherEnabled
|
|
742
773
|
? createElement(RefreshControl, extendObject({
|
|
743
774
|
progressBackgroundColor: refresherBackground,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Text, TextProps } from 'react-native'
|
|
2
2
|
import { JSX, createElement } from 'react'
|
|
3
3
|
import useInnerProps from './getInnerListeners'
|
|
4
|
+
import { extendObject } from './utils'
|
|
4
5
|
|
|
5
6
|
const SimpleText = (props: TextProps): JSX.Element => {
|
|
6
7
|
const {
|
|
@@ -8,9 +9,15 @@ const SimpleText = (props: TextProps): JSX.Element => {
|
|
|
8
9
|
children
|
|
9
10
|
} = props
|
|
10
11
|
|
|
11
|
-
const innerProps = useInnerProps(
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const innerProps = useInnerProps(
|
|
13
|
+
extendObject(
|
|
14
|
+
{},
|
|
15
|
+
props,
|
|
16
|
+
{
|
|
17
|
+
allowFontScaling
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
)
|
|
14
21
|
|
|
15
22
|
return createElement(Text, innerProps, children)
|
|
16
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { View, ViewProps, TextStyle } from 'react-native'
|
|
2
2
|
import { createElement } from 'react'
|
|
3
|
-
import { splitProps, splitStyle, wrapChildren } from './utils'
|
|
3
|
+
import { splitProps, splitStyle, wrapChildren, extendObject } from './utils'
|
|
4
4
|
import useInnerProps from './getInnerListeners'
|
|
5
5
|
|
|
6
6
|
const SimpleView = (simpleViewProps: ViewProps): JSX.Element => {
|
|
@@ -8,9 +8,15 @@ const SimpleView = (simpleViewProps: ViewProps): JSX.Element => {
|
|
|
8
8
|
|
|
9
9
|
const { textStyle, innerStyle = {} } = splitStyle(props.style || {})
|
|
10
10
|
|
|
11
|
-
const innerProps = useInnerProps(
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const innerProps = useInnerProps(
|
|
12
|
+
extendObject(
|
|
13
|
+
{},
|
|
14
|
+
props,
|
|
15
|
+
{
|
|
16
|
+
style: innerStyle
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
)
|
|
14
20
|
|
|
15
21
|
return createElement(View, innerProps, wrapChildren(
|
|
16
22
|
props,
|
|
@@ -0,0 +1,179 @@
|
|
|
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
|
+
}
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
_StickyHeader.displayName = 'MpxStickyHeader'
|
|
179
|
+
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
|