@mpxjs/webpack-plugin 2.9.65 → 2.9.67

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 (80) hide show
  1. package/lib/dependencies/RecordGlobalComponentsDependency.js +11 -12
  2. package/lib/dependencies/RecordRuntimeInfoDependency.js +1 -1
  3. package/lib/index.js +28 -8
  4. package/lib/json-compiler/index.js +2 -11
  5. package/lib/loader.js +24 -45
  6. package/lib/native-loader.js +49 -64
  7. package/lib/platform/json/wx/index.js +3 -10
  8. package/lib/platform/style/wx/index.js +32 -56
  9. package/lib/react/index.js +4 -3
  10. package/lib/react/processJSON.js +5 -13
  11. package/lib/react/processMainScript.js +7 -3
  12. package/lib/react/processScript.js +3 -4
  13. package/lib/react/processTemplate.js +6 -4
  14. package/lib/resolver/AddModePlugin.js +17 -4
  15. package/lib/runtime/components/react/context.ts +8 -0
  16. package/lib/runtime/components/react/dist/context.js +1 -0
  17. package/lib/runtime/components/react/dist/mpx-button.jsx +1 -1
  18. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +30 -17
  19. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +1 -1
  20. package/lib/runtime/components/react/dist/mpx-form.jsx +33 -24
  21. package/lib/runtime/components/react/dist/mpx-icon.jsx +1 -1
  22. package/lib/runtime/components/react/dist/mpx-image/index.jsx +1 -1
  23. package/lib/runtime/components/react/dist/mpx-input.jsx +44 -38
  24. package/lib/runtime/components/react/dist/mpx-label.jsx +10 -7
  25. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +10 -17
  26. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +378 -294
  27. package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
  28. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +30 -17
  29. package/lib/runtime/components/react/dist/mpx-radio.jsx +1 -1
  30. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
  31. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +58 -30
  32. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +77 -77
  33. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +1 -1
  34. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +1 -1
  35. package/lib/runtime/components/react/dist/mpx-switch.jsx +8 -1
  36. package/lib/runtime/components/react/dist/mpx-text.jsx +1 -1
  37. package/lib/runtime/components/react/dist/mpx-textarea.jsx +1 -1
  38. package/lib/runtime/components/react/dist/mpx-view.jsx +31 -12
  39. package/lib/runtime/components/react/dist/mpx-web-view.jsx +2 -2
  40. package/lib/runtime/components/react/dist/useAnimationHooks.js +303 -0
  41. package/lib/runtime/components/react/dist/utils.jsx +13 -3
  42. package/lib/runtime/components/react/getInnerListeners.ts +1 -0
  43. package/lib/runtime/components/react/mpx-button.tsx +1 -1
  44. package/lib/runtime/components/react/mpx-checkbox-group.tsx +52 -29
  45. package/lib/runtime/components/react/mpx-checkbox.tsx +1 -1
  46. package/lib/runtime/components/react/mpx-form.tsx +42 -34
  47. package/lib/runtime/components/react/mpx-icon.tsx +1 -1
  48. package/lib/runtime/components/react/mpx-image/index.tsx +2 -3
  49. package/lib/runtime/components/react/mpx-input.tsx +68 -66
  50. package/lib/runtime/components/react/mpx-label.tsx +11 -8
  51. package/lib/runtime/components/react/mpx-movable-area.tsx +11 -19
  52. package/lib/runtime/components/react/mpx-movable-view.tsx +456 -334
  53. package/lib/runtime/components/react/mpx-navigator.tsx +1 -1
  54. package/lib/runtime/components/react/mpx-radio-group.tsx +55 -29
  55. package/lib/runtime/components/react/mpx-radio.tsx +1 -1
  56. package/lib/runtime/components/react/mpx-root-portal.tsx +1 -1
  57. package/lib/runtime/components/react/mpx-scroll-view.tsx +92 -37
  58. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +77 -76
  59. package/lib/runtime/components/react/mpx-swiper/index.tsx +2 -1
  60. package/lib/runtime/components/react/mpx-swiper-item.tsx +1 -1
  61. package/lib/runtime/components/react/mpx-switch.tsx +10 -2
  62. package/lib/runtime/components/react/mpx-text.tsx +1 -1
  63. package/lib/runtime/components/react/mpx-textarea.tsx +1 -1
  64. package/lib/runtime/components/react/mpx-view.tsx +40 -20
  65. package/lib/runtime/components/react/mpx-web-view.tsx +2 -2
  66. package/lib/runtime/components/react/types/common.ts +8 -2
  67. package/lib/runtime/components/react/useAnimationHooks.ts +332 -0
  68. package/lib/runtime/components/react/useNodesRef.ts +1 -0
  69. package/lib/runtime/components/react/utils.tsx +23 -6
  70. package/lib/runtime/optionProcessorReact.js +0 -15
  71. package/lib/runtime/swanHelper.wxs +1 -1
  72. package/lib/style-compiler/index.js +1 -1
  73. package/lib/style-compiler/plugins/scope-id.js +1 -0
  74. package/lib/template-compiler/compiler.js +68 -33
  75. package/lib/template-compiler/index.js +4 -4
  76. package/lib/utils/pre-process-json.js +113 -0
  77. package/lib/web/index.js +5 -4
  78. package/lib/web/processJSON.js +5 -13
  79. package/lib/web/processTemplate.js +2 -2
  80. package/package.json +5 -4
@@ -190,13 +190,22 @@ module.exports = function getSpec ({ warn, error }) {
190
190
  flex: ['flexGrow', 'flexShrink', 'flexBasis'],
191
191
  // flex-flow: <'flex-direction'> or flex-flow: <'flex-direction'> and <'flex-wrap'>
192
192
  'flex-flow': ['flexDirection', 'flexWrap'],
193
- 'border-radius': ['borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius']
193
+ 'border-radius': ['borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius'],
194
+ 'border-width': ['borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth'],
195
+ 'border-color': ['borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor'],
196
+ margin: ['marginTop', 'marginRight', 'marginBottom', 'marginLeft'],
197
+ padding: ['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft']
194
198
  }
195
199
  const formatAbbreviation = ({ prop, value, selector }, { mode }) => {
196
200
  const original = `${prop}:${value}`
197
201
  const props = AbbreviationMap[prop]
198
- const values = parseValues(value)
202
+ const values = Array.isArray(value) ? value : parseValues(value)
199
203
  const cssMap = []
204
+ // 复合属性不支持单个css var(css var可以接收单个值可以是复合值,复合值运行时不处理,这里前置提示一下)
205
+ if (values.length === 1 && cssVariableExp.test(value)) {
206
+ error(`Property ${prop} in ${selector} is abbreviated property and does not support a single CSS var`)
207
+ return cssMap
208
+ }
200
209
  let idx = 0
201
210
  let propsIdx = 0
202
211
  const diff = values.length - props.length
@@ -255,32 +264,20 @@ module.exports = function getSpec ({ warn, error }) {
255
264
  return cssMap
256
265
  }
257
266
 
258
- // margin padding
259
- const formatMargins = ({ prop, value, selector }) => {
260
- const values = parseValues(value)
261
- // format
262
- let suffix = []
267
+ const formatCompositeVal = ({ prop, value, selector }, { mode }) => {
268
+ const values = parseValues(value).splice(0, 4)
263
269
  switch (values.length) {
264
- // case 1:
270
+ case 1:
271
+ verifyValues({ prop, value, selector }, false)
272
+ return { prop, value }
265
273
  case 2:
266
- suffix = ['Vertical', 'Horizontal']
274
+ values.push(...values)
267
275
  break
268
276
  case 3:
269
- suffix = ['Top', 'Horizontal', 'Bottom']
270
- break
271
- case 4:
272
- suffix = ['Top', 'Right', 'Bottom', 'Left']
277
+ values.push(values[1])
273
278
  break
274
279
  }
275
- return values.map((value, index) => {
276
- const newProp = `${prop}${suffix[index] || ''}`
277
- // validate
278
- verifyValues({ prop: hump2dash(newProp), value, selector }, false)
279
- return {
280
- prop: newProp,
281
- value: value
282
- }
283
- })
280
+ return formatAbbreviation({ prop, value: values, selector }, { mode })
284
281
  }
285
282
 
286
283
  // line-height
@@ -304,16 +301,12 @@ module.exports = function getSpec ({ warn, error }) {
304
301
  all: 'background'
305
302
  }
306
303
  const urlExp = /url\(["']?(.*?)["']?\)/
307
- const linerExp = /linear-gradient\(.*\)\s*$/
304
+ const linearExp = /linear-gradient\(.*\)/
308
305
  switch (prop) {
309
306
  case bgPropMap.image: {
310
- // background-image 仅支持背景图
311
- const imgUrl = value.match(urlExp)?.[0]
312
- const linerVal = value.match(linerExp)?.[0]
313
- if (imgUrl) {
314
- return { prop, value: imgUrl }
315
- } else if (linerVal) {
316
- return { prop, value: linerVal }
307
+ // background-image 支持背景图/渐变/css var
308
+ if (cssVariableExp.test(value) || urlExp.test(value) || linearExp.test(value)) {
309
+ return { prop, value }
317
310
  } else {
318
311
  error(`Value of ${prop} in ${selector} selector only support value <url()> or <linear-gradient()>, received ${value}, please check again!`)
319
312
  return false
@@ -352,11 +345,15 @@ module.exports = function getSpec ({ warn, error }) {
352
345
  }
353
346
  case bgPropMap.all: {
354
347
  // background: 仅支持 background-image & background-color & background-repeat
348
+ if (cssVariableExp.test(value)) {
349
+ error(`Property [${bgPropMap.all}] in ${selector} is abbreviated property and does not support CSS var`)
350
+ return false
351
+ }
355
352
  const bgMap = []
356
353
  const values = parseValues(value)
357
354
  values.forEach(item => {
358
355
  const url = item.match(urlExp)?.[0]
359
- const linerVal = item.match(linerExp)?.[0]
356
+ const linerVal = item.match(linearExp)?.[0]
360
357
  if (url) {
361
358
  bgMap.push({ prop: bgPropMap.image, value: url })
362
359
  } else if (linerVal) {
@@ -374,22 +371,6 @@ module.exports = function getSpec ({ warn, error }) {
374
371
  return false
375
372
  }
376
373
 
377
- // border-radius 缩写转换
378
- const getBorderRadius = ({ prop, value, selector }, { mode }) => {
379
- const values = parseValues(value)
380
- if (values.length === 1) {
381
- verifyValues({ prop, value, selector }, false)
382
- return { prop, value }
383
- } else {
384
- if (values.length === 2) {
385
- values.push(...values)
386
- } else if (values.length === 3) {
387
- values.push(values[1])
388
- }
389
- return formatAbbreviation({ prop, value: values.join(' ') }, { mode })
390
- }
391
- }
392
-
393
374
  // transform 转换
394
375
  const formatTransform = ({ prop, value, selector }, { mode }) => {
395
376
  if (Array.isArray(value)) return { prop, value }
@@ -428,7 +409,7 @@ module.exports = function getSpec ({ warn, error }) {
428
409
  {
429
410
  // 2 个以上的值处理
430
411
  key = key.replace('3d', '')
431
- const vals = val.split(',').splice(0, key === 'rotate' ? 4 : 3)
412
+ const vals = val.split(',', key === 'rotate' ? 4 : 3)
432
413
  // scale(.5) === scaleX(.5) scaleY(.5)
433
414
  if (vals.length === 1 && key === 'scale') {
434
415
  vals.push(vals[0])
@@ -566,15 +547,10 @@ module.exports = function getSpec ({ warn, error }) {
566
547
  ios: checkBackgroundImage,
567
548
  android: checkBackgroundImage
568
549
  },
569
- {
570
- test: 'border-radius',
571
- ios: getBorderRadius,
572
- android: getBorderRadius
573
- },
574
550
  { // margin padding 内外边距的处理
575
- test: /^(margin|padding)$/,
576
- ios: formatMargins,
577
- android: formatMargins
551
+ test: /^(margin|padding|border-radius|border-width|border-color)$/,
552
+ ios: formatCompositeVal,
553
+ android: formatCompositeVal
578
554
  },
579
555
  { // line-height 换算
580
556
  test: 'line-height',
@@ -8,6 +8,7 @@ const RecordLoaderContentDependency = require('../dependencies/RecordLoaderConte
8
8
 
9
9
  module.exports = function ({
10
10
  parts,
11
+ jsonContent,
11
12
  loaderContext,
12
13
  pagesMap,
13
14
  componentsMap,
@@ -19,7 +20,7 @@ module.exports = function ({
19
20
  hasScoped,
20
21
  hasComment,
21
22
  isNative,
22
- usingComponents,
23
+ usingComponentsInfo,
23
24
  componentGenerics,
24
25
  autoScope,
25
26
  callback
@@ -50,7 +51,7 @@ module.exports = function ({
50
51
  srcMode,
51
52
  moduleId,
52
53
  ctorType,
53
- usingComponents,
54
+ usingComponentsInfo,
54
55
  componentGenerics
55
56
  }, callback)
56
57
  },
@@ -63,7 +64,7 @@ module.exports = function ({
63
64
  }, callback)
64
65
  },
65
66
  (callback) => {
66
- processJSON(parts.json, {
67
+ processJSON(jsonContent, {
67
68
  loaderContext,
68
69
  ctorType,
69
70
  pagesMap,
@@ -12,9 +12,8 @@ const createJSONHelper = require('../json-compiler/helper')
12
12
  const getRulesRunner = require('../platform/index')
13
13
  const { RESOLVE_IGNORED_ERR } = require('../utils/const')
14
14
  const RecordResourceMapDependency = require('../dependencies/RecordResourceMapDependency')
15
- const RecordGlobalComponentsDependency = require('../dependencies/RecordGlobalComponentsDependency')
16
15
 
17
- module.exports = function (json, {
16
+ module.exports = function (jsonContent, {
18
17
  loaderContext,
19
18
  ctorType,
20
19
  pagesMap,
@@ -81,12 +80,11 @@ module.exports = function (json, {
81
80
  }
82
81
 
83
82
  const isApp = ctorType === 'app'
84
- if (!json) {
83
+ if (!jsonContent) {
85
84
  return callback()
86
85
  }
87
- // 由于json需要提前读取在template处理中使用,src的场景已经在loader中处理了,此处无需考虑json.src的场景
88
86
  try {
89
- jsonObj = JSON5.parse(json.content)
87
+ jsonObj = JSON5.parse(jsonContent)
90
88
  // 处理runner
91
89
  const rulesRunnerOptions = {
92
90
  mode,
@@ -96,8 +94,8 @@ module.exports = function (json, {
96
94
  warn: emitWarning,
97
95
  error: emitError,
98
96
  data: {
99
- // polyfill global usingComponents & record globalComponents
100
- globalComponents: mpx.usingComponents
97
+ // polyfill global usingComponents
98
+ globalComponents: mpx.globalComponents
101
99
  }
102
100
  }
103
101
 
@@ -110,12 +108,6 @@ module.exports = function (json, {
110
108
  if (rulesRunner) {
111
109
  rulesRunner(jsonObj)
112
110
  }
113
- if (isApp) {
114
- // 收集全局组件
115
- Object.assign(mpx.usingComponents, jsonObj.usingComponents)
116
- // 在 rulesRunner 运行后保存全局注册组件
117
- loaderContext._module.addPresentationalDependency(new RecordGlobalComponentsDependency(mpx.usingComponents, loaderContext.context))
118
- }
119
111
  } catch (e) {
120
112
  return callback(e)
121
113
  }
@@ -8,7 +8,7 @@ const {
8
8
  module.exports = function ({
9
9
  loaderContext
10
10
  }, callback) {
11
- const { i18n, projectName } = loaderContext.getMpx()
11
+ const { i18n, rnConfig } = loaderContext.getMpx()
12
12
 
13
13
  let output = 'import { AppRegistry } from \'react-native\'\n'
14
14
 
@@ -16,8 +16,12 @@ module.exports = function ({
16
16
  output += buildI18n({ loaderContext })
17
17
  }
18
18
  // 此处可添加前置于App执行的语句
19
- output += `var App = require(${stringifyRequest(loaderContext, addQuery(loaderContext.resource, { isApp: true }))}).default\n`
20
- output += `AppRegistry.registerComponent(${JSON.stringify(projectName)}, () => App)\n`
19
+ output += `var app = require(${stringifyRequest(loaderContext, addQuery(loaderContext.resource, { isApp: true }))}).default\n`
20
+ if (rnConfig.projectName) {
21
+ output += `AppRegistry.registerComponent(${JSON.stringify(rnConfig.projectName)}, () => app)\n`
22
+ } else {
23
+ output += 'export default app\n'
24
+ }
21
25
 
22
26
  callback(null, {
23
27
  output
@@ -24,16 +24,15 @@ module.exports = function (script, {
24
24
  if (ctorType === 'app') {
25
25
  output += `
26
26
  import { getComponent } from ${stringifyRequest(loaderContext, optionProcessorPath)}
27
- import { NavigationContainer, createNavigationContainerRef, StackActions } from '@react-navigation/native'
28
- import { createNativeStackNavigator } from '@react-navigation/native-stack'
27
+ import { NavigationContainer, StackActions } from '@react-navigation/native'
28
+ import { createStackNavigator } from '@react-navigation/stack'
29
29
  import { Provider } from '@ant-design/react-native'
30
30
  import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'
31
31
  import { GestureHandlerRootView } from 'react-native-gesture-handler'
32
32
 
33
33
  global.__navigationHelper = {
34
34
  NavigationContainer: NavigationContainer,
35
- createNavigationContainerRef: createNavigationContainerRef,
36
- createNativeStackNavigator: createNativeStackNavigator,
35
+ createStackNavigator: createStackNavigator,
37
36
  StackActions: StackActions,
38
37
  GestureHandlerRootView: GestureHandlerRootView,
39
38
  Provider: Provider,
@@ -14,7 +14,7 @@ module.exports = function (template, {
14
14
  srcMode,
15
15
  moduleId,
16
16
  ctorType,
17
- usingComponents,
17
+ usingComponentsInfo,
18
18
  componentGenerics
19
19
  }, callback) {
20
20
  const mpx = loaderContext.getMpx()
@@ -27,7 +27,8 @@ module.exports = function (template, {
27
27
  decodeHTMLText,
28
28
  externalClasses,
29
29
  checkUsingComponents,
30
- autoVirtualHostRules
30
+ autoVirtualHostRules,
31
+ customTextRules
31
32
  } = mpx
32
33
  const { resourcePath } = parseRequest(loaderContext.resource)
33
34
  const builtInComponentsMap = {}
@@ -63,7 +64,7 @@ module.exports = function (template, {
63
64
  const { root, meta } = templateCompiler.parse(template.content, {
64
65
  warn,
65
66
  error,
66
- usingComponents,
67
+ usingComponentsInfo, // processTemplate中无其他地方使用,直接透传 string 类型
67
68
  hasComment,
68
69
  isNative,
69
70
  ctorType,
@@ -84,7 +85,8 @@ module.exports = function (template, {
84
85
  globalComponents: [],
85
86
  // web模式下实现抽象组件
86
87
  componentGenerics,
87
- hasVirtualHost: matchCondition(resourcePath, autoVirtualHostRules)
88
+ hasVirtualHost: matchCondition(resourcePath, autoVirtualHostRules),
89
+ isCustomText: matchCondition(resourcePath, customTextRules)
88
90
  })
89
91
 
90
92
  if (meta.wxsContentMap) {
@@ -6,16 +6,17 @@ const addInfix = require('../utils/add-infix')
6
6
  const { JSON_JS_EXT } = require('../utils/const')
7
7
 
8
8
  module.exports = class AddModePlugin {
9
- constructor (source, mode, fileConditionRules, target) {
9
+ constructor (source, mode, fileConditionRules, target, defaultMode) {
10
10
  this.source = source
11
11
  this.target = target
12
12
  this.mode = mode
13
13
  this.fileConditionRules = fileConditionRules
14
+ this.defaultMode = defaultMode
14
15
  }
15
16
 
16
17
  apply (resolver) {
17
18
  const target = resolver.ensureHook(this.target)
18
- const mode = this.mode
19
+ const { defaultMode, mode } = this
19
20
  resolver.getHook(this.source).tapAsync('AddModePlugin', (request, resolveContext, callback) => {
20
21
  if (request.mode || request.env) {
21
22
  return callback()
@@ -33,12 +34,24 @@ module.exports = class AddModePlugin {
33
34
  // 当前资源没有后缀名或者路径不符合fileConditionRules规则时,直接返回
34
35
  if (!extname || !matchCondition(resourcePath, this.fileConditionRules)) return callback()
35
36
  const queryObj = parseQuery(request.query || '?')
37
+ const queryInfix = queryObj.infix
36
38
  queryObj.mode = mode
37
- queryObj.infix = `${queryObj.infix || ''}.${mode}`
39
+ queryObj.infix = `${queryInfix || ''}.${mode}`
38
40
  obj.query = stringifyQuery(queryObj)
39
41
  obj.path = addInfix(resourcePath, mode, extname)
40
42
  obj.relativePath = request.relativePath && addInfix(request.relativePath, mode, extname)
41
- resolver.doResolve(target, Object.assign({}, request, obj), 'add mode: ' + mode, resolveContext, callback)
43
+ resolver.doResolve(target, Object.assign({}, request, obj), 'add mode: ' + mode, resolveContext, (err, result) => {
44
+ if (this.defaultMode && !result) {
45
+ queryObj.infix = `${queryInfix || ''}.${defaultMode}`
46
+ obj.query = stringifyQuery(queryObj)
47
+ obj.path = addInfix(resourcePath, defaultMode, extname)
48
+ resolver.doResolve(target, Object.assign({}, request, obj), 'add mode: ' + this.defaultMode, resolveContext, (err, result) => {
49
+ callback(err, result)
50
+ })
51
+ return
52
+ }
53
+ callback(err, result)
54
+ })
42
55
  })
43
56
  }
44
57
  }
@@ -25,6 +25,12 @@ export interface FormContextValue {
25
25
  reset: () => void
26
26
  }
27
27
 
28
+ export interface IntersectionObserver {
29
+ [key: number]: {
30
+ throttleMeasure: () => void
31
+ }
32
+ }
33
+
28
34
  export const MovableAreaContext = createContext({ width: 0, height: 0 })
29
35
 
30
36
  export const FormContext = createContext<FormContextValue | null>(null)
@@ -38,3 +44,5 @@ export const LabelContext = createContext<LabelContextValue | null>(null)
38
44
  export const PickerContext = createContext(null)
39
45
 
40
46
  export const VarContext = createContext({})
47
+
48
+ export const IntersectionObserverContext = createContext<IntersectionObserver | null>(null)
@@ -6,3 +6,4 @@ export const RadioGroupContext = createContext(null);
6
6
  export const LabelContext = createContext(null);
7
7
  export const PickerContext = createContext(null);
8
8
  export const VarContext = createContext({});
9
+ export const IntersectionObserverContext = createContext(null);
@@ -267,5 +267,5 @@ const Button = forwardRef((buttonProps, ref) => {
267
267
  })}
268
268
  </View>);
269
269
  });
270
- Button.displayName = 'mpx-button';
270
+ Button.displayName = 'MpxButton';
271
271
  export default Button;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * ✔ bindchange
3
3
  */
4
- import { useRef, forwardRef, useContext } from 'react';
4
+ import { useRef, forwardRef, useContext, useMemo, useEffect } from 'react';
5
5
  import { View } from 'react-native';
6
6
  import { warn } from '@mpxjs/utils';
7
7
  import { FormContext, CheckboxGroupContext } from './context';
@@ -9,7 +9,9 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners';
9
9
  import useNodesRef from './useNodesRef';
10
10
  import { useLayout, useTransformStyle, wrapChildren } from './utils';
11
11
  const CheckboxGroup = forwardRef((props, ref) => {
12
- const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, bindchange } = props;
12
+ const propsRef = useRef({});
13
+ propsRef.current = props;
14
+ const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
13
15
  const formContext = useContext(FormContext);
14
16
  let formValuesMap;
15
17
  if (formContext) {
@@ -28,7 +30,7 @@ const CheckboxGroup = forwardRef((props, ref) => {
28
30
  const nodeRef = useRef(null);
29
31
  useNodesRef(props, ref, nodeRef, { defaultStyle });
30
32
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
31
- const getSelectionValue = () => {
33
+ const getValue = () => {
32
34
  const arr = [];
33
35
  for (const key in groupValue) {
34
36
  if (groupValue[key].checked) {
@@ -37,9 +39,6 @@ const CheckboxGroup = forwardRef((props, ref) => {
37
39
  }
38
40
  return arr;
39
41
  };
40
- const getValue = () => {
41
- return getSelectionValue();
42
- };
43
42
  const resetValue = () => {
44
43
  Object.keys(groupValue).forEach((key) => {
45
44
  groupValue[key].checked = false;
@@ -54,15 +53,13 @@ const CheckboxGroup = forwardRef((props, ref) => {
54
53
  formValuesMap.set(props.name, { getValue, resetValue });
55
54
  }
56
55
  }
57
- const notifyChange = (evt) => {
58
- bindchange &&
59
- bindchange(getCustomEvent('tap', evt, {
60
- layoutRef,
61
- detail: {
62
- value: getSelectionValue()
63
- }
64
- }, props));
65
- };
56
+ useEffect(() => {
57
+ return () => {
58
+ if (formValuesMap && props.name) {
59
+ formValuesMap.delete(props.name);
60
+ }
61
+ };
62
+ }, []);
66
63
  const innerProps = useInnerProps(props, {
67
64
  ref: nodeRef,
68
65
  style: { ...normalStyle, ...layoutStyle },
@@ -70,8 +67,24 @@ const CheckboxGroup = forwardRef((props, ref) => {
70
67
  }, [], {
71
68
  layoutRef
72
69
  });
70
+ const contextValue = useMemo(() => {
71
+ const notifyChange = (evt) => {
72
+ const { bindchange } = propsRef.current;
73
+ bindchange &&
74
+ bindchange(getCustomEvent('tap', evt, {
75
+ layoutRef,
76
+ detail: {
77
+ value: getValue()
78
+ }
79
+ }, propsRef.current));
80
+ };
81
+ return {
82
+ groupValue,
83
+ notifyChange
84
+ };
85
+ }, []);
73
86
  return (<View {...innerProps}>
74
- <CheckboxGroupContext.Provider value={{ groupValue, notifyChange }}>
87
+ <CheckboxGroupContext.Provider value={contextValue}>
75
88
  {wrapChildren(props, {
76
89
  hasVarDec,
77
90
  varContext: varContextRef.current
@@ -79,5 +92,5 @@ const CheckboxGroup = forwardRef((props, ref) => {
79
92
  </CheckboxGroupContext.Provider>
80
93
  </View>);
81
94
  });
82
- CheckboxGroup.displayName = 'mpx-checkbox-group';
95
+ CheckboxGroup.displayName = 'MpxCheckboxGroup';
83
96
  export default CheckboxGroup;
@@ -136,5 +136,5 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
136
136
  })}
137
137
  </View>);
138
138
  });
139
- Checkbox.displayName = 'mpx-checkbox';
139
+ Checkbox.displayName = 'MpxCheckbox';
140
140
  export default Checkbox;
@@ -5,40 +5,21 @@
5
5
  * ✔ bindreset
6
6
  */
7
7
  import { View } from 'react-native';
8
- import { useRef, forwardRef } from 'react';
8
+ import { useRef, forwardRef, useMemo } from 'react';
9
9
  import useNodesRef from './useNodesRef';
10
10
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
11
11
  import { FormContext } from './context';
12
12
  import { useTransformStyle, splitProps, splitStyle, useLayout, wrapChildren } from './utils';
13
13
  const _Form = forwardRef((fromProps, ref) => {
14
14
  const { textProps, innerProps: props = {} } = splitProps(fromProps);
15
- const formValuesMap = useRef(new Map()).current;
16
15
  const { style, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
17
16
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
18
17
  const { textStyle, innerStyle } = splitStyle(normalStyle);
19
18
  const formRef = useRef(null);
20
19
  useNodesRef(props, ref, formRef);
20
+ const propsRef = useRef({});
21
+ propsRef.current = props;
21
22
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: formRef });
22
- const submit = () => {
23
- const { bindsubmit } = props;
24
- const formValue = {};
25
- for (const name of formValuesMap.keys()) {
26
- if (formValuesMap.get(name).getValue) {
27
- formValue[name] = formValuesMap.get(name).getValue();
28
- }
29
- }
30
- bindsubmit && bindsubmit(getCustomEvent('submit', {}, {
31
- detail: {
32
- value: formValue
33
- },
34
- layoutRef
35
- }, props));
36
- };
37
- const reset = () => {
38
- const { bindreset } = props;
39
- bindreset && bindreset();
40
- formValuesMap.forEach(item => item.resetValue());
41
- };
42
23
  const innerProps = useInnerProps(props, {
43
24
  style: { ...innerStyle, ...layoutStyle },
44
25
  ref: formRef,
@@ -47,8 +28,36 @@ const _Form = forwardRef((fromProps, ref) => {
47
28
  'bindsubmit',
48
29
  'bindreset'
49
30
  ], { layoutRef });
31
+ const contextValue = useMemo(() => {
32
+ const formValuesMap = new Map();
33
+ const submit = () => {
34
+ const { bindsubmit } = propsRef.current;
35
+ const formValue = {};
36
+ for (const name of formValuesMap.keys()) {
37
+ if (formValuesMap.get(name).getValue) {
38
+ formValue[name] = formValuesMap.get(name).getValue();
39
+ }
40
+ }
41
+ bindsubmit && bindsubmit(getCustomEvent('submit', {}, {
42
+ detail: {
43
+ value: formValue
44
+ },
45
+ layoutRef
46
+ }, propsRef.current));
47
+ };
48
+ const reset = () => {
49
+ const { bindreset } = propsRef.current;
50
+ bindreset && bindreset();
51
+ formValuesMap.forEach(item => item.resetValue());
52
+ };
53
+ return {
54
+ formValuesMap,
55
+ submit,
56
+ reset
57
+ };
58
+ }, []);
50
59
  return (<View {...innerProps}>
51
- <FormContext.Provider value={{ formValuesMap, submit, reset }}>
60
+ <FormContext.Provider value={contextValue}>
52
61
  {wrapChildren(props, {
53
62
  hasVarDec,
54
63
  varContext: varContextRef.current,
@@ -58,5 +67,5 @@ const _Form = forwardRef((fromProps, ref) => {
58
67
  </FormContext.Provider>
59
68
  </View>);
60
69
  });
61
- _Form.displayName = 'mpx-form';
70
+ _Form.displayName = 'MpxForm';
62
71
  export default _Form;
@@ -45,5 +45,5 @@ const Icon = forwardRef((props, ref) => {
45
45
  });
46
46
  return <Image {...innerProps}/>;
47
47
  });
48
- Icon.displayName = 'mpx-icon';
48
+ Icon.displayName = 'MpxIcon';
49
49
  export default Icon;
@@ -222,5 +222,5 @@ const Image = forwardRef((props, ref) => {
222
222
  }}/>}
223
223
  </View>);
224
224
  });
225
- Image.displayName = 'mpx-image';
225
+ Image.displayName = 'MpxImage';
226
226
  export default Image;