@mpxjs/webpack-plugin 2.10.17 → 2.10.18

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 (238) hide show
  1. package/lib/config.js +60 -0
  2. package/lib/file-loader.js +4 -1
  3. package/lib/global.d.ts +231 -0
  4. package/lib/index.js +58 -73
  5. package/lib/init.js +3 -0
  6. package/lib/json-compiler/index.js +13 -4
  7. package/lib/loader.js +4 -0
  8. package/lib/platform/json/wx/index.js +6 -0
  9. package/lib/platform/style/wx/index.js +102 -72
  10. package/lib/platform/template/wx/component-config/ad.js +5 -0
  11. package/lib/platform/template/wx/component-config/button.js +10 -3
  12. package/lib/platform/template/wx/component-config/camera.js +13 -3
  13. package/lib/platform/template/wx/component-config/canvas.js +8 -1
  14. package/lib/platform/template/wx/component-config/cover-image.js +7 -2
  15. package/lib/platform/template/wx/component-config/cover-view.js +3 -1
  16. package/lib/platform/template/wx/component-config/form.js +27 -2
  17. package/lib/platform/template/wx/component-config/image.js +5 -0
  18. package/lib/platform/template/wx/component-config/input.js +10 -0
  19. package/lib/platform/template/wx/component-config/label.js +10 -2
  20. package/lib/platform/template/wx/component-config/map.js +11 -0
  21. package/lib/platform/template/wx/component-config/movable-area.js +4 -1
  22. package/lib/platform/template/wx/component-config/movable-view.js +17 -2
  23. package/lib/platform/template/wx/component-config/navigator.js +26 -0
  24. package/lib/platform/template/wx/component-config/picker-view.js +12 -0
  25. package/lib/platform/template/wx/component-config/picker.js +3 -1
  26. package/lib/platform/template/wx/component-config/progress.js +11 -1
  27. package/lib/platform/template/wx/component-config/rich-text.js +5 -0
  28. package/lib/platform/template/wx/component-config/scroll-view.js +12 -1
  29. package/lib/platform/template/wx/component-config/slider.js +8 -0
  30. package/lib/platform/template/wx/component-config/swiper-item.js +5 -2
  31. package/lib/platform/template/wx/component-config/swiper.js +10 -0
  32. package/lib/platform/template/wx/component-config/text.js +5 -0
  33. package/lib/platform/template/wx/component-config/textarea.js +19 -2
  34. package/lib/platform/template/wx/component-config/unsupported.js +9 -0
  35. package/lib/platform/template/wx/component-config/video.js +10 -0
  36. package/lib/platform/template/wx/index.js +21 -1
  37. package/lib/react/LoadAsyncChunkModule.js +1 -1
  38. package/lib/react/processStyles.js +21 -9
  39. package/lib/react/script-helper.js +2 -2
  40. package/lib/react/style-helper.js +76 -13
  41. package/lib/resolver/AddModePlugin.js +17 -7
  42. package/lib/runtime/components/react/animationHooks/index.ts +75 -0
  43. package/lib/runtime/components/react/animationHooks/useAnimationAPIHooks.ts +197 -0
  44. package/lib/runtime/components/react/animationHooks/useTransitionHooks.ts +301 -0
  45. package/lib/runtime/components/react/animationHooks/utils.ts +197 -0
  46. package/lib/runtime/components/react/context.ts +12 -3
  47. package/lib/runtime/components/react/dist/animationHooks/index.d.ts +15 -0
  48. package/lib/runtime/components/react/dist/animationHooks/index.js +67 -0
  49. package/lib/runtime/components/react/dist/animationHooks/useAnimationAPIHooks.d.ts +3 -0
  50. package/lib/runtime/components/react/dist/animationHooks/useAnimationAPIHooks.js +181 -0
  51. package/lib/runtime/components/react/dist/animationHooks/useTransitionHooks.d.ts +3 -0
  52. package/lib/runtime/components/react/dist/animationHooks/useTransitionHooks.js +279 -0
  53. package/lib/runtime/components/react/dist/animationHooks/utils.d.ts +109 -0
  54. package/lib/runtime/components/react/dist/animationHooks/utils.js +151 -0
  55. package/lib/runtime/components/react/dist/context.d.ts +10 -3
  56. package/lib/runtime/components/react/dist/context.js +1 -2
  57. package/lib/runtime/components/react/dist/event.config.d.ts +0 -1
  58. package/lib/runtime/components/react/dist/getInnerListeners.d.ts +0 -1
  59. package/lib/runtime/components/react/dist/mpx-async-suspense.d.ts +0 -1
  60. package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +3 -1
  61. package/lib/runtime/components/react/dist/mpx-button.d.ts +0 -1
  62. package/lib/runtime/components/react/dist/mpx-canvas/Bus.d.ts +0 -1
  63. package/lib/runtime/components/react/dist/mpx-canvas/CanvasGradient.d.ts +0 -1
  64. package/lib/runtime/components/react/dist/mpx-canvas/CanvasRenderingContext2D.d.ts +0 -1
  65. package/lib/runtime/components/react/dist/mpx-canvas/Image.d.ts +0 -1
  66. package/lib/runtime/components/react/dist/mpx-canvas/ImageData.d.ts +0 -1
  67. package/lib/runtime/components/react/dist/mpx-canvas/constructorsRegistry.d.ts +0 -1
  68. package/lib/runtime/components/react/dist/mpx-canvas/html.d.ts +0 -1
  69. package/lib/runtime/components/react/dist/mpx-canvas/index.d.ts +0 -1
  70. package/lib/runtime/components/react/dist/mpx-canvas/utils.d.ts +0 -1
  71. package/lib/runtime/components/react/dist/mpx-checkbox-group.d.ts +0 -1
  72. package/lib/runtime/components/react/dist/mpx-checkbox.d.ts +0 -1
  73. package/lib/runtime/components/react/dist/mpx-form.d.ts +0 -1
  74. package/lib/runtime/components/react/dist/mpx-icon/index.d.ts +0 -1
  75. package/lib/runtime/components/react/dist/mpx-image.d.ts +0 -1
  76. package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
  77. package/lib/runtime/components/react/dist/mpx-inline-text.d.ts +0 -1
  78. package/lib/runtime/components/react/dist/mpx-input.d.ts +2 -1
  79. package/lib/runtime/components/react/dist/mpx-input.jsx +66 -50
  80. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.d.ts +0 -1
  81. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +35 -6
  82. package/lib/runtime/components/react/dist/mpx-label.d.ts +0 -1
  83. package/lib/runtime/components/react/dist/mpx-movable-area.d.ts +0 -1
  84. package/lib/runtime/components/react/dist/mpx-movable-view.d.ts +0 -1
  85. package/lib/runtime/components/react/dist/mpx-nav.d.ts +0 -1
  86. package/lib/runtime/components/react/dist/mpx-navigator.d.ts +0 -1
  87. package/lib/runtime/components/react/dist/mpx-picker/date.d.ts +0 -1
  88. package/lib/runtime/components/react/dist/mpx-picker/dateData.d.ts +0 -1
  89. package/lib/runtime/components/react/dist/mpx-picker/index.d.ts +0 -1
  90. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.d.ts +0 -1
  91. package/lib/runtime/components/react/dist/mpx-picker/region.d.ts +0 -1
  92. package/lib/runtime/components/react/dist/mpx-picker/regionData.d.ts +0 -1
  93. package/lib/runtime/components/react/dist/mpx-picker/selector.d.ts +0 -1
  94. package/lib/runtime/components/react/dist/mpx-picker/time.d.ts +0 -1
  95. package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +0 -1
  96. package/lib/runtime/components/react/dist/mpx-picker-view/index.d.ts +0 -1
  97. package/lib/runtime/components/react/dist/mpx-picker-view/pickerVIewContext.d.ts +0 -1
  98. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.d.ts +0 -1
  99. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItem.d.ts +0 -1
  100. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItemLite.d.ts +0 -1
  101. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewFaces.d.ts +0 -1
  102. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewIndicator.d.ts +0 -1
  103. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewMask.d.ts +0 -1
  104. package/lib/runtime/components/react/dist/mpx-popup/index.d.ts +0 -1
  105. package/lib/runtime/components/react/dist/mpx-popup/popupBase.d.ts +0 -1
  106. package/lib/runtime/components/react/dist/mpx-portal/index.d.ts +0 -1
  107. package/lib/runtime/components/react/dist/mpx-portal/portal-host.d.ts +0 -1
  108. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.d.ts +0 -1
  109. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +2 -2
  110. package/lib/runtime/components/react/dist/mpx-progress.d.ts +0 -1
  111. package/lib/runtime/components/react/dist/mpx-radio-group.d.ts +0 -1
  112. package/lib/runtime/components/react/dist/mpx-radio.d.ts +0 -1
  113. package/lib/runtime/components/react/dist/mpx-rich-text/html.d.ts +0 -1
  114. package/lib/runtime/components/react/dist/mpx-rich-text/index.d.ts +0 -1
  115. package/lib/runtime/components/react/dist/mpx-root-portal.d.ts +0 -1
  116. package/lib/runtime/components/react/dist/mpx-scroll-view.d.ts +0 -1
  117. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +84 -78
  118. package/lib/runtime/components/react/dist/mpx-simple-text.d.ts +0 -1
  119. package/lib/runtime/components/react/dist/mpx-simple-view.d.ts +0 -1
  120. package/lib/runtime/components/react/dist/mpx-slider.d.ts +0 -1
  121. package/lib/runtime/components/react/dist/mpx-sticky-header.d.ts +0 -1
  122. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +20 -20
  123. package/lib/runtime/components/react/dist/mpx-sticky-section.d.ts +0 -1
  124. package/lib/runtime/components/react/dist/mpx-swiper-item.d.ts +0 -1
  125. package/lib/runtime/components/react/dist/mpx-swiper.d.ts +10 -1
  126. package/lib/runtime/components/react/dist/mpx-swiper.jsx +95 -61
  127. package/lib/runtime/components/react/dist/mpx-switch.d.ts +0 -1
  128. package/lib/runtime/components/react/dist/mpx-text.d.ts +0 -1
  129. package/lib/runtime/components/react/dist/mpx-textarea.d.ts +0 -1
  130. package/lib/runtime/components/react/dist/mpx-textarea.jsx +1 -0
  131. package/lib/runtime/components/react/dist/mpx-video.d.ts +0 -1
  132. package/lib/runtime/components/react/dist/mpx-view.d.ts +3 -3
  133. package/lib/runtime/components/react/dist/mpx-view.jsx +22 -8
  134. package/lib/runtime/components/react/dist/mpx-web-view.d.ts +0 -1
  135. package/lib/runtime/components/react/dist/parser.d.ts +0 -1
  136. package/lib/runtime/components/react/dist/useNodesRef.d.ts +0 -1
  137. package/lib/runtime/components/react/dist/utils.d.ts +10 -9
  138. package/lib/runtime/components/react/dist/utils.jsx +47 -24
  139. package/lib/runtime/components/react/mpx-async-suspense.tsx +3 -1
  140. package/lib/runtime/components/react/mpx-image.tsx +2 -2
  141. package/lib/runtime/components/react/mpx-input.tsx +77 -54
  142. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +35 -6
  143. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +2 -2
  144. package/lib/runtime/components/react/mpx-scroll-view.tsx +110 -114
  145. package/lib/runtime/components/react/mpx-sticky-header.tsx +24 -24
  146. package/lib/runtime/components/react/mpx-swiper.tsx +115 -60
  147. package/lib/runtime/components/react/mpx-textarea.tsx +1 -0
  148. package/lib/runtime/components/react/mpx-view.tsx +27 -12
  149. package/lib/runtime/components/react/tsconfig.json +26 -0
  150. package/lib/runtime/components/react/types/global.d.ts +1 -0
  151. package/lib/runtime/components/react/utils.tsx +51 -27
  152. package/lib/runtime/optionProcessor.js +5 -0
  153. package/lib/runtime/optionProcessorReact.js +7 -0
  154. package/lib/runtime/stringify.wxs +2 -2
  155. package/lib/script-setup-compiler/index.js +1 -2
  156. package/lib/style-compiler/strip-conditional.js +243 -0
  157. package/lib/template-compiler/compiler.js +2 -5
  158. package/lib/utils/string.js +25 -1
  159. package/lib/wxss/loader.js +4 -1
  160. package/lib/wxss/utils.js +7 -2
  161. package/package.json +7 -14
  162. package/lib/runtime/components/react/dist/context.d.ts.map +0 -1
  163. package/lib/runtime/components/react/dist/event.config.d.ts.map +0 -1
  164. package/lib/runtime/components/react/dist/getInnerListeners.d.ts.map +0 -1
  165. package/lib/runtime/components/react/dist/mpx-async-suspense.d.ts.map +0 -1
  166. package/lib/runtime/components/react/dist/mpx-button.d.ts.map +0 -1
  167. package/lib/runtime/components/react/dist/mpx-canvas/Bus.d.ts.map +0 -1
  168. package/lib/runtime/components/react/dist/mpx-canvas/CanvasGradient.d.ts.map +0 -1
  169. package/lib/runtime/components/react/dist/mpx-canvas/CanvasRenderingContext2D.d.ts.map +0 -1
  170. package/lib/runtime/components/react/dist/mpx-canvas/Image.d.ts.map +0 -1
  171. package/lib/runtime/components/react/dist/mpx-canvas/ImageData.d.ts.map +0 -1
  172. package/lib/runtime/components/react/dist/mpx-canvas/constructorsRegistry.d.ts.map +0 -1
  173. package/lib/runtime/components/react/dist/mpx-canvas/html.d.ts.map +0 -1
  174. package/lib/runtime/components/react/dist/mpx-canvas/index.d.ts.map +0 -1
  175. package/lib/runtime/components/react/dist/mpx-canvas/utils.d.ts.map +0 -1
  176. package/lib/runtime/components/react/dist/mpx-checkbox-group.d.ts.map +0 -1
  177. package/lib/runtime/components/react/dist/mpx-checkbox.d.ts.map +0 -1
  178. package/lib/runtime/components/react/dist/mpx-form.d.ts.map +0 -1
  179. package/lib/runtime/components/react/dist/mpx-icon/index.d.ts.map +0 -1
  180. package/lib/runtime/components/react/dist/mpx-image.d.ts.map +0 -1
  181. package/lib/runtime/components/react/dist/mpx-inline-text.d.ts.map +0 -1
  182. package/lib/runtime/components/react/dist/mpx-input.d.ts.map +0 -1
  183. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.d.ts.map +0 -1
  184. package/lib/runtime/components/react/dist/mpx-label.d.ts.map +0 -1
  185. package/lib/runtime/components/react/dist/mpx-movable-area.d.ts.map +0 -1
  186. package/lib/runtime/components/react/dist/mpx-movable-view.d.ts.map +0 -1
  187. package/lib/runtime/components/react/dist/mpx-nav.d.ts.map +0 -1
  188. package/lib/runtime/components/react/dist/mpx-navigator.d.ts.map +0 -1
  189. package/lib/runtime/components/react/dist/mpx-picker/date.d.ts.map +0 -1
  190. package/lib/runtime/components/react/dist/mpx-picker/dateData.d.ts.map +0 -1
  191. package/lib/runtime/components/react/dist/mpx-picker/index.d.ts.map +0 -1
  192. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.d.ts.map +0 -1
  193. package/lib/runtime/components/react/dist/mpx-picker/region.d.ts.map +0 -1
  194. package/lib/runtime/components/react/dist/mpx-picker/regionData.d.ts.map +0 -1
  195. package/lib/runtime/components/react/dist/mpx-picker/selector.d.ts.map +0 -1
  196. package/lib/runtime/components/react/dist/mpx-picker/time.d.ts.map +0 -1
  197. package/lib/runtime/components/react/dist/mpx-picker/type.d.ts.map +0 -1
  198. package/lib/runtime/components/react/dist/mpx-picker-view/index.d.ts.map +0 -1
  199. package/lib/runtime/components/react/dist/mpx-picker-view/pickerVIewContext.d.ts.map +0 -1
  200. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.d.ts.map +0 -1
  201. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItem.d.ts.map +0 -1
  202. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItemLite.d.ts.map +0 -1
  203. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewFaces.d.ts.map +0 -1
  204. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewIndicator.d.ts.map +0 -1
  205. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewMask.d.ts.map +0 -1
  206. package/lib/runtime/components/react/dist/mpx-popup/index.d.ts.map +0 -1
  207. package/lib/runtime/components/react/dist/mpx-popup/popupBase.d.ts.map +0 -1
  208. package/lib/runtime/components/react/dist/mpx-portal/index.d.ts.map +0 -1
  209. package/lib/runtime/components/react/dist/mpx-portal/portal-host.d.ts.map +0 -1
  210. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.d.ts.map +0 -1
  211. package/lib/runtime/components/react/dist/mpx-progress.d.ts.map +0 -1
  212. package/lib/runtime/components/react/dist/mpx-radio-group.d.ts.map +0 -1
  213. package/lib/runtime/components/react/dist/mpx-radio.d.ts.map +0 -1
  214. package/lib/runtime/components/react/dist/mpx-rich-text/html.d.ts.map +0 -1
  215. package/lib/runtime/components/react/dist/mpx-rich-text/index.d.ts.map +0 -1
  216. package/lib/runtime/components/react/dist/mpx-root-portal.d.ts.map +0 -1
  217. package/lib/runtime/components/react/dist/mpx-scroll-view.d.ts.map +0 -1
  218. package/lib/runtime/components/react/dist/mpx-simple-text.d.ts.map +0 -1
  219. package/lib/runtime/components/react/dist/mpx-simple-view.d.ts.map +0 -1
  220. package/lib/runtime/components/react/dist/mpx-slider.d.ts.map +0 -1
  221. package/lib/runtime/components/react/dist/mpx-sticky-header.d.ts.map +0 -1
  222. package/lib/runtime/components/react/dist/mpx-sticky-section.d.ts.map +0 -1
  223. package/lib/runtime/components/react/dist/mpx-swiper-item.d.ts.map +0 -1
  224. package/lib/runtime/components/react/dist/mpx-swiper.d.ts.map +0 -1
  225. package/lib/runtime/components/react/dist/mpx-switch.d.ts.map +0 -1
  226. package/lib/runtime/components/react/dist/mpx-text.d.ts.map +0 -1
  227. package/lib/runtime/components/react/dist/mpx-textarea.d.ts.map +0 -1
  228. package/lib/runtime/components/react/dist/mpx-video.d.ts.map +0 -1
  229. package/lib/runtime/components/react/dist/mpx-view.d.ts.map +0 -1
  230. package/lib/runtime/components/react/dist/mpx-web-view.d.ts.map +0 -1
  231. package/lib/runtime/components/react/dist/parser.d.ts.map +0 -1
  232. package/lib/runtime/components/react/dist/useAnimationHooks.d.ts +0 -33
  233. package/lib/runtime/components/react/dist/useAnimationHooks.d.ts.map +0 -1
  234. package/lib/runtime/components/react/dist/useAnimationHooks.js +0 -289
  235. package/lib/runtime/components/react/dist/useNodesRef.d.ts.map +0 -1
  236. package/lib/runtime/components/react/dist/utils.d.ts.map +0 -1
  237. package/lib/runtime/components/react/useAnimationHooks.ts +0 -320
  238. package/lib/style-compiler/strip-conditional-loader.js +0 -289
@@ -4,7 +4,6 @@ import { isObject, isFunction, isNumber, hasOwn, diffAndCloneA, error, warn } fr
4
4
  import { VarContext, ScrollViewContext, RouteContext } from './context';
5
5
  import { ExpressionParser, parseFunc, ReplaceSource } from './parser';
6
6
  import { initialWindowMetrics } from 'react-native-safe-area-context';
7
- import FastImage from '@d11/react-native-fast-image';
8
7
  import { Gesture } from 'react-native-gesture-handler';
9
8
  export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/;
10
9
  export const PERCENT_REGEX = /^\s*-?\d+(\.\d+)?%\s*$/;
@@ -24,6 +23,7 @@ const varUseRegExp = /var\(/;
24
23
  const unoVarDecRegExp = /^--un-/;
25
24
  const unoVarUseRegExp = /var\(--un-/;
26
25
  const calcUseRegExp = /calc\(/;
26
+ const calcPercentExp = /^calc\(.*-?\d+(\.\d+)?%.*\)$/;
27
27
  const envUseRegExp = /env\(/;
28
28
  const filterRegExp = /(calc|env|%)/;
29
29
  const safeAreaInsetMap = {
@@ -32,6 +32,7 @@ const safeAreaInsetMap = {
32
32
  'safe-area-inset-bottom': 'bottom',
33
33
  'safe-area-inset-left': 'left'
34
34
  };
35
+ export const extendObject = Object.assign;
35
36
  function getSafeAreaInset(name, navigation) {
36
37
  const insets = extendObject({}, initialWindowMetrics?.insets, navigation?.insets);
37
38
  return insets[safeAreaInsetMap[name]];
@@ -110,15 +111,17 @@ export function splitStyle(styleObj) {
110
111
  }
111
112
  });
112
113
  }
113
- const selfPercentRule = {
114
- translateX: 'width',
115
- translateY: 'height',
114
+ const radiusPercentRule = {
116
115
  borderTopLeftRadius: 'width',
117
116
  borderBottomLeftRadius: 'width',
118
117
  borderBottomRightRadius: 'width',
119
118
  borderTopRightRadius: 'width',
120
119
  borderRadius: 'width'
121
120
  };
121
+ const selfPercentRule = extendObject({
122
+ translateX: 'width',
123
+ translateY: 'height'
124
+ }, radiusPercentRule);
122
125
  const parentHeightPercentRule = {
123
126
  height: true,
124
127
  minHeight: true,
@@ -170,19 +173,22 @@ function resolveVar(input, varContext) {
170
173
  const parsed = parseFunc(input, 'var');
171
174
  const replaced = new ReplaceSource(input);
172
175
  for (const { start, end, args } of parsed) {
176
+ // NOTE:
177
+ // - CSS var() fallback 允许包含空格、逗号等字符(如 font-family 的 fallback)
178
+ // - parseFunc 会按逗号分割 args,因此这里把 args[1..] 重新 join 回 fallback
173
179
  const varName = args[0];
174
- const fallback = args[1];
175
- let varValue = hasOwn(varContext, varName) ? varContext[varName] : fallback;
176
- if (varValue === undefined)
177
- return;
178
- if (varUseRegExp.test(varValue)) {
179
- varValue = resolveVar(varValue, varContext);
180
- if (varValue === undefined)
181
- return;
180
+ const fallback = args.length > 1 ? args.slice(1).join(',').trim() : undefined;
181
+ // 先处理 varValue
182
+ let varValue = hasOwn(varContext, varName) ? varContext[varName] : undefined;
183
+ if (varValue !== undefined) {
184
+ varValue = varUseRegExp.test(varValue) ? resolveVar(varValue, varContext) : global.__formatValue(varValue);
182
185
  }
183
- else {
184
- varValue = global.__formatValue(varValue);
186
+ // 再处理 fallback
187
+ if (varValue === undefined && fallback !== undefined) {
188
+ varValue = varUseRegExp.test(fallback) ? resolveVar(fallback, varContext) : global.__formatValue(fallback);
185
189
  }
190
+ if (varValue === undefined)
191
+ return;
186
192
  replaced.replace(start, end - 1, varValue);
187
193
  }
188
194
  return global.__formatValue(replaced.source());
@@ -241,6 +247,10 @@ function transformStringify(styleObj) {
241
247
  if (isNumber(styleObj.fontWeight)) {
242
248
  styleObj.fontWeight = '' + styleObj.fontWeight;
243
249
  }
250
+ // transformOrigin 20px 需要转换为 transformOrigin '20'
251
+ if (isNumber(styleObj.transformOrigin)) {
252
+ styleObj.transformOrigin = '' + styleObj.transformOrigin;
253
+ }
244
254
  }
245
255
  function transformPosition(styleObj, meta) {
246
256
  if (styleObj.position === 'fixed') {
@@ -249,7 +259,7 @@ function transformPosition(styleObj, meta) {
249
259
  }
250
260
  }
251
261
  // 多value解析
252
- function parseValues(str, char = ' ') {
262
+ export function parseValues(str, char = ' ') {
253
263
  let stack = 0;
254
264
  let temp = '';
255
265
  const result = [];
@@ -261,11 +271,11 @@ function parseValues(str, char = ' ') {
261
271
  stack--;
262
272
  }
263
273
  // 非括号内 或者 非分隔字符且非空
264
- if (stack !== 0 || (str[i] !== char && str[i] !== ' ')) {
274
+ if (stack !== 0 || str[i] !== char) {
265
275
  temp += str[i];
266
276
  }
267
277
  if ((stack === 0 && str[i] === char) || i === str.length - 1) {
268
- result.push(temp);
278
+ result.push(temp.trim());
269
279
  temp = '';
270
280
  }
271
281
  }
@@ -274,6 +284,8 @@ function parseValues(str, char = ' ') {
274
284
  // parse string transform, eg: transform: 'rotateX(45deg) rotateZ(0.785398rad)'
275
285
  function parseTransform(transformStr) {
276
286
  const values = parseValues(transformStr);
287
+ // Todo transform 排序不一致时,transform动画会闪烁,故这里同样的排序输出 transform
288
+ values.sort();
277
289
  const transform = [];
278
290
  values.forEach(item => {
279
291
  const match = item.match(/([/\w]+)\((.+)\)/);
@@ -337,7 +349,7 @@ function transformBoxShadow(styleObj) {
337
349
  return `${res}${idx === 0 ? '' : ' '}${global.__formatValue(i)}`;
338
350
  }, '');
339
351
  }
340
- export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight }) {
352
+ export function useTransformStyle(styleObj = {}, { enableVar, transformRadiusPercent, externalVarContext, parentFontSize, parentWidth, parentHeight }) {
341
353
  const varStyle = {};
342
354
  const unoVarStyle = {};
343
355
  const normalStyle = {};
@@ -386,13 +398,20 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
386
398
  envKeyPaths.push(keyPath.slice());
387
399
  }
388
400
  }
389
- function calcVisitor({ value, keyPath }) {
401
+ function calcVisitor({ key, value, keyPath }) {
390
402
  if (calcUseRegExp.test(value)) {
403
+ // calc translate & border-radius 的百分比计算
404
+ if (hasOwn(selfPercentRule, key) && calcPercentExp.test(value)) {
405
+ hasSelfPercent = true;
406
+ percentKeyPaths.push(keyPath.slice());
407
+ }
391
408
  calcKeyPaths.push(keyPath.slice());
392
409
  }
393
410
  }
394
411
  function percentVisitor({ key, value, keyPath }) {
395
- if (hasOwn(selfPercentRule, key) && PERCENT_REGEX.test(value)) {
412
+ // fixme 去掉 translate & border-radius 的百分比计算
413
+ // fixme Image 组件 borderRadius 仅支持 number
414
+ if (transformRadiusPercent && hasOwn(radiusPercentRule, key) && PERCENT_REGEX.test(value)) {
396
415
  hasSelfPercent = true;
397
416
  percentKeyPaths.push(keyPath.slice());
398
417
  }
@@ -467,7 +486,7 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
467
486
  transformStringify(normalStyle);
468
487
  // transform rpx to px
469
488
  transformBoxShadow(normalStyle);
470
- // transform 字符串格式转化数组格式
489
+ // transform 字符串格式转化数组格式(先转数组再处理css var)
471
490
  transformTransform(normalStyle);
472
491
  return {
473
492
  hasVarDec,
@@ -612,15 +631,19 @@ export function flatGesture(gestures = []) {
612
631
  return gesture?.current ? [gesture] : [];
613
632
  })) || [];
614
633
  }
615
- export const extendObject = Object.assign;
616
634
  export function getCurrentPage(pageId) {
617
635
  if (!global.getCurrentPages)
618
636
  return;
619
637
  const pages = global.getCurrentPages();
620
638
  return pages.find((page) => isFunction(page.getPageId) && page.getPageId() === pageId);
621
639
  }
622
- export function renderImage(imageProps, enableFastImage = false) {
623
- const Component = enableFastImage ? FastImage : Image;
640
+ export function renderImage(imageProps, enableFastImage = true) {
641
+ let Component = Image;
642
+ if (enableFastImage) {
643
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
644
+ const fastImageModule = require('@d11/react-native-fast-image');
645
+ Component = fastImageModule.default || fastImageModule;
646
+ }
624
647
  return createElement(Component, imageProps);
625
648
  }
626
649
  export function pickStyle(styleObj = {}, pickedKeys, callback) {
@@ -1,6 +1,5 @@
1
1
  import { useState, ComponentType, useEffect, useCallback, useRef, ReactNode, createElement } from 'react'
2
2
  import { View, Image, StyleSheet, Text, TouchableOpacity } from 'react-native'
3
- import FastImage from '@d11/react-native-fast-image'
4
3
  import { AnyFunc } from './types/common'
5
4
 
6
5
  const asyncChunkMap = new Map()
@@ -82,6 +81,9 @@ const DefaultFallback = ({ onReload }: DefaultFallbackProps) => {
82
81
  }
83
82
 
84
83
  const DefaultLoading = () => {
84
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
85
+ const FastImageModule = require('@d11/react-native-fast-image')
86
+ const FastImage = FastImageModule.default || FastImageModule
85
87
  return (
86
88
  <View style={styles.container}>
87
89
  <FastImage
@@ -26,7 +26,7 @@ import { noop } from '@mpxjs/utils'
26
26
  import { SvgCssUri } from 'react-native-svg/css'
27
27
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
28
28
  import useNodesRef, { HandlerRef } from './useNodesRef'
29
- import { SVG_REGEXP, useLayout, useTransformStyle, renderImage, extendObject } from './utils'
29
+ import { SVG_REGEXP, useLayout, useTransformStyle, renderImage, extendObject, isAndroid } from './utils'
30
30
  import Portal from './mpx-portal'
31
31
 
32
32
  export type Mode =
@@ -190,7 +190,7 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
190
190
  normalStyle,
191
191
  setWidth,
192
192
  setHeight
193
- } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
193
+ } = useTransformStyle(styleObj, { enableVar, transformRadiusPercent: isAndroid && !isSvg && !isLayoutMode, externalVarContext, parentFontSize, parentWidth, parentHeight })
194
194
 
195
195
  const { layoutRef, layoutStyle, layoutProps } = useLayout({
196
196
  props,
@@ -18,7 +18,7 @@
18
18
  * ✔ selection-start
19
19
  * ✔ selection-end
20
20
  * ✔ adjust-position
21
- * hold-keyboard
21
+ * hold-keyboard
22
22
  * ✘ safe-password-cert-path
23
23
  * ✘ safe-password-length
24
24
  * ✘ safe-password-time-stamp
@@ -54,7 +54,7 @@ import {
54
54
  NativeTouchEvent
55
55
  } from 'react-native'
56
56
  import { warn } from '@mpxjs/utils'
57
- import { useUpdateEffect, useTransformStyle, useLayout, extendObject, isIOS } from './utils'
57
+ import { useUpdateEffect, useTransformStyle, useLayout, extendObject, isAndroid } from './utils'
58
58
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
59
59
  import useNodesRef, { HandlerRef } from './useNodesRef'
60
60
  import { FormContext, FormFieldValue, KeyboardAvoidContext } from './context'
@@ -95,13 +95,16 @@ export interface InputProps {
95
95
  'selection-start'?: number
96
96
  'selection-end'?: number
97
97
  'placeholder-style'?: { color?: string }
98
- 'enable-offset'?: boolean,
98
+ 'enable-offset'?: boolean
99
99
  'enable-var'?: boolean
100
100
  'external-var-context'?: Record<string, any>
101
101
  'parent-font-size'?: number
102
102
  'parent-width'?: number
103
103
  'parent-height'?: number
104
- 'adjust-position': boolean,
104
+ // 只有 RN 环境读取
105
+ 'keyboard-type'?: string
106
+ 'adjust-position': boolean
107
+ 'hold-keyboard'?: boolean
105
108
  bindinput?: (evt: NativeSyntheticEvent<TextInputTextInputEventData> | unknown) => void
106
109
  bindfocus?: (evt: NativeSyntheticEvent<TextInputFocusEventData> | unknown) => void
107
110
  bindblur?: (evt: NativeSyntheticEvent<TextInputFocusEventData> | unknown) => void
@@ -118,11 +121,11 @@ export interface PrivateInputProps {
118
121
 
119
122
  type FinalInputProps = InputProps & PrivateInputProps
120
123
 
121
- const keyboardTypeMap: Record<Type, string> = {
122
- text: 'default',
124
+ const inputModeMap: Record<Type, string> = {
125
+ text: 'text',
123
126
  number: 'numeric',
124
- idcard: 'default',
125
- digit: isIOS ? 'decimal-pad' : 'numeric'
127
+ idcard: 'text',
128
+ digit: 'decimal'
126
129
  }
127
130
 
128
131
  const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps>((props: FinalInputProps, ref): JSX.Element => {
@@ -150,6 +153,8 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
150
153
  'parent-width': parentWidth,
151
154
  'parent-height': parentHeight,
152
155
  'adjust-position': adjustPosition = true,
156
+ 'keyboard-type': originalKeyboardType,
157
+ 'hold-keyboard': holdKeyboard = false,
153
158
  bindinput,
154
159
  bindfocus,
155
160
  bindblur,
@@ -182,9 +187,11 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
182
187
  return ''
183
188
  }
184
189
 
185
- const keyboardType = keyboardTypeMap[type]
186
190
  const defaultValue = parseValue(value)
191
+ // 微信小程序的 input 永远是单行,textAlignVertical 固定为 auto
192
+ // multiline 为 true 时表示是 textarea 组件复用此逻辑
187
193
  const textAlignVertical = multiline ? 'top' : 'auto'
194
+ const isAutoFocus = !!autoFocus || !!focus
188
195
 
189
196
  const tmpValue = useRef<string>(defaultValue)
190
197
  const cursorIndex = useRef<number>(0)
@@ -193,13 +200,10 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
193
200
  const [inputValue, setInputValue] = useState(defaultValue)
194
201
  const [contentHeight, setContentHeight] = useState(0)
195
202
  const [selection, setSelection] = useState({ start: -1, end: tmpValue.current.length })
196
-
197
203
  const styleObj = extendObject(
198
204
  { padding: 0, backgroundColor: '#fff' },
199
205
  style,
200
- multiline && autoHeight
201
- ? { height: 'auto', minHeight: Math.max((style as any)?.minHeight || 35, contentHeight) }
202
- : {}
206
+ multiline && autoHeight ? { height: 'auto' } : {}
203
207
  )
204
208
 
205
209
  const {
@@ -281,12 +285,13 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
281
285
 
282
286
  const setKeyboardAvoidContext = () => {
283
287
  if (keyboardAvoid) {
284
- keyboardAvoid.current = { cursorSpacing, ref: nodeRef, adjustPosition }
288
+ keyboardAvoid.current = { cursorSpacing, ref: nodeRef, adjustPosition, holdKeyboard, readyToShow: true }
285
289
  }
286
290
  }
287
291
 
288
292
  const onTouchStart = () => {
289
- // sometimes the focus event occurs later than the keyboardWillShow event
293
+ // 手动聚焦时初始化 keyboardAvoid 上下文
294
+ // auto-focus/focus 不会触发而是在 useEffect 中初始化
290
295
  setKeyboardAvoidContext()
291
296
  }
292
297
 
@@ -295,42 +300,49 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
295
300
  }
296
301
 
297
302
  const onFocus = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
298
- setKeyboardAvoidContext()
303
+ if (!keyboardAvoid?.current) {
304
+ // Android:从一个正聚焦状态 input,聚焦到另一个新的 input 时,正常会触发如下时序:
305
+ // 新的 Input `onTouchStart` -> 旧输入框键盘 `keyboardDidHide` -> 新的 Input `onFocus`
306
+ // 导致这里的 keyboardAvoid.current 为 null,所以需要判空重新初始化。
307
+ setKeyboardAvoidContext()
308
+ }
299
309
 
300
- if (bindfocus) {
301
- const focusAction = () => {
302
- bindfocus(
303
- getCustomEvent(
304
- 'focus',
305
- evt,
306
- {
307
- detail: {
308
- value: tmpValue.current || '',
309
- height: keyboardAvoid?.current?.keyboardHeight
310
- },
311
- layoutRef
310
+ const focusAction = () => {
311
+ bindfocus?.(
312
+ getCustomEvent(
313
+ 'focus',
314
+ evt,
315
+ {
316
+ detail: {
317
+ value: tmpValue.current || '',
318
+ height: keyboardAvoid?.current?.keyboardHeight
312
319
  },
313
- props
314
- )
320
+ layoutRef
321
+ },
322
+ props
315
323
  )
316
- if (keyboardAvoid?.current?.onKeyboardShow) {
317
- keyboardAvoid.current.onKeyboardShow = undefined
318
- }
324
+ )
325
+ if (keyboardAvoid?.current?.onKeyboardShow) {
326
+ keyboardAvoid.current.onKeyboardShow = undefined
319
327
  }
320
- if (keyboardAvoid?.current) {
321
- // 有 keyboardAvoiding
322
- if (keyboardAvoid.current.keyboardHeight) {
323
- // iOS: keyboard 获取高度时机 keyboardWillShow 在 input focus 之前,可以立即执行
324
- focusAction()
325
- } else {
326
- // Android,Harmony: keyboard 获取高度时机 keyboardDidShow 在 input focus 之后,需要延迟回调
327
- evt.persist()
328
- keyboardAvoid.current.onKeyboardShow = focusAction
329
- }
330
- } else {
331
- // 无 keyboardAvoiding,直接执行 focus 回调
328
+ }
329
+
330
+ if (keyboardAvoid?.current) {
331
+ // keyboardAvoiding
332
+ if (keyboardAvoid.current.keyboardHeight) {
333
+ // 仅以下场景触发顺序:先 keyboardWillShow 获取高度 -> 后 onFocus,可以立即执行
334
+ // - iOS + 手动点击聚焦
332
335
  focusAction()
336
+ } else {
337
+ // 其他场景触发顺序:先 onFocus -> 后 keyboardWillShow 获取高度 -> 执行回调
338
+ // - iOS + auto-focus/focus=true 自动聚焦
339
+ // - Android 手动点击聚焦/自动聚焦 都一样
340
+ evt.persist()
341
+ keyboardAvoid.current.onKeyboardShow = focusAction
333
342
  }
343
+ } else {
344
+ // 兜底:无 keyboardAvoiding 直接执行 focus 回调
345
+ focusAction()
334
346
  }
335
347
  }
336
348
 
@@ -440,19 +452,28 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
440
452
  }, [])
441
453
 
442
454
  useEffect(() => {
443
- if (focus) {
455
+ if (isAutoFocus) {
456
+ // auto-focus/focus=true 初始化 keyboardAvoidContext
444
457
  setKeyboardAvoidContext()
445
458
  }
446
- }, [focus])
459
+ }, [isAutoFocus])
447
460
 
448
461
  useUpdateEffect(() => {
449
462
  if (!nodeRef?.current) {
450
463
  return
451
464
  }
452
- focus
465
+ // RN autoFocus 属性仅在初次渲染时生效
466
+ // 后续更新需要手动调用 focus/blur 方法,和微信小程序对齐
467
+ isAutoFocus
453
468
  ? (nodeRef.current as TextInput)?.focus()
454
469
  : (nodeRef.current as TextInput)?.blur()
455
- }, [focus])
470
+ }, [isAutoFocus])
471
+
472
+ // 使用 multiline 来修复光标位置问题
473
+ // React Native 的 TextInput 在 textAlign center + placeholder 时光标会跑到右边
474
+ // 这个问题只在 Android 上出现
475
+ // 参考:https://github.com/facebook/react-native/issues/28794 (Android only)
476
+ const needMultilineFix = isAndroid && !multiline
456
477
 
457
478
  const innerProps = useInnerProps(
458
479
  extendObject(
@@ -463,20 +484,21 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
463
484
  ref: nodeRef,
464
485
  style: extendObject({}, normalStyle, layoutStyle),
465
486
  allowFontScaling,
466
- keyboardType: keyboardType,
487
+ inputMode: originalKeyboardType ? undefined : inputModeMap[type],
488
+ keyboardType: originalKeyboardType,
467
489
  secureTextEntry: !!password,
468
490
  defaultValue: defaultValue,
469
491
  value: inputValue,
470
492
  maxLength: maxlength === -1 ? undefined : maxlength,
471
493
  editable: !disabled,
472
- autoFocus: !!autoFocus || !!focus,
494
+ autoFocus: isAutoFocus,
473
495
  selection: selectionStart > -1 || typeof cursor === 'number' ? selection : undefined,
474
496
  selectionColor: cursorColor,
475
- blurOnSubmit: !multiline && !confirmHold,
497
+ blurOnSubmit: multiline ? confirmType !== 'return' : !confirmHold,
476
498
  underlineColorAndroid: 'rgba(0,0,0,0)',
477
499
  textAlignVertical: textAlignVertical,
478
500
  placeholderTextColor: placeholderStyle?.color,
479
- multiline: !!multiline,
501
+ multiline: multiline || needMultilineFix,
480
502
  onTouchStart,
481
503
  onTouchEnd,
482
504
  onFocus,
@@ -484,8 +506,9 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
484
506
  onChange,
485
507
  onSelectionChange,
486
508
  onContentSizeChange,
487
- onSubmitEditing: bindconfirm && !multiline && onSubmitEditing
509
+ onSubmitEditing: bindconfirm && onSubmitEditing
488
510
  },
511
+ needMultilineFix ? { numberOfLines: 1 } : {},
489
512
  !!multiline && confirmType === 'return' ? {} : { enterKeyHint: confirmType }
490
513
  ),
491
514
  [
@@ -23,10 +23,13 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
23
23
  // 比如机型 iPhone 11 Pro,可能会导致显隐动画冲突
24
24
  // 因此增加状态标记 + cancelAnimation 来优化
25
25
  const isShow = useRef<boolean>(false)
26
+ const keybaordHandleTimerRef = useRef<NodeJS.Timeout | null>(null)
26
27
 
27
28
  const animatedStyle = useAnimatedStyle(() => ({
28
- // translate/position top可能会导致底部渲染区域缺失
29
- marginTop: -offset.value,
29
+ // translate/position top+ overflow hidden 在 android 上时因为键盘顶起让页面高度变小,同时元素位置上移
30
+ // 此时最底部的区域是超出了页面高度的,hidden生效就被隐藏掉,因此需要 android 配置聚焦时禁用高度缩小
31
+ // margin-top 因为在 react-native 上和 flex 1 同时存在时,负值只会让容器高度整体变高,不会让元素上移
32
+ transform: [{ translateY: -offset.value }],
30
33
  flexBasis: basic.value as DimensionValue
31
34
  }))
32
35
 
@@ -39,11 +42,20 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
39
42
 
40
43
  if (keyboardAvoid?.current) {
41
44
  const inputRef = keyboardAvoid.current.ref?.current
42
- if (inputRef && inputRef.isFocused()) {
45
+ if (inputRef && inputRef.isFocused() && !keyboardAvoid.current.readyToShow) {
43
46
  // 修复 Android 点击键盘收起按钮时当前 input 没触发失焦的问题
47
+ // keyboardAvoid.current.readyToShow = true 表示聚焦到了新的输入框,不需要手动触发失焦
44
48
  inputRef.blur()
45
49
  }
46
- keyboardAvoid.current = null
50
+ if (!keyboardAvoid.current.onKeyboardShow) {
51
+ // 修复部分 Android 机型可能时序问题:当从 input 已聚焦状态,聚焦到另一个 input 时,可能时序:
52
+ // - 新的 Input `onTouchStart` -> 新的 Input `onFocus` -> 旧输入框键盘 `keyboardDidHide` -> 新输入框键盘 `keyboardDidShow`
53
+ // - 此时 keyboardAvoid.current 如果清空 null,会导致新输入框键盘 `keyboardDidShow` 回调 keybaordAvoding 执行失败。
54
+ // 修复方案:
55
+ // 如果出现时序问题,那么新的 Input `onFocus` 会更早执行,那么 `keyboardAvoid.current.onKeyboardShow` 存在,
56
+ // 那么不应该重置为 null,反之,说明时正常情况,应当重置为 null。
57
+ keyboardAvoid.current = null
58
+ }
47
59
  }
48
60
 
49
61
  cancelAnimation(offset)
@@ -53,6 +65,9 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
53
65
 
54
66
  const onTouchEnd = ({ nativeEvent }: NativeSyntheticEvent<NativeTouchEvent & { origin?: string }>) => {
55
67
  if (nativeEvent.origin !== 'input') {
68
+ if (keyboardAvoid?.current?.holdKeyboard) {
69
+ return
70
+ }
56
71
  Keyboard.isVisible() && Keyboard.dismiss()
57
72
  }
58
73
  }
@@ -61,7 +76,11 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
61
76
  let subscriptions: EmitterSubscription[] = []
62
77
 
63
78
  function keybaordAvoding(evt: any) {
64
- if (!keyboardAvoid?.current || isShow.current) {
79
+ if (keyboardAvoid?.current?.readyToShow) {
80
+ // 重置标记位
81
+ keyboardAvoid.current.readyToShow = false
82
+ }
83
+ if (!keyboardAvoid?.current) {
65
84
  return
66
85
  }
67
86
 
@@ -106,13 +125,23 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
106
125
  }
107
126
 
108
127
  if (isIOS) {
109
- subscriptions = [Keyboard.addListener('keyboardWillShow', keybaordAvoding), Keyboard.addListener('keyboardWillHide', resetKeyboard)]
128
+ subscriptions = [
129
+ Keyboard.addListener('keyboardWillShow', (evt: any) => {
130
+ if (keybaordHandleTimerRef.current) {
131
+ clearTimeout(keybaordHandleTimerRef.current)
132
+ }
133
+ // iphone 在input聚焦时长按滑动后会导致 show 事件先于 focus 事件发生,因此等一下,等 focus 先触发拿到 input,避免键盘出现但input没顶上去
134
+ keybaordHandleTimerRef.current = setTimeout(() => keybaordAvoding(evt), 32)
135
+ }),
136
+ Keyboard.addListener('keyboardWillHide', resetKeyboard)
137
+ ]
110
138
  } else {
111
139
  subscriptions = [Keyboard.addListener('keyboardDidShow', keybaordAvoding), Keyboard.addListener('keyboardDidHide', resetKeyboard)]
112
140
  }
113
141
 
114
142
  return () => {
115
143
  subscriptions.forEach(subscription => subscription.remove())
144
+ keybaordHandleTimerRef.current && clearTimeout(keybaordHandleTimerRef.current)
116
145
  }
117
146
  }, [keyboardAvoid])
118
147
 
@@ -19,7 +19,7 @@ const _PortalManager = forwardRef((props: PortalManagerProps, ref:ForwardedRef<u
19
19
  setState((prevState) => ({
20
20
  portals: [...prevState.portals, { key, children }]
21
21
  }))
22
- }, [state])
22
+ }, [])
23
23
 
24
24
  const update = useCallback((key: number, children: ReactNode) => {
25
25
  setState((prevState) => ({
@@ -30,7 +30,7 @@ const _PortalManager = forwardRef((props: PortalManagerProps, ref:ForwardedRef<u
30
30
  return item
31
31
  })
32
32
  }))
33
- }, [state])
33
+ }, [])
34
34
 
35
35
  const unmount = useCallback((key: number) => {
36
36
  setState((prevState) => ({