@mpxjs/core 2.10.16 → 2.10.17

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.
@@ -11,3 +11,6 @@ declare module '*?resolve' {
11
11
  const resourcePath: string
12
12
  export default resourcePath
13
13
  }
14
+
15
+ declare let setAppShow: () => void
16
+ declare let setAppHide: () => void
package/@types/index.d.ts CHANGED
@@ -9,6 +9,7 @@
9
9
 
10
10
  import type { GetComputedType } from '@mpxjs/store'
11
11
  import type { ScaledSize } from 'react-native'
12
+ import type { ComponentType } from 'react'
12
13
  export * from '@mpxjs/store'
13
14
 
14
15
  // utils
@@ -126,9 +127,17 @@ interface Context {
126
127
  type ExtendedComponentOptions = {
127
128
  disconnectOnUnmounted?: boolean
128
129
  shallowReactivePattern?: RegExp
130
+ /**
131
+ * 是否禁用render函数的useMemo,仅输出RN支持
132
+ */
133
+ disableMemo?: boolean
129
134
  } & WechatMiniprogram.Component.ComponentOptions
130
135
 
131
136
  interface ComponentOpt<D extends Data, P extends Properties, C, M extends Methods, Mi extends Array<any>, S extends Record<any, any>> extends Partial<WechatMiniprogram.Component.Lifetimes & WechatMiniprogram.Component.OtherOption> {
137
+ /**
138
+ * ReactNative 原生组件注册
139
+ */
140
+ components?: Record<string, ComponentType>,
132
141
  data?: D
133
142
  properties?: P
134
143
  computed?: C
@@ -221,7 +230,7 @@ type WxComponentIns<D extends Data = {}, P extends Properties = {}, M extends Me
221
230
  Omit<WechatMiniprogram.Component.Instance<D, P, M>, 'selectComponent' | 'selectAllComponents'>
222
231
  & ReplaceWxComponentIns
223
232
 
224
- type ComponentIns<D extends Data = {}, P extends Properties = {}, C = {}, M extends Methods = {}, Mi extends Array<any> = [], S extends Record<any, any> = {}, O = {}> =
233
+ export type ComponentIns<D extends Data = {}, P extends Properties = {}, C = {}, M extends Methods = {}, Mi extends Array<any> = [], S extends Record<any, any> = {}, O = {}> =
225
234
  GetDataType<D> & UnboxMixinsField<Mi, 'data'> &
226
235
  M & UnboxMixinsField<Mi, 'methods'> & { [K in keyof S]: S[K] extends Ref<infer V> ? V : S[K] } &
227
236
  GetPropsType<P & UnboxMixinsField<Mi, 'properties'>> &
@@ -296,7 +305,7 @@ export interface RnConfig {
296
305
  * - `true`:允许退出应用
297
306
  * - `false`:阻止退出应用
298
307
  */
299
- onAppBack?: () => boolean
308
+ onAppBack?: (delta: number) => boolean
300
309
 
301
310
  /**
302
311
  * 是否禁用框架内部的 AppStateChange 监听。
@@ -356,26 +365,6 @@ export interface RnConfig {
356
365
  dimensions: T
357
366
  ) => T | void
358
367
 
359
- /**
360
- * 异步分包加载配置。
361
- */
362
- asyncChunk?: {
363
- /**
364
- * 加载超时时长配置,单位为毫秒。
365
- */
366
- timeout: number
367
-
368
- /**
369
- * 异步分包页面加载超时或失败时,自定义兜底页面文件路径。
370
- */
371
- fallback: string
372
-
373
- /**
374
- * 异步分包页面加载时,自定义 loading 页面文件路径。
375
- */
376
- loading: string
377
- }
378
-
379
368
  /**
380
369
  * 加载并执行异步分包的方法。
381
370
  *
@@ -392,6 +381,13 @@ export interface RnConfig {
392
381
  * @param packages 分包名数组
393
382
  */
394
383
  downloadChunkAsync?: (packages: Array<string>) => void
384
+
385
+ /**
386
+ * bundle 中是否关闭 android 键盘避让功能,如果关闭需要将该配置设置为 false,使用 mpx 内置的键盘避让逻辑
387
+ * @platform android
388
+ * @default true
389
+ */
390
+ enableNativeKeyboardAvoiding?: boolean
395
391
  }
396
392
 
397
393
  interface MpxConfig {
@@ -399,10 +395,10 @@ interface MpxConfig {
399
395
  ignoreWarning: boolean | string | RegExp | ((msg: string, location: string, e: Error) => boolean)
400
396
  ignoreProxyWhiteList: Array<string>
401
397
  observeClassInstance: boolean | Array<AnyConstructor>
402
- errorHandler: (msg: String, location: String, e: Error) => any | null
403
- warnHandler: (msg: String, location: String, e: Error) => any | null
404
- proxyEventHandler: (e: WechatMiniprogram.CustomEvent, target: ComponentIns<{}, {}, {}, {}, []>) => any | null
405
- setDataHandler: (data: object, target: ComponentIns<{}, {}, {}, {}, []>) => any | null
398
+ errorHandler: (msg: String, location: String, e: Error) => void
399
+ warnHandler: (msg: String, location: String, e: Error) => void
400
+ proxyEventHandler: (e: WechatMiniprogram.CustomEvent, target: ComponentIns<{}, {}, {}, {}, []>) => void
401
+ setDataHandler: (data: object, target: ComponentIns<{}, {}, {}, {}, []>) => void
406
402
  forceFlushSync: boolean,
407
403
  webRouteConfig: object,
408
404
  webConfig: object,
@@ -413,7 +409,7 @@ interface MpxConfig {
413
409
  */
414
410
  webviewConfig: WebviewConfig,
415
411
  /** react-native 相关配置,用于挂载事件等,如 onShareAppMessage */
416
- rnConfig?: RnConfig,
412
+ rnConfig: RnConfig,
417
413
  }
418
414
 
419
415
  type SupportedMode = 'wx' | 'ali' | 'qq' | 'swan' | 'tt' | 'web' | 'qa'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.10.16",
3
+ "version": "2.10.17",
4
4
  "description": "mpx runtime core",
5
5
  "keywords": [
6
6
  "miniprogram",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "main": "src/index.js",
21
21
  "dependencies": {
22
- "@mpxjs/utils": "^2.10.16",
22
+ "@mpxjs/utils": "^2.10.17",
23
23
  "lodash": "^4.1.1",
24
24
  "miniprogram-api-typings": "^3.10.0"
25
25
  },
@@ -93,6 +93,10 @@
93
93
  "optional": true
94
94
  }
95
95
  },
96
+ "devDependencies": {
97
+ "@types/react": "^18.2.79",
98
+ "react-native": "^0.74.5"
99
+ },
96
100
  "publishConfig": {
97
101
  "registry": "https://registry.npmjs.org",
98
102
  "access": "public"
@@ -109,5 +113,5 @@
109
113
  "url": "https://github.com/didi/mpx/issues"
110
114
  },
111
115
  "sideEffects": false,
112
- "gitHead": "be4129320e298edf935ea35f9ca3d375f75ac51c"
116
+ "gitHead": "33fbd0bb8d4b83555239a8931fabb23022af0866"
113
117
  }
@@ -7,7 +7,7 @@ import { implemented } from '../core/implement'
7
7
  const unsupported = ['moved', 'definitionFilter']
8
8
 
9
9
  function convertErrorDesc (key) {
10
- error(`Options.${key} is not supported in runtime conversion from wx to ali.`, global.currentResource)
10
+ error(`Options.${key} is not supported in runtime conversion from wx to ali.`, global.currentResource || global.currentModuleId)
11
11
  }
12
12
 
13
13
  function notSupportTip (options) {
@@ -8,7 +8,7 @@ import { implemented } from '../core/implement'
8
8
  const unsupported = ['moved', 'definitionFilter']
9
9
 
10
10
  function convertErrorDesc (key) {
11
- error(`Options.${key} is not supported in runtime conversion from wx to react native.`, global.currentResource)
11
+ error(`Options.${key} is not supported in runtime conversion from wx to react native.`, global.currentResource || global.currentModuleId)
12
12
  }
13
13
 
14
14
  function notSupportTip (options) {
@@ -12,7 +12,7 @@ const BEHAVIORS_MAP = {
12
12
  const unsupported = ['moved', 'relations']
13
13
 
14
14
  function convertErrorDesc (key) {
15
- error(`Options.${key} is not supported in runtime conversion from wx to swan.`, global.currentResource)
15
+ error(`Options.${key} is not supported in runtime conversion from wx to swan.`, global.currentResource || global.currentModuleId)
16
16
  }
17
17
 
18
18
  function notSupportTip (options) {
@@ -12,7 +12,7 @@ export default {
12
12
  if (options.behaviors) {
13
13
  options.behaviors.forEach((behavior, idx) => {
14
14
  if (BEHAVIORS_MAP.includes(behavior)) {
15
- error(`Built-in behavior "${behavior}" is not supported in tt environment!`, global.currentResource)
15
+ error(`Built-in behavior "${behavior}" is not supported in tt environment!`, global.currentResource || global.currentModuleId)
16
16
  options.behaviors.splice(idx, 1)
17
17
  }
18
18
  })
@@ -14,7 +14,7 @@ import { implemented } from '../core/implement'
14
14
  const unsupported = ['moved', 'definitionFilter', 'onShareAppMessage']
15
15
 
16
16
  function convertErrorDesc (key) {
17
- error(`Options.${key} is not supported in runtime conversion from wx to web.`, global.currentResource)
17
+ error(`Options.${key} is not supported in runtime conversion from wx to web.`, global.currentResource || global.currentModuleId)
18
18
  }
19
19
 
20
20
  function notSupportTip (options) {
@@ -13,7 +13,7 @@ export default function transferOptions (options, type, needConvert = true) {
13
13
  }
14
14
  }
15
15
  // 文件编译路径
16
- options.mpxFileResource = global.currentResource
16
+ options.mpxFileResource = global.currentResource || global.currentModuleId
17
17
  // 注入全局写入的mixins,原生模式下不进行注入
18
18
  if (!options.__nativeRender__) {
19
19
  options = mergeInjectedMixins(options, type)
@@ -8,10 +8,6 @@ const rawDimensions = {
8
8
  }
9
9
  let width, height
10
10
 
11
- // TODO 临时适配折叠屏场景适配
12
- // const isLargeFoldableLike = (__mpx_mode__ === 'android') && (height / width < 1.5) && (width > 600)
13
- // if (isLargeFoldableLike) width = width / 2
14
-
15
11
  function customDimensions (dimensions) {
16
12
  if (typeof Mpx.config.rnConfig?.customDimensions === 'function') {
17
13
  dimensions = Mpx.config.rnConfig.customDimensions(dimensions) || dimensions
@@ -236,8 +232,14 @@ export default function styleHelperMixin () {
236
232
  flex: 0,
237
233
  height: 0,
238
234
  width: 0,
239
- padding: 0,
240
- margin: 0,
235
+ paddingTop: 0,
236
+ paddingRight: 0,
237
+ paddingBottom: 0,
238
+ paddingLeft: 0,
239
+ marginTop: 0,
240
+ marginRight: 0,
241
+ marginBottom: 0,
242
+ marginLeft: 0,
241
243
  overflow: 'hidden'
242
244
  })
243
245
  }
@@ -10,7 +10,7 @@ import { createElement, memo, useRef, useEffect } from 'react'
10
10
  import * as ReactNative from 'react-native'
11
11
  import { initAppProvides } from './export/inject'
12
12
  import { NavigationContainer, createNativeStackNavigator, SafeAreaProvider, GestureHandlerRootView } from './env/navigationHelper'
13
- import { innerNav } from './env/nav'
13
+ import MpxNav from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-nav'
14
14
 
15
15
  const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
16
16
 
@@ -66,8 +66,8 @@ export default function createApp (options) {
66
66
  flex: 1
67
67
  }
68
68
  },
69
- createElement(innerNav, {
70
- pageConfig: pageConfig,
69
+ createElement(MpxNav, {
70
+ pageConfig,
71
71
  navigation
72
72
  }),
73
73
  children
@@ -230,7 +230,7 @@ export default function createApp (options) {
230
230
  const { initialRouteName, initialParams } = initialRouteRef.current
231
231
  const navScreenOpts = {
232
232
  headerShown: false,
233
- statusBarTranslucent: true,
233
+ statusBarTranslucent: Mpx.config.rnConfig.statusBarTranslucent ?? true,
234
234
  statusBarBackgroundColor: 'transparent'
235
235
  }
236
236
 
@@ -13,12 +13,12 @@ import MpxKeyboardAvoidingView from '@mpxjs/webpack-plugin/lib/runtime/component
13
13
  import {
14
14
  IntersectionObserverContext,
15
15
  KeyboardAvoidContext,
16
+ ProviderContext,
16
17
  RouteContext
17
18
  } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
18
19
  import { PortalHost, useSafeAreaInsets } from '../env/navigationHelper'
19
- import { useInnerHeaderHeight } from '../env/nav'
20
+ import { useInnerHeaderHeight } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-nav'
20
21
 
21
- const ProviderContext = createContext(null)
22
22
  function getSystemInfo () {
23
23
  const windowDimensions = ReactNative.Dimensions.get('window')
24
24
  const screenDimensions = ReactNative.Dimensions.get('screen')
@@ -420,6 +420,11 @@ function usePageStatus (navigation, pageId) {
420
420
  set(pageStatusMap, pageId, '')
421
421
  }
422
422
  useEffect(() => {
423
+ if (navigation.isFocused && navigation.isFocused()) {
424
+ Promise.resolve().then(() => {
425
+ pageStatusMap[pageId] = 'show'
426
+ })
427
+ }
423
428
  const focusSubscription = navigation.addListener('focus', () => {
424
429
  pageStatusMap[pageId] = 'show'
425
430
  })
@@ -497,7 +502,6 @@ function getLayoutData (headerHeight) {
497
502
 
498
503
  export function PageWrapperHOC (WrappedComponent, pageConfig = {}) {
499
504
  return function PageWrapperCom ({ navigation, route, ...props }) {
500
- const rootRef = useRef(null)
501
505
  const keyboardAvoidRef = useRef(null)
502
506
  const intersectionObservers = useRef({})
503
507
  const currentPageId = useMemo(() => ++pageId, [])
@@ -545,36 +549,36 @@ export function PageWrapperHOC (WrappedComponent, pageConfig = {}) {
545
549
  // android存在第一次打开insets都返回为0情况,后续会触发第二次渲染后正确
546
550
  navigation.insets = useSafeAreaInsets()
547
551
  return withKeyboardAvoidingView(
548
- createElement(ReactNative.View,
549
- {
550
- style: {
551
- flex: 1,
552
- backgroundColor: currentPageConfig?.backgroundColor || '#fff',
553
- // 解决页面内有元素定位relative left为负值的时候,回退的时候还能看到对应元素问题
554
- overflow: 'hidden'
555
- },
556
- ref: rootRef
557
- },
558
- createElement(RouteContext.Provider,
559
- {
560
- value: routeContextValRef.current
561
- },
562
- createElement(IntersectionObserverContext.Provider,
552
+ createElement(ReactNative.View,
563
553
  {
564
- value: intersectionObservers.current
554
+ style: {
555
+ flex: 1,
556
+ // 页面容器背景色
557
+ backgroundColor: currentPageConfig?.backgroundColorContent || '#fff',
558
+ // 解决页面内有元素定位relative left为负值的时候,回退的时候还能看到对应元素问题
559
+ overflow: 'hidden'
560
+ }
565
561
  },
566
- createElement(PortalHost,
567
- null,
568
- createElement(WrappedComponent, {
569
- ...props,
570
- navigation,
571
- route,
572
- id: currentPageId
573
- })
562
+ createElement(RouteContext.Provider,
563
+ {
564
+ value: routeContextValRef.current
565
+ },
566
+ createElement(IntersectionObserverContext.Provider,
567
+ {
568
+ value: intersectionObservers.current
569
+ },
570
+ createElement(PortalHost,
571
+ null,
572
+ createElement(WrappedComponent, {
573
+ ...props,
574
+ navigation,
575
+ route,
576
+ id: currentPageId
577
+ })
578
+ )
579
+ )
574
580
  )
575
- )
576
581
  )
577
- )
578
582
  )
579
583
  }
580
584
  }
@@ -1,137 +0,0 @@
1
- import { createElement, useState, useMemo, memo } from 'react'
2
- import { useSafeAreaInsets } from 'react-native-safe-area-context'
3
- import { StatusBar, processColor, TouchableWithoutFeedback, Image, View, StyleSheet, Text } from 'react-native'
4
- import Mpx from '../../index'
5
-
6
- function convertToHex (color) {
7
- try {
8
- const intColor = processColor(color)
9
- if (intColor === null || intColor === undefined) {
10
- return null
11
- }
12
- // 将32位整数颜色值转换为RGBA
13
- const r = (intColor >> 16) & 255
14
- const g = (intColor >> 8) & 255
15
- const b = intColor & 255
16
- // 转换为十六进制
17
- const hexR = r.toString(16).padStart(2, '0')
18
- const hexG = g.toString(16).padStart(2, '0')
19
- const hexB = b.toString(16).padStart(2, '0')
20
- return `#${hexR}${hexG}${hexB}`
21
- } catch (error) {
22
- return null
23
- }
24
- }
25
-
26
- const titleHeight = 44
27
- export function useInnerHeaderHeight (pageconfig) {
28
- if (pageconfig.navigationStyle === 'custom') {
29
- return 0
30
- } else {
31
- const safeAreaTop = useSafeAreaInsets()?.top || 0
32
- const headerHeight = safeAreaTop + titleHeight
33
- return headerHeight
34
- }
35
- }
36
-
37
- const styles = StyleSheet.create({
38
- header: {
39
- elevation: 3
40
- },
41
- headerContent: {
42
- flexDirection: 'row',
43
- alignItems: 'center',
44
- justifyContent: 'center'
45
- },
46
- backButton: {
47
- position: 'absolute',
48
- height: '100%',
49
- width: 40,
50
- left: 0,
51
- top: 0,
52
- alignItems: 'center',
53
- justifyContent: 'center'
54
- },
55
- backButtonImage: {
56
- width: 22,
57
- height: 22
58
- },
59
- title: {
60
- fontSize: 17,
61
- fontWeight: 600,
62
- width: '60%',
63
- textAlign: 'center'
64
- }
65
- })
66
- const NavColor = {
67
- White: '#ffffff',
68
- Black: '#000000'
69
- }
70
- // navigationBarTextStyle只支持黑白'white'/'black
71
- const validBarTextStyle = (textStyle) => {
72
- const textStyleColor = convertToHex(textStyle)
73
- if (textStyle && [NavColor.White, NavColor.Black].includes(textStyleColor)) {
74
- return textStyleColor
75
- } else {
76
- return NavColor.White
77
- }
78
- }
79
- export const innerNav = memo(({ pageConfig, navigation }) => {
80
- const [innerPageConfig, setPageConfig] = useState(pageConfig || {})
81
- navigation.setPageConfig = (config) => {
82
- const newConfig = Object.assign({}, innerPageConfig, config)
83
- setPageConfig(newConfig)
84
- }
85
- const isCustom = innerPageConfig.navigationStyle === 'custom'
86
- const navigationBarTextStyle = useMemo(() => validBarTextStyle(innerPageConfig.navigationBarTextStyle), [innerPageConfig.navigationBarTextStyle])
87
- // 状态栏的颜色
88
- const statusBarElement = createElement(StatusBar, {
89
- translucent: true,
90
- backgroundColor: 'transparent',
91
- barStyle: (navigationBarTextStyle === NavColor.White) ? 'light-content' : 'dark-content' // 'default'/'light-content'/'dark-content'
92
- })
93
-
94
- if (isCustom) return statusBarElement
95
- const safeAreaTop = useSafeAreaInsets()?.top || 0
96
- // 假设是栈导航,获取栈的长度
97
- const stackLength = navigation.getState()?.routes?.length
98
- const onStackTopBack = Mpx.config?.rnConfig?.onStackTopBack
99
- const isHandleStackTopBack = typeof onStackTopBack === 'function'
100
-
101
- // 回退按钮与图标
102
- const backElement = stackLength > 1 || isHandleStackTopBack
103
- ? createElement(TouchableWithoutFeedback, {
104
- onPress: () => {
105
- if (stackLength <= 1 && isHandleStackTopBack) {
106
- onStackTopBack()
107
- return
108
- }
109
- navigation.goBack()
110
- }
111
- }, createElement(View, {
112
- style: [styles.backButton]
113
- }, createElement(Image, {
114
- source: { uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAABICAYAAACqT5alAAAA2UlEQVR4nO3bMQrCUBRE0Yla6AYEN2nnBrTL+izcitW3MRDkEUWSvPzJvfCqgMwhZbAppWhNbbIHzB1g9wATERFRVyvpkj1irlpJ5X326D7WHh1hbdFD2CLpLmmftm7kfsEe09aNHFiBrT+wAlt/YAW2/sAKbP2BFdj6Ayuwy+ufz6XPL893krZ//O6iu2n4LT8kndLWTRTo4EC7BDo40C6BDg60S6CDA+0S6OBAuwQ6uNWiD2nrJmoIfU7cNWkR2hbb1UfbY7uuWhGWiIg+a/iHuHmA3QPs3gu4JW9Gan+OJAAAAABJRU5ErkJggg==' },
115
- // 回退按钮的颜色与设置的title文案颜色一致
116
- style: [styles.backButtonImage, { tintColor: navigationBarTextStyle }]
117
- })
118
- ))
119
- : null
120
-
121
- return createElement(View, {
122
- style: [styles.header, {
123
- paddingTop: safeAreaTop,
124
- backgroundColor: innerPageConfig.navigationBarBackgroundColor || '#000000'
125
- }]
126
- },
127
- statusBarElement,
128
- createElement(View, {
129
- style: styles.headerContent,
130
- height: titleHeight
131
- }, backElement,
132
- createElement(Text, {
133
- style: [styles.title, { color: navigationBarTextStyle }],
134
- numberOfLines: 1
135
- }, innerPageConfig.navigationBarTitleText?.trim() || ''))
136
- )
137
- })