@mpxjs/webpack-plugin 2.10.2 → 2.10.3-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 (74) hide show
  1. package/lib/config.js +2 -1
  2. package/lib/dependencies/RecordPageConfigsMapDependency.js +45 -0
  3. package/lib/index.js +13 -1
  4. package/lib/platform/json/wx/index.js +6 -3
  5. package/lib/platform/style/wx/index.js +29 -16
  6. package/lib/platform/template/wx/component-config/button.js +19 -2
  7. package/lib/platform/template/wx/component-config/canvas.js +4 -0
  8. package/lib/platform/template/wx/component-config/checkbox-group.js +4 -0
  9. package/lib/platform/template/wx/component-config/checkbox.js +4 -0
  10. package/lib/platform/template/wx/component-config/cover-image.js +7 -1
  11. package/lib/platform/template/wx/component-config/cover-view.js +4 -0
  12. package/lib/platform/template/wx/component-config/fix-component-name.js +3 -2
  13. package/lib/platform/template/wx/component-config/form.js +7 -1
  14. package/lib/platform/template/wx/component-config/icon.js +4 -0
  15. package/lib/platform/template/wx/component-config/image.js +7 -1
  16. package/lib/platform/template/wx/component-config/input.js +17 -2
  17. package/lib/platform/template/wx/component-config/label.js +4 -0
  18. package/lib/platform/template/wx/component-config/movable-area.js +7 -1
  19. package/lib/platform/template/wx/component-config/movable-view.js +12 -3
  20. package/lib/platform/template/wx/component-config/navigator.js +4 -0
  21. package/lib/platform/template/wx/component-config/picker-view-column.js +4 -0
  22. package/lib/platform/template/wx/component-config/picker-view.js +7 -1
  23. package/lib/platform/template/wx/component-config/picker.js +7 -1
  24. package/lib/platform/template/wx/component-config/radio-group.js +4 -0
  25. package/lib/platform/template/wx/component-config/radio.js +4 -0
  26. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  27. package/lib/platform/template/wx/component-config/root-portal.js +4 -0
  28. package/lib/platform/template/wx/component-config/scroll-view.js +10 -2
  29. package/lib/platform/template/wx/component-config/swiper-item.js +7 -1
  30. package/lib/platform/template/wx/component-config/swiper.js +12 -3
  31. package/lib/platform/template/wx/component-config/switch.js +4 -0
  32. package/lib/platform/template/wx/component-config/text.js +7 -1
  33. package/lib/platform/template/wx/component-config/textarea.js +17 -2
  34. package/lib/platform/template/wx/component-config/unsupported.js +7 -0
  35. package/lib/platform/template/wx/component-config/video.js +10 -2
  36. package/lib/platform/template/wx/component-config/view.js +24 -2
  37. package/lib/platform/template/wx/component-config/web-view.js +4 -0
  38. package/lib/platform/template/wx/index.js +32 -13
  39. package/lib/react/index.js +0 -1
  40. package/lib/react/processJSON.js +13 -2
  41. package/lib/react/processScript.js +5 -3
  42. package/lib/react/processTemplate.js +18 -3
  43. package/lib/react/script-helper.js +18 -4
  44. package/lib/runtime/components/react/dist/mpx-input.jsx +1 -11
  45. package/lib/runtime/components/react/dist/{KeyboardAvoidingView.jsx → mpx-keyboard-avoiding-view.jsx} +4 -3
  46. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +2 -2
  47. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +1 -2
  48. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +10 -5
  49. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +22 -0
  50. package/lib/runtime/components/react/dist/mpx-view.jsx +10 -5
  51. package/lib/runtime/components/react/dist/mpx-web-view.jsx +6 -6
  52. package/lib/runtime/components/react/dist/useAnimationHooks.js +46 -48
  53. package/lib/runtime/components/react/dist/utils.jsx +18 -7
  54. package/lib/runtime/components/react/mpx-input.tsx +1 -19
  55. package/lib/runtime/components/react/{KeyboardAvoidingView.tsx → mpx-keyboard-avoiding-view.tsx} +4 -2
  56. package/lib/runtime/components/react/mpx-picker-view-column.tsx +2 -2
  57. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +1 -2
  58. package/lib/runtime/components/react/mpx-scroll-view.tsx +13 -4
  59. package/lib/runtime/components/react/mpx-simple-view.tsx +32 -0
  60. package/lib/runtime/components/react/mpx-view.tsx +17 -10
  61. package/lib/runtime/components/react/mpx-web-view.tsx +11 -11
  62. package/lib/runtime/components/react/types/getInnerListeners.d.ts +1 -1
  63. package/lib/runtime/components/react/types/global.d.ts +1 -1
  64. package/lib/runtime/components/react/useAnimationHooks.ts +46 -48
  65. package/lib/runtime/components/react/utils.tsx +23 -11
  66. package/lib/runtime/components/web/mini-video-controls.min.js +1 -1
  67. package/lib/runtime/optionProcessor.js +3 -2
  68. package/lib/style-compiler/index.js +8 -6
  69. package/lib/template-compiler/compiler.js +21 -13
  70. package/lib/utils/env.js +1 -1
  71. package/lib/utils/match-condition.js +14 -8
  72. package/lib/web/processJSON.js +1 -3
  73. package/package.json +3 -3
  74. package/LICENSE +0 -433
@@ -1,6 +1,5 @@
1
1
  import { useState, useCallback, forwardRef, ForwardedRef, useImperativeHandle, ReactNode, ReactElement } from 'react'
2
2
  import { View, StyleSheet } from 'react-native'
3
- import { extendObject } from '../utils'
4
3
 
5
4
  export type State = {
6
5
  portals: Array<{
@@ -27,7 +26,7 @@ const _PortalManager = forwardRef((props: PortalManagerProps, ref:ForwardedRef<u
27
26
  setState((prevState) => ({
28
27
  portals: prevState.portals.map((item) => {
29
28
  if (item.key === key) {
30
- return extendObject({}, item, { children })
29
+ return Object.assign({}, item, { children })
31
30
  }
32
31
  return item
33
32
  })
@@ -70,6 +70,7 @@ interface ScrollViewProps {
70
70
  'parent-height'?: number;
71
71
  'wait-for'?: Array<GestureHandler>;
72
72
  'simultaneous-handlers'?: Array<GestureHandler>;
73
+ 'scroll-event-throttle'?:number;
73
74
  bindscrolltoupper?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
74
75
  bindscrolltolower?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
75
76
  bindscroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -140,6 +141,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
140
141
  'parent-height': parentHeight,
141
142
  'simultaneous-handlers': originSimultaneousHandlers,
142
143
  'wait-for': waitFor,
144
+ 'scroll-event-throttle': scrollEventThrottle = 0,
143
145
  __selectRef
144
146
  } = props
145
147
 
@@ -159,7 +161,6 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
159
161
  visibleLength: 0
160
162
  })
161
163
 
162
- const scrollEventThrottle = 50
163
164
  const hasCallScrollToUpper = useRef(true)
164
165
  const hasCallScrollToLower = useRef(false)
165
166
  const initialTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
@@ -202,6 +203,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
202
203
 
203
204
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
204
205
 
206
+ const lastOffset = useRef(0)
207
+
205
208
  if (scrollX && scrollY) {
206
209
  warn('scroll-x and scroll-y cannot be set to true at the same time, Mpx will use the value of scroll-y as the criterion')
207
210
  }
@@ -263,7 +266,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
263
266
  function onStartReached (e: NativeSyntheticEvent<NativeScrollEvent>) {
264
267
  const { bindscrolltoupper } = props
265
268
  const { offset } = scrollOptions.current
266
- if (bindscrolltoupper && (offset <= upperThreshold)) {
269
+ const isScrollingBackward = offset < lastOffset.current
270
+ if (bindscrolltoupper && (offset <= upperThreshold) && isScrollingBackward) {
267
271
  if (!hasCallScrollToUpper.current) {
268
272
  bindscrolltoupper(
269
273
  getCustomEvent('scrolltoupper', e, {
@@ -284,13 +288,15 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
284
288
  const { bindscrolltolower } = props
285
289
  const { contentLength, visibleLength, offset } = scrollOptions.current
286
290
  const distanceFromEnd = contentLength - visibleLength - offset
287
- if (bindscrolltolower && (distanceFromEnd < lowerThreshold)) {
291
+ const isScrollingForward = offset > lastOffset.current
292
+
293
+ if (bindscrolltolower && (distanceFromEnd < lowerThreshold) && isScrollingForward) {
288
294
  if (!hasCallScrollToLower.current) {
289
295
  hasCallScrollToLower.current = true
290
296
  bindscrolltolower(
291
297
  getCustomEvent('scrolltolower', e, {
292
298
  detail: {
293
- direction: scrollX ? 'right' : 'botttom'
299
+ direction: scrollX ? 'right' : 'bottom'
294
300
  },
295
301
  layoutRef
296
302
  }, props)
@@ -345,6 +351,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
345
351
  onStartReached(e)
346
352
  onEndReached(e)
347
353
  updateIntersection()
354
+ // 在 onStartReached、onEndReached 执行完后更新 lastOffset
355
+ lastOffset.current = scrollOptions.current.offset
348
356
  }
349
357
 
350
358
  function onScrollEnd (e: NativeSyntheticEvent<NativeScrollEvent>) {
@@ -367,6 +375,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
367
375
  onStartReached(e)
368
376
  onEndReached(e)
369
377
  updateIntersection()
378
+ lastOffset.current = scrollOptions.current.offset
370
379
  }
371
380
  function updateIntersection () {
372
381
  if (enableTriggerIntersectionObserver && intersectionObservers) {
@@ -0,0 +1,32 @@
1
+ import { View, ViewProps, TextStyle } from 'react-native'
2
+ import { createElement, forwardRef, useRef } from 'react'
3
+ import useNodesRef, { HandlerRef } from './useNodesRef'
4
+ import { extendObject, splitProps, splitStyle, wrapChildren } from './utils'
5
+
6
+ const _View2 = forwardRef<HandlerRef<View, ViewProps>, ViewProps>((simpleViewProps: ViewProps, ref) => {
7
+ const nodeRef = useRef(null)
8
+
9
+ const { textProps, innerProps: props = {} } = splitProps(simpleViewProps)
10
+
11
+ const { textStyle, innerStyle = {} } = splitStyle(props.style || {})
12
+
13
+ useNodesRef(props, ref, nodeRef, {
14
+ style: innerStyle || {}
15
+ })
16
+
17
+ return createElement(View, extendObject({}, props, {
18
+ style: innerStyle,
19
+ ref: nodeRef
20
+ }), wrapChildren(
21
+ props,
22
+ {
23
+ hasVarDec: false,
24
+ textStyle: textStyle as TextStyle,
25
+ textProps
26
+ }
27
+ ))
28
+ })
29
+
30
+ _View2.displayName = 'MpxSimpleView'
31
+
32
+ export default _View2
@@ -16,6 +16,7 @@ import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wra
16
16
  import { error } from '@mpxjs/utils'
17
17
  import LinearGradient from 'react-native-linear-gradient'
18
18
  import { GestureDetector, PanGesture } from 'react-native-gesture-handler'
19
+ import Portal from './mpx-portal'
19
20
 
20
21
  export interface _ViewProps extends ViewProps {
21
22
  style?: ExtendedViewStyle
@@ -79,7 +80,7 @@ type PreImageInfo = {
79
80
  type ImageProps = {
80
81
  style: ImageStyle,
81
82
  src?: string,
82
- source?: {uri: string },
83
+ source?: { uri: string },
83
84
  colors: Array<string>,
84
85
  locations?: Array<number>
85
86
  angle?: number
@@ -483,8 +484,8 @@ function parseLinearGradient (text: string): LinearInfo | undefined {
483
484
  }
484
485
 
485
486
  function parseBgImage (text: string): {
486
- linearInfo?: LinearInfo;
487
- direction?: string;
487
+ linearInfo?: LinearInfo
488
+ direction?: string
488
489
  type?: 'image' | 'linear'
489
490
  src?: string
490
491
  } {
@@ -578,7 +579,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
578
579
  if (!src) {
579
580
  setShow(false)
580
581
  return
581
- // 一开始未出现,数据改变时出现
582
+ // 一开始未出现,数据改变时出现
582
583
  } else if (!(needLayout || needImageSize)) {
583
584
  setShow(true)
584
585
  return
@@ -602,7 +603,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
602
603
  }
603
604
  })
604
605
  }
605
- // type 添加type 处理无渐变 有渐变的场景
606
+ // type 添加type 处理无渐变 有渐变的场景
606
607
  }, [src, type])
607
608
 
608
609
  if (!type) return null
@@ -636,7 +637,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
636
637
  }
637
638
 
638
639
  return <View key='backgroundImage' {...needLayout ? { onLayout } : null} style={{ ...inheritStyle(innerStyle), ...StyleSheet.absoluteFillObject, overflow: 'hidden' }}>
639
- {show && type === 'linear' && <LinearGradient useAngle={true} {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} /> }
640
+ {show && type === 'linear' && <LinearGradient useAngle={true} {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} />}
640
641
  {show && type === 'image' && (renderImage(imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size), enableFastImage))}
641
642
  </View>
642
643
  }
@@ -703,6 +704,7 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
703
704
  const {
704
705
  normalStyle,
705
706
  hasSelfPercent,
707
+ hasPositionFixed,
706
708
  hasVarDec,
707
709
  varContextRef,
708
710
  setWidth,
@@ -769,13 +771,18 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
769
771
  enableFastImage
770
772
  })
771
773
 
772
- const BaseComponent = enableStyleAnimation
774
+ let finalComponent: JSX.Element = enableStyleAnimation
773
775
  ? createElement(Animated.View, innerProps, childNode)
774
776
  : createElement(View, innerProps, childNode)
775
777
 
776
- return enableHover
777
- ? createElement(GestureDetector, { gesture: gesture as PanGesture }, BaseComponent)
778
- : BaseComponent
778
+ if (enableHover) {
779
+ finalComponent = createElement(GestureDetector, { gesture: gesture as PanGesture }, finalComponent)
780
+ }
781
+
782
+ if (hasPositionFixed) {
783
+ finalComponent = createElement(Portal, null, finalComponent)
784
+ }
785
+ return finalComponent
779
786
  })
780
787
 
781
788
  _View.displayName = 'MpxView'
@@ -89,7 +89,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
89
89
  button: 'Reload'
90
90
  }
91
91
  }
92
- const currentErrorText = errorText[(mpx.i18n.locale as LanguageCode) || 'zh-CN']
92
+ const currentErrorText = errorText[(mpx.i18n?.locale as LanguageCode) || 'zh-CN']
93
93
 
94
94
  if (props.style) {
95
95
  warn('The web-view component does not support the style prop.')
@@ -103,11 +103,11 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
103
103
  const statusCode = useRef<string|number>('')
104
104
  const [isLoaded, setIsLoaded] = useState<boolean>(true)
105
105
  const defaultWebViewStyle = {
106
- position: 'absolute' as 'absolute' | 'relative' | 'static',
107
- left: 0 as number,
108
- right: 0 as number,
109
- top: 0 as number,
110
- bottom: 0 as number
106
+ position: 'absolute' as const,
107
+ left: 0,
108
+ right: 0,
109
+ top: 0,
110
+ bottom: 0
111
111
  }
112
112
  const canGoBack = useRef<boolean>(false)
113
113
  const isNavigateBack = useRef<boolean>(false)
@@ -140,7 +140,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
140
140
  }
141
141
 
142
142
  const _reload = function () {
143
- if (__mpx_mode__ === 'android') {
143
+ if (__mpx_mode__ === 'android' || __mpx_mode__ === 'harmony') {
144
144
  fristLoaded.current = false // 安卓需要重新设置
145
145
  }
146
146
  setPageLoadErr(false)
@@ -186,7 +186,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
186
186
  }
187
187
 
188
188
  const _onLoadProgress = function (event: WebViewProgressEvent) {
189
- if (__mpx_mode__ === 'android') {
189
+ if (__mpx_mode__ === 'android' || __mpx_mode__ === 'harmony') {
190
190
  canGoBack.current = event.nativeEvent.canGoBack
191
191
  }
192
192
  }
@@ -302,8 +302,8 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
302
302
  }
303
303
  }
304
304
  const onLoadEnd = function (res: WebViewEvent) {
305
- if (__mpx_mode__ === 'android') {
306
- res.persist()
305
+ res.persist()
306
+ if (__mpx_mode__ === 'android' || __mpx_mode__ === 'harmony') {
307
307
  setTimeout(() => {
308
308
  onLoadEndHandle(res)
309
309
  }, 0)
@@ -329,7 +329,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
329
329
  }
330
330
 
331
331
  return (
332
- <Portal key={pageLoadErr ? 'error' : 'webview'}>
332
+ <Portal>
333
333
  {pageLoadErr
334
334
  ? (
335
335
  <View style={[styles.loadErrorContext, defaultWebViewStyle]}>
@@ -46,7 +46,7 @@ interface InnerRef {
46
46
  };
47
47
  }
48
48
  interface UseInnerPropsConfig {
49
- layoutRef: LayoutRef;
49
+ layoutRef?: LayoutRef;
50
50
  disableTouch?: boolean;
51
51
  disableTap?: boolean
52
52
  }
@@ -1,4 +1,4 @@
1
- declare let __mpx_mode__: 'wx' | 'ali' | 'swan' | 'qq' | 'tt' | 'web' | 'dd' | 'qa' | 'jd' | 'android' | 'ios'
1
+ declare let __mpx_mode__: 'wx' | 'ali' | 'swan' | 'qq' | 'tt' | 'web' | 'dd' | 'qa' | 'jd' | 'android' | 'ios' | 'harmony'
2
2
  declare module '@mpxjs/utils' {
3
3
  export function isEmptyObject (obj: Object): boolean
4
4
  export function isFunction (fn: unknown): boolean
@@ -13,7 +13,7 @@ import {
13
13
  WithTimingConfig,
14
14
  AnimationCallback
15
15
  } from 'react-native-reanimated'
16
- import { error } from '@mpxjs/utils'
16
+ import { error, hasOwn } from '@mpxjs/utils'
17
17
  import { ExtendedViewStyle } from './types/common'
18
18
  import type { _ViewProps } from './mpx-view'
19
19
 
@@ -50,20 +50,20 @@ const EasingKey = {
50
50
  const TransformInitial: ExtendedViewStyle = {
51
51
  // matrix: 0,
52
52
  // matrix3d: 0,
53
- rotate: '0deg',
53
+ // rotate: '0deg',
54
54
  rotateX: '0deg',
55
55
  rotateY: '0deg',
56
56
  rotateZ: '0deg',
57
57
  // rotate3d:[0,0,0]
58
- scale: 1,
58
+ // scale: 1,
59
59
  // scale3d: [1, 1, 1],
60
60
  scaleX: 1,
61
61
  scaleY: 1,
62
62
  // scaleZ: 1,
63
- skew: 0,
63
+ // skew: 0,
64
64
  skewX: '0deg',
65
65
  skewY: '0deg',
66
- translate: 0,
66
+ // translate: 0,
67
67
  // translate3d: 0,
68
68
  translateX: 0,
69
69
  translateY: 0
@@ -127,23 +127,23 @@ const parseTransform = (transformStr: string) => {
127
127
  case 'skewX':
128
128
  case 'skewY':
129
129
  case 'perspective':
130
+ // rotate 处理成 rotateZ
131
+ key = key === 'rotate' ? 'rotateZ' : key
130
132
  // 单个值处理
131
133
  transform.push({ [key]: global.__formatValue(val) })
132
134
  break
133
135
  case 'matrix':
134
- case 'matrix3d':
135
136
  transform.push({ [key]: parseValues(val, ',').map(val => +val) })
136
137
  break
137
138
  case 'translate':
138
139
  case 'scale':
139
140
  case 'skew':
140
- case 'rotate3d': // x y z angle
141
141
  case 'translate3d': // x y 支持 z不支持
142
142
  case 'scale3d': // x y 支持 z不支持
143
143
  {
144
144
  // 2 个以上的值处理
145
145
  key = key.replace('3d', '')
146
- const vals = parseValues(val, ',').splice(0, key === 'rotate' ? 4 : 3)
146
+ const vals = parseValues(val, ',').splice(0, 3)
147
147
  // scale(.5) === scaleX(.5) scaleY(.5)
148
148
  if (vals.length === 1 && key === 'scale') {
149
149
  vals.push(vals[0])
@@ -167,6 +167,14 @@ const formatStyle = (style: ExtendedViewStyle): ExtendedViewStyle => {
167
167
  })
168
168
  }
169
169
 
170
+ // transform 数组转对象
171
+ function getTransformObj (transforms: { [propName: string]: string | number }[]) {
172
+ 'worklet'
173
+ return transforms.reduce((transformObj, item) => {
174
+ return Object.assign(transformObj, item)
175
+ }, {} as { [propName: string]: string | number })
176
+ }
177
+
170
178
  export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAnimation?: boolean }) {
171
179
  const { style = {}, animation, enableAnimation } = props
172
180
 
@@ -187,7 +195,9 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
187
195
  // 记录动画key的style样式值 没有的话设置为false
188
196
  // eslint-disable-next-line react-hooks/rules-of-hooks
189
197
  const animatedKeys = useRef({} as {[propName: keyof ExtendedViewStyle]: boolean})
190
- // const animatedKeys = useRef({} as {[propName: keyof ExtendedViewStyle]: boolean|number|string})
198
+ // 记录上次style map
199
+ // eslint-disable-next-line react-hooks/rules-of-hooks
200
+ const lastStyleRef = useRef({} as {[propName: keyof ExtendedViewStyle]: number|string})
191
201
  // ** 全量 style prop sharedValue
192
202
  // 不能做增量的原因:
193
203
  // 1 尝试用 useRef,但 useAnimatedStyle 访问后的 ref 不能在增加新的值,被冻结
@@ -200,6 +210,12 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
200
210
  return valMap
201
211
  }, {} as { [propName: keyof ExtendedViewStyle]: SharedValue<string|number> })
202
212
  }, [])
213
+ // ** style更新同步
214
+ // eslint-disable-next-line react-hooks/rules-of-hooks
215
+ useEffect(() => {
216
+ // style 更新后同步更新 lastStyleRef & shareValMap
217
+ updateStyleVal()
218
+ }, [style])
203
219
  // ** 获取动画样式prop & 驱动动画
204
220
  // eslint-disable-next-line react-hooks/rules-of-hooks
205
221
  useEffect(() => {
@@ -211,16 +227,6 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
211
227
  // 驱动动画
212
228
  createAnimation(keys)
213
229
  }, [id])
214
- // 同步style更新
215
- // useEffect(() => {
216
- // Object.keys(animatedKeys.current).forEach(key => {
217
- // const originVal = getOriginalStyleVal(key, isTransform(key))
218
- // if (originVal && animatedKeys.current[key] !== originVal) {
219
- // animatedKeys.current[key] = originVal
220
- // shareValMap[key].value = originVal
221
- // }
222
- // })
223
- // }, [style])
224
230
  // ** 清空动画
225
231
  // eslint-disable-next-line react-hooks/rules-of-hooks
226
232
  useEffect(() => {
@@ -230,7 +236,7 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
230
236
  })
231
237
  }
232
238
  }, [])
233
- // 根据 animation action 创建&驱动动画 key => wi
239
+ // 根据 animation action 创建&驱动动画
234
240
  function createAnimation (animatedKeys: string[] = []) {
235
241
  const actions = animation?.actions || []
236
242
  const sequence = {} as { [propName: keyof ExtendedViewStyle]: (string|number)[] }
@@ -286,6 +292,7 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
286
292
  : withTiming(value, { duration, easing })
287
293
  return delay ? withDelay(delay, animation) : animation
288
294
  }
295
+ // 获取样式初始值(prop style or 默认值)
289
296
  function getInitialVal (key: keyof ExtendedViewStyle, isTransform = false) {
290
297
  if (isTransform && Array.isArray(originalStyle.transform)) {
291
298
  let initialVal = InitialValue[key]
@@ -297,38 +304,19 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
297
304
  }
298
305
  return originalStyle[key] === undefined ? InitialValue[key] : originalStyle[key]
299
306
  }
300
- // 从 prop style 中获取样式初始值 没有为undefined
301
- // function getOriginalStyleVal (key: keyof ExtendedViewStyle, isTransform = false) {
302
- // if (isTransform && Array.isArray(originalStyle.transform)) {
303
- // let initialVal = undefined // InitialValue[key]
304
- // // 仅支持 { transform: [{rotateX: '45deg'}, {rotateZ: '0.785398rad'}] } 格式的初始样式
305
- // originalStyle.transform.forEach(item => {
306
- // if (item[key] !== undefined) initialVal = item[key]
307
- // })
308
- // return initialVal
309
- // }
310
- // return originalStyle[key] // === undefined ? InitialValue[key] : originalStyle[key]
311
- // }
312
- // 获取动画shareVal初始值(prop style or 默认值)
313
- // function getInitialVal (key: keyof ExtendedViewStyle, isTransform = false) {
314
- // const originalVal = getOriginalStyleVal(key, isTransform)
315
- // return originalVal === undefined ? InitialValue[key] : originalStyle[key]
316
- // }
317
307
  // 循环 animation actions 获取所有有动画的 style prop name
318
308
  function getAnimatedStyleKeys () {
319
309
  return (animation?.actions || []).reduce((keyMap, action) => {
320
310
  const { rules, transform } = action
321
311
  const ruleArr = [...rules.keys(), ...transform.keys()]
322
312
  ruleArr.forEach(key => {
323
- // const originalVal = getOriginalStyleVal(key, isTransform(key))
324
- // if (!keyMap[key]) keyMap[key] = originalVal === undefined ? false : originalVal
325
313
  if (!keyMap[key]) keyMap[key] = true
326
314
  })
327
315
  return keyMap
328
316
  }, animatedKeys.current)
329
317
  }
330
318
  // animated key transform 格式化
331
- function formatAnimatedKeys (keys: string[] = []) {
319
+ function formatAnimatedKeys (keys: string[]) {
332
320
  const animatedKeys = [] as (string|string[])[]
333
321
  const transforms = [] as string[]
334
322
  keys.forEach(key => {
@@ -341,13 +329,23 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
341
329
  if (transforms.length) animatedKeys.push(transforms)
342
330
  return animatedKeys
343
331
  }
344
- // transform 数组转对象
345
- function getTransformObj () {
346
- 'worklet'
347
- const transforms = originalStyle.transform || []
348
- return transforms.reduce((transformObj, item) => {
349
- return Object.assign(transformObj, item)
350
- }, {} as { [propName: string]: string | number })
332
+ // 设置 lastShareValRef & shareValMap
333
+ function updateStyleVal () {
334
+ Object.entries(originalStyle).forEach(([key, value]) => {
335
+ if (key === 'transform') {
336
+ Object.entries(getTransformObj(value)).forEach(([key, value]) => {
337
+ if (value !== lastStyleRef.current[key]) {
338
+ lastStyleRef.current[key] = value
339
+ shareValMap[key].value = value
340
+ }
341
+ })
342
+ } else if (hasOwn(shareValMap, key)) {
343
+ if (value !== lastStyleRef.current[key]) {
344
+ lastStyleRef.current[key] = value
345
+ shareValMap[key].value = value
346
+ }
347
+ }
348
+ })
351
349
  }
352
350
  // ** 生成动画样式
353
351
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -356,7 +354,7 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
356
354
  return animatedStyleKeys.value.reduce((styles, key) => {
357
355
  // console.info('getAnimationStyles', key, shareValMap[key].value)
358
356
  if (Array.isArray(key)) {
359
- const transformStyle = getTransformObj()
357
+ const transformStyle = getTransformObj(originalStyle.transform || [])
360
358
  key.forEach((transformKey) => {
361
359
  transformStyle[transformKey] = shareValMap[transformKey].value
362
360
  })
@@ -1,11 +1,11 @@
1
1
  import { useEffect, useCallback, useMemo, useRef, ReactNode, ReactElement, isValidElement, useContext, useState, Dispatch, SetStateAction, Children, cloneElement } from 'react'
2
- import { LayoutChangeEvent, TextStyle, ImageProps, Image, Platform } from 'react-native'
2
+ import { LayoutChangeEvent, TextStyle, ImageProps, Image } from 'react-native'
3
3
  import { isObject, isFunction, isNumber, hasOwn, diffAndCloneA, error, warn } from '@mpxjs/utils'
4
4
  import { VarContext, ScrollViewContext, RouteContext } from './context'
5
5
  import { ExpressionParser, parseFunc, ReplaceSource } from './parser'
6
6
  import { initialWindowMetrics } from 'react-native-safe-area-context'
7
7
  import FastImage, { FastImageProps } from '@d11/react-native-fast-image'
8
- import type { AnyFunc, ExtendedFunctionComponent, ExtendedViewStyle } from './types/common'
8
+ import type { AnyFunc, ExtendedFunctionComponent } from './types/common'
9
9
  import { runOnJS } from 'react-native-reanimated'
10
10
  import { Gesture } from 'react-native-gesture-handler'
11
11
 
@@ -20,10 +20,11 @@ export const HIDDEN_STYLE = {
20
20
  opacity: 0
21
21
  }
22
22
 
23
- declare const __mpx_mode__: 'ios' | 'android'
23
+ declare const __mpx_mode__: 'ios' | 'android' | 'harmony'
24
24
 
25
25
  export const isIOS = __mpx_mode__ === 'ios'
26
26
  export const isAndroid = __mpx_mode__ === 'android'
27
+ export const isHarmony = __mpx_mode__ === 'harmony'
27
28
 
28
29
  const varDecRegExp = /^--/
29
30
  const varUseRegExp = /var\(/
@@ -291,12 +292,8 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
291
292
  const normalStyleChangedRef = useRef(false)
292
293
  let hasVarDec = false
293
294
  let hasVarUse = false
294
- let hasSelfPercent = false
295
295
  const varKeyPaths: Array<Array<string>> = []
296
296
  const unoVarKeyPaths: Array<Array<string>> = []
297
- const percentKeyPaths: Array<Array<string>> = []
298
- const calcKeyPaths: Array<Array<string>> = []
299
- const envKeyPaths: Array<Array<string>> = []
300
297
  const [width, setWidth] = useState(0)
301
298
  const [height, setHeight] = useState(0)
302
299
  const navigation = useNavigation()
@@ -359,6 +356,11 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
359
356
  }
360
357
 
361
358
  const memoResult = useMemo(() => {
359
+ let hasSelfPercent = false
360
+ let hasPositionFixed = false
361
+ const percentKeyPaths: Array<Array<string>> = []
362
+ const calcKeyPaths: Array<Array<string>> = []
363
+ const envKeyPaths: Array<Array<string>> = []
362
364
  // transform can be memoized
363
365
  function envVisitor ({ value, keyPath }: VisitorArg) {
364
366
  if (envUseRegExp.test(value)) {
@@ -381,6 +383,13 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
381
383
  }
382
384
  }
383
385
 
386
+ function transformPosition (styleObj: Record<string, any>) {
387
+ if (styleObj.position === 'fixed') {
388
+ hasPositionFixed = true
389
+ styleObj.position = 'absolute'
390
+ }
391
+ }
392
+
384
393
  // traverse env & calc & percent
385
394
  traverseStyle(normalStyle, [envVisitor, percentVisitor, calcVisitor])
386
395
 
@@ -412,12 +421,15 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
412
421
  }
413
422
  }
414
423
  })
424
+ // apply position
425
+ transformPosition(normalStyle)
415
426
  // transform number enum stringify
416
427
  transformStringify(normalStyle)
417
428
 
418
429
  return {
419
430
  normalStyle,
420
- hasSelfPercent
431
+ hasSelfPercent,
432
+ hasPositionFixed
421
433
  }
422
434
  }, [normalStyleChangedRef.current, width, height, parentWidth, parentHeight, parentFontSize])
423
435
 
@@ -515,8 +527,8 @@ export const useLayout = ({ props, hasSelfPercent, setWidth, setHeight, onLayout
515
527
  hasLayoutRef.current = true
516
528
  if (hasSelfPercent) {
517
529
  const { width, height } = e?.nativeEvent?.layout || {}
518
- setWidth(width || 0)
519
- setHeight(height || 0)
530
+ setWidth && setWidth(width || 0)
531
+ setHeight && setHeight(height || 0)
520
532
  }
521
533
  if (enableOffset) {
522
534
  nodeRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
@@ -643,7 +655,7 @@ export function pickStyle (styleObj: Record<string, any> = {}, pickedKeys: Array
643
655
  }, {})
644
656
  }
645
657
 
646
- export function useHover ({ enableHover, hoverStartTime, hoverStayTime, disabled } : { enableHover: boolean, hoverStartTime: number, hoverStayTime: number, disabled?: boolean }) {
658
+ export function useHover ({ enableHover, hoverStartTime, hoverStayTime, disabled }: { enableHover: boolean, hoverStartTime: number, hoverStayTime: number, disabled?: boolean }) {
647
659
  const enableHoverRef = useRef(enableHover)
648
660
  if (enableHoverRef.current !== enableHover) {
649
661
  error('[Mpx runtime error]: hover-class use should be stable in the component lifecycle.')