@unif/react-native-design 0.20.0 → 0.21.1

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 (562) hide show
  1. package/README.md +121 -12
  2. package/lib/module/components/business/AvatarWithRing/AvatarWithRing.js +4 -5
  3. package/lib/module/components/business/AvatarWithRing/AvatarWithRing.js.map +1 -1
  4. package/lib/module/components/business/AvatarWithRing/styles.js +10 -9
  5. package/lib/module/components/business/AvatarWithRing/styles.js.map +1 -1
  6. package/lib/module/components/business/VersionPill/VersionPill.js +32 -15
  7. package/lib/module/components/business/VersionPill/VersionPill.js.map +1 -1
  8. package/lib/module/components/business/VersionPill/content.js +30 -0
  9. package/lib/module/components/business/VersionPill/content.js.map +1 -0
  10. package/lib/module/components/business/VersionPill/styles.js +4 -0
  11. package/lib/module/components/business/VersionPill/styles.js.map +1 -1
  12. package/lib/module/components/business/useSvgId.js +17 -8
  13. package/lib/module/components/business/useSvgId.js.map +1 -1
  14. package/lib/module/components/ui/Avatar/Avatar.js +22 -29
  15. package/lib/module/components/ui/Avatar/Avatar.js.map +1 -1
  16. package/lib/module/components/ui/Button/Button.js +40 -23
  17. package/lib/module/components/ui/Button/Button.js.map +1 -1
  18. package/lib/module/components/ui/Button/ButtonBase.js +13 -13
  19. package/lib/module/components/ui/Button/ButtonBase.js.map +1 -1
  20. package/lib/module/components/ui/Carousel/Carousel.js +68 -40
  21. package/lib/module/components/ui/Carousel/Carousel.js.map +1 -1
  22. package/lib/module/components/ui/Carousel/behavior.js +60 -0
  23. package/lib/module/components/ui/Carousel/behavior.js.map +1 -0
  24. package/lib/module/components/ui/Carousel/styles.js +6 -8
  25. package/lib/module/components/ui/Carousel/styles.js.map +1 -1
  26. package/lib/module/components/ui/Cell/Cell.js +76 -65
  27. package/lib/module/components/ui/Cell/Cell.js.map +1 -1
  28. package/lib/module/components/ui/Cell/Leading.js +11 -5
  29. package/lib/module/components/ui/Cell/Leading.js.map +1 -1
  30. package/lib/module/components/ui/Cell/content.js +34 -0
  31. package/lib/module/components/ui/Cell/content.js.map +1 -0
  32. package/lib/module/components/ui/Checkbox/Checkbox.js +25 -8
  33. package/lib/module/components/ui/Checkbox/Checkbox.js.map +1 -1
  34. package/lib/module/components/ui/Confirm/ConfirmHost.js +49 -25
  35. package/lib/module/components/ui/Confirm/ConfirmHost.js.map +1 -1
  36. package/lib/module/components/ui/Confirm/confirm.js +15 -29
  37. package/lib/module/components/ui/Confirm/confirm.js.map +1 -1
  38. package/lib/module/components/ui/Confirm/labels.js +10 -0
  39. package/lib/module/components/ui/Confirm/labels.js.map +1 -0
  40. package/lib/module/components/ui/Confirm/store.js +113 -0
  41. package/lib/module/components/ui/Confirm/store.js.map +1 -0
  42. package/lib/module/components/ui/Confirm/styles.js +4 -0
  43. package/lib/module/components/ui/Confirm/styles.js.map +1 -1
  44. package/lib/module/components/ui/DrawerHeader/DrawerHeader.js +17 -25
  45. package/lib/module/components/ui/DrawerHeader/DrawerHeader.js.map +1 -1
  46. package/lib/module/components/ui/Grid/Grid.js +26 -9
  47. package/lib/module/components/ui/Grid/Grid.js.map +1 -1
  48. package/lib/module/components/ui/Grid/accessibility.js +13 -0
  49. package/lib/module/components/ui/Grid/accessibility.js.map +1 -0
  50. package/lib/module/components/ui/IconButton/IconButton.js +16 -3
  51. package/lib/module/components/ui/IconButton/IconButton.js.map +1 -1
  52. package/lib/module/components/ui/Input/Input.js +8 -5
  53. package/lib/module/components/ui/Input/Input.js.map +1 -1
  54. package/lib/module/components/ui/Logo/Logo.js +22 -4
  55. package/lib/module/components/ui/Logo/Logo.js.map +1 -1
  56. package/lib/module/components/ui/NavBar/NavBar.js +23 -14
  57. package/lib/module/components/ui/NavBar/NavBar.js.map +1 -1
  58. package/lib/module/components/ui/NavBar/isSlot.js +297 -4
  59. package/lib/module/components/ui/NavBar/isSlot.js.map +1 -1
  60. package/lib/module/components/ui/PasswordInput/PasswordInput.js +61 -66
  61. package/lib/module/components/ui/PasswordInput/PasswordInput.js.map +1 -1
  62. package/lib/module/components/ui/Pulse/Pulse.js +1 -1
  63. package/lib/module/components/ui/Pulse/Pulse.js.map +1 -1
  64. package/lib/module/components/ui/Pulse/PulseDot.js +5 -7
  65. package/lib/module/components/ui/Pulse/PulseDot.js.map +1 -1
  66. package/lib/module/components/ui/Pulse/index.js +1 -1
  67. package/lib/module/components/ui/Pulse/index.js.map +1 -1
  68. package/lib/module/components/ui/Pulse/normalizePulseOptions.js +45 -0
  69. package/lib/module/components/ui/Pulse/normalizePulseOptions.js.map +1 -0
  70. package/lib/module/components/ui/Pulse/usePulse.js +61 -24
  71. package/lib/module/components/ui/Pulse/usePulse.js.map +1 -1
  72. package/lib/module/components/ui/Pulse/usePulseDriver.js +44 -0
  73. package/lib/module/components/ui/Pulse/usePulseDriver.js.map +1 -0
  74. package/lib/module/components/ui/Pulse/usePulseDriver.web.js +67 -0
  75. package/lib/module/components/ui/Pulse/usePulseDriver.web.js.map +1 -0
  76. package/lib/module/components/ui/Radio/Radio.js +31 -14
  77. package/lib/module/components/ui/Radio/Radio.js.map +1 -1
  78. package/lib/module/components/ui/Radio/RadioGroup.js +15 -2
  79. package/lib/module/components/ui/Radio/RadioGroup.js.map +1 -1
  80. package/lib/module/components/ui/Reveal/Reveal.js +4 -3
  81. package/lib/module/components/ui/Reveal/Reveal.js.map +1 -1
  82. package/lib/module/components/ui/Reveal/Reveal.web.js +55 -32
  83. package/lib/module/components/ui/Reveal/Reveal.web.js.map +1 -1
  84. package/lib/module/components/ui/Reveal/webTransition.js +157 -0
  85. package/lib/module/components/ui/Reveal/webTransition.js.map +1 -0
  86. package/lib/module/components/ui/Search/Search.js +85 -58
  87. package/lib/module/components/ui/Search/Search.js.map +1 -1
  88. package/lib/module/components/ui/Segmented/Segmented.js +4 -2
  89. package/lib/module/components/ui/Segmented/Segmented.js.map +1 -1
  90. package/lib/module/components/ui/Skeleton/Skeleton.js +5 -7
  91. package/lib/module/components/ui/Skeleton/Skeleton.js.map +1 -1
  92. package/lib/module/components/ui/Spinner/Spinner.js +18 -11
  93. package/lib/module/components/ui/Spinner/Spinner.js.map +1 -1
  94. package/lib/module/components/ui/Spinner/Spinner.web.js +18 -14
  95. package/lib/module/components/ui/Spinner/Spinner.web.js.map +1 -1
  96. package/lib/module/components/ui/Spinner/shared.js +6 -0
  97. package/lib/module/components/ui/Spinner/shared.js.map +1 -1
  98. package/lib/module/components/ui/Stepper/Stepper.js +131 -99
  99. package/lib/module/components/ui/Stepper/Stepper.js.map +1 -1
  100. package/lib/module/components/ui/Stepper/StepperPressable.js +4 -0
  101. package/lib/module/components/ui/Stepper/StepperPressable.js.map +1 -0
  102. package/lib/module/components/ui/Stepper/StepperPressable.web.js +4 -0
  103. package/lib/module/components/ui/Stepper/StepperPressable.web.js.map +1 -0
  104. package/lib/module/components/ui/Stepper/accessibility.js +30 -0
  105. package/lib/module/components/ui/Stepper/accessibility.js.map +1 -0
  106. package/lib/module/components/ui/Stepper/accessibility.types.js +4 -0
  107. package/lib/module/components/ui/Stepper/accessibility.types.js.map +1 -0
  108. package/lib/module/components/ui/Stepper/accessibility.web.js +57 -0
  109. package/lib/module/components/ui/Stepper/accessibility.web.js.map +1 -0
  110. package/lib/module/components/ui/Stepper/layout.js +28 -0
  111. package/lib/module/components/ui/Stepper/layout.js.map +1 -0
  112. package/lib/module/components/ui/Stepper/normalizeStepper.js +53 -0
  113. package/lib/module/components/ui/Stepper/normalizeStepper.js.map +1 -0
  114. package/lib/module/components/ui/Stepper/styles.js +9 -2
  115. package/lib/module/components/ui/Stepper/styles.js.map +1 -1
  116. package/lib/module/components/ui/Switch/Switch.js +45 -19
  117. package/lib/module/components/ui/Switch/Switch.js.map +1 -1
  118. package/lib/module/components/ui/Switch/Switch.web.js +47 -20
  119. package/lib/module/components/ui/Switch/Switch.web.js.map +1 -1
  120. package/lib/module/components/ui/Switch/styles.js +12 -5
  121. package/lib/module/components/ui/Switch/styles.js.map +1 -1
  122. package/lib/module/components/ui/Tag/Tag.js +3 -2
  123. package/lib/module/components/ui/Tag/Tag.js.map +1 -1
  124. package/lib/module/components/ui/TextField/TextFieldBase.js +131 -86
  125. package/lib/module/components/ui/TextField/TextFieldBase.js.map +1 -1
  126. package/lib/module/components/ui/TextField/TextFieldSlot.js +82 -0
  127. package/lib/module/components/ui/TextField/TextFieldSlot.js.map +1 -0
  128. package/lib/module/components/ui/TextField/normalize.js +238 -0
  129. package/lib/module/components/ui/TextField/normalize.js.map +1 -0
  130. package/lib/module/components/ui/TextField/styles.js +31 -0
  131. package/lib/module/components/ui/TextField/styles.js.map +1 -1
  132. package/lib/module/components/ui/TextField/useErrorAnnouncement.js +27 -0
  133. package/lib/module/components/ui/TextField/useErrorAnnouncement.js.map +1 -0
  134. package/lib/module/components/ui/TextField/useTextFieldValue.js +66 -0
  135. package/lib/module/components/ui/TextField/useTextFieldValue.js.map +1 -0
  136. package/lib/module/components/ui/TextField/valueState.js +93 -0
  137. package/lib/module/components/ui/TextField/valueState.js.map +1 -0
  138. package/lib/module/components/ui/Textarea/Textarea.js +7 -3
  139. package/lib/module/components/ui/Textarea/Textarea.js.map +1 -1
  140. package/lib/module/components/ui/Thumbnail/Thumbnail.js +67 -48
  141. package/lib/module/components/ui/Thumbnail/Thumbnail.js.map +1 -1
  142. package/lib/module/components/ui/Thumbnail/normalize.js +58 -0
  143. package/lib/module/components/ui/Thumbnail/normalize.js.map +1 -0
  144. package/lib/module/components/ui/Thumbnail/styles.js +6 -11
  145. package/lib/module/components/ui/Thumbnail/styles.js.map +1 -1
  146. package/lib/module/components/ui/Toast/ToastHost.js +64 -21
  147. package/lib/module/components/ui/Toast/ToastHost.js.map +1 -1
  148. package/lib/module/components/ui/Toast/ToastHost.web.js +73 -24
  149. package/lib/module/components/ui/Toast/ToastHost.web.js.map +1 -1
  150. package/lib/module/components/ui/Toast/store.js +110 -0
  151. package/lib/module/components/ui/Toast/store.js.map +1 -0
  152. package/lib/module/components/ui/Toast/toast.js +17 -7
  153. package/lib/module/components/ui/Toast/toast.js.map +1 -1
  154. package/lib/module/components/ui/index.js.map +1 -1
  155. package/lib/module/components/ui/shared/ImageAttempt.js +28 -0
  156. package/lib/module/components/ui/shared/ImageAttempt.js.map +1 -0
  157. package/lib/module/components/ui/shared/a11y.js +21 -0
  158. package/lib/module/components/ui/shared/a11y.js.map +1 -0
  159. package/lib/module/components/ui/shared/accessibilityName.js +9 -0
  160. package/lib/module/components/ui/shared/accessibilityName.js.map +1 -0
  161. package/lib/module/components/ui/shared/selectImageAttemptSource.js +5 -0
  162. package/lib/module/components/ui/shared/selectImageAttemptSource.js.map +1 -0
  163. package/lib/module/components/ui/shared/selectImageAttemptSource.shared.js +13 -0
  164. package/lib/module/components/ui/shared/selectImageAttemptSource.shared.js.map +1 -0
  165. package/lib/module/components/ui/shared/selectImageAttemptSource.web.js +5 -0
  166. package/lib/module/components/ui/shared/selectImageAttemptSource.web.js.map +1 -0
  167. package/lib/module/icons/data.js +1 -1
  168. package/lib/module/icons/data.js.map +1 -1
  169. package/lib/module/theme/ThemeProvider.js +14 -4
  170. package/lib/module/theme/ThemeProvider.js.map +1 -1
  171. package/lib/module/theme/fontScale.js +13 -0
  172. package/lib/module/theme/fontScale.js.map +1 -0
  173. package/lib/module/theme/index.js +2 -4
  174. package/lib/module/theme/index.js.map +1 -1
  175. package/lib/module/theme/themeContext.js +15 -0
  176. package/lib/module/theme/themeContext.js.map +1 -0
  177. package/lib/module/theme/themeDiagnostics.js +29 -0
  178. package/lib/module/theme/themeDiagnostics.js.map +1 -0
  179. package/lib/module/theme/usePrefersReducedMotion.js +11 -4
  180. package/lib/module/theme/usePrefersReducedMotion.js.map +1 -1
  181. package/lib/module/theme/usePrefersReducedMotion.web.js +5 -2
  182. package/lib/module/theme/usePrefersReducedMotion.web.js.map +1 -1
  183. package/lib/module/theme/useTheme.js +12 -25
  184. package/lib/module/theme/useTheme.js.map +1 -1
  185. package/lib/module/theme/useThemedStyles.js +9 -6
  186. package/lib/module/theme/useThemedStyles.js.map +1 -1
  187. package/lib/module/utils/imageSource.js +198 -0
  188. package/lib/module/utils/imageSource.js.map +1 -0
  189. package/lib/typescript/manual-tests/runtime-api/RuntimeApiScreen.d.ts +12 -0
  190. package/lib/typescript/manual-tests/runtime-api/RuntimeApiScreen.d.ts.map +1 -0
  191. package/lib/typescript/src/components/business/AvatarWithRing/AvatarWithRing.d.ts.map +1 -1
  192. package/lib/typescript/src/components/business/AvatarWithRing/styles.d.ts +8 -7
  193. package/lib/typescript/src/components/business/AvatarWithRing/styles.d.ts.map +1 -1
  194. package/lib/typescript/src/components/business/VersionPill/VersionPill.d.ts +1 -1
  195. package/lib/typescript/src/components/business/VersionPill/VersionPill.d.ts.map +1 -1
  196. package/lib/typescript/src/components/business/VersionPill/content.d.ts +19 -0
  197. package/lib/typescript/src/components/business/VersionPill/content.d.ts.map +1 -0
  198. package/lib/typescript/src/components/business/VersionPill/index.d.ts +1 -1
  199. package/lib/typescript/src/components/business/VersionPill/index.d.ts.map +1 -1
  200. package/lib/typescript/src/components/business/VersionPill/styles.d.ts +4 -0
  201. package/lib/typescript/src/components/business/VersionPill/styles.d.ts.map +1 -1
  202. package/lib/typescript/src/components/business/VersionPill/types.d.ts +6 -2
  203. package/lib/typescript/src/components/business/VersionPill/types.d.ts.map +1 -1
  204. package/lib/typescript/src/components/business/index.d.ts +1 -1
  205. package/lib/typescript/src/components/business/index.d.ts.map +1 -1
  206. package/lib/typescript/src/components/business/useSvgId.d.ts +6 -5
  207. package/lib/typescript/src/components/business/useSvgId.d.ts.map +1 -1
  208. package/lib/typescript/src/components/ui/Avatar/Avatar.d.ts +2 -2
  209. package/lib/typescript/src/components/ui/Avatar/Avatar.d.ts.map +1 -1
  210. package/lib/typescript/src/components/ui/Avatar/types.d.ts +6 -2
  211. package/lib/typescript/src/components/ui/Avatar/types.d.ts.map +1 -1
  212. package/lib/typescript/src/components/ui/Button/Button.d.ts +1 -1
  213. package/lib/typescript/src/components/ui/Button/Button.d.ts.map +1 -1
  214. package/lib/typescript/src/components/ui/Button/ButtonBase.d.ts +5 -3
  215. package/lib/typescript/src/components/ui/Button/ButtonBase.d.ts.map +1 -1
  216. package/lib/typescript/src/components/ui/Button/types.d.ts +5 -3
  217. package/lib/typescript/src/components/ui/Button/types.d.ts.map +1 -1
  218. package/lib/typescript/src/components/ui/Carousel/Carousel.d.ts.map +1 -1
  219. package/lib/typescript/src/components/ui/Carousel/behavior.d.ts +25 -0
  220. package/lib/typescript/src/components/ui/Carousel/behavior.d.ts.map +1 -0
  221. package/lib/typescript/src/components/ui/Carousel/styles.d.ts +4 -6
  222. package/lib/typescript/src/components/ui/Carousel/styles.d.ts.map +1 -1
  223. package/lib/typescript/src/components/ui/Carousel/types.d.ts +14 -6
  224. package/lib/typescript/src/components/ui/Carousel/types.d.ts.map +1 -1
  225. package/lib/typescript/src/components/ui/Cell/Cell.d.ts +1 -1
  226. package/lib/typescript/src/components/ui/Cell/Cell.d.ts.map +1 -1
  227. package/lib/typescript/src/components/ui/Cell/Leading.d.ts +2 -3
  228. package/lib/typescript/src/components/ui/Cell/Leading.d.ts.map +1 -1
  229. package/lib/typescript/src/components/ui/Cell/content.d.ts +18 -0
  230. package/lib/typescript/src/components/ui/Cell/content.d.ts.map +1 -0
  231. package/lib/typescript/src/components/ui/Cell/index.d.ts +1 -1
  232. package/lib/typescript/src/components/ui/Cell/index.d.ts.map +1 -1
  233. package/lib/typescript/src/components/ui/Cell/types.d.ts +66 -30
  234. package/lib/typescript/src/components/ui/Cell/types.d.ts.map +1 -1
  235. package/lib/typescript/src/components/ui/Checkbox/Checkbox.d.ts +1 -1
  236. package/lib/typescript/src/components/ui/Checkbox/Checkbox.d.ts.map +1 -1
  237. package/lib/typescript/src/components/ui/Checkbox/types.d.ts +12 -3
  238. package/lib/typescript/src/components/ui/Checkbox/types.d.ts.map +1 -1
  239. package/lib/typescript/src/components/ui/Confirm/ConfirmHost.d.ts +6 -3
  240. package/lib/typescript/src/components/ui/Confirm/ConfirmHost.d.ts.map +1 -1
  241. package/lib/typescript/src/components/ui/Confirm/confirm.d.ts +10 -4
  242. package/lib/typescript/src/components/ui/Confirm/confirm.d.ts.map +1 -1
  243. package/lib/typescript/src/components/ui/Confirm/labels.d.ts +6 -0
  244. package/lib/typescript/src/components/ui/Confirm/labels.d.ts.map +1 -0
  245. package/lib/typescript/src/components/ui/Confirm/store.d.ts +44 -0
  246. package/lib/typescript/src/components/ui/Confirm/store.d.ts.map +1 -0
  247. package/lib/typescript/src/components/ui/Confirm/styles.d.ts +3 -0
  248. package/lib/typescript/src/components/ui/Confirm/styles.d.ts.map +1 -1
  249. package/lib/typescript/src/components/ui/Confirm/types.d.ts +0 -9
  250. package/lib/typescript/src/components/ui/Confirm/types.d.ts.map +1 -1
  251. package/lib/typescript/src/components/ui/DrawerHeader/DrawerHeader.d.ts.map +1 -1
  252. package/lib/typescript/src/components/ui/DrawerHeader/types.d.ts +7 -1
  253. package/lib/typescript/src/components/ui/DrawerHeader/types.d.ts.map +1 -1
  254. package/lib/typescript/src/components/ui/Grid/Grid.d.ts.map +1 -1
  255. package/lib/typescript/src/components/ui/Grid/accessibility.d.ts +5 -0
  256. package/lib/typescript/src/components/ui/Grid/accessibility.d.ts.map +1 -0
  257. package/lib/typescript/src/components/ui/Grid/types.d.ts +2 -0
  258. package/lib/typescript/src/components/ui/Grid/types.d.ts.map +1 -1
  259. package/lib/typescript/src/components/ui/IconButton/IconButton.d.ts +1 -1
  260. package/lib/typescript/src/components/ui/IconButton/IconButton.d.ts.map +1 -1
  261. package/lib/typescript/src/components/ui/IconButton/types.d.ts +4 -2
  262. package/lib/typescript/src/components/ui/IconButton/types.d.ts.map +1 -1
  263. package/lib/typescript/src/components/ui/Input/Input.d.ts +5 -383
  264. package/lib/typescript/src/components/ui/Input/Input.d.ts.map +1 -1
  265. package/lib/typescript/src/components/ui/Input/index.d.ts +1 -0
  266. package/lib/typescript/src/components/ui/Input/index.d.ts.map +1 -1
  267. package/lib/typescript/src/components/ui/Input/types.d.ts +3 -17
  268. package/lib/typescript/src/components/ui/Input/types.d.ts.map +1 -1
  269. package/lib/typescript/src/components/ui/Logo/Logo.d.ts +2 -2
  270. package/lib/typescript/src/components/ui/Logo/Logo.d.ts.map +1 -1
  271. package/lib/typescript/src/components/ui/Logo/types.d.ts +2 -2
  272. package/lib/typescript/src/components/ui/Logo/types.d.ts.map +1 -1
  273. package/lib/typescript/src/components/ui/NavBar/NavBar.d.ts.map +1 -1
  274. package/lib/typescript/src/components/ui/NavBar/index.d.ts +1 -1
  275. package/lib/typescript/src/components/ui/NavBar/index.d.ts.map +1 -1
  276. package/lib/typescript/src/components/ui/NavBar/isSlot.d.ts +24 -4
  277. package/lib/typescript/src/components/ui/NavBar/isSlot.d.ts.map +1 -1
  278. package/lib/typescript/src/components/ui/NavBar/types.d.ts +8 -8
  279. package/lib/typescript/src/components/ui/NavBar/types.d.ts.map +1 -1
  280. package/lib/typescript/src/components/ui/PasswordInput/PasswordInput.d.ts +6 -14
  281. package/lib/typescript/src/components/ui/PasswordInput/PasswordInput.d.ts.map +1 -1
  282. package/lib/typescript/src/components/ui/PasswordInput/types.d.ts +4 -14
  283. package/lib/typescript/src/components/ui/PasswordInput/types.d.ts.map +1 -1
  284. package/lib/typescript/src/components/ui/Pulse/PulseDot.d.ts +1 -1
  285. package/lib/typescript/src/components/ui/Pulse/PulseDot.d.ts.map +1 -1
  286. package/lib/typescript/src/components/ui/Pulse/normalizePulseOptions.d.ts +32 -0
  287. package/lib/typescript/src/components/ui/Pulse/normalizePulseOptions.d.ts.map +1 -0
  288. package/lib/typescript/src/components/ui/Pulse/usePulse.d.ts +10 -5
  289. package/lib/typescript/src/components/ui/Pulse/usePulse.d.ts.map +1 -1
  290. package/lib/typescript/src/components/ui/Pulse/usePulseDriver.d.ts +11 -0
  291. package/lib/typescript/src/components/ui/Pulse/usePulseDriver.d.ts.map +1 -0
  292. package/lib/typescript/src/components/ui/Pulse/usePulseDriver.web.d.ts +18 -0
  293. package/lib/typescript/src/components/ui/Pulse/usePulseDriver.web.d.ts.map +1 -0
  294. package/lib/typescript/src/components/ui/Radio/Radio.d.ts +1 -1
  295. package/lib/typescript/src/components/ui/Radio/Radio.d.ts.map +1 -1
  296. package/lib/typescript/src/components/ui/Radio/RadioGroup.d.ts +2 -2
  297. package/lib/typescript/src/components/ui/Radio/RadioGroup.d.ts.map +1 -1
  298. package/lib/typescript/src/components/ui/Radio/types.d.ts +14 -3
  299. package/lib/typescript/src/components/ui/Radio/types.d.ts.map +1 -1
  300. package/lib/typescript/src/components/ui/Reveal/Reveal.d.ts.map +1 -1
  301. package/lib/typescript/src/components/ui/Reveal/Reveal.web.d.ts +2 -8
  302. package/lib/typescript/src/components/ui/Reveal/Reveal.web.d.ts.map +1 -1
  303. package/lib/typescript/src/components/ui/Reveal/types.d.ts +1 -1
  304. package/lib/typescript/src/components/ui/Reveal/types.d.ts.map +1 -1
  305. package/lib/typescript/src/components/ui/Reveal/webTransition.d.ts +38 -0
  306. package/lib/typescript/src/components/ui/Reveal/webTransition.d.ts.map +1 -0
  307. package/lib/typescript/src/components/ui/Search/Search.d.ts +4 -214
  308. package/lib/typescript/src/components/ui/Search/Search.d.ts.map +1 -1
  309. package/lib/typescript/src/components/ui/Search/types.d.ts +13 -6
  310. package/lib/typescript/src/components/ui/Search/types.d.ts.map +1 -1
  311. package/lib/typescript/src/components/ui/Segmented/Segmented.d.ts.map +1 -1
  312. package/lib/typescript/src/components/ui/Skeleton/Skeleton.d.ts +3 -3
  313. package/lib/typescript/src/components/ui/Skeleton/Skeleton.d.ts.map +1 -1
  314. package/lib/typescript/src/components/ui/Spinner/Spinner.d.ts +1 -1
  315. package/lib/typescript/src/components/ui/Spinner/Spinner.d.ts.map +1 -1
  316. package/lib/typescript/src/components/ui/Spinner/Spinner.web.d.ts +1 -1
  317. package/lib/typescript/src/components/ui/Spinner/Spinner.web.d.ts.map +1 -1
  318. package/lib/typescript/src/components/ui/Spinner/shared.d.ts +5 -0
  319. package/lib/typescript/src/components/ui/Spinner/shared.d.ts.map +1 -1
  320. package/lib/typescript/src/components/ui/Spinner/types.d.ts +1 -1
  321. package/lib/typescript/src/components/ui/Spinner/types.d.ts.map +1 -1
  322. package/lib/typescript/src/components/ui/Stepper/Stepper.d.ts +3 -3
  323. package/lib/typescript/src/components/ui/Stepper/Stepper.d.ts.map +1 -1
  324. package/lib/typescript/src/components/ui/Stepper/StepperPressable.d.ts +2 -0
  325. package/lib/typescript/src/components/ui/Stepper/StepperPressable.d.ts.map +1 -0
  326. package/lib/typescript/src/components/ui/Stepper/StepperPressable.web.d.ts +2 -0
  327. package/lib/typescript/src/components/ui/Stepper/StepperPressable.web.d.ts.map +1 -0
  328. package/lib/typescript/src/components/ui/Stepper/accessibility.d.ts +3 -0
  329. package/lib/typescript/src/components/ui/Stepper/accessibility.d.ts.map +1 -0
  330. package/lib/typescript/src/components/ui/Stepper/accessibility.types.d.ts +23 -0
  331. package/lib/typescript/src/components/ui/Stepper/accessibility.types.d.ts.map +1 -0
  332. package/lib/typescript/src/components/ui/Stepper/accessibility.web.d.ts +9 -0
  333. package/lib/typescript/src/components/ui/Stepper/accessibility.web.d.ts.map +1 -0
  334. package/lib/typescript/src/components/ui/Stepper/layout.d.ts +22 -0
  335. package/lib/typescript/src/components/ui/Stepper/layout.d.ts.map +1 -0
  336. package/lib/typescript/src/components/ui/Stepper/normalizeStepper.d.ts +31 -0
  337. package/lib/typescript/src/components/ui/Stepper/normalizeStepper.d.ts.map +1 -0
  338. package/lib/typescript/src/components/ui/Stepper/styles.d.ts +9 -2
  339. package/lib/typescript/src/components/ui/Stepper/styles.d.ts.map +1 -1
  340. package/lib/typescript/src/components/ui/Stepper/types.d.ts +3 -1
  341. package/lib/typescript/src/components/ui/Stepper/types.d.ts.map +1 -1
  342. package/lib/typescript/src/components/ui/Switch/Switch.d.ts.map +1 -1
  343. package/lib/typescript/src/components/ui/Switch/Switch.web.d.ts.map +1 -1
  344. package/lib/typescript/src/components/ui/Switch/styles.d.ts +9 -3
  345. package/lib/typescript/src/components/ui/Switch/styles.d.ts.map +1 -1
  346. package/lib/typescript/src/components/ui/Switch/types.d.ts +2 -2
  347. package/lib/typescript/src/components/ui/Switch/types.d.ts.map +1 -1
  348. package/lib/typescript/src/components/ui/Tag/Tag.d.ts.map +1 -1
  349. package/lib/typescript/src/components/ui/TextField/TextFieldBase.d.ts +4 -401
  350. package/lib/typescript/src/components/ui/TextField/TextFieldBase.d.ts.map +1 -1
  351. package/lib/typescript/src/components/ui/TextField/TextFieldSlot.d.ts +13 -0
  352. package/lib/typescript/src/components/ui/TextField/TextFieldSlot.d.ts.map +1 -0
  353. package/lib/typescript/src/components/ui/TextField/normalize.d.ts +51 -0
  354. package/lib/typescript/src/components/ui/TextField/normalize.d.ts.map +1 -0
  355. package/lib/typescript/src/components/ui/TextField/styles.d.ts +30 -0
  356. package/lib/typescript/src/components/ui/TextField/styles.d.ts.map +1 -1
  357. package/lib/typescript/src/components/ui/TextField/types.d.ts +92 -18
  358. package/lib/typescript/src/components/ui/TextField/types.d.ts.map +1 -1
  359. package/lib/typescript/src/components/ui/TextField/useErrorAnnouncement.d.ts +3 -0
  360. package/lib/typescript/src/components/ui/TextField/useErrorAnnouncement.d.ts.map +1 -0
  361. package/lib/typescript/src/components/ui/TextField/useTextFieldValue.d.ts +18 -0
  362. package/lib/typescript/src/components/ui/TextField/useTextFieldValue.d.ts.map +1 -0
  363. package/lib/typescript/src/components/ui/TextField/valueState.d.ts +50 -0
  364. package/lib/typescript/src/components/ui/TextField/valueState.d.ts.map +1 -0
  365. package/lib/typescript/src/components/ui/Textarea/Textarea.d.ts +4 -382
  366. package/lib/typescript/src/components/ui/Textarea/Textarea.d.ts.map +1 -1
  367. package/lib/typescript/src/components/ui/Textarea/index.d.ts +1 -0
  368. package/lib/typescript/src/components/ui/Textarea/index.d.ts.map +1 -1
  369. package/lib/typescript/src/components/ui/Textarea/types.d.ts +3 -14
  370. package/lib/typescript/src/components/ui/Textarea/types.d.ts.map +1 -1
  371. package/lib/typescript/src/components/ui/Thumbnail/Thumbnail.d.ts +5 -12
  372. package/lib/typescript/src/components/ui/Thumbnail/Thumbnail.d.ts.map +1 -1
  373. package/lib/typescript/src/components/ui/Thumbnail/index.d.ts +1 -1
  374. package/lib/typescript/src/components/ui/Thumbnail/index.d.ts.map +1 -1
  375. package/lib/typescript/src/components/ui/Thumbnail/normalize.d.ts +13 -0
  376. package/lib/typescript/src/components/ui/Thumbnail/normalize.d.ts.map +1 -0
  377. package/lib/typescript/src/components/ui/Thumbnail/styles.d.ts +4 -8
  378. package/lib/typescript/src/components/ui/Thumbnail/styles.d.ts.map +1 -1
  379. package/lib/typescript/src/components/ui/Thumbnail/types.d.ts +21 -13
  380. package/lib/typescript/src/components/ui/Thumbnail/types.d.ts.map +1 -1
  381. package/lib/typescript/src/components/ui/Toast/ToastHost.d.ts +6 -2
  382. package/lib/typescript/src/components/ui/Toast/ToastHost.d.ts.map +1 -1
  383. package/lib/typescript/src/components/ui/Toast/ToastHost.web.d.ts +6 -3
  384. package/lib/typescript/src/components/ui/Toast/ToastHost.web.d.ts.map +1 -1
  385. package/lib/typescript/src/components/ui/Toast/store.d.ts +39 -0
  386. package/lib/typescript/src/components/ui/Toast/store.d.ts.map +1 -0
  387. package/lib/typescript/src/components/ui/Toast/toast.d.ts +7 -2
  388. package/lib/typescript/src/components/ui/Toast/toast.d.ts.map +1 -1
  389. package/lib/typescript/src/components/ui/Toast/types.d.ts +5 -3
  390. package/lib/typescript/src/components/ui/Toast/types.d.ts.map +1 -1
  391. package/lib/typescript/src/components/ui/index.d.ts +4 -4
  392. package/lib/typescript/src/components/ui/index.d.ts.map +1 -1
  393. package/lib/typescript/src/components/ui/shared/ImageAttempt.d.ts +13 -0
  394. package/lib/typescript/src/components/ui/shared/ImageAttempt.d.ts.map +1 -0
  395. package/lib/typescript/src/components/ui/shared/a11y.d.ts +19 -0
  396. package/lib/typescript/src/components/ui/shared/a11y.d.ts.map +1 -0
  397. package/lib/typescript/src/components/ui/shared/accessibilityName.d.ts +3 -0
  398. package/lib/typescript/src/components/ui/shared/accessibilityName.d.ts.map +1 -0
  399. package/lib/typescript/src/components/ui/shared/selectImageAttemptSource.d.ts +3 -0
  400. package/lib/typescript/src/components/ui/shared/selectImageAttemptSource.d.ts.map +1 -0
  401. package/lib/typescript/src/components/ui/shared/selectImageAttemptSource.shared.d.ts +4 -0
  402. package/lib/typescript/src/components/ui/shared/selectImageAttemptSource.shared.d.ts.map +1 -0
  403. package/lib/typescript/src/components/ui/shared/selectImageAttemptSource.web.d.ts +3 -0
  404. package/lib/typescript/src/components/ui/shared/selectImageAttemptSource.web.d.ts.map +1 -0
  405. package/lib/typescript/src/theme/ThemeProvider.d.ts +2 -3
  406. package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -1
  407. package/lib/typescript/src/theme/fontScale.d.ts +4 -0
  408. package/lib/typescript/src/theme/fontScale.d.ts.map +1 -0
  409. package/lib/typescript/src/theme/index.d.ts +2 -1
  410. package/lib/typescript/src/theme/index.d.ts.map +1 -1
  411. package/lib/typescript/src/theme/themeContext.d.ts +6 -0
  412. package/lib/typescript/src/theme/themeContext.d.ts.map +1 -0
  413. package/lib/typescript/src/theme/themeDiagnostics.d.ts +6 -0
  414. package/lib/typescript/src/theme/themeDiagnostics.d.ts.map +1 -0
  415. package/lib/typescript/src/theme/usePrefersReducedMotion.d.ts +8 -3
  416. package/lib/typescript/src/theme/usePrefersReducedMotion.d.ts.map +1 -1
  417. package/lib/typescript/src/theme/usePrefersReducedMotion.web.d.ts +5 -2
  418. package/lib/typescript/src/theme/usePrefersReducedMotion.web.d.ts.map +1 -1
  419. package/lib/typescript/src/theme/useTheme.d.ts +1 -1
  420. package/lib/typescript/src/theme/useTheme.d.ts.map +1 -1
  421. package/lib/typescript/src/theme/useThemedStyles.d.ts +1 -1
  422. package/lib/typescript/src/theme/useThemedStyles.d.ts.map +1 -1
  423. package/lib/typescript/src/utils/imageSource.d.ts +20 -0
  424. package/lib/typescript/src/utils/imageSource.d.ts.map +1 -0
  425. package/lib/typescript/type-tests/public-api.d.ts +2 -0
  426. package/lib/typescript/type-tests/public-api.d.ts.map +1 -0
  427. package/lib/typescript/website/src/components/iconCatalogCategories.d.ts +11 -0
  428. package/lib/typescript/website/src/components/iconCatalogCategories.d.ts.map +1 -0
  429. package/package.json +30 -14
  430. package/src/components/business/AvatarWithRing/AvatarWithRing.tsx +11 -4
  431. package/src/components/business/AvatarWithRing/styles.ts +11 -9
  432. package/src/components/business/VersionPill/VersionPill.tsx +31 -25
  433. package/src/components/business/VersionPill/content.ts +47 -0
  434. package/src/components/business/VersionPill/index.ts +1 -1
  435. package/src/components/business/VersionPill/styles.ts +4 -0
  436. package/src/components/business/VersionPill/types.ts +7 -2
  437. package/src/components/business/index.ts +1 -1
  438. package/src/components/business/useSvgId.ts +29 -8
  439. package/src/components/ui/Avatar/Avatar.tsx +25 -34
  440. package/src/components/ui/Avatar/types.ts +6 -2
  441. package/src/components/ui/Button/Button.tsx +39 -20
  442. package/src/components/ui/Button/ButtonBase.tsx +21 -12
  443. package/src/components/ui/Button/types.ts +5 -3
  444. package/src/components/ui/Carousel/Carousel.tsx +102 -40
  445. package/src/components/ui/Carousel/behavior.ts +78 -0
  446. package/src/components/ui/Carousel/styles.ts +5 -7
  447. package/src/components/ui/Carousel/types.ts +18 -6
  448. package/src/components/ui/Cell/Cell.tsx +85 -74
  449. package/src/components/ui/Cell/Leading.tsx +14 -14
  450. package/src/components/ui/Cell/content.ts +53 -0
  451. package/src/components/ui/Cell/index.ts +7 -1
  452. package/src/components/ui/Cell/types.ts +64 -30
  453. package/src/components/ui/Checkbox/Checkbox.tsx +35 -8
  454. package/src/components/ui/Checkbox/types.ts +15 -3
  455. package/src/components/ui/Confirm/ConfirmHost.tsx +51 -26
  456. package/src/components/ui/Confirm/confirm.ts +17 -34
  457. package/src/components/ui/Confirm/labels.ts +14 -0
  458. package/src/components/ui/Confirm/store.ts +147 -0
  459. package/src/components/ui/Confirm/styles.ts +4 -0
  460. package/src/components/ui/Confirm/types.ts +2 -10
  461. package/src/components/ui/DrawerHeader/DrawerHeader.tsx +22 -27
  462. package/src/components/ui/DrawerHeader/types.ts +7 -1
  463. package/src/components/ui/Grid/Grid.tsx +44 -12
  464. package/src/components/ui/Grid/accessibility.ts +21 -0
  465. package/src/components/ui/Grid/types.ts +2 -0
  466. package/src/components/ui/IconButton/IconButton.tsx +20 -3
  467. package/src/components/ui/IconButton/types.ts +4 -2
  468. package/src/components/ui/Input/Input.tsx +16 -6
  469. package/src/components/ui/Input/index.ts +5 -0
  470. package/src/components/ui/Input/types.ts +12 -23
  471. package/src/components/ui/Logo/Logo.tsx +27 -4
  472. package/src/components/ui/Logo/types.ts +2 -2
  473. package/src/components/ui/NavBar/NavBar.tsx +27 -19
  474. package/src/components/ui/NavBar/index.ts +1 -1
  475. package/src/components/ui/NavBar/isSlot.ts +372 -5
  476. package/src/components/ui/NavBar/types.ts +9 -8
  477. package/src/components/ui/PasswordInput/PasswordInput.tsx +67 -69
  478. package/src/components/ui/PasswordInput/types.ts +12 -14
  479. package/src/components/ui/Pulse/PulseDot.tsx +5 -4
  480. package/src/components/ui/Pulse/normalizePulseOptions.ts +76 -0
  481. package/src/components/ui/Pulse/usePulse.ts +80 -34
  482. package/src/components/ui/Pulse/usePulseDriver.ts +49 -0
  483. package/src/components/ui/Pulse/usePulseDriver.web.ts +66 -0
  484. package/src/components/ui/Radio/Radio.tsx +44 -15
  485. package/src/components/ui/Radio/RadioGroup.tsx +21 -3
  486. package/src/components/ui/Radio/types.ts +17 -3
  487. package/src/components/ui/Reveal/Reveal.tsx +5 -3
  488. package/src/components/ui/Reveal/Reveal.web.tsx +72 -29
  489. package/src/components/ui/Reveal/types.ts +1 -1
  490. package/src/components/ui/Reveal/webTransition.ts +206 -0
  491. package/src/components/ui/Search/Search.tsx +127 -58
  492. package/src/components/ui/Search/types.ts +30 -9
  493. package/src/components/ui/Segmented/Segmented.tsx +10 -2
  494. package/src/components/ui/Skeleton/Skeleton.tsx +9 -5
  495. package/src/components/ui/Spinner/Spinner.tsx +25 -17
  496. package/src/components/ui/Spinner/Spinner.web.tsx +23 -18
  497. package/src/components/ui/Spinner/shared.ts +7 -0
  498. package/src/components/ui/Spinner/types.ts +1 -1
  499. package/src/components/ui/Stepper/Stepper.tsx +166 -86
  500. package/src/components/ui/Stepper/StepperPressable.tsx +1 -0
  501. package/src/components/ui/Stepper/StepperPressable.web.tsx +1 -0
  502. package/src/components/ui/Stepper/accessibility.ts +32 -0
  503. package/src/components/ui/Stepper/accessibility.types.ts +22 -0
  504. package/src/components/ui/Stepper/accessibility.web.ts +65 -0
  505. package/src/components/ui/Stepper/layout.ts +44 -0
  506. package/src/components/ui/Stepper/normalizeStepper.ts +85 -0
  507. package/src/components/ui/Stepper/styles.ts +9 -2
  508. package/src/components/ui/Stepper/types.ts +3 -1
  509. package/src/components/ui/Switch/Switch.tsx +54 -15
  510. package/src/components/ui/Switch/Switch.web.tsx +57 -19
  511. package/src/components/ui/Switch/styles.ts +11 -4
  512. package/src/components/ui/Switch/types.ts +2 -2
  513. package/src/components/ui/Tag/Tag.tsx +6 -2
  514. package/src/components/ui/TextField/TextFieldBase.tsx +175 -70
  515. package/src/components/ui/TextField/TextFieldSlot.tsx +91 -0
  516. package/src/components/ui/TextField/normalize.ts +280 -0
  517. package/src/components/ui/TextField/styles.ts +31 -0
  518. package/src/components/ui/TextField/types.ts +118 -22
  519. package/src/components/ui/TextField/useErrorAnnouncement.ts +27 -0
  520. package/src/components/ui/TextField/useTextFieldValue.ts +94 -0
  521. package/src/components/ui/TextField/valueState.ts +125 -0
  522. package/src/components/ui/Textarea/Textarea.tsx +11 -4
  523. package/src/components/ui/Textarea/index.ts +5 -0
  524. package/src/components/ui/Textarea/types.ts +14 -22
  525. package/src/components/ui/Thumbnail/Thumbnail.tsx +86 -51
  526. package/src/components/ui/Thumbnail/index.ts +5 -1
  527. package/src/components/ui/Thumbnail/normalize.ts +78 -0
  528. package/src/components/ui/Thumbnail/styles.ts +5 -10
  529. package/src/components/ui/Thumbnail/types.ts +43 -13
  530. package/src/components/ui/Toast/ToastHost.tsx +81 -22
  531. package/src/components/ui/Toast/ToastHost.web.tsx +91 -29
  532. package/src/components/ui/Toast/store.ts +148 -0
  533. package/src/components/ui/Toast/toast.ts +19 -10
  534. package/src/components/ui/Toast/types.ts +7 -3
  535. package/src/components/ui/index.ts +19 -4
  536. package/src/components/ui/shared/ImageAttempt.tsx +30 -0
  537. package/src/components/ui/shared/a11y.ts +18 -0
  538. package/src/components/ui/shared/accessibilityName.ts +6 -0
  539. package/src/components/ui/shared/selectImageAttemptSource.shared.ts +17 -0
  540. package/src/components/ui/shared/selectImageAttemptSource.ts +3 -0
  541. package/src/components/ui/shared/selectImageAttemptSource.web.ts +3 -0
  542. package/src/icons/data.ts +1 -1
  543. package/src/theme/ThemeProvider.tsx +18 -7
  544. package/src/theme/fontScale.ts +15 -0
  545. package/src/theme/index.ts +2 -3
  546. package/src/theme/themeContext.ts +24 -0
  547. package/src/theme/themeDiagnostics.ts +41 -0
  548. package/src/theme/usePrefersReducedMotion.ts +11 -4
  549. package/src/theme/usePrefersReducedMotion.web.ts +5 -2
  550. package/src/theme/useTheme.ts +19 -27
  551. package/src/theme/useThemedStyles.ts +12 -7
  552. package/src/utils/imageSource.ts +303 -0
  553. package/lib/module/components/ui/PasswordInput/styles.js +0 -12
  554. package/lib/module/components/ui/PasswordInput/styles.js.map +0 -1
  555. package/lib/module/components/ui/Pulse/usePulse.web.js +0 -76
  556. package/lib/module/components/ui/Pulse/usePulse.web.js.map +0 -1
  557. package/lib/typescript/src/components/ui/PasswordInput/styles.d.ts +0 -7
  558. package/lib/typescript/src/components/ui/PasswordInput/styles.d.ts.map +0 -1
  559. package/lib/typescript/src/components/ui/Pulse/usePulse.web.d.ts +0 -21
  560. package/lib/typescript/src/components/ui/Pulse/usePulse.web.d.ts.map +0 -1
  561. package/src/components/ui/PasswordInput/styles.ts +0 -7
  562. package/src/components/ui/Pulse/usePulse.web.ts +0 -74
@@ -1,35 +1,40 @@
1
- import React, { type ComponentRef, forwardRef, useState } from 'react';
2
- import { Text, TextInput, View } from 'react-native';
3
- import { control, r, space, useColors, useThemedStyles } from '../../../theme';
1
+ import React, {
2
+ type ComponentRef,
3
+ forwardRef,
4
+ useEffect,
5
+ useImperativeHandle,
6
+ useState,
7
+ } from 'react';
8
+ import { Platform, Text, TextInput, View } from 'react-native';
9
+ import type { TextInputProps } from 'react-native';
10
+ import { fixed, space, useColors, useThemedStyles } from '../../../theme';
4
11
  import { childTestID } from '../../../utils/testID';
12
+ import { createLogger } from '../../../utils/logger';
13
+ import {
14
+ normalizeInputHeight,
15
+ normalizeTextareaHeights,
16
+ sanitizeTextFieldContainerStyle,
17
+ } from './normalize';
5
18
  import { makeStyles } from './styles';
6
- import type { TextFieldBaseProps } from './types';
19
+ import { TextFieldSlot } from './TextFieldSlot';
20
+ import type { TextFieldBaseProps, TextFieldHandle } from './types';
21
+ import { useErrorAnnouncement } from './useErrorAnnouncement';
22
+ import { useTextFieldValue } from './useTextFieldValue';
7
23
 
8
- /** `TextInput` react-native-strict-api 下是组件类型(`TextInputType`),
9
- * ref 实例类型走 `ComponentRef<typeof TextInput>`(对应内部 `_TextInputInstance`)。 */
10
- export type TextInputRef = ComponentRef<typeof TextInput>;
24
+ const log = createLogger('TextField');
11
25
 
12
- /**
13
- * Input / Textarea 共享 primitive —— internal,不在主 barrel 导出。
14
- *
15
- * 行为:
16
- * - 视觉 4 态:idle(浅灰)/ focus(白底 brand 边)/ filled(白底 outline 边)/ error
17
- * - leading / trailing 左右 slot
18
- * - disabled 优先于 editable
19
- * - multiline=false → 单行 fixed height(默认 control.lg)
20
- * - multiline=true → 多行 minHeight/maxHeight,文字顶对齐,wrap 上下加 padding
21
- * - forwardRef<TextInput> —— 业务表单 inputRef.current?.focus() 聚焦
22
- *
23
- * 公开 API 是 Input / Textarea(本组件不直接给业务用)。
24
- */
25
- export const TextFieldBase = forwardRef<TextInputRef, TextFieldBaseProps>(
26
- function TextFieldBase(
27
- {
28
- multiline = false,
29
- height = control.lg,
30
- // [L-81] multiline minHeight 裸 96 → r(96),随设备缩放
31
- minHeight = r(96),
26
+ /** internal native ref type;公开 ref 一律用 TextFieldHandle。 */
27
+ type NativeTextInputRef = ComponentRef<typeof TextInput>;
28
+
29
+ /** Input / Textarea / Search 共享的严格输入 primitive — internal,不进公共 barrel。 */
30
+ export const TextFieldBase = forwardRef<TextFieldHandle, TextFieldBaseProps>(
31
+ function TextFieldBase(props, forwardedRef): React.JSX.Element {
32
+ const {
33
+ multiline,
34
+ height,
35
+ minHeight,
32
36
  maxHeight,
37
+ searchLayout,
33
38
  leading,
34
39
  trailing,
35
40
  error,
@@ -37,29 +42,96 @@ export const TextFieldBase = forwardRef<TextInputRef, TextFieldBaseProps>(
37
42
  editable,
38
43
  containerStyle,
39
44
  value,
45
+ defaultValue,
46
+ onChangeText,
47
+ accessibilityState,
48
+ accessibilityRole,
49
+ placeholderTextColor: callerPlaceholder,
40
50
  onFocus,
41
51
  onBlur,
42
- onChangeText,
43
52
  testID,
44
- ...rest
45
- },
46
- ref
47
- ): React.JSX.Element {
48
- const c = useColors();
53
+ style: _style,
54
+ numberOfLines: _numberOfLines,
55
+ ['aria-disabled']: _ariaDisabled,
56
+ readOnly: _readOnly,
57
+ role: _role,
58
+ enterKeyHint: _enterKeyHint,
59
+ clearTextOnFocus: _clearTextOnFocus,
60
+ ...allowedNativeProps
61
+ } = props as TextFieldBaseProps & Record<string, unknown>;
62
+ const removedNativeAliasKey = Object.entries({
63
+ 'style': _style,
64
+ 'numberOfLines': _numberOfLines,
65
+ 'aria-disabled': _ariaDisabled,
66
+ 'readOnly': _readOnly,
67
+ 'role': _role,
68
+ 'enterKeyHint': _enterKeyHint,
69
+ 'clearTextOnFocus': _clearTextOnFocus,
70
+ })
71
+ .filter(([, entry]) => entry !== undefined)
72
+ .map(([name]) => name)
73
+ .join(',');
74
+ const colors = useColors();
49
75
  const styles = useThemedStyles(makeStyles);
50
76
  const [focused, setFocused] = useState(false);
51
- // [M-9] 内部镜像 state:非受控场景 value 不传,用 _mirror 做 hasValue 判断
52
- const [_mirror, setMirror] = useState('');
53
- // [M-9] filled 在受控 value 和内部镜像 state 之间取 hasValue,
54
- // 保证非受控场景 filled 视觉态能正确响应用户输入,且受控用法行为不变
55
- const filled =
56
- value != null ? String(value).length > 0 : _mirror.length > 0;
57
- const isEditable = disabled ? false : editable;
58
- // [L-31] editable=false(非 disabled)时也应进入 disabled a11y state
59
- const isDisabledA11y = disabled || editable === false;
77
+ const nativeRef = React.useRef<NativeTextInputRef>(null);
78
+ const scope = multiline ? 'Textarea' : 'Input';
79
+ const controller = useTextFieldValue(
80
+ {
81
+ value,
82
+ defaultValue,
83
+ onChangeText:
84
+ typeof onChangeText === 'function'
85
+ ? (onChangeText as (next: string) => void)
86
+ : undefined,
87
+ },
88
+ scope
89
+ );
90
+ const normalizedInputHeight = normalizeInputHeight(
91
+ height === undefined ? fixed.hitTarget : height
92
+ );
93
+ const normalizedTextareaHeights = normalizeTextareaHeights(
94
+ minHeight,
95
+ maxHeight
96
+ );
97
+ const sanitizedContainer = sanitizeTextFieldContainerStyle(containerStyle);
98
+ const effectiveEditable = disabled !== true && editable !== false;
99
+ const mergedAccessibilityState = {
100
+ ...accessibilityState,
101
+ disabled: !effectiveEditable,
102
+ };
103
+ const normalizedHeight = multiline
104
+ ? normalizedTextareaHeights.minHeight
105
+ : normalizedInputHeight.value;
106
+ const filled = controller.value.length > 0;
107
+ const diagnostics = [
108
+ ...normalizedInputHeight.diagnostics,
109
+ ...normalizedTextareaHeights.diagnostics,
110
+ ...sanitizedContainer.diagnostics,
111
+ ];
112
+ const diagnosticKey = diagnostics.join(',');
113
+
114
+ useEffect(() => {
115
+ if (diagnosticKey.length > 0) {
116
+ log.warn(`${scope}: 非法布局值(${diagnosticKey})已回退。`);
117
+ }
118
+ }, [diagnosticKey, scope]);
119
+ useEffect(() => {
120
+ if (removedNativeAliasKey.length > 0) {
121
+ log.warn(`${scope}: 已忽略受管原生 props(${removedNativeAliasKey})。`);
122
+ }
123
+ }, [removedNativeAliasKey, scope]);
124
+ useErrorAnnouncement(error);
125
+
126
+ useImperativeHandle(
127
+ forwardedRef,
128
+ () => ({
129
+ focus: () => nativeRef.current?.focus(),
130
+ blur: () => nativeRef.current?.blur(),
131
+ }),
132
+ []
133
+ );
60
134
 
61
- // 视觉态优先级:error > focused > filled > idle。
62
- // active 三态(focus/filled/error)共享 wrapActive 白底,各自只覆 borderColor 差量。
63
135
  const wrapStateStyles = error
64
136
  ? [styles.wrapActive, styles.wrapError]
65
137
  : focused
@@ -67,62 +139,95 @@ export const TextFieldBase = forwardRef<TextInputRef, TextFieldBaseProps>(
67
139
  : filled
68
140
  ? [styles.wrapActive, styles.wrapFilled]
69
141
  : [styles.wrapIdle];
142
+ const interactiveHeight =
143
+ searchLayout?.interactiveHeight ?? normalizedHeight;
70
144
 
71
145
  return (
72
146
  <View
73
- style={[containerStyle, disabled && styles.containerDisabled]}
147
+ style={[
148
+ sanitizedContainer.style,
149
+ !effectiveEditable && styles.containerDisabled,
150
+ searchLayout !== undefined && !multiline && styles.rootCentered,
151
+ { minWidth: fixed.hitTarget, minHeight: normalizedHeight },
152
+ ]}
74
153
  testID={testID}
75
154
  >
76
155
  <View
77
156
  style={[
78
157
  styles.wrap,
79
158
  multiline && styles.wrapMultiline,
80
- ...wrapStateStyles,
159
+ searchLayout === undefined && wrapStateStyles,
160
+ searchLayout !== undefined && styles.searchInteractiveRow,
81
161
  multiline
82
- ? { minHeight, ...(maxHeight != null && { maxHeight }) }
83
- : { height },
162
+ ? {
163
+ minHeight: normalizedHeight,
164
+ ...(normalizedTextareaHeights.maxHeight !== undefined && {
165
+ maxHeight: normalizedTextareaHeights.maxHeight,
166
+ }),
167
+ }
168
+ : { height: interactiveHeight },
84
169
  ]}
85
170
  >
86
- {leading != null ? <View>{leading}</View> : null}
171
+ {searchLayout ? (
172
+ <View
173
+ pointerEvents="none"
174
+ style={[
175
+ styles.searchVisibleSurface,
176
+ ...wrapStateStyles,
177
+ {
178
+ top: searchLayout.verticalInset,
179
+ bottom: searchLayout.verticalInset,
180
+ },
181
+ ]}
182
+ />
183
+ ) : null}
184
+ <TextFieldSlot
185
+ slot={leading}
186
+ effectiveEditable={effectiveEditable}
187
+ testID={childTestID(testID, 'leading')}
188
+ />
87
189
  <TextInput
88
- ref={ref}
89
- {...rest}
90
- editable={isEditable}
91
- value={value}
92
- onChangeText={(text) => {
93
- // [M-9] 同步内部镜像,非受控场景 filled 视觉态依赖此 state
94
- setMirror(text);
95
- onChangeText?.(text);
96
- }}
190
+ ref={nativeRef}
191
+ {...(allowedNativeProps as TextInputProps)}
192
+ value={controller.value}
193
+ onChangeText={controller.onChangeText}
194
+ editable={effectiveEditable}
97
195
  multiline={multiline}
98
- onFocus={(e) => {
196
+ onFocus={(event) => {
99
197
  setFocused(true);
100
- onFocus?.(e);
198
+ onFocus?.(event);
101
199
  }}
102
- onBlur={(e) => {
200
+ onBlur={(event) => {
103
201
  setFocused(false);
104
- onBlur?.(e);
202
+ onBlur?.(event);
105
203
  }}
106
204
  style={[
107
205
  styles.input,
108
206
  multiline && styles.inputMultiline,
109
- // multiline:wrap 上下 padding 为 space[4]*2=20,input 内部 minHeight 减掉避免溢出
110
207
  multiline && {
111
- minHeight: Math.max(0, minHeight - space[4] * 2),
208
+ minHeight: Math.max(0, normalizedHeight - space[4] * 2),
209
+ },
210
+ searchLayout !== undefined && {
211
+ minHeight: searchLayout.interactiveHeight,
112
212
  },
113
213
  ]}
114
- placeholderTextColor={c.foregroundSubtle}
115
- // [L-31] editable=false 并入 disabled a11y state,SR 能正确播报不可编辑
116
- accessibilityState={isDisabledA11y ? { disabled: true } : undefined}
214
+ placeholderTextColor={callerPlaceholder ?? colors.foregroundSubtle}
215
+ accessibilityRole={accessibilityRole}
216
+ accessibilityState={mergedAccessibilityState}
117
217
  testID={childTestID(testID, 'input')}
118
218
  />
119
- {trailing != null ? <View>{trailing}</View> : null}
219
+ <TextFieldSlot
220
+ slot={trailing}
221
+ effectiveEditable={effectiveEditable}
222
+ testID={childTestID(testID, 'trailing')}
223
+ />
120
224
  </View>
121
- {/* [L-31] error Text 补 accessibilityLiveRegion="polite" —— 错误出现时 SR 自动播报 */}
122
225
  {error ? (
123
226
  <Text
124
227
  style={styles.errorMsg}
125
- accessibilityLiveRegion="polite"
228
+ accessibilityLiveRegion={
229
+ Platform.OS === 'android' ? 'polite' : undefined
230
+ }
126
231
  testID={childTestID(testID, 'error')}
127
232
  >
128
233
  {error}
@@ -0,0 +1,91 @@
1
+ import { useEffect } from 'react';
2
+ import { Text, View } from 'react-native';
3
+ import { Pressable } from 'react-native-gesture-handler';
4
+ import { useColors, useThemedStyles } from '../../../theme';
5
+ import { createLogger } from '../../../utils/logger';
6
+ import { A11Y_HIDDEN_PROPS } from '../shared/a11y';
7
+ import { Icon } from '../Icon';
8
+ import { normalizeSlotIconSize, normalizeTextFieldSlot } from './normalize';
9
+ import { makeStyles } from './styles';
10
+ import type { TextFieldSlot as TextFieldSlotConfig } from './types';
11
+
12
+ const log = createLogger('TextFieldSlot');
13
+
14
+ type TextFieldSlotProps = {
15
+ slot: TextFieldSlotConfig | unknown;
16
+ effectiveEditable: boolean;
17
+ testID?: string;
18
+ };
19
+
20
+ /**
21
+ * 受控 slot renderer。展示内容与真实操作在这里分叉,避免未知 ReactNode 绕过
22
+ * 44pt action frame 或可访问名称约束。
23
+ */
24
+ export function TextFieldSlot({
25
+ slot,
26
+ effectiveEditable,
27
+ testID,
28
+ }: TextFieldSlotProps): React.JSX.Element | null {
29
+ const colors = useColors();
30
+ const styles = useThemedStyles(makeStyles);
31
+ const normalizedSlot = normalizeTextFieldSlot(slot);
32
+ const safeSlot = normalizedSlot.slot;
33
+ const iconSize =
34
+ safeSlot?.kind === 'icon'
35
+ ? normalizeSlotIconSize(safeSlot.size)
36
+ : undefined;
37
+ const iconDiagnosticKey = iconSize?.diagnostics.join(',') ?? '';
38
+ const slotDiagnosticKey = normalizedSlot.diagnostics.join(',');
39
+
40
+ useEffect(() => {
41
+ if (iconDiagnosticKey.length > 0) {
42
+ log.warn('slot.icon.size 非法,已回退为 18。');
43
+ }
44
+ }, [iconDiagnosticKey]);
45
+ useEffect(() => {
46
+ if (slotDiagnosticKey.length > 0) {
47
+ log.warn(`非法 TextField slot(${slotDiagnosticKey})已移除。`);
48
+ }
49
+ }, [slotDiagnosticKey]);
50
+
51
+ if (!safeSlot) return null;
52
+
53
+ switch (safeSlot.kind) {
54
+ case 'icon':
55
+ return (
56
+ <View {...A11Y_HIDDEN_PROPS} style={styles.slotDisplay} testID={testID}>
57
+ <Icon
58
+ name={safeSlot.icon}
59
+ size={iconSize?.value ?? 18}
60
+ color={safeSlot.color ?? colors.foregroundMuted}
61
+ />
62
+ </View>
63
+ );
64
+ case 'text':
65
+ return (
66
+ <Text
67
+ {...A11Y_HIDDEN_PROPS}
68
+ style={[styles.slotDisplay, styles.slotText]}
69
+ testID={testID}
70
+ >
71
+ {safeSlot.value}
72
+ </Text>
73
+ );
74
+ case 'action': {
75
+ const disabled = !effectiveEditable || safeSlot.disabled === true;
76
+ return (
77
+ <Pressable
78
+ onPress={disabled ? undefined : safeSlot.onPress}
79
+ disabled={disabled}
80
+ accessibilityRole="button"
81
+ accessibilityLabel={safeSlot.accessibilityLabel}
82
+ accessibilityState={{ disabled }}
83
+ style={styles.actionFrame}
84
+ testID={testID}
85
+ >
86
+ <Icon name={safeSlot.icon} size={18} color={colors.foregroundMuted} />
87
+ </Pressable>
88
+ );
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,280 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import type { StyleProp, ViewStyle } from 'react-native';
3
+ import { fixed } from '../../../theme';
4
+ import { ICONS, type IconName } from '../../../icons';
5
+ import { normalizeNonBlankText } from '../shared/accessibilityName';
6
+ import type {
7
+ SearchFieldLayout,
8
+ TextFieldContainerStyle,
9
+ TextFieldSlot,
10
+ } from './types';
11
+
12
+ /**
13
+ * TextField 家族的**纯布局归一化** —— 无 React 依赖,可直接单测。
14
+ *
15
+ * 纪律与 Pulse 一致:非法值**整体回退默认值并记诊断**,不做 clamp、不做取整。
16
+ * 悄悄把 `height: 20` 夹成 44 会让调用方永远发现不了自己传了一个碰不到的输入框。
17
+ */
18
+
19
+ /** slot 图标的默认与合法上界。18 是 body 字号下视觉平衡的取值;>32 会撑破 44pt frame。 */
20
+ const DEFAULT_SLOT_ICON_SIZE = 18;
21
+ const MAX_SLOT_ICON_SIZE = 32;
22
+ /** Textarea 默认最小高度(约 5 行)。 */
23
+ const DEFAULT_TEXTAREA_MIN_HEIGHT = 96;
24
+ const DEFAULT_SEARCH_VISIBLE_HEIGHT = 36;
25
+
26
+ /** 这六个字段会破坏 TextField 自持的最小命中框,一律从 containerStyle 剥离。 */
27
+ const RESERVED_CONTAINER_KEYS = [
28
+ 'height',
29
+ 'minHeight',
30
+ 'maxHeight',
31
+ 'minWidth',
32
+ 'maxWidth',
33
+ 'overflow',
34
+ ] as const;
35
+
36
+ const isFiniteAtLeast = (value: unknown, min: number): value is number =>
37
+ typeof value === 'number' && Number.isFinite(value) && value >= min;
38
+
39
+ const isFiniteWithin = (
40
+ value: unknown,
41
+ min: number,
42
+ max: number
43
+ ): value is number =>
44
+ typeof value === 'number' &&
45
+ Number.isFinite(value) &&
46
+ value >= min &&
47
+ value <= max;
48
+
49
+ export type NormalizedNumber = {
50
+ value: number;
51
+ diagnostics: readonly string[];
52
+ };
53
+
54
+ /** 单行高度 —— 不得低于 `fixed.hitTarget`(44pt),否则整行都碰不满一个手指。 */
55
+ export function normalizeInputHeight(value: unknown): NormalizedNumber {
56
+ return isFiniteAtLeast(value, fixed.hitTarget)
57
+ ? { value, diagnostics: [] }
58
+ : { value: fixed.hitTarget, diagnostics: ['height'] };
59
+ }
60
+
61
+ export type NormalizedTextareaHeights = {
62
+ minHeight: number;
63
+ maxHeight: number | undefined;
64
+ diagnostics: readonly string[];
65
+ };
66
+
67
+ /** 多行高度 —— `maxHeight` 只有在有限且不小于归一化后的 `minHeight` 时才保留。 */
68
+ export function normalizeTextareaHeights(
69
+ minHeight: unknown,
70
+ maxHeight: unknown
71
+ ): NormalizedTextareaHeights {
72
+ const diagnostics: string[] = [];
73
+ let safeMin: number;
74
+ if (minHeight === undefined) {
75
+ safeMin = DEFAULT_TEXTAREA_MIN_HEIGHT;
76
+ } else if (isFiniteAtLeast(minHeight, fixed.hitTarget)) {
77
+ safeMin = minHeight;
78
+ } else {
79
+ safeMin = DEFAULT_TEXTAREA_MIN_HEIGHT;
80
+ diagnostics.push('minHeight');
81
+ }
82
+ if (maxHeight === undefined) {
83
+ return { minHeight: safeMin, maxHeight: undefined, diagnostics };
84
+ }
85
+ // 注意用**归一化后**的 min 比较:min 被回退时 max 必须跟着重新判定,
86
+ // 否则会留下一个比实际 min 还小的 max,直接把内容压没。
87
+ if (isFiniteAtLeast(maxHeight, safeMin)) {
88
+ return { minHeight: safeMin, maxHeight, diagnostics };
89
+ }
90
+ diagnostics.push('maxHeight');
91
+ return { minHeight: safeMin, maxHeight: undefined, diagnostics };
92
+ }
93
+
94
+ /** slot 图标尺寸 —— 只接受有限的 `[1, 32]`。 */
95
+ export function normalizeSlotIconSize(value: unknown): NormalizedNumber {
96
+ return isFiniteWithin(value, 1, MAX_SLOT_ICON_SIZE)
97
+ ? { value, diagnostics: [] }
98
+ : { value: DEFAULT_SLOT_ICON_SIZE, diagnostics: ['slot.size'] };
99
+ }
100
+
101
+ export type NormalizedTextFieldSlot = {
102
+ slot: TextFieldSlot | undefined;
103
+ diagnostics: readonly string[];
104
+ };
105
+
106
+ function isIconName(value: unknown): value is IconName {
107
+ return (
108
+ typeof value === 'string' &&
109
+ Object.prototype.hasOwnProperty.call(ICONS, value)
110
+ );
111
+ }
112
+
113
+ /** 未类型化 JS 必须完整匹配一个受支持分支,不能靠 discriminant 后 cast 绕过校验。 */
114
+ export function normalizeTextFieldSlot(slot: unknown): NormalizedTextFieldSlot {
115
+ if (slot === undefined) {
116
+ return { slot: undefined, diagnostics: [] };
117
+ }
118
+ if (typeof slot !== 'object' || slot === null) {
119
+ return { slot: undefined, diagnostics: ['slot'] };
120
+ }
121
+ const candidate = slot as Record<string, unknown>;
122
+ switch (candidate.kind) {
123
+ case 'icon': {
124
+ const size =
125
+ typeof candidate.size === 'number' && Number.isFinite(candidate.size)
126
+ ? candidate.size
127
+ : undefined;
128
+ const color =
129
+ typeof candidate.color === 'string' ? candidate.color : undefined;
130
+ const hasValidSize = candidate.size === undefined || size !== undefined;
131
+ const hasValidColor =
132
+ candidate.color === undefined || color !== undefined;
133
+ if (!isIconName(candidate.icon) || !hasValidSize || !hasValidColor) {
134
+ return { slot: undefined, diagnostics: ['slot.icon'] };
135
+ }
136
+ return {
137
+ slot: {
138
+ kind: 'icon',
139
+ icon: candidate.icon,
140
+ ...(size !== undefined && { size }),
141
+ ...(color !== undefined && { color }),
142
+ },
143
+ diagnostics: [],
144
+ };
145
+ }
146
+ case 'text':
147
+ if (
148
+ typeof candidate.value !== 'string' &&
149
+ typeof candidate.value !== 'number'
150
+ ) {
151
+ return { slot: undefined, diagnostics: ['slot.text'] };
152
+ }
153
+ return {
154
+ slot: { kind: 'text', value: candidate.value },
155
+ diagnostics: [],
156
+ };
157
+ case 'action': {
158
+ const accessibilityLabel = normalizeNonBlankText(
159
+ candidate.accessibilityLabel
160
+ );
161
+ const hasValidDisabled =
162
+ candidate.disabled === undefined ||
163
+ typeof candidate.disabled === 'boolean';
164
+ const slotDisabled =
165
+ typeof candidate.disabled === 'boolean'
166
+ ? candidate.disabled
167
+ : undefined;
168
+ if (
169
+ !isIconName(candidate.icon) ||
170
+ typeof candidate.onPress !== 'function' ||
171
+ accessibilityLabel === undefined ||
172
+ !hasValidDisabled
173
+ ) {
174
+ return { slot: undefined, diagnostics: ['slot.action'] };
175
+ }
176
+ return {
177
+ slot: {
178
+ kind: 'action',
179
+ icon: candidate.icon,
180
+ onPress: candidate.onPress as () => void,
181
+ accessibilityLabel,
182
+ ...(slotDisabled !== undefined && { disabled: slotDisabled }),
183
+ },
184
+ diagnostics: [],
185
+ };
186
+ }
187
+ default:
188
+ return { slot: undefined, diagnostics: ['slot.kind'] };
189
+ }
190
+ }
191
+
192
+ export type NormalizedSearchLayout = SearchFieldLayout & {
193
+ diagnostics: readonly string[];
194
+ };
195
+
196
+ /** 搜索框的可见面可为 36pt,但承载输入/操作的实际行永远不得小于 44pt。 */
197
+ export function normalizeSearchLayout(
198
+ interactiveHeight: unknown,
199
+ visibleHeight: unknown
200
+ ): NormalizedSearchLayout {
201
+ const diagnostics: string[] = [];
202
+ const safeInteractive = isFiniteAtLeast(interactiveHeight, fixed.hitTarget)
203
+ ? interactiveHeight
204
+ : fixed.hitTarget;
205
+ if (safeInteractive !== interactiveHeight) {
206
+ diagnostics.push('interactiveHeight');
207
+ }
208
+ const safeVisible =
209
+ typeof visibleHeight === 'number' &&
210
+ Number.isFinite(visibleHeight) &&
211
+ visibleHeight > 0 &&
212
+ visibleHeight <= safeInteractive
213
+ ? visibleHeight
214
+ : DEFAULT_SEARCH_VISIBLE_HEIGHT;
215
+ if (safeVisible !== visibleHeight) {
216
+ diagnostics.push('visibleHeight');
217
+ }
218
+ return {
219
+ interactiveHeight: safeInteractive,
220
+ visibleHeight: safeVisible,
221
+ verticalInset: (safeInteractive - safeVisible) / 2,
222
+ diagnostics,
223
+ };
224
+ }
225
+
226
+ export type SanitizedContainerStyle = {
227
+ style: TextFieldContainerStyle;
228
+ diagnostics: readonly string[];
229
+ };
230
+
231
+ export type SanitizedTextFieldWrapperProps = {
232
+ props: Record<string, unknown>;
233
+ diagnostics: readonly string[];
234
+ };
235
+
236
+ /**
237
+ * 公开 Input / Textarea 不允许未类型化 JS 覆盖内部 layout 开关。
238
+ *
239
+ * 返回新对象而不是 delete 原 props,既不改变调用方对象,也让 wrapper 能在安全 spread
240
+ * 后由可信边界写入自己的 `multiline`。
241
+ */
242
+ export function sanitizeTextFieldWrapperProps(
243
+ props: Record<string, unknown>
244
+ ): SanitizedTextFieldWrapperProps {
245
+ const { multiline, searchLayout, ...safeProps } = props;
246
+ const diagnostics: string[] = [];
247
+ if (multiline !== undefined) {
248
+ diagnostics.push('multiline');
249
+ }
250
+ if (searchLayout !== undefined) {
251
+ diagnostics.push('searchLayout');
252
+ }
253
+ return { props: safeProps, diagnostics };
254
+ }
255
+
256
+ /**
257
+ * 剥掉 containerStyle 里会覆盖最小 frame 的六个字段。
258
+ *
259
+ * 先 `StyleSheet.flatten` 再解构到新对象 —— 绝不原地修改调用方对象或已注册的
260
+ * StyleSheet 条目(那会污染同一 sheet 的其他使用者)。
261
+ */
262
+ export function sanitizeTextFieldContainerStyle(
263
+ style: StyleProp<ViewStyle> | undefined
264
+ ): SanitizedContainerStyle {
265
+ const flattened = (StyleSheet.flatten(style) ?? {}) as Record<
266
+ string,
267
+ unknown
268
+ >;
269
+ const reserved: readonly string[] = RESERVED_CONTAINER_KEYS;
270
+ const sanitized: Record<string, unknown> = {};
271
+ const diagnostics: string[] = [];
272
+ for (const [key, entry] of Object.entries(flattened)) {
273
+ if (reserved.includes(key)) {
274
+ diagnostics.push(key);
275
+ continue;
276
+ }
277
+ sanitized[key] = entry;
278
+ }
279
+ return { style: sanitized as TextFieldContainerStyle, diagnostics };
280
+ }