@mpxjs/webpack-plugin 2.9.69-beta.3 → 2.9.69-beta.4

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 (65) hide show
  1. package/lib/index.js +17 -1
  2. package/lib/platform/style/wx/index.js +18 -18
  3. package/lib/platform/template/wx/component-config/movable-view.js +8 -1
  4. package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
  5. package/lib/react/processScript.js +1 -1
  6. package/lib/resolver/AddEnvPlugin.js +1 -0
  7. package/lib/resolver/AddModePlugin.js +1 -0
  8. package/lib/runtime/components/react/context.ts +25 -0
  9. package/lib/runtime/components/react/dist/context.js +2 -0
  10. package/lib/runtime/components/react/dist/getInnerListeners.js +2 -2
  11. package/lib/runtime/components/react/dist/locale-provider.jsx +15 -0
  12. package/lib/runtime/components/react/dist/mpx-button.jsx +9 -37
  13. package/lib/runtime/components/react/dist/mpx-image.jsx +13 -9
  14. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +2 -1
  15. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +12 -13
  16. package/lib/runtime/components/react/dist/mpx-portal/portal-consumer.jsx +23 -0
  17. package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +124 -0
  18. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +40 -0
  19. package/lib/runtime/components/react/dist/mpx-portal.jsx +12 -0
  20. package/lib/runtime/components/react/dist/mpx-provider.jsx +31 -0
  21. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
  22. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +10 -16
  23. package/lib/runtime/components/react/dist/mpx-swiper.jsx +10 -5
  24. package/lib/runtime/components/react/dist/mpx-view.jsx +15 -21
  25. package/lib/runtime/components/react/dist/mpx-web-view.jsx +78 -20
  26. package/lib/runtime/components/react/dist/pickerFaces.js +1 -1
  27. package/lib/runtime/components/react/dist/useAnimationHooks.js +14 -2
  28. package/lib/runtime/components/react/getInnerListeners.ts +5 -7
  29. package/lib/runtime/components/react/locale-provider.tsx +83 -0
  30. package/lib/runtime/components/react/mpx-button.tsx +13 -49
  31. package/lib/runtime/components/react/mpx-image.tsx +41 -25
  32. package/lib/runtime/components/react/mpx-input.tsx +1 -1
  33. package/lib/runtime/components/react/mpx-movable-view.tsx +1 -1
  34. package/lib/runtime/components/react/mpx-picker/time.tsx +2 -1
  35. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +88 -0
  36. package/lib/runtime/components/react/mpx-picker-view-column.tsx +180 -163
  37. package/lib/runtime/components/react/mpx-picker-view.tsx +35 -37
  38. package/lib/runtime/components/react/mpx-portal/portal-consumer.tsx +32 -0
  39. package/lib/runtime/components/react/mpx-portal/portal-host.tsx +158 -0
  40. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +64 -0
  41. package/lib/runtime/components/react/mpx-portal.tsx +29 -0
  42. package/lib/runtime/components/react/mpx-provider.tsx +51 -0
  43. package/lib/runtime/components/react/mpx-rich-text/index.tsx +12 -18
  44. package/lib/runtime/components/react/mpx-root-portal.tsx +1 -1
  45. package/lib/runtime/components/react/mpx-scroll-view.tsx +29 -18
  46. package/lib/runtime/components/react/mpx-swiper-item.tsx +38 -10
  47. package/lib/runtime/components/react/mpx-swiper.tsx +696 -0
  48. package/lib/runtime/components/react/mpx-view.tsx +25 -71
  49. package/lib/runtime/components/react/mpx-web-view.tsx +156 -23
  50. package/lib/runtime/components/react/pickerFaces.ts +15 -7
  51. package/lib/runtime/components/react/pickerVIewContext.ts +18 -0
  52. package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
  53. package/lib/runtime/components/react/{pickerOverlay.tsx → pickerViewOverlay.tsx} +5 -3
  54. package/lib/runtime/components/react/types/global.d.ts +6 -1
  55. package/lib/runtime/components/react/useAnimationHooks.ts +20 -4
  56. package/lib/runtime/components/react/utils.tsx +75 -5
  57. package/lib/style-compiler/index.js +3 -4
  58. package/lib/style-compiler/strip-conditional-loader.js +118 -0
  59. package/lib/template-compiler/compiler.js +9 -14
  60. package/lib/utils/hump-dash.js +1 -1
  61. package/lib/utils/pre-process-json.js +5 -9
  62. package/package.json +1 -1
  63. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
  64. package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
  65. package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
@@ -1,5 +1,5 @@
1
1
  import { View } from 'react-native'
2
- import React, { forwardRef, useState, useRef } from 'react'
2
+ import React, { forwardRef, useRef } from 'react'
3
3
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
4
4
  import useNodesRef, { HandlerRef } from './useNodesRef'
5
5
  import {
@@ -9,8 +9,6 @@ import {
9
9
  wrapChildren,
10
10
  parseInlineStyle,
11
11
  useTransformStyle,
12
- useDebounceCallback,
13
- useStableCallback,
14
12
  extendObject
15
13
  } from './utils'
16
14
  import type { AnyFunc } from './types/common'
@@ -21,21 +19,21 @@ import type { AnyFunc } from './types/common'
21
19
  * ✘ bindpickend
22
20
  * ✘ mask-class
23
21
  * ✔ indicator-style: 优先级indicator-style.height > pick-view-column中的子元素设置的height
22
+ * WebView Only:
24
23
  * ✘ indicator-class
25
- * mask-style
24
+ * mask-style
26
25
  * ✘ immediate-change
27
26
  */
28
27
 
29
28
  interface PickerViewProps {
30
29
  children: React.ReactNode
31
- // 初始的defaultValue数组中的数字依次表示 picker-view 内的 picker-view-column 选择的第几项(下标从 0 开始),
32
- // 数字大于 picker-view-column 可选项长度时,选择最后一项。
33
30
  value?: Array<number>
34
31
  bindchange?: AnyFunc
35
32
  style: {
36
33
  [key: string]: any
37
34
  }
38
35
  'indicator-style'?: string
36
+ 'mask-style'?: string
39
37
  'enable-var': boolean
40
38
  'external-var-context'?: Record<string, any>,
41
39
  'enable-offset': boolean
@@ -62,6 +60,8 @@ const styles: { [key: string]: Object } = {
62
60
  }
63
61
  }
64
62
 
63
+ const DefaultPickerItemH = 36
64
+
65
65
  const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProps>((props: PickerViewProps, ref) => {
66
66
  const {
67
67
  children,
@@ -71,16 +71,16 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
71
71
  'enable-var': enableVar,
72
72
  'external-var-context': externalVarContext
73
73
  } = props
74
-
75
- // indicatorStyle 需要转换为rn的style
76
- // 微信设置到pick-view上上设置的normalStyle如border等需要转换成RN的style然后进行透传
77
74
  const indicatorStyle = parseInlineStyle(props['indicator-style'])
75
+ const pickerMaskStyle = parseInlineStyle(props['mask-style'])
78
76
  const { height: indicatorH, ...pickerOverlayStyle } = indicatorStyle
79
- const [pickMaxH, setPickMaxH] = useState(0)
80
77
  const nodeRef = useRef(null)
81
78
  const cloneRef = useRef(null)
82
79
  const activeValueRef = useRef(value)
83
80
  activeValueRef.current = value.slice()
81
+ const snapActiveValueRef = useRef<number[] | null>(null)
82
+
83
+ console.log('[mpx-picker-view] value=', value, Date.now())
84
84
 
85
85
  const {
86
86
  normalStyle,
@@ -96,7 +96,6 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
96
96
  })
97
97
 
98
98
  const {
99
- // 存储layout布局信息
100
99
  layoutRef,
101
100
  layoutProps,
102
101
  layoutStyle
@@ -104,33 +103,34 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
104
103
  const { textProps } = splitProps(props)
105
104
  const { textStyle } = splitStyle(normalStyle)
106
105
 
107
- const onColumnItemRawHChange = (height: number) => {
108
- if (height > pickMaxH) {
109
- setPickMaxH(height)
110
- }
111
- }
112
-
113
- const bindchangeDebounce = useDebounceCallback(useStableCallback(bindchange), 300)
114
-
115
106
  const onSelectChange = (columnIndex: number, selectedIndex: number) => {
116
- bindchangeDebounce.clear()
117
107
  const activeValue = activeValueRef.current
118
108
  activeValue[columnIndex] = selectedIndex
109
+ console.log('[mpx-picker-view], onSelectChange ---> columnIndex=', columnIndex, 'selectedIndex=', selectedIndex, 'activeValue=', activeValue)
119
110
  const eventData = getCustomEvent(
120
111
  'change',
121
112
  {},
122
113
  { detail: { value: activeValue, source: 'change' }, layoutRef }
123
114
  )
124
- bindchangeDebounce(eventData)
115
+ bindchange?.(eventData)
116
+ snapActiveValueRef.current = activeValueRef.current
125
117
  }
126
118
 
127
- const onInitialChange = (value: number[]) => {
128
- const eventData = getCustomEvent(
129
- 'change',
130
- {},
131
- { detail: { value, source: 'change' }, layoutRef }
132
- )
133
- bindchange?.(eventData) // immediate
119
+ const hasDiff = (a: number[] = [], b: number[]) => {
120
+ return a.some((v, i) => v !== b[i])
121
+ }
122
+
123
+ const onInitialChange = (isInvalid: boolean, value: number[]) => {
124
+ if (isInvalid || !snapActiveValueRef.current || hasDiff(snapActiveValueRef.current, value)) {
125
+ console.log('[mpx-picker-view], onInitialChange ===> value=', value)
126
+ const eventData = getCustomEvent(
127
+ 'change',
128
+ {},
129
+ { detail: { value, source: 'change' }, layoutRef }
130
+ )
131
+ bindchange?.(eventData)
132
+ snapActiveValueRef.current = value.slice()
133
+ }
134
134
  }
135
135
 
136
136
  const innerProps = useInnerProps(
@@ -153,7 +153,6 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
153
153
  )
154
154
 
155
155
  const renderColumn = (child: React.ReactElement, index: number, columnData: React.ReactNode[], initialIndex: number) => {
156
- const extraProps = {}
157
156
  const childProps = child?.props || {}
158
157
  const wrappedProps = extendObject(
159
158
  {},
@@ -164,15 +163,15 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
164
163
  columnIndex: index,
165
164
  key: `pick-view-${index}`,
166
165
  wrapperStyle: {
167
- height: normalStyle?.height || 0,
168
- itemHeight: indicatorH || 0
166
+ height: normalStyle?.height || DefaultPickerItemH,
167
+ itemHeight: indicatorH || DefaultPickerItemH
169
168
  },
170
- onColumnItemRawHChange,
169
+ columnStyle: normalStyle,
171
170
  onSelectChange: onSelectChange.bind(null, index),
172
171
  initialIndex,
173
- pickerOverlayStyle
174
- },
175
- extraProps
172
+ pickerOverlayStyle,
173
+ pickerMaskStyle
174
+ }
176
175
  )
177
176
  const realElement = React.cloneElement(child, wrappedProps)
178
177
  return wrapChildren(
@@ -215,7 +214,7 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
215
214
  validValue.push(validIndex)
216
215
  renderColumns.push(renderColumn(item, index, columnData, validIndex))
217
216
  })
218
- isInvalid && onInitialChange(validValue)
217
+ onInitialChange(isInvalid, validValue)
219
218
  return renderColumns
220
219
  }
221
220
 
@@ -227,5 +226,4 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
227
226
  })
228
227
 
229
228
  _PickerView.displayName = 'MpxPickerView'
230
-
231
229
  export default _PickerView
@@ -0,0 +1,32 @@
1
+ import { useEffect, useRef, ReactNode } from 'react'
2
+ import { PortalContextValue } from '../context'
3
+ import { getFocusedNavigation } from '@mpxjs/utils'
4
+
5
+ export type PortalConsumerProps = {
6
+ manager: PortalContextValue
7
+ children?: ReactNode
8
+ }
9
+ const PortalConsumer = ({ manager, children } :PortalConsumerProps): JSX.Element | null => {
10
+ const keyRef = useRef<any>(null)
11
+ useEffect(() => {
12
+ const navigation = getFocusedNavigation()
13
+ const curPageId = navigation?.pageId
14
+ manager.update(keyRef.current, children, curPageId)
15
+ }, [children])
16
+ useEffect(() => {
17
+ if (!manager) {
18
+ throw new Error(
19
+ 'Looks like you forgot to wrap your root component with `Provider` component from `@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal`.\n\n'
20
+ )
21
+ }
22
+ const navigation = getFocusedNavigation()
23
+ const curPageId = navigation?.pageId
24
+ keyRef.current = manager.mount(children, undefined, curPageId)
25
+ return () => {
26
+ manager.unmount(keyRef.current, curPageId)
27
+ }
28
+ }, [])
29
+ return null
30
+ }
31
+
32
+ export default PortalConsumer
@@ -0,0 +1,158 @@
1
+ import { useEffect, useRef, ReactNode } from 'react'
2
+ import {
3
+ View,
4
+ DeviceEventEmitter,
5
+ EventSubscription,
6
+ NativeEventEmitter,
7
+ StyleSheet
8
+ } from 'react-native'
9
+ import PortalManager from './portal-manager'
10
+ import { getFocusedNavigation } from '@mpxjs/utils'
11
+ import { PortalManagerContextValue, PortalContext } from '../context'
12
+
13
+ export type PortalHostProps = {
14
+ children: ReactNode
15
+ }
16
+
17
+ type addIdsMapsType = {
18
+ [key: number]: number[]
19
+ }
20
+
21
+ export type Operation =
22
+ | { type: 'mount'; key: number; children: ReactNode }
23
+ | { type: 'update'; key: number; children: ReactNode }
24
+ | { type: 'unmount'; key: number }
25
+
26
+ // events
27
+ const addType = 'MPX_RN_ADD_PORTAL'
28
+ const removeType = 'MPX_RN_REMOVE_PORTAL'
29
+ // fix react native web does not support DeviceEventEmitter
30
+ const TopViewEventEmitter = DeviceEventEmitter || new NativeEventEmitter()
31
+
32
+ const styles = StyleSheet.create({
33
+ container: {
34
+ flex: 1
35
+ }
36
+ })
37
+
38
+ class PortalGuard {
39
+ private nextKey = 10000
40
+ add = (e: ReactNode) => {
41
+ const key = this.nextKey++
42
+ TopViewEventEmitter.emit(addType, e, key)
43
+ return key
44
+ }
45
+
46
+ remove = (key: number) => {
47
+ TopViewEventEmitter.emit(removeType, key)
48
+ }
49
+ }
50
+ /**
51
+ * portal
52
+ */
53
+ export const portal = new PortalGuard()
54
+
55
+ const PortalHost = ({ children } :PortalHostProps): JSX.Element => {
56
+ const _nextKey = useRef(0)
57
+ const _queue = useRef<Operation[]>([])
58
+ const _addType = useRef<EventSubscription | null>(null)
59
+ const _removeType = useRef<EventSubscription | null>(null)
60
+ const manager = useRef<PortalManagerContextValue | null>(null)
61
+ let currentPageId: number | undefined
62
+ const _mount = (children: ReactNode, _key?: number, curPageId?: number) => {
63
+ const navigation = getFocusedNavigation()
64
+ const pageId = navigation?.pageId
65
+ if (pageId !== (curPageId ?? currentPageId)) {
66
+ return
67
+ }
68
+ const key = _key || _nextKey.current++
69
+ if (manager.current) {
70
+ manager.current.mount(key, children)
71
+ } else {
72
+ _queue.current.push({ type: 'mount', key, children })
73
+ }
74
+ return key
75
+ }
76
+
77
+ const _unmount = (key: number, curPageId?: number) => {
78
+ const navigation = getFocusedNavigation()
79
+ const pageId = navigation?.pageId
80
+ if (pageId !== (curPageId ?? currentPageId)) {
81
+ return
82
+ }
83
+ if (manager.current) {
84
+ manager.current.unmount(key)
85
+ } else {
86
+ _queue.current.push({ type: 'unmount', key })
87
+ }
88
+ }
89
+
90
+ const _update = (key: number, children: ReactNode, curPageId?: number) => {
91
+ const navigation = getFocusedNavigation()
92
+ const pageId = navigation?.pageId
93
+ if (pageId !== (curPageId ?? currentPageId)) {
94
+ return
95
+ }
96
+ if (manager.current) {
97
+ manager.current.update(key, children)
98
+ } else {
99
+ const op: Operation = { type: 'mount', key, children }
100
+ const index = _queue.current.findIndex(
101
+ (o) => o.type === 'mount' || (o.type === 'update' && o.key === key)
102
+ )
103
+
104
+ if (index > -1) {
105
+ _queue.current[index] = op
106
+ } else {
107
+ _queue.current.push(op)
108
+ }
109
+ }
110
+ }
111
+
112
+ useEffect(() => {
113
+ const navigation = getFocusedNavigation()
114
+ currentPageId = navigation?.pageId
115
+ _addType.current = TopViewEventEmitter.addListener(addType, _mount)
116
+ _removeType.current = TopViewEventEmitter.addListener(
117
+ removeType,
118
+ _unmount
119
+ )
120
+ return () => {
121
+ while (_queue.current.length && manager.current) {
122
+ const action = _queue.current.pop()
123
+ if (!action) {
124
+ continue
125
+ }
126
+ // tslint:disable-next-line:switch-default
127
+ switch (action.type) {
128
+ case 'mount':
129
+ manager.current?.mount(action.key, action.children)
130
+ break
131
+ case 'update':
132
+ manager.current?.update(action.key, action.children)
133
+ break
134
+ case 'unmount':
135
+ manager.current?.unmount(action.key)
136
+ break
137
+ }
138
+ }
139
+ }
140
+ }, [])
141
+ return (
142
+ <PortalContext.Provider
143
+ value={{
144
+ mount: _mount,
145
+ update: _update,
146
+ unmount: _unmount
147
+ }}
148
+ >
149
+ {/* Need collapsable=false here to clip the elevations, otherwise they appear above Portal components */}
150
+ <View style={styles.container} collapsable={false}>
151
+ {children}
152
+ </View>
153
+ <PortalManager ref={manager} />
154
+ </PortalContext.Provider>
155
+ )
156
+ }
157
+
158
+ export default PortalHost
@@ -0,0 +1,64 @@
1
+ import { useState, useCallback, forwardRef, ForwardedRef, useImperativeHandle, ReactNode, ReactElement } from 'react'
2
+ import { View, StyleSheet } from 'react-native'
3
+
4
+ export type State = {
5
+ portals: Array<{
6
+ key: number
7
+ children: ReactNode
8
+ }>
9
+ }
10
+
11
+ type PortalManagerProps = {
12
+ }
13
+
14
+ const _PortalManager = forwardRef((props: PortalManagerProps, ref:ForwardedRef<unknown>): ReactElement => {
15
+ const [state, setState] = useState<State>({
16
+ portals: []
17
+ })
18
+
19
+ const mount = useCallback((key: number, children: ReactNode) => {
20
+ setState((prevState) => ({
21
+ portals: [...prevState.portals, { key, children }]
22
+ }))
23
+ }, [state])
24
+
25
+ const update = useCallback((key: number, children: ReactNode) => {
26
+ setState((prevState) => ({
27
+ portals: prevState.portals.map((item) => {
28
+ if (item.key === key) {
29
+ return { ...item, children }
30
+ }
31
+ return item
32
+ })
33
+ }))
34
+ }, [state])
35
+
36
+ const unmount = useCallback((key: number) => {
37
+ setState((prevState) => ({
38
+ portals: prevState.portals.filter((item) => item.key !== key)
39
+ }))
40
+ }, [])
41
+
42
+ useImperativeHandle(ref, () => ({
43
+ mount,
44
+ update,
45
+ unmount,
46
+ portals: state.portals
47
+ }))
48
+
49
+ return (
50
+ <>
51
+ {state.portals.map(({ key, children }, i) => (
52
+ <View
53
+ key={key}
54
+ collapsable={false} // Need collapsable=false here to clip the elevations
55
+ pointerEvents="box-none"
56
+ style={[StyleSheet.absoluteFill, { zIndex: 1000 + i }]}>
57
+ {children}
58
+ </View>
59
+ ))}
60
+ </>
61
+ )
62
+ })
63
+
64
+ export default _PortalManager
@@ -0,0 +1,29 @@
1
+ import { ReactNode } from 'react'
2
+ import { PortalContext, PortalContextValue } from './context'
3
+ import PortalConsumer from './mpx-portal/portal-consumer'
4
+ import PortalHost, { portal } from './mpx-portal/portal-host'
5
+
6
+ export type PortalProps = {
7
+ /**
8
+ * Content of the `Portal`.
9
+ */
10
+ children?: ReactNode
11
+ key?: string
12
+ manager?: PortalContextValue
13
+ }
14
+
15
+ const Portal = ({ children }:PortalProps): JSX.Element => {
16
+ return (
17
+ <PortalContext.Consumer>
18
+ {(manager) => (
19
+ <PortalConsumer manager={manager}>{children}</PortalConsumer>
20
+ )}
21
+ </PortalContext.Consumer>
22
+ )
23
+ }
24
+
25
+ Portal.Host = PortalHost
26
+ Portal.add = portal.add
27
+ Portal.remove = portal.remove
28
+
29
+ export default Portal
@@ -0,0 +1,51 @@
1
+ import { ReactNode, createContext, useMemo } from 'react'
2
+ import LocaleProvider, { LocaleContextProps } from './locale-provider'
3
+ import Portal from './mpx-portal'
4
+ import { extendObject } from './utils'
5
+
6
+ export type Theme = typeof defaultTheme & { [key: string]: any }
7
+
8
+ export interface ProviderProps {
9
+ locale?: LocaleContextProps
10
+ theme?: Partial<Theme>
11
+ children: ReactNode
12
+ }
13
+ const defaultTheme = {
14
+ color_text_base: '#000000', // 基本
15
+ color_text_base_inverse: '#ffffff', // 基本 _ 反色
16
+ color_text_secondary: '#a4a9b0', // 辅助色
17
+ color_text_placeholder: '#bbbbbb', // 文本框提示
18
+ color_text_disabled: '#bbbbbb', // 失效
19
+ color_text_caption: '#888888', // 辅助描述
20
+ color_text_paragraph: '#333333', // 段落
21
+ color_error: '#ff4d4f', // 错误(form validate)
22
+ color_warning: '#faad14', // 警告
23
+ color_success: '#52c41a',
24
+ color_primary: '#1677ff'
25
+ }
26
+ export const ThemeContext = createContext(defaultTheme)
27
+
28
+ export type PartialTheme = Partial<Theme>
29
+
30
+ export interface ThemeProviderProps {
31
+ value?: PartialTheme
32
+ children?: React.ReactNode
33
+ }
34
+
35
+ const ThemeProvider = (props: ThemeProviderProps) => {
36
+ const { value, children } = props
37
+ const theme = useMemo(() => (extendObject({}, defaultTheme, value)), [value])
38
+ return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
39
+ }
40
+
41
+ const Provider = ({ locale, theme, children }:ProviderProps): JSX.Element => {
42
+ return (
43
+ <LocaleProvider locale={locale}>
44
+ <ThemeProvider value={theme}>
45
+ <Portal.Host>{children}</Portal.Host>
46
+ </ThemeProvider>
47
+ </LocaleProvider>
48
+ )
49
+ }
50
+
51
+ export default Provider
@@ -3,10 +3,10 @@
3
3
  * ✔ nodes
4
4
  */
5
5
  import { View, ViewProps, ViewStyle } from 'react-native'
6
- import { useRef, forwardRef, JSX, useState } from 'react'
6
+ import { useRef, forwardRef, JSX, useState, createElement } from 'react'
7
7
  import useInnerProps from '../getInnerListeners'
8
8
  import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
9
- import { useTransformStyle, useLayout } from '../utils'
9
+ import { useTransformStyle, useLayout, extendObject } from '../utils'
10
10
  import { WebView, WebViewMessageEvent } from 'react-native-webview'
11
11
  import { generateHTML } from './html'
12
12
 
@@ -91,28 +91,22 @@ const _RichText = forwardRef<HandlerRef<View, _RichTextProps>, _RichTextProps>((
91
91
  layoutRef
92
92
  })
93
93
 
94
- const innerProps = useInnerProps(props, {
94
+ const innerProps = useInnerProps(props, extendObject({
95
95
  ref: nodeRef,
96
- style: { ...normalStyle, ...layoutStyle },
97
- ...layoutProps
98
- }, [], {
96
+ style: extendObject(normalStyle, layoutStyle)
97
+ }, layoutProps), [], {
99
98
  layoutRef
100
99
  })
101
100
 
102
101
  const html: string = typeof nodes === 'string' ? nodes : jsonToHtmlStr(nodes)
103
102
 
104
- return (
105
- <View
106
- {...innerProps}
107
- >
108
- <WebView
109
- source={{ html: generateHTML(html) }}
110
- onMessage={(event: WebViewMessageEvent) => {
111
- setWebViewHeight(+event.nativeEvent.data)
112
- }}
113
- >
114
- </WebView>
115
- </View>
103
+ return createElement(View, innerProps,
104
+ createElement(WebView, {
105
+ source: { html: generateHTML(html) },
106
+ onMessage: (event: WebViewMessageEvent) => {
107
+ setWebViewHeight(+event.nativeEvent.data)
108
+ }
109
+ })
116
110
  )
117
111
  })
118
112
 
@@ -2,7 +2,7 @@
2
2
  * ✔ enable
3
3
  */
4
4
  import { ReactNode, createElement, Fragment } from 'react'
5
- import { Portal } from '@ant-design/react-native'
5
+ import Portal from './mpx-portal'
6
6
  import { warn } from '@mpxjs/utils'
7
7
  interface RootPortalProps {
8
8
  enable?: boolean
@@ -32,15 +32,14 @@
32
32
  * ✔ bindscroll
33
33
  */
34
34
  import { ScrollView } from 'react-native-gesture-handler'
35
- import { View, RefreshControl, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle } from 'react-native'
36
- import { JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef, useContext, createElement } from 'react'
35
+ import { View, RefreshControl, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle, Platform } from 'react-native'
36
+ import { JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef, useContext, createElement, useMemo } from 'react'
37
37
  import { useAnimatedRef } from 'react-native-reanimated'
38
38
  import { warn } from '@mpxjs/utils'
39
39
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
40
40
  import useNodesRef, { HandlerRef } from './useNodesRef'
41
41
  import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, GestureHandler } from './utils'
42
- import { IntersectionObserverContext } from './context'
43
-
42
+ import { IntersectionObserverContext, ScrollViewContext } from './context'
44
43
  interface ScrollViewProps {
45
44
  children?: ReactNode;
46
45
  enhanced?: boolean;
@@ -194,6 +193,12 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
194
193
  gestureRef: scrollViewRef
195
194
  })
196
195
 
196
+ const contextValue = useMemo(() => {
197
+ return {
198
+ gestureRef: scrollViewRef
199
+ }
200
+ }, [])
201
+
197
202
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
198
203
 
199
204
  if (scrollX && scrollY) {
@@ -332,11 +337,6 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
332
337
  }, props)
333
338
  )
334
339
  updateScrollOptions(e, { scrollLeft, scrollTop })
335
- if (enableTriggerIntersectionObserver && intersectionObservers) {
336
- for (const key in intersectionObservers) {
337
- intersectionObservers[key].throttleMeasure()
338
- }
339
- }
340
340
  }
341
341
 
342
342
  function onScrollEnd (e: NativeSyntheticEvent<NativeScrollEvent>) {
@@ -358,8 +358,15 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
358
358
  updateScrollOptions(e, { scrollLeft, scrollTop })
359
359
  onStartReached(e)
360
360
  onEndReached(e)
361
+ updateIntersection()
362
+ }
363
+ function updateIntersection () {
364
+ if (enableTriggerIntersectionObserver && intersectionObservers) {
365
+ for (const key in intersectionObservers) {
366
+ intersectionObservers[key].throttleMeasure();
367
+ }
368
+ }
361
369
  }
362
-
363
370
  function scrollToOffset (x = 0, y = 0) {
364
371
  if (scrollViewRef.current) {
365
372
  scrollViewRef.current.scrollTo({ x, y, animated: !!scrollWithAnimation })
@@ -429,6 +436,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
429
436
  function onScrollDrag (e: NativeSyntheticEvent<NativeScrollEvent>) {
430
437
  const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset
431
438
  updateScrollOptions(e, { scrollLeft, scrollTop })
439
+ updateIntersection()
432
440
  }
433
441
 
434
442
  const scrollAdditionalProps: ScrollAdditionalProps = extendObject(
@@ -507,14 +515,17 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
507
515
  }, (refresherDefaultStyle && refresherDefaultStyle !== 'none' ? { colors: refreshColor[refresherDefaultStyle] } : null)))
508
516
  : undefined
509
517
  }),
510
- wrapChildren(
511
- props,
512
- {
513
- hasVarDec,
514
- varContext: varContextRef.current,
515
- textStyle,
516
- textProps
517
- }
518
+ createElement(ScrollViewContext.Provider,
519
+ { value: contextValue },
520
+ wrapChildren(
521
+ props,
522
+ {
523
+ hasVarDec,
524
+ varContext: varContextRef.current,
525
+ textStyle,
526
+ textProps
527
+ }
528
+ )
518
529
  )
519
530
  )
520
531
  })