@mpxjs/core 2.9.67 → 2.9.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.9.67",
3
+ "version": "2.9.69",
4
4
  "description": "mpx runtime core",
5
5
  "keywords": [
6
6
  "miniprogram",
@@ -19,21 +19,23 @@
19
19
  ],
20
20
  "main": "src/index.js",
21
21
  "dependencies": {
22
- "@mpxjs/utils": "^2.9.67",
22
+ "@mpxjs/utils": "^2.9.69",
23
23
  "lodash": "^4.1.1",
24
24
  "miniprogram-api-typings": "^3.10.0"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "@ant-design/react-native": "^5.1.3",
28
+ "@d11/react-native-fast-image": "^8.6.12",
28
29
  "@mpxjs/api-proxy": "^2.9.0",
29
30
  "@mpxjs/store": "^2.9.0",
30
- "@react-navigation/native": "^6.1.17",
31
- "@react-navigation/native-stack": "^6.9.26",
31
+ "@react-navigation/native": "^7.0.3",
32
+ "@react-navigation/stack": "^7.0.4",
32
33
  "react": "*",
33
34
  "react-native": "*",
34
35
  "react-native-gesture-handler": "^2.19.0",
35
36
  "react-native-linear-gradient": "^2.8.3",
36
- "react-native-safe-area-context": "^4.10.1",
37
+ "react-native-safe-area-context": "^4.14.0",
38
+ "react-native-screens": "^4.1.0",
37
39
  "react-native-webview": "^13.10.5",
38
40
  "vue": "^2.7.10",
39
41
  "vue-demi": "^0.14.6",
@@ -62,7 +64,7 @@
62
64
  "@react-navigation/native": {
63
65
  "optional": true
64
66
  },
65
- "@react-navigation/native-stack": {
67
+ "@react-navigation/stack": {
66
68
  "optional": true
67
69
  },
68
70
  "@ant-design/react-native": {
@@ -71,6 +73,9 @@
71
73
  "react-native-safe-area-context": {
72
74
  "optional": true
73
75
  },
76
+ "react-native-screens": {
77
+ "optional": true
78
+ },
74
79
  "react-native-webview": {
75
80
  "optional": true
76
81
  },
@@ -79,6 +84,9 @@
79
84
  },
80
85
  "react-native-linear-gradient": {
81
86
  "optional": true
87
+ },
88
+ "@d11/react-native-fast-image": {
89
+ "optional": true
82
90
  }
83
91
  },
84
92
  "publishConfig": {
@@ -97,5 +105,5 @@
97
105
  "url": "https://github.com/didi/mpx/issues"
98
106
  },
99
107
  "sideEffects": false,
100
- "gitHead": "b23d3850c16543c5998811b8d1d8e6ee7988c0f8"
108
+ "gitHead": "e23c51acc4c2ffdd31fcc6c27aae1aed42d1ade2"
101
109
  }
@@ -5,7 +5,7 @@ import {
5
5
  import { implemented } from '../core/implement'
6
6
 
7
7
  // 暂不支持的wx选项,后期需要各种花式支持
8
- const unsupported = ['relations', 'moved', 'definitionFilter', 'onShareAppMessage']
8
+ const unsupported = ['relations', 'moved', 'definitionFilter']
9
9
 
10
10
  function convertErrorDesc (key) {
11
11
  error(`Options.${key} is not supported in runtime conversion from wx to react native.`, global.currentResource)
@@ -1,19 +1,22 @@
1
- import { isObject, isArray, dash2hump, isFunction, cached, getFocusedNavigation } from '@mpxjs/utils'
1
+ import { isObject, isArray, dash2hump, cached } from '@mpxjs/utils'
2
2
  import { Dimensions, StyleSheet } from 'react-native'
3
3
 
4
+ let { width, height } = Dimensions.get('screen')
5
+
6
+ Dimensions.addEventListener('change', ({ screen }) => {
7
+ width = screen.width
8
+ height = screen.height
9
+ })
10
+
4
11
  function rpx (value) {
5
- const { width } = Dimensions.get('screen')
6
12
  // rn 单位 dp = 1(css)px = 1 物理像素 * pixelRatio(像素比)
7
13
  // px = rpx * (750 / 屏幕宽度)
8
14
  return value * width / 750
9
15
  }
10
16
  function vw (value) {
11
- const { width } = Dimensions.get('screen')
12
17
  return value * width / 100
13
18
  }
14
19
  function vh (value) {
15
- const navigation = getFocusedNavigation()
16
- const height = navigation?.layout?.height || Dimensions.get('screen').height
17
20
  return value * height / 100
18
21
  }
19
22
 
@@ -24,14 +27,15 @@ const unit = {
24
27
  }
25
28
 
26
29
  function formatValue (value) {
27
- let matched
28
- if ((matched = numberRegExp.exec(value))) {
29
- value = +matched[1]
30
- } else if ((matched = unitRegExp.exec(value))) {
31
- value = unit[matched[2]](+matched[1])
32
- } else if (hairlineRegExp.test(value)) {
33
- value = StyleSheet.hairlineWidth
30
+ const matched = unitRegExp.exec(value)
31
+ if (matched) {
32
+ if (!matched[2] || matched[2] === 'px') {
33
+ return +matched[1]
34
+ } else {
35
+ return unit[matched[2]](+matched[1])
36
+ }
34
37
  }
38
+ if (hairlineRegExp.test(value)) return StyleSheet.hairlineWidth
35
39
  return value
36
40
  }
37
41
 
@@ -106,8 +110,7 @@ function stringifyDynamicClass (value) {
106
110
 
107
111
  const listDelimiter = /;(?![^(]*[)])/g
108
112
  const propertyDelimiter = /:(.+)/
109
- const unitRegExp = /^\s*(-?\d+(?:\.\d+)?)(rpx|vw|vh)\s*$/
110
- const numberRegExp = /^\s*(-?\d+(\.\d+)?)(px)?\s*$/
113
+ const unitRegExp = /^\s*(-?\d+(?:\.\d+)?)(rpx|vw|vh|px)?\s*$/
111
114
  const hairlineRegExp = /^\s*hairlineWidth\s*$/
112
115
  const varRegExp = /^--/
113
116
 
@@ -164,14 +167,8 @@ export default function styleHelperMixin () {
164
167
  },
165
168
  __getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, hide) {
166
169
  const result = {}
167
- const classMap = {}
168
- // todo 全局样式在每个页面和组件中生效,以支持全局原子类,后续支持样式模块复用后可考虑移除
169
- if (isFunction(global.__getAppClassMap)) {
170
- Object.assign(classMap, global.__getAppClassMap())
171
- }
172
- if (isFunction(this.__getClassMap)) {
173
- Object.assign(classMap, this.__getClassMap())
174
- }
170
+ const classMap = this.__getClassMap?.() || {}
171
+ const appClassMap = global.__getAppClassMap?.() || {}
175
172
 
176
173
  if (staticClass || dynamicClass) {
177
174
  // todo 当前为了复用小程序unocss产物,暂时进行mpEscape,等后续正式支持unocss后可不进行mpEscape
@@ -179,6 +176,9 @@ export default function styleHelperMixin () {
179
176
  classString.split(/\s+/).forEach((className) => {
180
177
  if (classMap[className]) {
181
178
  Object.assign(result, classMap[className])
179
+ } else if (appClassMap[className]) {
180
+ // todo 全局样式在每个页面和组件中生效,以支持全局原子类,后续支持样式模块复用后可考虑移除
181
+ Object.assign(result, appClassMap[className])
182
182
  } else if (this.props[className] && isObject(this.props[className])) {
183
183
  // externalClasses必定以对象形式传递下来
184
184
  Object.assign(result, this.props[className])
@@ -1,6 +1,6 @@
1
1
  import transferOptions from '../core/transferOptions'
2
2
  import builtInKeysMap from './patch/builtInKeysMap'
3
- import { makeMap, spreadProp, parseUrlQuery } from '@mpxjs/utils'
3
+ import { makeMap, spreadProp, parseUrlQuery, getFocusedNavigation } from '@mpxjs/utils'
4
4
  import { mergeLifecycle } from '../convertor/mergeLifecycle'
5
5
  import * as wxLifecycle from '../platform/patch/wx/lifecycle'
6
6
  import Mpx from '../index'
@@ -143,8 +143,21 @@ export default function createApp (option, config = {}) {
143
143
 
144
144
  const changeSubscription = ReactNative.AppState.addEventListener('change', (currentState) => {
145
145
  if (currentState === 'active') {
146
+ let options = global.__mpxEnterOptions
147
+ const navigation = getFocusedNavigation()
148
+ if (navigation) {
149
+ const state = navigation.getState()
150
+ const current = state.routes[state.index]
151
+ options = {
152
+ path: current.name,
153
+ query: current.params,
154
+ scene: 0,
155
+ shareTicket: '',
156
+ referrerInfo: {}
157
+ }
158
+ }
146
159
  global.__mpxAppCbs.show.forEach((cb) => {
147
- cb(global.__mpxEnterOptions)
160
+ cb(options)
148
161
  })
149
162
  global.__mpxAppFocusedState.value = 'show'
150
163
  } else if (currentState === 'inactive') {
@@ -180,9 +193,13 @@ export default function createApp (option, config = {}) {
180
193
  createElement(Stack.Navigator,
181
194
  {
182
195
  initialRouteName,
183
- headerBackButtonDisplayMode: 'minimal',
184
- headerMode: 'float',
185
- gestureEnabled: true
196
+ screenOptions: {
197
+ gestureEnabled: true,
198
+ // 7.x替换headerBackTitleVisible
199
+ // headerBackButtonDisplayMode: 'minimal',
200
+ headerBackTitleVisible: false,
201
+ headerMode: 'float'
202
+ }
186
203
  },
187
204
  ...getPageScreens(initialRouteName, initialParams)
188
205
  )
@@ -191,7 +208,7 @@ export default function createApp (option, config = {}) {
191
208
  })
192
209
 
193
210
  global.getCurrentPages = function () {
194
- const navigation = Object.values(global.__mpxPagesMap || {})[0]?.[1]
211
+ const navigation = getFocusedNavigation()
195
212
  if (navigation) {
196
213
  return navigation.getState().routes.map((route) => {
197
214
  return global.__mpxPagesMap[route.key] && global.__mpxPagesMap[route.key][0]
@@ -1,15 +1,15 @@
1
- import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useCallback, createElement, memo, forwardRef, useImperativeHandle, useContext, createContext, Fragment, cloneElement } from 'react'
1
+ import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useCallback, createElement, memo, forwardRef, useImperativeHandle, useContext, Fragment, cloneElement } from 'react'
2
2
  import * as ReactNative from 'react-native'
3
3
  import { ReactiveEffect } from '../../../observer/effect'
4
4
  import { watch } from '../../../observer/watch'
5
5
  import { reactive, set, del } from '../../../observer/reactive'
6
- import { hasOwn, isFunction, noop, isObject, getByPath, collectDataset, hump2dash, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
6
+ import { hasOwn, isFunction, noop, isObject, isArray, getByPath, collectDataset, hump2dash, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
7
7
  import MpxProxy from '../../../core/proxy'
8
8
  import { BEFOREUPDATE, ONLOAD, UPDATED, ONSHOW, ONHIDE, ONRESIZE, REACTHOOKSEXEC } from '../../../core/innerLifecycle'
9
9
  import mergeOptions from '../../../core/mergeOptions'
10
10
  import { queueJob } from '../../../observer/scheduler'
11
11
  import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
12
- import { IntersectionObserverContext } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
12
+ import { IntersectionObserverContext, RouteContext } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
13
13
 
14
14
  function getSystemInfo () {
15
15
  const window = ReactNative.Dimensions.get('window')
@@ -105,26 +105,33 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
105
105
  this.__refs = {}
106
106
  this.__dispatchedSlotSet = new WeakSet()
107
107
  },
108
- __getSlot (name) {
108
+ __getSlot (name, slot) {
109
109
  const { children } = propsRef.current
110
110
  if (children) {
111
- const result = []
112
- if (Array.isArray(children)) {
111
+ let result = []
112
+ if (isArray(children) && !hasOwn(children, '__slot')) {
113
113
  children.forEach(child => {
114
- if (child?.props?.slot === name) {
114
+ if (isObject(child) && hasOwn(child, '__slot')) {
115
+ if (child.__slot === name) result.push(...child)
116
+ } else if (child?.props?.slot === name) {
115
117
  result.push(child)
116
118
  }
117
119
  })
118
120
  } else {
119
- if (children?.props?.slot === name) {
121
+ if (isObject(children) && hasOwn(children, '__slot')) {
122
+ if (children.__slot === name) result.push(...children)
123
+ } else if (children?.props?.slot === name) {
120
124
  result.push(children)
121
125
  }
122
126
  }
123
- return result.filter(item => {
127
+ result = result.filter(item => {
124
128
  if (!isObject(item) || this.__dispatchedSlotSet.has(item)) return false
125
129
  this.__dispatchedSlotSet.add(item)
126
130
  return true
127
131
  })
132
+ if (!result.length) return null
133
+ result.__slot = slot
134
+ return result
128
135
  }
129
136
  return null
130
137
  },
@@ -134,7 +141,7 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
134
141
  _i (val, fn) {
135
142
  let i, l, keys, key
136
143
  const result = []
137
- if (Array.isArray(val) || typeof val === 'string') {
144
+ if (isArray(val) || typeof val === 'string') {
138
145
  for (i = 0, l = val.length; i < l; i++) {
139
146
  result.push(fn.call(this, val[i], i))
140
147
  }
@@ -266,8 +273,6 @@ function hasPageHook (mpxProxy, hookNames) {
266
273
  })
267
274
  }
268
275
 
269
- const RouteContext = createContext(null)
270
-
271
276
  const triggerPageStatusHook = (mpxProxy, event) => {
272
277
  mpxProxy.callHook(event === 'show' ? ONSHOW : ONHIDE)
273
278
  const pageLifetimes = mpxProxy.options.pageLifetimes
@@ -447,24 +452,20 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
447
452
 
448
453
  useLayoutEffect(() => {
449
454
  const isCustom = pageConfig.navigationStyle === 'custom'
450
- const opt = {}
451
- if (__mpx_mode__ === 'android') {
452
- // opt = {
453
- // statusBarTranslucent: isCustom,
454
- // statusBarStyle: pageConfig.statusBarStyle, // 枚举值 'auto' | 'dark' | 'light' 控制statusbar字体颜色
455
- // statusBarColor: isCustom ? 'transparent' : pageConfig.statusBarColor // 控制statusbar背景颜色
456
- // }
457
- }
458
455
  navigation.setOptions({
459
456
  headerShown: !isCustom,
460
457
  title: pageConfig.navigationBarTitleText || '',
461
458
  headerStyle: {
462
459
  backgroundColor: pageConfig.navigationBarBackgroundColor || '#000000'
463
460
  },
464
- // headerTitleAlign: 'center',
465
- headerTintColor: pageConfig.navigationBarTextStyle || 'white',
466
- ...opt
461
+ headerTintColor: pageConfig.navigationBarTextStyle || 'white'
467
462
  })
463
+ if (__mpx_mode__ === 'android') {
464
+ ReactNative.StatusBar.setBarStyle(pageConfig.barStyle || 'dark-content')
465
+ ReactNative.StatusBar.setTranslucent(isCustom) // 控制statusbar是否占位
466
+ const color = isCustom ? 'transparent' : pageConfig.statusBarColor
467
+ color && ReactNative.StatusBar.setBackgroundColor(color)
468
+ }
468
469
  }, [])
469
470
 
470
471
  const rootRef = useRef(null)