@mpxjs/webpack-plugin 2.9.70 → 2.9.71

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 (60) hide show
  1. package/lib/platform/template/wx/component-config/movable-view.js +8 -1
  2. package/lib/platform/template/wx/component-config/picker-view.js +1 -5
  3. package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
  4. package/lib/platform/template/wx/index.js +0 -4
  5. package/lib/runtime/components/react/context.ts +8 -0
  6. package/lib/runtime/components/react/dist/context.js +2 -0
  7. package/lib/runtime/components/react/dist/getInnerListeners.js +34 -31
  8. package/lib/runtime/components/react/dist/mpx-button.jsx +16 -44
  9. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +93 -58
  10. package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
  11. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +35 -0
  12. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +151 -127
  13. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +38 -34
  14. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -11
  15. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +11 -4
  16. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +31 -8
  17. package/lib/runtime/components/react/dist/mpx-swiper.jsx +670 -0
  18. package/lib/runtime/components/react/dist/mpx-view.jsx +15 -53
  19. package/lib/runtime/components/react/dist/pickerFaces.js +7 -6
  20. package/lib/runtime/components/react/dist/pickerVIewContext.js +14 -0
  21. package/lib/runtime/components/react/dist/pickerViewIndicator.jsx +23 -0
  22. package/lib/runtime/components/react/dist/pickerViewMask.jsx +18 -0
  23. package/lib/runtime/components/react/dist/useAnimationHooks.js +20 -2
  24. package/lib/runtime/components/react/dist/utils.jsx +74 -11
  25. package/lib/runtime/components/react/getInnerListeners.ts +43 -32
  26. package/lib/runtime/components/react/mpx-button.tsx +20 -57
  27. package/lib/runtime/components/react/mpx-movable-view.tsx +119 -74
  28. package/lib/runtime/components/react/mpx-navigator.tsx +1 -1
  29. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +76 -0
  30. package/lib/runtime/components/react/mpx-picker-view-column.tsx +206 -183
  31. package/lib/runtime/components/react/mpx-picker-view.tsx +49 -48
  32. package/lib/runtime/components/react/mpx-rich-text/index.tsx +12 -18
  33. package/lib/runtime/components/react/mpx-scroll-view.tsx +21 -10
  34. package/lib/runtime/components/react/mpx-swiper-item.tsx +45 -11
  35. package/lib/runtime/components/react/mpx-swiper.tsx +742 -0
  36. package/lib/runtime/components/react/mpx-view.tsx +18 -65
  37. package/lib/runtime/components/react/pickerFaces.ts +10 -7
  38. package/lib/runtime/components/react/pickerVIewContext.ts +27 -0
  39. package/lib/runtime/components/react/pickerViewIndicator.tsx +34 -0
  40. package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
  41. package/lib/runtime/components/react/types/{getInnerListeners.ts → getInnerListeners.d.ts} +4 -5
  42. package/lib/runtime/components/react/types/global.d.ts +10 -0
  43. package/lib/runtime/components/react/useAnimationHooks.ts +24 -3
  44. package/lib/runtime/components/react/utils.tsx +85 -12
  45. package/lib/runtime/components/web/mpx-checkbox.vue +1 -1
  46. package/lib/runtime/components/web/mpx-picker-view-column.vue +9 -4
  47. package/lib/template-compiler/compiler.js +61 -13
  48. package/lib/wxss/loader.js +15 -2
  49. package/package.json +3 -3
  50. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +0 -480
  51. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +0 -68
  52. package/lib/runtime/components/react/dist/mpx-swiper/type.js +0 -1
  53. package/lib/runtime/components/react/dist/pickerOverlay.jsx +0 -21
  54. package/lib/runtime/components/react/dist/types/common.js +0 -1
  55. package/lib/runtime/components/react/dist/types/getInnerListeners.js +0 -1
  56. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
  57. package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
  58. package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
  59. package/lib/runtime/components/react/pickerOverlay.tsx +0 -32
  60. /package/lib/runtime/components/react/types/{common.ts → common.d.ts} +0 -0
@@ -12,9 +12,10 @@ import useAnimationHooks from './useAnimationHooks'
12
12
  import type { AnimationProp } from './useAnimationHooks'
13
13
  import { ExtendedViewStyle } from './types/common'
14
14
  import useNodesRef, { HandlerRef } from './useNodesRef'
15
- import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout, renderImage, pickStyle, extendObject } from './utils'
15
+ import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout, renderImage, pickStyle, extendObject, useHover } from './utils'
16
16
  import { error } from '@mpxjs/utils'
17
17
  import LinearGradient from 'react-native-linear-gradient'
18
+ import { GestureDetector, PanGesture } from 'react-native-gesture-handler'
18
19
 
19
20
  export interface _ViewProps extends ViewProps {
20
21
  style?: ExtendedViewStyle
@@ -642,7 +643,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
642
643
 
643
644
  interface WrapChildrenConfig {
644
645
  hasVarDec: boolean
645
- enableBackground: boolean
646
+ enableBackground?: boolean
646
647
  textStyle?: TextStyle
647
648
  backgroundStyle?: ExtendedViewStyle
648
649
  varContext?: Record<string, any>
@@ -684,8 +685,6 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
684
685
  animation
685
686
  } = props
686
687
 
687
- const [isHover, setIsHover] = useState(false)
688
-
689
688
  // 默认样式
690
689
  const defaultStyle: ExtendedViewStyle = style.display === 'flex'
691
690
  ? {
@@ -696,6 +695,9 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
696
695
  }
697
696
  : {}
698
697
 
698
+ const enableHover = !!hoverStyle
699
+ const { isHover, gesture } = useHover({ enableHover, hoverStartTime, hoverStayTime })
700
+
699
701
  const styleObj: ExtendedViewStyle = extendObject({}, defaultStyle, style, isHover ? hoverStyle as ExtendedViewStyle : {})
700
702
 
701
703
  const {
@@ -726,45 +728,6 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
726
728
  style: normalStyle
727
729
  })
728
730
 
729
- const dataRef = useRef<{
730
- startTimer?: ReturnType<typeof setTimeout>
731
- stayTimer?: ReturnType<typeof setTimeout>
732
- }>({})
733
-
734
- useEffect(() => {
735
- return () => {
736
- dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
737
- dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer)
738
- }
739
- }, [])
740
-
741
- const setStartTimer = () => {
742
- dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
743
- dataRef.current.startTimer = setTimeout(() => {
744
- setIsHover(true)
745
- }, +hoverStartTime)
746
- }
747
-
748
- const setStayTimer = () => {
749
- dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer)
750
- dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
751
- dataRef.current.stayTimer = setTimeout(() => {
752
- setIsHover(false)
753
- }, +hoverStayTime)
754
- }
755
-
756
- function onTouchStart (e: NativeSyntheticEvent<TouchEvent>) {
757
- const { bindtouchstart } = props
758
- bindtouchstart && bindtouchstart(e)
759
- setStartTimer()
760
- }
761
-
762
- function onTouchEnd (e: NativeSyntheticEvent<TouchEvent>) {
763
- const { bindtouchend } = props
764
- bindtouchend && bindtouchend(e)
765
- setStayTimer()
766
- }
767
-
768
731
  const {
769
732
  layoutRef,
770
733
  layoutStyle,
@@ -773,33 +736,19 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
773
736
 
774
737
  const viewStyle = extendObject({}, innerStyle, layoutStyle)
775
738
 
776
- enableAnimation = enableAnimation || !!animation
777
- const enableAnimationRef = useRef(enableAnimation)
778
- if (enableAnimationRef.current !== enableAnimation) {
779
- error('[Mpx runtime error]: animation use should be stable in the component lifecycle, or you can set [enable-animation] with true.')
780
- }
739
+ const { enableStyleAnimation, animationStyle } = useAnimationHooks({
740
+ enableAnimation,
741
+ animation,
742
+ style: viewStyle
743
+ })
781
744
 
782
- const finalStyle = enableAnimationRef.current
783
- ? [viewStyle,
784
- // eslint-disable-next-line react-hooks/rules-of-hooks
785
- useAnimationHooks({
786
- animation,
787
- style: viewStyle
788
- })]
789
- : viewStyle
790
745
  const innerProps = useInnerProps(
791
746
  props,
792
747
  extendObject({
793
748
  ref: nodeRef,
794
- style: finalStyle
749
+ style: enableStyleAnimation ? [viewStyle, animationStyle] : viewStyle
795
750
  },
796
- layoutProps,
797
- hoverStyle
798
- ? {
799
- bindtouchstart: onTouchStart,
800
- bindtouchend: onTouchEnd
801
- }
802
- : {}
751
+ layoutProps
803
752
  ), [
804
753
  'hover-start-time',
805
754
  'hover-stay-time',
@@ -820,9 +769,13 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
820
769
  enableFastImage
821
770
  })
822
771
 
823
- return enableAnimation
772
+ const BaseComponent = enableStyleAnimation
824
773
  ? createElement(Animated.View, innerProps, childNode)
825
774
  : createElement(View, innerProps, childNode)
775
+
776
+ return enableHover
777
+ ? createElement(GestureDetector, { gesture: gesture as PanGesture }, BaseComponent)
778
+ : BaseComponent
826
779
  })
827
780
 
828
781
  _View.displayName = 'MpxView'
@@ -8,6 +8,7 @@ export type Faces = {
8
8
  deg: number
9
9
  offsetY: number
10
10
  opacity: number
11
+ scale: number
11
12
  screenHeight: number
12
13
  }
13
14
 
@@ -33,7 +34,7 @@ export const createFaces = (
33
34
  const maxStep = Math.trunc((visibleCount + 2) / 2) // + 2 because there are 2 more faces at 90 degrees
34
35
  const stepDegree = 90 / maxStep
35
36
 
36
- const result = []
37
+ const result: number[] = []
37
38
  for (let i = 1; i <= maxStep; i++) {
38
39
  result.push(i * stepDegree)
39
40
  }
@@ -62,17 +63,17 @@ export const createFaces = (
62
63
  const getOpacity = (index: number) => {
63
64
  const map: Record<number, number> = {
64
65
  0: 0,
65
- 1: 0.2,
66
- 2: 0.35,
67
- 3: 0.45,
68
- 4: 0.5
66
+ 1: 0.8,
67
+ 2: 0.9
69
68
  }
70
- return map[index] ?? Math.min(1, map[4] + index * 0.5)
69
+ return map[index] ?? Math.min(1, map[2] + index * 0.05)
71
70
  }
72
71
 
73
72
  const degrees = getDegreesRelativeCenter()
74
73
  const [screenHeight, offsets] = getScreenHeightsAndOffsets(degrees)
75
74
 
75
+ const scales = [0.973, 0.9, 0.8]
76
+
76
77
  return [
77
78
  // top items
78
79
  ...degrees
@@ -82,13 +83,14 @@ export const createFaces = (
82
83
  deg: degree,
83
84
  opacity: getOpacity(degrees.length - 1 - index),
84
85
  offsetY: -1 * offsets[index],
86
+ scale: scales[index],
85
87
  screenHeight: screenHeight[index]
86
88
  }
87
89
  })
88
90
  .reverse(),
89
91
 
90
92
  // center item
91
- { index: 0, deg: 0, opacity: 1, offsetY: 0, screenHeight: itemHeight },
93
+ { index: 0, deg: 0, opacity: 1, offsetY: 0, scale: 1, screenHeight: itemHeight },
92
94
 
93
95
  // bottom items
94
96
  ...degrees.map<Faces>((degree, index) => {
@@ -97,6 +99,7 @@ export const createFaces = (
97
99
  deg: -1 * degree,
98
100
  opacity: getOpacity(degrees.length - 1 - index),
99
101
  offsetY: offsets[index],
102
+ scale: scales[index],
100
103
  screenHeight: screenHeight[index]
101
104
  }
102
105
  })
@@ -0,0 +1,27 @@
1
+ import { createContext, useContext } from 'react'
2
+ import { SharedValue } from 'react-native-reanimated'
3
+
4
+ type ContextValue = SharedValue<number>
5
+
6
+ export const PickerViewColumnAnimationContext = createContext<
7
+ ContextValue | undefined
8
+ >(undefined)
9
+
10
+ export const usePickerViewColumnAnimationContext = () => {
11
+ const value = useContext(PickerViewColumnAnimationContext)
12
+ if (value === undefined) {
13
+ throw new Error(
14
+ 'usePickerViewColumnAnimationContext must be called from within PickerViewColumnAnimationContext.Provider!'
15
+ )
16
+ }
17
+ return value
18
+ }
19
+
20
+ export const PickerViewStyleContext = createContext<
21
+ Record<string, any> | undefined
22
+ >(undefined)
23
+
24
+ export const usePickerViewStyleContext = () => {
25
+ const value = useContext(PickerViewStyleContext)
26
+ return value
27
+ }
@@ -0,0 +1,34 @@
1
+ import React from 'react'
2
+ import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
3
+
4
+ type IndicatorProps = {
5
+ itemHeight: number
6
+ indicatorItemStyle?: StyleProp<ViewStyle>
7
+ indicatorContainerStyle?: StyleProp<ViewStyle>
8
+ }
9
+
10
+ const _PickerViewIndicator = ({ itemHeight, indicatorItemStyle, indicatorContainerStyle }: IndicatorProps) => {
11
+ return (
12
+ <View style={[styles.indicatorContainer, indicatorContainerStyle]} pointerEvents={'none'}>
13
+ <View style={[styles.selection, { height: itemHeight }, indicatorItemStyle]} />
14
+ </View>
15
+ )
16
+ }
17
+
18
+ const styles = StyleSheet.create({
19
+ indicatorContainer: {
20
+ ...StyleSheet.absoluteFillObject,
21
+ justifyContent: 'center',
22
+ alignItems: 'center',
23
+ zIndex: 200
24
+ },
25
+ selection: {
26
+ borderTopWidth: 1,
27
+ borderBottomWidth: 1,
28
+ borderColor: 'rgba(0, 0, 0, 0.05)',
29
+ alignSelf: 'stretch'
30
+ }
31
+ })
32
+
33
+ _PickerViewIndicator.displayName = 'MpxPickerViewIndicator'
34
+ export default _PickerViewIndicator
@@ -0,0 +1,30 @@
1
+ import React from 'react'
2
+ import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
3
+ import LinearGradient from 'react-native-linear-gradient'
4
+
5
+ type MaskProps = {
6
+ itemHeight: number
7
+ maskContainerStyle?: StyleProp<ViewStyle>
8
+ }
9
+
10
+ const _PickerViewMask = ({
11
+ itemHeight,
12
+ maskContainerStyle
13
+ }: MaskProps) => {
14
+ return (
15
+ <View style={[styles.maskContainer, maskContainerStyle]} pointerEvents={'none'}>
16
+ <LinearGradient colors={['rgba(255,255,255,1)', 'rgba(255,255,255,0.5)']} style={{ flex: 1 }} />
17
+ <View style={{ height: itemHeight }} />
18
+ <LinearGradient colors={['rgba(255,255,255,0.5)', 'rgba(255,255,255,1)']} style={{ flex: 1 }} />
19
+ </View>
20
+ )
21
+ }
22
+ const styles = StyleSheet.create({
23
+ maskContainer: {
24
+ ...StyleSheet.absoluteFillObject,
25
+ zIndex: 100
26
+ }
27
+ })
28
+
29
+ _PickerViewMask.displayName = 'MpxPickerViewMask'
30
+ export default _PickerViewMask
@@ -13,6 +13,8 @@ type RemoveProps = string[];
13
13
 
14
14
  type NativeTouchEvent = NativeSyntheticEvent<NativeEvent>
15
15
 
16
+ type Navigation = Record<string, any>
17
+
16
18
  interface NativeEvent {
17
19
  timestamp: number;
18
20
  pageX: number;
@@ -36,10 +38,6 @@ interface InnerRef {
36
38
  bubble: null | ReturnType<typeof setTimeout>;
37
39
  capture: null | ReturnType<typeof setTimeout>;
38
40
  };
39
- needPress: {
40
- bubble: boolean;
41
- capture: boolean;
42
- };
43
41
  mpxPressInfo: {
44
42
  detail: {
45
43
  x: number;
@@ -65,5 +63,6 @@ export {
65
63
  InnerRef,
66
64
  LayoutRef,
67
65
  SetTimeoutReturnType,
68
- DataSetType
66
+ DataSetType,
67
+ Navigation
69
68
  }
@@ -20,6 +20,12 @@ declare module '@mpxjs/utils' {
20
20
  left: number
21
21
  right: number
22
22
  },
23
+ layout: {
24
+ x: number
25
+ y: number
26
+ width: number
27
+ height: number
28
+ },
23
29
  setOptions: (params: Record<string, any>) => void
24
30
  } | undefined
25
31
  }
@@ -27,3 +33,7 @@ declare module '@mpxjs/utils' {
27
33
  declare let global: {
28
34
  __formatValue (value: string): string | number
29
35
  } & Record<string, any>
36
+
37
+ declare module '@react-navigation/native' {
38
+ export function useNavigation (): Record<string, any>
39
+ }
@@ -13,6 +13,7 @@ import {
13
13
  WithTimingConfig,
14
14
  AnimationCallback
15
15
  } from 'react-native-reanimated'
16
+ import { error } from '@mpxjs/utils'
16
17
  import { ExtendedViewStyle } from './types/common'
17
18
  import type { _ViewProps } from './mpx-view'
18
19
 
@@ -166,20 +167,32 @@ const formatStyle = (style: ExtendedViewStyle): ExtendedViewStyle => {
166
167
  })
167
168
  }
168
169
 
169
- export default function useAnimationHooks<T, P> (props: _ViewProps) {
170
- const { style = {}, animation } = props
170
+ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAnimation?: boolean }) {
171
+ const { style = {}, animation, enableAnimation } = props
172
+
173
+ const enableStyleAnimation = enableAnimation || !!animation
174
+ const enableAnimationRef = useRef(enableStyleAnimation)
175
+ if (enableAnimationRef.current !== enableStyleAnimation) {
176
+ error('[Mpx runtime error]: animation use should be stable in the component lifecycle, or you can set [enable-animation] with true.')
177
+ }
178
+
179
+ if (!enableAnimationRef.current) return { enableStyleAnimation: false }
180
+
171
181
  const originalStyle = formatStyle(style)
172
182
  // id 标识
173
183
  const id = animation?.id || -1
174
184
  // 有动画样式的 style key
185
+ // eslint-disable-next-line react-hooks/rules-of-hooks
175
186
  const animatedStyleKeys = useSharedValue([] as (string|string[])[])
176
187
  // 记录动画key的style样式值 没有的话设置为false
188
+ // eslint-disable-next-line react-hooks/rules-of-hooks
177
189
  const animatedKeys = useRef({} as {[propName: keyof ExtendedViewStyle]: boolean})
178
190
  // const animatedKeys = useRef({} as {[propName: keyof ExtendedViewStyle]: boolean|number|string})
179
191
  // ** 全量 style prop sharedValue
180
192
  // 不能做增量的原因:
181
193
  // 1 尝试用 useRef,但 useAnimatedStyle 访问后的 ref 不能在增加新的值,被冻结
182
194
  // 2 尝试用 useSharedValue,因为实际触发的 style prop 需要是 sharedValue 才能驱动动画,若外层 shareValMap 也是 sharedValue,动画无法驱动。
195
+ // eslint-disable-next-line react-hooks/rules-of-hooks
183
196
  const shareValMap = useMemo(() => {
184
197
  return Object.keys(InitialValue).reduce((valMap, key) => {
185
198
  const defaultVal = getInitialVal(key, isTransform(key))
@@ -188,6 +201,7 @@ export default function useAnimationHooks<T, P> (props: _ViewProps) {
188
201
  }, {} as { [propName: keyof ExtendedViewStyle]: SharedValue<string|number> })
189
202
  }, [])
190
203
  // ** 获取动画样式prop & 驱动动画
204
+ // eslint-disable-next-line react-hooks/rules-of-hooks
191
205
  useEffect(() => {
192
206
  if (id === -1) return
193
207
  // 更新动画样式 key map
@@ -208,6 +222,7 @@ export default function useAnimationHooks<T, P> (props: _ViewProps) {
208
222
  // })
209
223
  // }, [style])
210
224
  // ** 清空动画
225
+ // eslint-disable-next-line react-hooks/rules-of-hooks
211
226
  useEffect(() => {
212
227
  return () => {
213
228
  Object.values(shareValMap).forEach((value) => {
@@ -335,7 +350,8 @@ export default function useAnimationHooks<T, P> (props: _ViewProps) {
335
350
  }, {} as { [propName: string]: string | number })
336
351
  }
337
352
  // ** 生成动画样式
338
- return useAnimatedStyle(() => {
353
+ // eslint-disable-next-line react-hooks/rules-of-hooks
354
+ const animationStyle = useAnimatedStyle(() => {
339
355
  // console.info(`useAnimatedStyle styles=`, originalStyle)
340
356
  return animatedStyleKeys.value.reduce((styles, key) => {
341
357
  // console.info('getAnimationStyles', key, shareValMap[key].value)
@@ -353,4 +369,9 @@ export default function useAnimationHooks<T, P> (props: _ViewProps) {
353
369
  return styles
354
370
  }, {} as ExtendedViewStyle)
355
371
  })
372
+
373
+ return {
374
+ enableStyleAnimation: enableAnimationRef.current,
375
+ animationStyle
376
+ }
356
377
  }
@@ -1,11 +1,14 @@
1
1
  import { useEffect, useCallback, useMemo, useRef, ReactNode, ReactElement, isValidElement, useContext, useState, Dispatch, SetStateAction, Children, cloneElement } from 'react'
2
- import { LayoutChangeEvent, TextStyle, ImageProps, Image } from 'react-native'
3
- import { isObject, isFunction, isNumber, hasOwn, diffAndCloneA, error, warn, getFocusedNavigation } from '@mpxjs/utils'
4
- import { VarContext } from './context'
2
+ import { LayoutChangeEvent, TextStyle, ImageProps, Image, Platform } from 'react-native'
3
+ import { isObject, isFunction, isNumber, hasOwn, diffAndCloneA, error, warn } from '@mpxjs/utils'
4
+ import { VarContext, ScrollViewContext } from './context'
5
5
  import { ExpressionParser, parseFunc, ReplaceSource } from './parser'
6
6
  import { initialWindowMetrics } from 'react-native-safe-area-context'
7
+ import { useNavigation } from '@react-navigation/native'
7
8
  import FastImage, { FastImageProps } from '@d11/react-native-fast-image'
8
- import type { AnyFunc, ExtendedFunctionComponent } from './types/common'
9
+ import type { AnyFunc, ExtendedFunctionComponent, ExtendedViewStyle } from './types/common'
10
+ import { runOnJS } from 'react-native-reanimated'
11
+ import { Gesture } from 'react-native-gesture-handler'
9
12
 
10
13
  export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/
11
14
  export const PERCENT_REGEX = /^\s*-?\d+(\.\d+)?%\s*$/
@@ -18,6 +21,11 @@ export const HIDDEN_STYLE = {
18
21
  opacity: 0
19
22
  }
20
23
 
24
+ declare const __mpx_mode__: 'ios' | 'android'
25
+
26
+ export const isIOS = __mpx_mode__ === 'ios'
27
+ export const isAndroid = __mpx_mode__ === 'android'
28
+
21
29
  const varDecRegExp = /^--/
22
30
  const varUseRegExp = /var\(/
23
31
  const unoVarDecRegExp = /^--un-/
@@ -32,8 +40,7 @@ const safeAreaInsetMap: Record<string, 'top' | 'right' | 'bottom' | 'left'> = {
32
40
  'safe-area-inset-left': 'left'
33
41
  }
34
42
 
35
- function getSafeAreaInset (name: string) {
36
- const navigation = getFocusedNavigation()
43
+ function getSafeAreaInset (name: string, navigation: Record<string, any>) {
37
44
  const insets = extendObject({}, initialWindowMetrics?.insets, navigation?.insets)
38
45
  return insets[safeAreaInsetMap[name]]
39
46
  }
@@ -232,7 +239,7 @@ function transformVar (styleObj: Record<string, any>, varKeyPaths: Array<Array<s
232
239
  })
233
240
  }
234
241
 
235
- function transformEnv (styleObj: Record<string, any>, envKeyPaths: Array<Array<string>>) {
242
+ function transformEnv (styleObj: Record<string, any>, envKeyPaths: Array<Array<string>>, navigation: Record<string, any>) {
236
243
  envKeyPaths.forEach((envKeyPath) => {
237
244
  setStyle(styleObj, envKeyPath, ({ target, key, value }) => {
238
245
  const parsed = parseFunc(value, 'env')
@@ -240,7 +247,7 @@ function transformEnv (styleObj: Record<string, any>, envKeyPaths: Array<Array<s
240
247
  parsed.forEach(({ start, end, args }) => {
241
248
  const name = args[0]
242
249
  const fallback = args[1] || ''
243
- const value = '' + (getSafeAreaInset(name) ?? global.__formatValue(fallback))
250
+ const value = '' + (getSafeAreaInset(name, navigation) ?? global.__formatValue(fallback))
244
251
  replaced.replace(start, end - 1, value)
245
252
  })
246
253
  target[key] = global.__formatValue(replaced.source())
@@ -302,6 +309,7 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
302
309
  const envKeyPaths: Array<Array<string>> = []
303
310
  const [width, setWidth] = useState(0)
304
311
  const [height, setHeight] = useState(0)
312
+ const navigation = useNavigation()
305
313
 
306
314
  function varVisitor ({ key, value, keyPath }: VisitorArg) {
307
315
  if (keyPath.length === 1) {
@@ -396,7 +404,7 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
396
404
  }
397
405
 
398
406
  // apply env
399
- transformEnv(normalStyle, envKeyPaths)
407
+ transformEnv(normalStyle, envKeyPaths, navigation)
400
408
  // apply percent
401
409
  transformPercent(normalStyle, percentKeyPaths, percentConfig)
402
410
  // apply calc
@@ -565,13 +573,14 @@ export const debounce = <T extends AnyFunc> (
565
573
  ): ((...args: Parameters<T>) => void) & { clear: () => void } => {
566
574
  let timer: any
567
575
  const wrapper = (...args: ReadonlyArray<any>) => {
568
- clearTimeout(timer)
576
+ timer && clearTimeout(timer)
569
577
  timer = setTimeout(() => {
570
578
  func(...args)
571
579
  }, delay)
572
580
  }
573
581
  wrapper.clear = () => {
574
- clearTimeout(timer)
582
+ timer && clearTimeout(timer)
583
+ timer = null
575
584
  }
576
585
  return wrapper
577
586
  }
@@ -595,7 +604,7 @@ export const useStableCallback = <T extends AnyFunc | null | undefined> (
595
604
  )
596
605
  }
597
606
 
598
- export const usePrevious = <T, > (value: T): T | undefined => {
607
+ export function usePrevious<T> (value: T): T | undefined {
599
608
  const ref = useRef<T | undefined>()
600
609
  const prev = ref.current
601
610
  ref.current = value
@@ -641,3 +650,67 @@ export function pickStyle (styleObj: Record<string, any> = {}, pickedKeys: Array
641
650
  return acc
642
651
  }, {})
643
652
  }
653
+
654
+ export function useHover ({ enableHover, hoverStartTime, hoverStayTime, disabled } : { enableHover: boolean, hoverStartTime: number, hoverStayTime: number, disabled?: boolean }) {
655
+ const enableHoverRef = useRef(enableHover)
656
+ if (enableHoverRef.current !== enableHover) {
657
+ error('[Mpx runtime error]: hover-class use should be stable in the component lifecycle.')
658
+ }
659
+
660
+ if (!enableHoverRef.current) return { isHover: false }
661
+ // eslint-disable-next-line react-hooks/rules-of-hooks
662
+ const gestureRef = useContext(ScrollViewContext).gestureRef
663
+ // eslint-disable-next-line react-hooks/rules-of-hooks
664
+ const [isHover, setIsHover] = useState(false)
665
+ // eslint-disable-next-line react-hooks/rules-of-hooks
666
+ const dataRef = useRef<{
667
+ startTimer?: ReturnType<typeof setTimeout>
668
+ stayTimer?: ReturnType<typeof setTimeout>
669
+ }>({})
670
+
671
+ // eslint-disable-next-line react-hooks/rules-of-hooks
672
+ useEffect(() => {
673
+ return () => {
674
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
675
+ dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer)
676
+ }
677
+ }, [])
678
+
679
+ const setStartTimer = () => {
680
+ if (disabled) return
681
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
682
+ dataRef.current.startTimer = setTimeout(() => {
683
+ setIsHover(true)
684
+ }, +hoverStartTime)
685
+ }
686
+
687
+ const setStayTimer = () => {
688
+ if (disabled) return
689
+ dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer)
690
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
691
+ dataRef.current.stayTimer = setTimeout(() => {
692
+ setIsHover(false)
693
+ }, +hoverStayTime)
694
+ }
695
+ // eslint-disable-next-line react-hooks/rules-of-hooks
696
+ const gesture = useMemo(() => {
697
+ return Gesture.Pan()
698
+ .onTouchesDown(() => {
699
+ 'worklet'
700
+ runOnJS(setStartTimer)()
701
+ })
702
+ .onTouchesUp(() => {
703
+ 'worklet'
704
+ runOnJS(setStayTimer)()
705
+ })
706
+ }, [])
707
+
708
+ if (gestureRef) {
709
+ gesture.simultaneousWithExternalGesture(gestureRef)
710
+ }
711
+
712
+ return {
713
+ isHover,
714
+ gesture
715
+ }
716
+ }
@@ -30,10 +30,10 @@
30
30
  if (this.disabled) {
31
31
  return
32
32
  }
33
+ this.isChecked = !this.isChecked
33
34
  if (this.group) {
34
35
  this.group.notifyChange()
35
36
  }
36
- this.isChecked = !this.isChecked
37
37
  }
38
38
  },
39
39
  force: true
@@ -40,14 +40,14 @@ export default {
40
40
  this.wheels[0].wheelTo(newVal[0])
41
41
  })
42
42
  }
43
- }
43
+ },
44
44
  },
45
45
  mounted () {
46
46
  this.wheels = []
47
47
  this.refresh()
48
- for (let i = 0; i < this.$refs.wheelScroll.children.length; i++) {
49
- this.$refs.wheelScroll.children[i].style.height = `${this.$parent.$refs.indicatorMask.offsetHeight}px`
50
- }
48
+ },
49
+ updated () {
50
+ this.refresh()
51
51
  },
52
52
  beforeDestroy () {
53
53
  this.wheels.forEach((wheel) => {
@@ -58,11 +58,16 @@ export default {
58
58
  methods: {
59
59
  refresh () {
60
60
  if (this.refreshing) return
61
+
61
62
  this.refreshing = true
63
+ for (let i = 0; i < this.$refs.wheelScroll.children.length; i++) {
64
+ this.$refs.wheelScroll.children[i].style.height = `${this.$parent.$refs.indicatorMask.offsetHeight}px`
65
+ }
62
66
  this.$nextTick(() => {
63
67
  const wheelWrapper = this.$refs.wheelWrapper
64
68
  if (this.wheels[0]) {
65
69
  this.wheels[0].refresh()
70
+ this.refreshing = false
66
71
  return
67
72
  }
68
73
  this.wheels[0] = new BScroll(wheelWrapper, extend({