@mpxjs/webpack-plugin 2.10.24-test.1 → 2.11.0

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 (128) hide show
  1. package/LICENSE +433 -0
  2. package/lib/index.js +4 -1
  3. package/lib/platform/style/wx/index.js +44 -38
  4. package/lib/platform/template/wx/component-config/picker.js +0 -6
  5. package/lib/resolver/AddEnvPlugin.js +1 -1
  6. package/lib/resolver/AddModePlugin.js +1 -1
  7. package/lib/resolver/ExtendComponentsPlugin.js +68 -0
  8. package/lib/runtime/components/extends/section-list.mpx +14 -0
  9. package/lib/runtime/components/react/dist/mpx-button.d.ts +0 -1
  10. package/lib/runtime/components/react/dist/mpx-button.jsx +2 -2
  11. package/lib/runtime/components/react/dist/mpx-camera.d.ts +0 -1
  12. package/lib/runtime/components/react/dist/mpx-camera.jsx +36 -4
  13. package/lib/runtime/components/react/dist/mpx-canvas/index.d.ts +0 -1
  14. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +1 -2
  15. package/lib/runtime/components/react/dist/mpx-checkbox-group.d.ts +0 -1
  16. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -2
  17. package/lib/runtime/components/react/dist/mpx-checkbox.d.ts +0 -1
  18. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +2 -2
  19. package/lib/runtime/components/react/dist/mpx-form.d.ts +0 -1
  20. package/lib/runtime/components/react/dist/mpx-form.jsx +2 -2
  21. package/lib/runtime/components/react/dist/mpx-icon/index.d.ts +0 -1
  22. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +2 -2
  23. package/lib/runtime/components/react/dist/mpx-image.d.ts +0 -1
  24. package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
  25. package/lib/runtime/components/react/dist/mpx-inline-text.jsx +13 -4
  26. package/lib/runtime/components/react/dist/mpx-input.d.ts +0 -1
  27. package/lib/runtime/components/react/dist/mpx-input.jsx +16 -8
  28. package/lib/runtime/components/react/dist/mpx-label.d.ts +0 -1
  29. package/lib/runtime/components/react/dist/mpx-label.jsx +2 -2
  30. package/lib/runtime/components/react/dist/mpx-movable-area.d.ts +0 -1
  31. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +2 -2
  32. package/lib/runtime/components/react/dist/mpx-movable-view.d.ts +0 -1
  33. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +2 -2
  34. package/lib/runtime/components/react/dist/mpx-nav.jsx +1 -1
  35. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +72 -23
  36. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +2 -2
  37. package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +4 -0
  38. package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +6 -8
  39. package/lib/runtime/components/react/dist/mpx-picker-view/pickerVIewContext.d.ts +0 -2
  40. package/lib/runtime/components/react/dist/mpx-picker-view/pickerVIewContext.js +0 -5
  41. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.d.ts +1 -0
  42. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +34 -14
  43. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItem.d.ts +0 -2
  44. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItem.jsx +4 -5
  45. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItemLite.d.ts +0 -2
  46. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItemLite.jsx +3 -5
  47. package/lib/runtime/components/react/dist/mpx-popup/index.d.ts +5 -4
  48. package/lib/runtime/components/react/dist/mpx-popup/index.jsx +2 -2
  49. package/lib/runtime/components/react/dist/mpx-popup/popupBase.jsx +3 -2
  50. package/lib/runtime/components/react/dist/mpx-progress.d.ts +0 -1
  51. package/lib/runtime/components/react/dist/mpx-progress.jsx +1 -2
  52. package/lib/runtime/components/react/dist/mpx-radio-group.d.ts +0 -1
  53. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +2 -2
  54. package/lib/runtime/components/react/dist/mpx-radio.d.ts +0 -1
  55. package/lib/runtime/components/react/dist/mpx-radio.jsx +2 -2
  56. package/lib/runtime/components/react/dist/mpx-rich-text/index.d.ts +0 -1
  57. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +1 -2
  58. package/lib/runtime/components/react/dist/mpx-scroll-view.d.ts +0 -1
  59. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +2 -2
  60. package/lib/runtime/components/react/dist/mpx-section-list.d.ts +51 -0
  61. package/lib/runtime/components/react/dist/mpx-section-list.jsx +376 -0
  62. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +27 -14
  63. package/lib/runtime/components/react/dist/mpx-simple-view.d.ts +1 -0
  64. package/lib/runtime/components/react/dist/mpx-slider.d.ts +0 -1
  65. package/lib/runtime/components/react/dist/mpx-slider.jsx +1 -2
  66. package/lib/runtime/components/react/dist/mpx-sticky-header.d.ts +0 -1
  67. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +2 -2
  68. package/lib/runtime/components/react/dist/mpx-sticky-section.d.ts +0 -1
  69. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +2 -2
  70. package/lib/runtime/components/react/dist/mpx-swiper-item.d.ts +0 -1
  71. package/lib/runtime/components/react/dist/mpx-swiper.d.ts +0 -1
  72. package/lib/runtime/components/react/dist/mpx-swiper.jsx +1 -2
  73. package/lib/runtime/components/react/dist/mpx-switch.d.ts +0 -1
  74. package/lib/runtime/components/react/dist/mpx-switch.jsx +1 -2
  75. package/lib/runtime/components/react/dist/mpx-text.d.ts +0 -1
  76. package/lib/runtime/components/react/dist/mpx-text.jsx +22 -8
  77. package/lib/runtime/components/react/dist/mpx-video.d.ts +0 -1
  78. package/lib/runtime/components/react/dist/mpx-video.jsx +1 -2
  79. package/lib/runtime/components/react/dist/mpx-view.d.ts +0 -1
  80. package/lib/runtime/components/react/dist/mpx-view.jsx +1 -2
  81. package/lib/runtime/components/react/dist/mpx-web-view.d.ts +2 -1
  82. package/lib/runtime/components/react/dist/utils.d.ts +6 -9
  83. package/lib/runtime/components/react/dist/utils.jsx +70 -84
  84. package/lib/runtime/components/react/mpx-button.tsx +1 -3
  85. package/lib/runtime/components/react/mpx-camera.tsx +40 -5
  86. package/lib/runtime/components/react/mpx-canvas/index.tsx +5 -5
  87. package/lib/runtime/components/react/mpx-checkbox-group.tsx +1 -3
  88. package/lib/runtime/components/react/mpx-checkbox.tsx +1 -3
  89. package/lib/runtime/components/react/mpx-form.tsx +1 -3
  90. package/lib/runtime/components/react/mpx-icon/index.tsx +1 -3
  91. package/lib/runtime/components/react/mpx-image.tsx +2 -5
  92. package/lib/runtime/components/react/mpx-inline-text.tsx +13 -4
  93. package/lib/runtime/components/react/mpx-input.tsx +19 -10
  94. package/lib/runtime/components/react/mpx-label.tsx +1 -3
  95. package/lib/runtime/components/react/mpx-movable-area.tsx +2 -3
  96. package/lib/runtime/components/react/mpx-movable-view.tsx +1 -3
  97. package/lib/runtime/components/react/mpx-nav.tsx +1 -1
  98. package/lib/runtime/components/react/mpx-picker/index.tsx +100 -29
  99. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +3 -3
  100. package/lib/runtime/components/react/mpx-picker/selector.tsx +1 -1
  101. package/lib/runtime/components/react/mpx-picker/type.ts +4 -0
  102. package/lib/runtime/components/react/mpx-picker-view/index.tsx +12 -17
  103. package/lib/runtime/components/react/mpx-picker-view/pickerVIewContext.ts +0 -9
  104. package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +44 -21
  105. package/lib/runtime/components/react/mpx-picker-view-column/pickerViewColumnItem.tsx +1 -9
  106. package/lib/runtime/components/react/mpx-picker-view-column/pickerViewColumnItemLite.tsx +0 -9
  107. package/lib/runtime/components/react/mpx-popup/index.tsx +7 -3
  108. package/lib/runtime/components/react/mpx-popup/popupBase.tsx +3 -2
  109. package/lib/runtime/components/react/mpx-progress.tsx +0 -3
  110. package/lib/runtime/components/react/mpx-radio-group.tsx +1 -3
  111. package/lib/runtime/components/react/mpx-radio.tsx +1 -3
  112. package/lib/runtime/components/react/mpx-rich-text/index.tsx +0 -3
  113. package/lib/runtime/components/react/mpx-scroll-view.tsx +1 -3
  114. package/lib/runtime/components/react/mpx-section-list.tsx +557 -0
  115. package/lib/runtime/components/react/mpx-simple-text.tsx +26 -13
  116. package/lib/runtime/components/react/mpx-slider.tsx +0 -3
  117. package/lib/runtime/components/react/mpx-sticky-header.tsx +1 -3
  118. package/lib/runtime/components/react/mpx-sticky-section.tsx +1 -3
  119. package/lib/runtime/components/react/mpx-swiper-item.tsx +0 -1
  120. package/lib/runtime/components/react/mpx-swiper.tsx +0 -3
  121. package/lib/runtime/components/react/mpx-switch.tsx +0 -3
  122. package/lib/runtime/components/react/mpx-text.tsx +21 -9
  123. package/lib/runtime/components/react/mpx-video.tsx +0 -3
  124. package/lib/runtime/components/react/mpx-view.tsx +0 -3
  125. package/lib/runtime/components/react/mpx-web-view.tsx +4 -3
  126. package/lib/runtime/components/react/utils.tsx +82 -88
  127. package/lib/template-compiler/compiler.js +6 -0
  128. package/package.json +5 -5
@@ -29,6 +29,7 @@ const varUseRegExp = /var\(/;
29
29
  const unoVarDecRegExp = /^--un-/;
30
30
  const unoVarUseRegExp = /var\(--un-/;
31
31
  const lengthValueRegExp = /^(-?(?:\d+(?:\.\d+)?|\.\d+)(?:rpx|px|%|vw|vh)?|hairlineWidth)$/;
32
+ const DEFAULT_FONT_SIZE = 16;
32
33
  // transform: 'rotateX(45deg) ...' 单段拆出 fn 名与括号内值
33
34
  const transformFnRegExp = /([/\w]+)\((.+)\)/;
34
35
  // boxShadow 子值识别 rpx 单位(仅 rpx 需要换算为 px,其它单位保留原样)
@@ -88,7 +89,7 @@ const runtimeAbbreviationMap = {
88
89
  // 因此进入 runtimeForceExpandCompositeMap,避免「单值透传」捷径放过这类多值串残留。
89
90
  // 百分比(`gap: 50%` / `gap: 10px 50%`)由 transformShorthand 写回阶段就地 resolvePercent 落成 number
90
91
  gap: ['rowGap', 'columnGap'],
91
- // inset:4 槽位等价 margin 四值语法;RN inset 长属性非稳定,单值也必须展开到 top/right/bottom/left
92
+ // inset:4 槽位等价 margin 四值语法;RN 0.74+ 原生支持单值 DimensionValue,单值走 runtimeCompositeStyleMap 短路透传
92
93
  inset: ['top', 'right', 'bottom', 'left'],
93
94
  // outline: <outline-width> || <outline-style> || <outline-color>,顺序不敏感
94
95
  outline: ['outlineWidth', 'outlineStyle', 'outlineColor']
@@ -102,15 +103,6 @@ const runtimeCompositeStyleMap = {
102
103
  gap: true,
103
104
  inset: true
104
105
  };
105
- // 即使单值也必须展开(不走「单值透传」捷径):
106
- // - inset:RN inset 长属性不稳定,单值透传会留下不可靠的 inset key
107
- // - gap:RN gap / rowGap / columnGap 严格要求 number;单值串虽已在 __getStyle 阶段被 __formatValue 换算,
108
- // 但多值串(如 '10px 20px')会原样透传到这里,需展开后逐 token 再过 __formatValue 才能落成 number;
109
- // `%` 在写回阶段由 transformShorthand 调 resolvePercent 落成 number(rowGap 基 parentHeight、columnGap 基 parentWidth)
110
- const runtimeForceExpandCompositeMap = {
111
- inset: true,
112
- gap: true
113
- };
114
106
  const runtimeUnorderedAbbreviationMap = {
115
107
  border: true,
116
108
  borderTop: true,
@@ -123,13 +115,18 @@ const runtimeUnorderedAbbreviationMap = {
123
115
  // outline 与 border 简写共享同一套缺省值处理
124
116
  outline: true
125
117
  };
126
- const runtimeBorderLikeShorthandMap = {
118
+ // 单值简写在 __getStyle 阶段经 __formatValue 把带单位长度换算为 number 后,
119
+ // 需要在 transformShorthand 入口转回字符串 token 交给展开逻辑的 key 集合。
120
+ // margin / padding / borderRadius / borderWidth / borderColor / inset 不在此列:
121
+ // RN 原生支持这些 key 直接吃单值 number,无需展开。
122
+ const runtimeNumericExpandShorthandMap = {
127
123
  border: true,
128
124
  borderTop: true,
129
125
  borderRight: true,
130
126
  borderBottom: true,
131
127
  borderLeft: true,
132
- outline: true
128
+ outline: true,
129
+ gap: true
133
130
  };
134
131
  // CSS border-width: medium 的实测值(各主流浏览器一致取 3px)
135
132
  // 与编译期 wx/index.js 同名常量保持一致;调整需两侧一起改
@@ -332,7 +329,7 @@ export function transformBoxSizing(style = {}) {
332
329
  style.boxSizing = global.__mpx?.config?.rnConfig?.defaultBoxSizing ?? defaultBoxSizingStyle.boxSizing;
333
330
  }
334
331
  }
335
- export function splitStyle(styleObj, sideEffect) {
332
+ export function splitStyle(styleObj = {}, sideEffect) {
336
333
  const keys = Object.keys(styleObj);
337
334
  let textStyle;
338
335
  let backgroundStyle;
@@ -370,7 +367,7 @@ export function splitStyle(styleObj, sideEffect) {
370
367
  }
371
368
  return { textStyle, backgroundStyle, innerStyle };
372
369
  }
373
- export function splitProps(props) {
370
+ export function splitProps(props = {}) {
374
371
  const keys = Object.keys(props);
375
372
  let textProps;
376
373
  let innerProps;
@@ -474,8 +471,8 @@ function resolvePercent(value, key, percentConfig) {
474
471
  let base;
475
472
  let reason;
476
473
  if (key === 'fontSize') {
477
- base = percentConfig.parentFontSize;
478
- reason = 'parent-font-size';
474
+ base = DEFAULT_FONT_SIZE;
475
+ reason = 'default-font-size';
479
476
  }
480
477
  else if (key === 'lineHeight') {
481
478
  base = resolvePercent(percentConfig.fontSize, 'fontSize', percentConfig);
@@ -839,7 +836,7 @@ function expandFlex(value) {
839
836
  // RN 等效子集语法:font: [ <font-style> ] [ <font-variant-css2> ] [ <font-weight> ] <font-size> [ / <line-height> ] <font-family>
840
837
  // - 必填项:font-size 与 font-family;缺其一整条 font 声明丢弃(error)
841
838
  // - 非必填 token(font-stretch / 数字型 font-variant-numeric / system 关键字等):warn 提示并忽略,保留其余槽位
842
- function transformFont(styleObj, percentConfig) {
839
+ function transformFont(styleObj) {
843
840
  const value = styleObj.font;
844
841
  if (typeof value !== 'string')
845
842
  return;
@@ -850,7 +847,7 @@ function transformFont(styleObj, percentConfig) {
850
847
  // 1. 定位 font-size(第一个 length,可能带 /<line-height>)
851
848
  // 注意:unit-less 数字也命中 length 正则,需要先排除 font-weight 数字(100..900 / bold / normal),
852
849
  // 否则 `font: 500 16px Arial` 会把 500 误判为 fontSize。
853
- // fontSize 自身可能是 %(如 `font: 50% Arial`),就地用 resolvePercent 按 parentFontSize 解析;
850
+ // fontSize 自身可能是 %(如 `font: 50% Arial`),保留给文本透传阶段按继承 fontSize 解析;
854
851
  // fontSize % 校验通过的是 `isLengthValue`(length 正则含 %),主流程已用 length 分支接住,无需特判
855
852
  for (let i = 0; i < tokens.length; i++) {
856
853
  let t = tokens[i];
@@ -871,10 +868,7 @@ function transformFont(styleObj, percentConfig) {
871
868
  continue;
872
869
  if (isLengthValue(sizePart)) {
873
870
  sizeIdx = i;
874
- const sizeVal = percentRegExp.test(sizePart)
875
- ? resolvePercent(sizePart, 'fontSize', percentConfig)
876
- : global.__formatValue(sizePart);
877
- result.push(['fontSize', sizeVal]);
871
+ result.push(['fontSize', global.__formatValue(sizePart)]);
878
872
  if (lhPart)
879
873
  lineHeight = lhPart;
880
874
  break;
@@ -907,37 +901,18 @@ function transformFont(styleObj, percentConfig) {
907
901
  warn(`Token [${t}] in [font: ${value}] is not supported (only font-style / small-caps / font-weight are valid before <font-size>), dropped.`);
908
902
  }
909
903
  }
910
- // 3. line-height:RN lineHeight 不接受百分比字符串,必须当场数值化。
911
- // - unit-less 数字(1.5)→ '150%' 后走 resolvePercent
912
- // - 显式百分比(120%)→ 直接走 resolvePercent
913
- // - 带单位(40px / 40rpx)→ __formatValue
914
- // 基数 fontSize 取值(「长属性不覆盖简写」一致):
915
- // - user 已显式写 fontSize 长属性 → 优先(先经 __formatValue 归一 '24px' → 24)
916
- // - 否则用 font 简写解析出的 fontSize(result[0][1],已可能是 number / 解析后的 % 值)
904
+ // 3. line-height:文本透传阶段会基于当前 / 继承 fontSize 解析百分比。
905
+ // - unit-less 数字(1.5)→ '150%' 中间态,避免和已格式化 RN 绝对 number 混淆
906
+ // - 其它值(120% / 40px / 40rpx)→ __formatValue
917
907
  if (lineHeight !== undefined) {
918
- // percentConfig.fontSize 用于 resolvePercent 的 base:
919
- // - user 已显式写 fontSize 长属性 → 外层用 normalStyle.fontSize 初始化,已被前置 styleHelperMixin
920
- // 的 transformStyleObj 经 __formatValue 归一为 number,可直接用,不覆盖(「长属性优先」一致)
921
- // - 否则用 font 简写解析出的 fontSize(result[0][1],本身已 number 或解析后的 % 值)回填
922
- if (percentConfig.fontSize === undefined)
923
- percentConfig.fontSize = result[0][1];
924
- let lh;
925
- if (percentRegExp.test(lineHeight)) {
926
- lh = resolvePercent(lineHeight, 'lineHeight', percentConfig);
927
- }
928
- else if (!isNaN(+lineHeight)) {
929
- lh = resolvePercent(`${+lineHeight * 100}%`, 'lineHeight', percentConfig);
930
- }
931
- else {
932
- lh = global.__formatValue(lineHeight);
933
- }
934
- // lh 仍是字符串说明 resolvePercent 因 base 非 number 原样返回(已 error 过)或带单位 __formatValue
935
- // 未能换算成 number(如 fontSize 是未解析的 var())。RN lineHeight 不接受字符串,丢弃避免运行时报错
936
- if (typeof lh === 'number') {
908
+ const lh = !isNaN(+lineHeight)
909
+ ? `${+lineHeight * 100}%`
910
+ : global.__formatValue(lineHeight);
911
+ if (lh !== undefined) {
937
912
  result.push(['lineHeight', lh]);
938
913
  }
939
914
  else {
940
- warn(`Line-height [${lineHeight}] in [font: ${value}] could not be resolved to a number (font-size unresolved?), dropped.`);
915
+ warn(`Line-height [${lineHeight}] in [font: ${value}] could not be resolved, dropped.`);
941
916
  }
942
917
  }
943
918
  // 4. font-family(font-size 之后剩余部分;多字体取首值、去引号)
@@ -981,8 +956,11 @@ export function transformShorthand(styleObj, shorthandKeys, percentConfig) {
981
956
  if (typeof value === 'string') {
982
957
  values = parseValues(value);
983
958
  }
984
- else if (value === 0 && hasOwn(runtimeBorderLikeShorthandMap, key)) {
985
- values = ['0'];
959
+ else if (typeof value === 'number' && hasOwn(runtimeNumericExpandShorthandMap, key)) {
960
+ // runtimeNumericExpandShorthandMap 中的简写(border / outline / gap)在 __getStyle 的 transformStyleObj
961
+ // 阶段已被 __formatValue 把带单位长度换算为 number;这里转回字符串 token 交给后续展开,
962
+ // 否则会原样残留为 RN 不认识或行为不一致的简写 key。
963
+ values = ['' + value];
986
964
  }
987
965
  else {
988
966
  continue;
@@ -990,11 +968,13 @@ export function transformShorthand(styleObj, shorthandKeys, percentConfig) {
990
968
  const props = runtimeAbbreviationMap[key];
991
969
  if (!props)
992
970
  continue;
993
- // 单值短路:composite 且单值通常透传(RN 原生支持 margin / padding 单值 DimensionValue);
994
- // 但 inset / gap 必须展开(理由见 runtimeForceExpandCompositeMap 注释)
971
+ // 单值短路:composite 且单值通常透传(RN 原生支持 margin / padding / inset / border-* 单值 DimensionValue);
972
+ // 但 gap 必须展开 —— RN gap / rowGap / columnGap 严格要求 number,单值串虽已在 __getStyle 阶段被 __formatValue 换算,
973
+ // 多值串(如 '10px 20px')仍会原样透传到这里,需展开后逐 token 再过 __formatValue 才能落成 number;
974
+ // `%` 在写回阶段由 transformShorthand 调 resolvePercent 落成 number(rowGap 基 parentHeight、columnGap 基 parentWidth)
995
975
  if (hasOwn(runtimeCompositeStyleMap, key) &&
996
976
  values.length === 1 &&
997
- !hasOwn(runtimeForceExpandCompositeMap, key))
977
+ key !== 'gap')
998
978
  continue;
999
979
  let expandedValues = values;
1000
980
  let pairs;
@@ -1176,7 +1156,7 @@ export function setStyle(styleObj, keyPath, setter) {
1176
1156
  // ============================================================
1177
1157
  // core style hook
1178
1158
  // ============================================================
1179
- export function useTransformStyle(styleObj = {}, { enableVar, transformRadiusPercent, parentFontSize, parentWidth, parentHeight, defaultStyle }) {
1159
+ export function useTransformStyle(styleObj = {}, { enableVar, transformRadiusPercent, parentWidth, parentHeight, defaultStyle }) {
1180
1160
  const varStyle = {};
1181
1161
  const unoVarStyle = {};
1182
1162
  const normalStyle = {};
@@ -1247,10 +1227,9 @@ export function useTransformStyle(styleObj = {}, { enableVar, transformRadiusPer
1247
1227
  // fixme 去掉 translate & border-radius 的百分比计算
1248
1228
  // fixme Image 组件 borderRadius 仅支持 number
1249
1229
  const needRadiusPercent = transformRadiusPercent && hasOwn(radiusPercentRule, key);
1250
- const needFontPercent = key === 'fontSize' || key === 'lineHeight';
1251
1230
  // RN gap / rowGap / columnGap 不支持 %,需要运行时换算为 number 喂给 RN
1252
1231
  const needGapPercent = key === 'rowGap' || key === 'columnGap';
1253
- if ((needRadiusPercent || needFontPercent || needGapPercent) && percentRegExp.test(value)) {
1232
+ if ((needRadiusPercent || needGapPercent) && percentRegExp.test(value)) {
1254
1233
  if (needRadiusPercent)
1255
1234
  hasSelfPercent = true;
1256
1235
  resolvedKeyPath = resolvedKeyPath ?? keyPath.slice();
@@ -1336,12 +1315,10 @@ export function useTransformStyle(styleObj = {}, { enableVar, transformRadiusPer
1336
1315
  height,
1337
1316
  fontSize: normalStyle.fontSize,
1338
1317
  parentWidth,
1339
- parentHeight,
1340
- parentFontSize
1318
+ parentHeight
1341
1319
  };
1342
- // transformFont 可能会更新 percentConfig 配置,必须在 transformPercent 之前执行,保证 fontSize / lineHeight 的百分比能被正确解析
1343
1320
  if (hasFont)
1344
- transformFont(normalStyle, percentConfig);
1321
+ transformFont(normalStyle);
1345
1322
  if (percentKeyPaths.length)
1346
1323
  transformPercent(normalStyle, percentKeyPaths, percentConfig);
1347
1324
  if (calcKeyPaths.length) {
@@ -1420,6 +1397,31 @@ export function useNavigation() {
1420
1397
  const { navigation } = useContext(RouteContext) || {};
1421
1398
  return navigation;
1422
1399
  }
1400
+ function getTextPercentBase(currentFontSize, parentTextStyle) {
1401
+ return typeof currentFontSize === 'number'
1402
+ ? currentFontSize
1403
+ : typeof parentTextStyle?.fontSize === 'number'
1404
+ ? parentTextStyle.fontSize
1405
+ : DEFAULT_FONT_SIZE;
1406
+ }
1407
+ export function resolveTextFontSizePercentStyle(textStyle, parentTextStyle) {
1408
+ if (!textStyle)
1409
+ return textStyle;
1410
+ if (typeof textStyle.fontSize === 'string' && percentRegExp.test(textStyle.fontSize)) {
1411
+ const base = getTextPercentBase(undefined, parentTextStyle);
1412
+ textStyle.fontSize = parseFloat(textStyle.fontSize) / 100 * base;
1413
+ }
1414
+ return textStyle;
1415
+ }
1416
+ export function resolveTextLineHeightPercentStyle(textStyle, parentTextStyle) {
1417
+ if (!textStyle)
1418
+ return textStyle;
1419
+ if (typeof textStyle.lineHeight === 'string' && percentRegExp.test(textStyle.lineHeight)) {
1420
+ const base = getTextPercentBase(textStyle.fontSize, parentTextStyle);
1421
+ textStyle.lineHeight = parseFloat(textStyle.lineHeight) / 100 * base;
1422
+ }
1423
+ return textStyle;
1424
+ }
1423
1425
  /**
1424
1426
  * 用法等同于 useEffect,但是会忽略首次执行,只在依赖更新时执行
1425
1427
  */
@@ -1486,8 +1488,9 @@ export function useTextPassThrough(textStyle, textProps, { enableTextPassThrough
1486
1488
  const parent = useContext(TextPassThroughContext);
1487
1489
  // eslint-disable-next-line react-hooks/rules-of-hooks
1488
1490
  const valueRef = useRef(null);
1489
- const nextTextStyle = textStyle
1490
- ? extendObject({}, parent?.textStyle, textStyle)
1491
+ const resolvedTextStyle = resolveTextFontSizePercentStyle(textStyle, parent?.textStyle);
1492
+ const nextTextStyle = resolvedTextStyle
1493
+ ? extendObject({}, parent?.textStyle, resolvedTextStyle)
1491
1494
  : parent?.textStyle;
1492
1495
  const nextTextProps = textProps
1493
1496
  ? extendObject({}, parent?.pendingTextProps, textProps)
@@ -1501,26 +1504,6 @@ export function useTextPassThrough(textStyle, textProps, { enableTextPassThrough
1501
1504
  }
1502
1505
  return valueRef.current;
1503
1506
  }
1504
- export function useTextPassThroughText(textStyle) {
1505
- const inheritedText = useContext(TextPassThroughContext);
1506
- const valueRef = useRef(null);
1507
- if (!textStyle) {
1508
- return {
1509
- inheritedText,
1510
- textPassThrough: null
1511
- };
1512
- }
1513
- const nextValue = {
1514
- textStyle: extendObject({}, inheritedText?.textStyle, textStyle)
1515
- };
1516
- if (diffAndCloneA(valueRef.current, nextValue).diff) {
1517
- valueRef.current = nextValue;
1518
- }
1519
- return {
1520
- inheritedText,
1521
- textPassThrough: valueRef.current
1522
- };
1523
- }
1524
1507
  export function useHover({ enableHover, hoverStartTime, hoverStayTime, disabled }) {
1525
1508
  const enableHoverRef = useRef(enableHover);
1526
1509
  if (enableHoverRef.current !== enableHover) {
@@ -1637,7 +1620,10 @@ export function flatGesture(gestures = []) {
1637
1620
  return gesture.nodeRefs
1638
1621
  .map((item) => item.getNodeInstance()?.instance?.gestureRef || {});
1639
1622
  }
1640
- return gesture?.current ? [gesture] : [];
1623
+ if (gesture && (gesture.current || gesture.handlerTag !== undefined)) {
1624
+ return [gesture];
1625
+ }
1626
+ return [];
1641
1627
  })) || [];
1642
1628
  }
1643
1629
  export function getCurrentPage(pageId) {
@@ -80,7 +80,6 @@ export interface ButtonProps {
80
80
  'enable-offset'?: boolean,
81
81
  'enable-var'?: boolean
82
82
  'enable-text-pass-through'?: boolean
83
- 'parent-font-size'?: number
84
83
  'parent-width'?: number
85
84
  'parent-height'?: number
86
85
  style?: ViewStyle & TextStyle & Record<string, any>
@@ -212,7 +211,6 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
212
211
  'form-type': formType,
213
212
  'enable-var': enableVar,
214
213
  'enable-text-pass-through': enableTextPassThrough,
215
- 'parent-font-size': parentFontSize,
216
214
  'parent-width': parentWidth,
217
215
  'parent-height': parentHeight,
218
216
  style = {},
@@ -301,7 +299,7 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
301
299
  varContextRef,
302
300
  setWidth,
303
301
  setHeight
304
- } = useTransformStyle(styleObj, { enableVar, parentFontSize, parentWidth, parentHeight, defaultStyle })
302
+ } = useTransformStyle(styleObj, { enableVar, parentWidth, parentHeight, defaultStyle })
305
303
 
306
304
  const nodeRef = useRef(null)
307
305
 
@@ -24,7 +24,6 @@ interface CameraProps {
24
24
  binderror?: (error: { message: string }) => void
25
25
  bindinitdone?: (result: { type: string, data: string }) => void
26
26
  bindscancode?: (result: { type: string, data: string }) => void
27
- 'parent-font-size'?: number
28
27
  'parent-width'?: number
29
28
  'parent-height'?: number
30
29
  'enable-var'?: boolean
@@ -58,12 +57,29 @@ interface CameraRef {
58
57
  stopRecord: (options?: StopRecordOptions) => void
59
58
  }
60
59
 
60
+ interface CameraPermissionCache {
61
+ promise?: Promise<any>
62
+ result?: boolean
63
+ }
64
+
61
65
  type HandlerRef<T, P> = {
62
66
  current: T | null
63
67
  }
64
68
 
65
69
  let RecordRes: any = null
66
70
 
71
+ const cameraPermissionCacheMap = new Map<number, CameraPermissionCache>()
72
+
73
+ function getCameraPermissionCache (pageId: number | undefined) {
74
+ if (pageId == null) return
75
+ let cache = cameraPermissionCacheMap.get(pageId)
76
+ if (!cache) {
77
+ cache = {}
78
+ cameraPermissionCacheMap.set(pageId, cache)
79
+ }
80
+ return cache
81
+ }
82
+
67
83
  const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: CameraProps, ref): JSX.Element | null => {
68
84
  // eslint-disable-next-line @typescript-eslint/no-var-requires
69
85
  const cameraRef = useRef<any>(null)
@@ -76,7 +92,6 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
76
92
  bindinitdone,
77
93
  bindstop,
78
94
  bindscancode,
79
- 'parent-font-size': parentFontSize,
80
95
  'parent-width': parentWidth,
81
96
  'parent-height': parentHeight,
82
97
  'enable-var': enableVar,
@@ -93,7 +108,6 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
93
108
  setHeight
94
109
  } = useTransformStyle(styleObj, {
95
110
  enableVar,
96
- parentFontSize,
97
111
  parentWidth,
98
112
  parentHeight
99
113
  })
@@ -283,12 +297,33 @@ const _camera = forwardRef<HandlerRef<any, CameraProps>, CameraProps>((props: Ca
283
297
  try {
284
298
  const cameraPermission = global?.__mpx?.config?.rnConfig?.cameraPermission
285
299
  if (typeof cameraPermission === 'function') {
286
- const permissionResult = await cameraPermission()
287
- setHasPermission(permissionResult === true)
300
+ const permissionCache = getCameraPermissionCache(pageId)
301
+ if (permissionCache && hasOwn(permissionCache, 'result')) {
302
+ setHasPermission(permissionCache.result === true)
303
+ return
304
+ }
305
+ let permissionResult
306
+ if (permissionCache) {
307
+ if (!permissionCache.promise) {
308
+ permissionCache.promise = cameraPermission()
309
+ }
310
+ permissionResult = await permissionCache.promise
311
+ } else {
312
+ permissionResult = await cameraPermission()
313
+ }
314
+ const granted = permissionResult === true
315
+ if (permissionCache) {
316
+ permissionCache.result = granted
317
+ }
318
+ setHasPermission(granted)
288
319
  } else {
289
320
  setHasPermission(true)
290
321
  }
291
322
  } catch (error) {
323
+ const permissionCache = getCameraPermissionCache(pageId)
324
+ if (permissionCache) {
325
+ permissionCache.result = false
326
+ }
292
327
  setHasPermission(false)
293
328
  }
294
329
  }
@@ -33,6 +33,8 @@ import { createImageData as canvasCreateImageData } from './ImageData'
33
33
  import { useConstructorsRegistry } from './constructorsRegistry'
34
34
  import Portal from '../mpx-portal'
35
35
 
36
+ type WebViewInstance = WebView<any>
37
+
36
38
  const stylesheet = StyleSheet.create({
37
39
  container: { overflow: 'hidden', flex: 0 },
38
40
  webview: {
@@ -52,7 +54,6 @@ interface CanvasProps {
52
54
  style?: Record<string, any>
53
55
  originWhitelist?: Array<string>
54
56
  'enable-var'?: boolean
55
- 'parent-font-size'?: number
56
57
  'parent-width'?: number
57
58
  'parent-height'?: number
58
59
  bindtouchstart?: (event: NativeSyntheticEvent<TouchEvent>) => void
@@ -64,7 +65,7 @@ interface CanvasProps {
64
65
  }
65
66
 
66
67
  const _Canvas = forwardRef<HandlerRef<CanvasProps & View, CanvasProps>, CanvasProps>((props: CanvasProps = {}, ref): JSX.Element => {
67
- const { style = {}, originWhitelist = ['*'], 'enable-var': enableVar, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props
68
+ const { style = {}, originWhitelist = ['*'], 'enable-var': enableVar, 'parent-width': parentWidth, 'parent-height': parentHeight } = props
68
69
  const [isLoaded, setIsLoaded] = useState(false)
69
70
  const nodeRef = useRef(null)
70
71
 
@@ -76,7 +77,6 @@ const _Canvas = forwardRef<HandlerRef<CanvasProps & View, CanvasProps>, CanvasPr
76
77
  setHeight
77
78
  } = useTransformStyle(extendObject({}, style, stylesheet.container), {
78
79
  enableVar,
79
- parentFontSize,
80
80
  parentWidth,
81
81
  parentHeight
82
82
  })
@@ -266,7 +266,7 @@ const _Canvas = forwardRef<HandlerRef<CanvasProps & View, CanvasProps>, CanvasPr
266
266
  canvasComponent = createElement(View, innerProps, createElement(
267
267
  WebView,
268
268
  {
269
- ref: (element) => {
269
+ ref: (element: WebViewInstance | null) => {
270
270
  if (canvasRef.current) {
271
271
  canvasRef.current.webview = element
272
272
  }
@@ -291,7 +291,7 @@ const _Canvas = forwardRef<HandlerRef<CanvasProps & View, CanvasProps>, CanvasPr
291
291
  }
292
292
 
293
293
  canvasComponent = createElement(View, innerProps, createElement(WebView, {
294
- ref: (element) => {
294
+ ref: (element: WebViewInstance | null) => {
295
295
  if (canvasRef.current) {
296
296
  canvasRef.current.webview = element
297
297
  }
@@ -28,7 +28,6 @@ export interface CheckboxGroupProps {
28
28
  style?: ViewStyle & Record<string, any>
29
29
  'enable-offset'?: boolean
30
30
  'enable-var'?: boolean
31
- 'parent-font-size'?: number
32
31
  'parent-width'?: number
33
32
  'parent-height'?: number
34
33
  children: ReactNode
@@ -44,7 +43,6 @@ const CheckboxGroup = forwardRef<
44
43
  const {
45
44
  style = {},
46
45
  'enable-var': enableVar,
47
- 'parent-font-size': parentFontSize,
48
46
  'parent-width': parentWidth,
49
47
  'parent-height': parentHeight
50
48
  } = props
@@ -72,7 +70,7 @@ const CheckboxGroup = forwardRef<
72
70
  varContextRef,
73
71
  setWidth,
74
72
  setHeight
75
- } = useTransformStyle(style, { enableVar, parentFontSize, parentWidth, parentHeight, defaultStyle })
73
+ } = useTransformStyle(style, { enableVar, parentWidth, parentHeight, defaultStyle })
76
74
 
77
75
  const nodeRef = useRef(null)
78
76
 
@@ -43,7 +43,6 @@ export interface CheckboxProps extends Selection {
43
43
  'enable-offset'?: boolean
44
44
  'enable-var'?: boolean
45
45
  'enable-text-pass-through'?: boolean
46
- 'parent-font-size'?: number
47
46
  'parent-width'?: number
48
47
  'parent-height'?: number
49
48
  children?: ReactNode
@@ -90,7 +89,6 @@ const Checkbox = forwardRef<HandlerRef<View, CheckboxProps>, CheckboxProps>(
90
89
  style = {},
91
90
  'enable-var': enableVar,
92
91
  'enable-text-pass-through': enableTextPassThrough,
93
- 'parent-font-size': parentFontSize,
94
92
  'parent-width': parentWidth,
95
93
  'parent-height': parentHeight,
96
94
  bindtap,
@@ -134,7 +132,7 @@ const Checkbox = forwardRef<HandlerRef<View, CheckboxProps>, CheckboxProps>(
134
132
  varContextRef,
135
133
  setWidth,
136
134
  setHeight
137
- } = useTransformStyle(style, { enableVar, parentFontSize, parentWidth, parentHeight, defaultStyle: styles.container })
135
+ } = useTransformStyle(style, { enableVar, parentWidth, parentHeight, defaultStyle: styles.container })
138
136
 
139
137
  const nodeRef = useRef(null)
140
138
 
@@ -16,7 +16,6 @@ interface FormProps {
16
16
  'enable-offset'?: boolean
17
17
  'enable-var'?: boolean
18
18
  'enable-text-pass-through'?: boolean
19
- 'parent-font-size'?: number
20
19
  'parent-width'?: number
21
20
  'parent-height'?: number
22
21
  bindsubmit?: (evt: {
@@ -33,7 +32,6 @@ const _Form = forwardRef<HandlerRef<View, FormProps>, FormProps>((fromProps: For
33
32
  style,
34
33
  'enable-var': enableVar,
35
34
  'enable-text-pass-through': enableTextPassThrough,
36
- 'parent-font-size': parentFontSize,
37
35
  'parent-width': parentWidth,
38
36
  'parent-height': parentHeight
39
37
  } = props
@@ -45,7 +43,7 @@ const _Form = forwardRef<HandlerRef<View, FormProps>, FormProps>((fromProps: For
45
43
  varContextRef,
46
44
  setWidth,
47
45
  setHeight
48
- } = useTransformStyle(style, { enableVar, parentFontSize, parentWidth, parentHeight })
46
+ } = useTransformStyle(style, { enableVar, parentWidth, parentHeight })
49
47
 
50
48
  const { textStyle, innerStyle = {} } = splitStyle(normalStyle)
51
49
  const textPassThrough = useTextPassThrough(textStyle, textProps, { enableTextPassThrough })
@@ -37,7 +37,6 @@ export interface IconProps {
37
37
  style?: TextStyle & Record<string, any>
38
38
  'enable-offset'?: boolean
39
39
  'enable-var'?: boolean
40
- 'parent-font-size'?: number
41
40
  'parent-width'?: number
42
41
  'parent-height'?: number
43
42
  }
@@ -62,7 +61,6 @@ const Icon = forwardRef<HandlerRef<Text, IconProps>, IconProps>(
62
61
  color,
63
62
  style = {},
64
63
  'enable-var': enableVar,
65
- 'parent-font-size': parentFontSize,
66
64
  'parent-width': parentWidth,
67
65
  'parent-height': parentHeight
68
66
  } = props
@@ -79,7 +77,7 @@ const Icon = forwardRef<HandlerRef<Text, IconProps>, IconProps>(
79
77
  normalStyle,
80
78
  setWidth,
81
79
  setHeight
82
- } = useTransformStyle(styleObj, { enableVar, parentFontSize, parentWidth, parentHeight })
80
+ } = useTransformStyle(styleObj, { enableVar, parentWidth, parentHeight })
83
81
 
84
82
  const nodeRef = useRef(null)
85
83
  useNodesRef(props, ref, nodeRef, { style: normalStyle })
@@ -52,7 +52,6 @@ export interface ImageProps {
52
52
  style?: ImageStyle & Record<string, any>
53
53
  'enable-offset'?: boolean
54
54
  'enable-var'?: boolean
55
- 'parent-font-size'?: number
56
55
  'parent-width'?: number
57
56
  'parent-height'?: number
58
57
  'enable-fast-image'?: boolean
@@ -176,9 +175,7 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
176
175
  src = '',
177
176
  mode = 'scaleToFill',
178
177
  style = {},
179
- 'enable-var': enableVar,
180
- 'parent-font-size': parentFontSize,
181
- 'enable-fast-image': enableFastImage,
178
+ 'enable-var': enableVar, 'enable-fast-image': enableFastImage,
182
179
  'parent-width': parentWidth,
183
180
  'parent-height': parentHeight,
184
181
  'is-svg': isSvgProp,
@@ -223,7 +220,7 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
223
220
  normalStyle,
224
221
  setWidth,
225
222
  setHeight
226
- } = useTransformStyle(styleObj, { enableVar, transformRadiusPercent: isAndroid && !isSvg && !isLayoutMode, parentFontSize, parentWidth, parentHeight, defaultStyle: DEFAULT_IMAGE_STYLE })
223
+ } = useTransformStyle(styleObj, { enableVar, transformRadiusPercent: isAndroid && !isSvg && !isLayoutMode, parentWidth, parentHeight, defaultStyle: DEFAULT_IMAGE_STYLE })
227
224
 
228
225
  // normalStyle 已合入 DEFAULT_IMAGE_STYLE,对外暴露完整 style(含 default 兜底的 width/height)
229
226
  useNodesRef(props, ref, nodeRef, {
@@ -1,20 +1,29 @@
1
1
  import { Text, TextProps } from 'react-native'
2
2
  import { JSX, createElement, useContext } from 'react'
3
3
 
4
- import { extendObject, getDefaultAllowFontScaling } from './utils'
4
+ import { extendObject, getDefaultAllowFontScaling, resolveTextLineHeightPercentStyle } from './utils'
5
5
  import { TextPassThroughContext } from './context'
6
6
 
7
7
  const InlineText = (props: TextProps): JSX.Element => {
8
8
  const inheritedText = useContext(TextPassThroughContext)
9
- const style = extendObject({}, inheritedText?.textStyle, props.style)
10
- const mergedProps = extendObject({}, inheritedText?.pendingTextProps, props, { style })
9
+ const mergedStyle = inheritedText?.textStyle
10
+ ? extendObject({}, inheritedText.textStyle)
11
+ : undefined
12
+ // inline-text 只包裹裸文本,消费继承文本样式中的相对 lineHeight,不处理本地样式。
13
+ if (inheritedText?.textStyle) {
14
+ resolveTextLineHeightPercentStyle(mergedStyle, inheritedText.textStyle)
15
+ }
16
+ const mergedProps = inheritedText?.pendingTextProps
17
+ ? extendObject({}, inheritedText.pendingTextProps, props)
18
+ : props
11
19
  const {
12
20
  allowFontScaling,
13
21
  children
14
22
  } = mergedProps
15
23
 
16
24
  return createElement(Text, extendObject({}, mergedProps, {
17
- allowFontScaling: allowFontScaling ?? getDefaultAllowFontScaling()
25
+ allowFontScaling: allowFontScaling ?? getDefaultAllowFontScaling(),
26
+ style: mergedStyle
18
27
  }), children)
19
28
  }
20
29