@multiplatform.one/forms 7.7.6 → 7.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (497) hide show
  1. package/dist/cjs/Button/index.cjs +1 -4
  2. package/dist/cjs/Button/index.native.js +5 -6
  3. package/dist/cjs/Button/index.native.js.map +1 -1
  4. package/dist/cjs/Chip/index.cjs +1 -1
  5. package/dist/cjs/Chip/index.native.js +1 -1
  6. package/dist/cjs/Chip/index.native.js.map +1 -1
  7. package/dist/cjs/FloatingPanel/index.cjs +59 -14
  8. package/dist/cjs/FloatingPanel/index.native.js +16 -7
  9. package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
  10. package/dist/cjs/FloatingPanel/nestedAction.cjs +37 -0
  11. package/dist/cjs/FloatingPanel/nestedAction.native.js +42 -0
  12. package/dist/cjs/FloatingPanel/nestedAction.native.js.map +1 -0
  13. package/dist/cjs/InputParts/index.cjs +19 -8
  14. package/dist/cjs/InputParts/index.native.js +20 -11
  15. package/dist/cjs/InputParts/index.native.js.map +1 -1
  16. package/dist/cjs/Wheel/index.cjs +3 -3
  17. package/dist/cjs/Wheel/index.native.js +3 -3
  18. package/dist/cjs/Wheel/index.native.js.map +1 -1
  19. package/dist/cjs/fieldLayout.cjs +3 -3
  20. package/dist/cjs/fieldLayout.native.js +3 -3
  21. package/dist/cjs/fieldLayout.native.js.map +1 -1
  22. package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.cjs +9 -2
  23. package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
  24. package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
  25. package/dist/cjs/fields/Combobox/index.cjs +36 -29
  26. package/dist/cjs/fields/Combobox/index.native.js +38 -38
  27. package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
  28. package/dist/cjs/fields/DatePicker/Calendar.cjs +6 -1
  29. package/dist/cjs/fields/DatePicker/Calendar.native.js +6 -1
  30. package/dist/cjs/fields/DatePicker/Calendar.native.js.map +1 -1
  31. package/dist/cjs/fields/DatePicker/DateRangePicker.cjs +2 -2
  32. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +2 -2
  33. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  34. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.cjs +15 -12
  35. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
  36. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  37. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +39 -14
  38. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  39. package/dist/cjs/fields/DatePicker/MonthPicker.cjs +10 -3
  40. package/dist/cjs/fields/DatePicker/MonthPicker.native.js +10 -3
  41. package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
  42. package/dist/cjs/fields/DatePicker/MultiDatePicker.cjs +2 -2
  43. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +2 -2
  44. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  45. package/dist/cjs/fields/DatePicker/index.native.js +3 -0
  46. package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
  47. package/dist/cjs/fields/DatePicker/parts.cjs +26 -14
  48. package/dist/cjs/fields/DatePicker/parts.native.js +28 -14
  49. package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
  50. package/dist/cjs/fields/FileUpload/index.cjs +6 -0
  51. package/dist/cjs/fields/FileUpload/index.native.js +6 -0
  52. package/dist/cjs/fields/FileUpload/index.native.js.map +1 -1
  53. package/dist/cjs/fields/Geolocation/GeolocationMap.native.js.map +1 -1
  54. package/dist/cjs/fields/Geolocation/geocoder.cjs +63 -0
  55. package/dist/cjs/fields/Geolocation/geocoder.native.js +68 -0
  56. package/dist/cjs/fields/Geolocation/geocoder.native.js.map +1 -0
  57. package/dist/cjs/fields/Geolocation/index.cjs +801 -152
  58. package/dist/cjs/fields/Geolocation/index.native.js +856 -167
  59. package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
  60. package/dist/cjs/fields/Geolocation/nativeSearchFocus.cjs +44 -0
  61. package/dist/cjs/fields/Geolocation/nativeSearchFocus.native.js +47 -0
  62. package/dist/cjs/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
  63. package/dist/cjs/fields/Icon/drawnSet.cjs +16 -3
  64. package/dist/cjs/fields/Icon/drawnSet.native.js +20 -3
  65. package/dist/cjs/fields/Icon/drawnSet.native.js.map +1 -1
  66. package/dist/cjs/fields/Icon/index.cjs +102 -27
  67. package/dist/cjs/fields/Icon/index.native.js +115 -31
  68. package/dist/cjs/fields/Icon/index.native.js.map +1 -1
  69. package/dist/cjs/fields/Input/index.cjs +5 -12
  70. package/dist/cjs/fields/Input/index.native.js +5 -13
  71. package/dist/cjs/fields/Input/index.native.js.map +1 -1
  72. package/dist/cjs/fields/PhoneInput/index.cjs +2 -2
  73. package/dist/cjs/fields/PhoneInput/index.native.js +2 -2
  74. package/dist/cjs/fields/PhoneInput/index.native.js.map +1 -1
  75. package/dist/cjs/fields/RadioGroup/index.cjs +34 -5
  76. package/dist/cjs/fields/RadioGroup/index.native.js +49 -7
  77. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  78. package/dist/cjs/fields/SearchInput/index.cjs +8 -9
  79. package/dist/cjs/fields/SearchInput/index.native.js +8 -9
  80. package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
  81. package/dist/cjs/fields/Select/index.cjs +42 -11
  82. package/dist/cjs/fields/Select/index.native.js +52 -20
  83. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  84. package/dist/cjs/fields/Stepper/index.cjs +144 -31
  85. package/dist/cjs/fields/Stepper/index.native.js +151 -31
  86. package/dist/cjs/fields/Stepper/index.native.js.map +1 -1
  87. package/dist/cjs/fields/ToggleGroup/index.cjs +35 -2
  88. package/dist/cjs/fields/ToggleGroup/index.native.js +42 -2
  89. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  90. package/dist/cjs/index.cjs +2 -0
  91. package/dist/cjs/index.native.js +2 -0
  92. package/dist/cjs/index.native.js.map +1 -1
  93. package/dist/cjs/shared/focusManagement.cjs +24 -11
  94. package/dist/cjs/shared/focusManagement.native.js +24 -11
  95. package/dist/cjs/shared/focusManagement.native.js.map +1 -1
  96. package/dist/cjs/shared/nativeA11y.cjs +57 -0
  97. package/dist/cjs/shared/nativeA11y.native.js +61 -0
  98. package/dist/cjs/shared/nativeA11y.native.js.map +1 -0
  99. package/dist/esm/Button/index.mjs +1 -4
  100. package/dist/esm/Button/index.mjs.map +1 -1
  101. package/dist/esm/Button/index.native.js +5 -6
  102. package/dist/esm/Button/index.native.js.map +1 -1
  103. package/dist/esm/Chip/index.mjs +1 -1
  104. package/dist/esm/Chip/index.mjs.map +1 -1
  105. package/dist/esm/Chip/index.native.js +1 -1
  106. package/dist/esm/Chip/index.native.js.map +1 -1
  107. package/dist/esm/FloatingPanel/index.mjs +58 -15
  108. package/dist/esm/FloatingPanel/index.mjs.map +1 -1
  109. package/dist/esm/FloatingPanel/index.native.js +15 -8
  110. package/dist/esm/FloatingPanel/index.native.js.map +1 -1
  111. package/dist/esm/FloatingPanel/nestedAction.mjs +11 -0
  112. package/dist/esm/FloatingPanel/nestedAction.mjs.map +1 -0
  113. package/dist/esm/FloatingPanel/nestedAction.native.js +13 -0
  114. package/dist/esm/FloatingPanel/nestedAction.native.js.map +1 -0
  115. package/dist/esm/InputParts/index.mjs +20 -9
  116. package/dist/esm/InputParts/index.mjs.map +1 -1
  117. package/dist/esm/InputParts/index.native.js +21 -12
  118. package/dist/esm/InputParts/index.native.js.map +1 -1
  119. package/dist/esm/Wheel/index.mjs +3 -3
  120. package/dist/esm/Wheel/index.mjs.map +1 -1
  121. package/dist/esm/Wheel/index.native.js +3 -3
  122. package/dist/esm/Wheel/index.native.js.map +1 -1
  123. package/dist/esm/fieldLayout.mjs +3 -3
  124. package/dist/esm/fieldLayout.mjs.map +1 -1
  125. package/dist/esm/fieldLayout.native.js +3 -3
  126. package/dist/esm/fieldLayout.native.js.map +1 -1
  127. package/dist/esm/fields/Checkbox/CheckboxFieldFrame.mjs +8 -1
  128. package/dist/esm/fields/Checkbox/CheckboxFieldFrame.mjs.map +1 -1
  129. package/dist/esm/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
  130. package/dist/esm/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
  131. package/dist/esm/fields/Combobox/index.mjs +36 -29
  132. package/dist/esm/fields/Combobox/index.mjs.map +1 -1
  133. package/dist/esm/fields/Combobox/index.native.js +38 -38
  134. package/dist/esm/fields/Combobox/index.native.js.map +1 -1
  135. package/dist/esm/fields/DatePicker/Calendar.mjs +6 -1
  136. package/dist/esm/fields/DatePicker/Calendar.mjs.map +1 -1
  137. package/dist/esm/fields/DatePicker/Calendar.native.js +6 -1
  138. package/dist/esm/fields/DatePicker/Calendar.native.js.map +1 -1
  139. package/dist/esm/fields/DatePicker/DateRangePicker.mjs +2 -2
  140. package/dist/esm/fields/DatePicker/DateRangePicker.mjs.map +1 -1
  141. package/dist/esm/fields/DatePicker/DateRangePicker.native.js +2 -2
  142. package/dist/esm/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  143. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs +15 -12
  144. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
  145. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
  146. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  147. package/dist/esm/fields/DatePicker/DatetimePicker.native.js +39 -14
  148. package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  149. package/dist/esm/fields/DatePicker/MonthPicker.mjs +10 -3
  150. package/dist/esm/fields/DatePicker/MonthPicker.mjs.map +1 -1
  151. package/dist/esm/fields/DatePicker/MonthPicker.native.js +10 -3
  152. package/dist/esm/fields/DatePicker/MonthPicker.native.js.map +1 -1
  153. package/dist/esm/fields/DatePicker/MultiDatePicker.mjs +2 -2
  154. package/dist/esm/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
  155. package/dist/esm/fields/DatePicker/MultiDatePicker.native.js +2 -2
  156. package/dist/esm/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  157. package/dist/esm/fields/DatePicker/index.native.js +3 -0
  158. package/dist/esm/fields/DatePicker/index.native.js.map +1 -1
  159. package/dist/esm/fields/DatePicker/parts.mjs +28 -16
  160. package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
  161. package/dist/esm/fields/DatePicker/parts.native.js +30 -16
  162. package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
  163. package/dist/esm/fields/FileUpload/index.mjs +6 -0
  164. package/dist/esm/fields/FileUpload/index.mjs.map +1 -1
  165. package/dist/esm/fields/FileUpload/index.native.js +6 -0
  166. package/dist/esm/fields/FileUpload/index.native.js.map +1 -1
  167. package/dist/esm/fields/Geolocation/GeolocationMap.mjs.map +1 -1
  168. package/dist/esm/fields/Geolocation/GeolocationMap.native.js.map +1 -1
  169. package/dist/esm/fields/Geolocation/geocoder.mjs +33 -0
  170. package/dist/esm/fields/Geolocation/geocoder.mjs.map +1 -0
  171. package/dist/esm/fields/Geolocation/geocoder.native.js +35 -0
  172. package/dist/esm/fields/Geolocation/geocoder.native.js.map +1 -0
  173. package/dist/esm/fields/Geolocation/index.mjs +792 -149
  174. package/dist/esm/fields/Geolocation/index.mjs.map +1 -1
  175. package/dist/esm/fields/Geolocation/index.native.js +847 -164
  176. package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
  177. package/dist/esm/fields/Geolocation/nativeSearchFocus.mjs +19 -0
  178. package/dist/esm/fields/Geolocation/nativeSearchFocus.mjs.map +1 -0
  179. package/dist/esm/fields/Geolocation/nativeSearchFocus.native.js +19 -0
  180. package/dist/esm/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
  181. package/dist/esm/fields/Icon/drawnSet.mjs +16 -3
  182. package/dist/esm/fields/Icon/drawnSet.mjs.map +1 -1
  183. package/dist/esm/fields/Icon/drawnSet.native.js +20 -3
  184. package/dist/esm/fields/Icon/drawnSet.native.js.map +1 -1
  185. package/dist/esm/fields/Icon/index.mjs +93 -18
  186. package/dist/esm/fields/Icon/index.mjs.map +1 -1
  187. package/dist/esm/fields/Icon/index.native.js +106 -22
  188. package/dist/esm/fields/Icon/index.native.js.map +1 -1
  189. package/dist/esm/fields/Input/index.mjs +5 -12
  190. package/dist/esm/fields/Input/index.mjs.map +1 -1
  191. package/dist/esm/fields/Input/index.native.js +5 -13
  192. package/dist/esm/fields/Input/index.native.js.map +1 -1
  193. package/dist/esm/fields/PhoneInput/index.mjs +2 -2
  194. package/dist/esm/fields/PhoneInput/index.mjs.map +1 -1
  195. package/dist/esm/fields/PhoneInput/index.native.js +2 -2
  196. package/dist/esm/fields/PhoneInput/index.native.js.map +1 -1
  197. package/dist/esm/fields/RadioGroup/index.mjs +34 -5
  198. package/dist/esm/fields/RadioGroup/index.mjs.map +1 -1
  199. package/dist/esm/fields/RadioGroup/index.native.js +49 -7
  200. package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
  201. package/dist/esm/fields/SearchInput/index.mjs +9 -10
  202. package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
  203. package/dist/esm/fields/SearchInput/index.native.js +9 -10
  204. package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
  205. package/dist/esm/fields/Select/index.mjs +42 -11
  206. package/dist/esm/fields/Select/index.mjs.map +1 -1
  207. package/dist/esm/fields/Select/index.native.js +52 -20
  208. package/dist/esm/fields/Select/index.native.js.map +1 -1
  209. package/dist/esm/fields/Stepper/index.mjs +145 -32
  210. package/dist/esm/fields/Stepper/index.mjs.map +1 -1
  211. package/dist/esm/fields/Stepper/index.native.js +152 -32
  212. package/dist/esm/fields/Stepper/index.native.js.map +1 -1
  213. package/dist/esm/fields/ToggleGroup/index.mjs +35 -2
  214. package/dist/esm/fields/ToggleGroup/index.mjs.map +1 -1
  215. package/dist/esm/fields/ToggleGroup/index.native.js +42 -2
  216. package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
  217. package/dist/esm/index.mjs +2 -1
  218. package/dist/esm/index.mjs.map +1 -1
  219. package/dist/esm/index.native.js +2 -1
  220. package/dist/esm/index.native.js.map +1 -1
  221. package/dist/esm/shared/focusManagement.mjs +24 -11
  222. package/dist/esm/shared/focusManagement.mjs.map +1 -1
  223. package/dist/esm/shared/focusManagement.native.js +24 -11
  224. package/dist/esm/shared/focusManagement.native.js.map +1 -1
  225. package/dist/esm/shared/nativeA11y.mjs +31 -0
  226. package/dist/esm/shared/nativeA11y.mjs.map +1 -0
  227. package/dist/esm/shared/nativeA11y.native.js +32 -0
  228. package/dist/esm/shared/nativeA11y.native.js.map +1 -0
  229. package/dist/jsx/Button/index.mjs +1 -4
  230. package/dist/jsx/Button/index.mjs.map +1 -1
  231. package/dist/jsx/Button/index.native.js +5 -6
  232. package/dist/jsx/Button/index.native.js.map +1 -1
  233. package/dist/jsx/Chip/index.mjs +1 -1
  234. package/dist/jsx/Chip/index.mjs.map +1 -1
  235. package/dist/jsx/Chip/index.native.js +1 -1
  236. package/dist/jsx/Chip/index.native.js.map +1 -1
  237. package/dist/jsx/FloatingPanel/index.mjs +58 -15
  238. package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
  239. package/dist/jsx/FloatingPanel/index.native.js +16 -7
  240. package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
  241. package/dist/jsx/FloatingPanel/nestedAction.mjs +11 -0
  242. package/dist/jsx/FloatingPanel/nestedAction.mjs.map +1 -0
  243. package/dist/jsx/FloatingPanel/nestedAction.native.js +42 -0
  244. package/dist/jsx/FloatingPanel/nestedAction.native.js.map +1 -0
  245. package/dist/jsx/InputParts/index.mjs +20 -9
  246. package/dist/jsx/InputParts/index.mjs.map +1 -1
  247. package/dist/jsx/InputParts/index.native.js +20 -11
  248. package/dist/jsx/InputParts/index.native.js.map +1 -1
  249. package/dist/jsx/Wheel/index.mjs +3 -3
  250. package/dist/jsx/Wheel/index.mjs.map +1 -1
  251. package/dist/jsx/Wheel/index.native.js +3 -3
  252. package/dist/jsx/Wheel/index.native.js.map +1 -1
  253. package/dist/jsx/fieldLayout.mjs +3 -3
  254. package/dist/jsx/fieldLayout.mjs.map +1 -1
  255. package/dist/jsx/fieldLayout.native.js +3 -3
  256. package/dist/jsx/fieldLayout.native.js.map +1 -1
  257. package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.mjs +8 -1
  258. package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.mjs.map +1 -1
  259. package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.native.js +10 -1
  260. package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
  261. package/dist/jsx/fields/Combobox/index.mjs +36 -29
  262. package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
  263. package/dist/jsx/fields/Combobox/index.native.js +38 -38
  264. package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
  265. package/dist/jsx/fields/DatePicker/Calendar.mjs +6 -1
  266. package/dist/jsx/fields/DatePicker/Calendar.mjs.map +1 -1
  267. package/dist/jsx/fields/DatePicker/Calendar.native.js +6 -1
  268. package/dist/jsx/fields/DatePicker/Calendar.native.js.map +1 -1
  269. package/dist/jsx/fields/DatePicker/DateRangePicker.mjs +2 -2
  270. package/dist/jsx/fields/DatePicker/DateRangePicker.mjs.map +1 -1
  271. package/dist/jsx/fields/DatePicker/DateRangePicker.native.js +2 -2
  272. package/dist/jsx/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  273. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs +15 -12
  274. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
  275. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js +16 -12
  276. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  277. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +39 -14
  278. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  279. package/dist/jsx/fields/DatePicker/MonthPicker.mjs +10 -3
  280. package/dist/jsx/fields/DatePicker/MonthPicker.mjs.map +1 -1
  281. package/dist/jsx/fields/DatePicker/MonthPicker.native.js +10 -3
  282. package/dist/jsx/fields/DatePicker/MonthPicker.native.js.map +1 -1
  283. package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs +2 -2
  284. package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
  285. package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js +2 -2
  286. package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  287. package/dist/jsx/fields/DatePicker/index.native.js +3 -0
  288. package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
  289. package/dist/jsx/fields/DatePicker/parts.mjs +28 -16
  290. package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
  291. package/dist/jsx/fields/DatePicker/parts.native.js +28 -14
  292. package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
  293. package/dist/jsx/fields/FileUpload/index.mjs +6 -0
  294. package/dist/jsx/fields/FileUpload/index.mjs.map +1 -1
  295. package/dist/jsx/fields/FileUpload/index.native.js +6 -0
  296. package/dist/jsx/fields/FileUpload/index.native.js.map +1 -1
  297. package/dist/jsx/fields/Geolocation/GeolocationMap.mjs.map +1 -1
  298. package/dist/jsx/fields/Geolocation/GeolocationMap.native.js.map +1 -1
  299. package/dist/jsx/fields/Geolocation/geocoder.mjs +33 -0
  300. package/dist/jsx/fields/Geolocation/geocoder.mjs.map +1 -0
  301. package/dist/jsx/fields/Geolocation/geocoder.native.js +68 -0
  302. package/dist/jsx/fields/Geolocation/geocoder.native.js.map +1 -0
  303. package/dist/jsx/fields/Geolocation/index.mjs +792 -149
  304. package/dist/jsx/fields/Geolocation/index.mjs.map +1 -1
  305. package/dist/jsx/fields/Geolocation/index.native.js +856 -167
  306. package/dist/jsx/fields/Geolocation/index.native.js.map +1 -1
  307. package/dist/jsx/fields/Geolocation/nativeSearchFocus.mjs +19 -0
  308. package/dist/jsx/fields/Geolocation/nativeSearchFocus.mjs.map +1 -0
  309. package/dist/jsx/fields/Geolocation/nativeSearchFocus.native.js +47 -0
  310. package/dist/jsx/fields/Geolocation/nativeSearchFocus.native.js.map +1 -0
  311. package/dist/jsx/fields/Icon/drawnSet.mjs +16 -3
  312. package/dist/jsx/fields/Icon/drawnSet.mjs.map +1 -1
  313. package/dist/jsx/fields/Icon/drawnSet.native.js +20 -3
  314. package/dist/jsx/fields/Icon/drawnSet.native.js.map +1 -1
  315. package/dist/jsx/fields/Icon/index.mjs +93 -18
  316. package/dist/jsx/fields/Icon/index.mjs.map +1 -1
  317. package/dist/jsx/fields/Icon/index.native.js +115 -31
  318. package/dist/jsx/fields/Icon/index.native.js.map +1 -1
  319. package/dist/jsx/fields/Input/index.mjs +5 -12
  320. package/dist/jsx/fields/Input/index.mjs.map +1 -1
  321. package/dist/jsx/fields/Input/index.native.js +5 -13
  322. package/dist/jsx/fields/Input/index.native.js.map +1 -1
  323. package/dist/jsx/fields/PhoneInput/index.mjs +2 -2
  324. package/dist/jsx/fields/PhoneInput/index.mjs.map +1 -1
  325. package/dist/jsx/fields/PhoneInput/index.native.js +2 -2
  326. package/dist/jsx/fields/PhoneInput/index.native.js.map +1 -1
  327. package/dist/jsx/fields/RadioGroup/index.mjs +34 -5
  328. package/dist/jsx/fields/RadioGroup/index.mjs.map +1 -1
  329. package/dist/jsx/fields/RadioGroup/index.native.js +49 -7
  330. package/dist/jsx/fields/RadioGroup/index.native.js.map +1 -1
  331. package/dist/jsx/fields/SearchInput/index.mjs +9 -10
  332. package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
  333. package/dist/jsx/fields/SearchInput/index.native.js +8 -9
  334. package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
  335. package/dist/jsx/fields/Select/index.mjs +42 -11
  336. package/dist/jsx/fields/Select/index.mjs.map +1 -1
  337. package/dist/jsx/fields/Select/index.native.js +52 -20
  338. package/dist/jsx/fields/Select/index.native.js.map +1 -1
  339. package/dist/jsx/fields/Stepper/index.mjs +145 -32
  340. package/dist/jsx/fields/Stepper/index.mjs.map +1 -1
  341. package/dist/jsx/fields/Stepper/index.native.js +151 -31
  342. package/dist/jsx/fields/Stepper/index.native.js.map +1 -1
  343. package/dist/jsx/fields/ToggleGroup/index.mjs +35 -2
  344. package/dist/jsx/fields/ToggleGroup/index.mjs.map +1 -1
  345. package/dist/jsx/fields/ToggleGroup/index.native.js +42 -2
  346. package/dist/jsx/fields/ToggleGroup/index.native.js.map +1 -1
  347. package/dist/jsx/index.js +2 -1
  348. package/dist/jsx/index.js.map +1 -1
  349. package/dist/jsx/index.mjs +2 -1
  350. package/dist/jsx/index.mjs.map +1 -1
  351. package/dist/jsx/index.native.js +2 -0
  352. package/dist/jsx/index.native.js.map +1 -1
  353. package/dist/jsx/shared/focusManagement.mjs +24 -11
  354. package/dist/jsx/shared/focusManagement.mjs.map +1 -1
  355. package/dist/jsx/shared/focusManagement.native.js +24 -11
  356. package/dist/jsx/shared/focusManagement.native.js.map +1 -1
  357. package/dist/jsx/shared/nativeA11y.mjs +31 -0
  358. package/dist/jsx/shared/nativeA11y.mjs.map +1 -0
  359. package/dist/jsx/shared/nativeA11y.native.js +61 -0
  360. package/dist/jsx/shared/nativeA11y.native.js.map +1 -0
  361. package/package.json +9 -7
  362. package/src/Button/Button.fontWeight.spec.tsx +75 -0
  363. package/src/Button/Button.labelInk.spec.tsx +21 -18
  364. package/src/Button/Button.outlinedChannel.spec.tsx +46 -0
  365. package/src/Button/Button.sizeLadder.spec.tsx +4 -3
  366. package/src/Button/Button.stories.tsx +20 -0
  367. package/src/Button/index.tsx +30 -7
  368. package/src/Chip/Chip.spec.tsx +3 -1
  369. package/src/Chip/index.tsx +1 -5
  370. package/src/FieldGroup.stories.tsx +3 -7
  371. package/src/FieldLayout.stories.tsx +75 -12
  372. package/src/Fieldset.stories.tsx +3 -7
  373. package/src/FloatingPanel/FloatingPanel.native.spec.tsx +54 -0
  374. package/src/FloatingPanel/FloatingPanel.spec.tsx +109 -0
  375. package/src/FloatingPanel/index.native.tsx +24 -7
  376. package/src/FloatingPanel/index.tsx +80 -13
  377. package/src/FloatingPanel/nestedAction.spec.ts +36 -0
  378. package/src/FloatingPanel/nestedAction.ts +15 -0
  379. package/src/FloatingPanel/panelWidthContract.spec.ts +12 -15
  380. package/src/FormGrid.stories.tsx +5 -11
  381. package/src/FormsIntegration.stories.tsx +2 -6
  382. package/src/InputParts/InputButton.spec.tsx +16 -0
  383. package/src/InputParts/index.tsx +34 -7
  384. package/src/InputParts/layoutGap.spec.tsx +43 -0
  385. package/src/Wheel/Wheel.spec.tsx +16 -0
  386. package/src/Wheel/index.tsx +3 -3
  387. package/src/fieldFamilyStories.radius.spec.tsx +118 -0
  388. package/src/fieldLayout.spec.tsx +42 -1
  389. package/src/fieldLayout.tsx +9 -9
  390. package/src/fields/Barcode/Barcode.spec.tsx +2 -0
  391. package/src/fields/Checkbox/CheckboxFieldFrame.spec.tsx +18 -0
  392. package/src/fields/Checkbox/CheckboxFieldFrame.tsx +6 -1
  393. package/src/fields/Combobox/Combobox.spec.tsx +48 -1
  394. package/src/fields/Combobox/index.tsx +53 -39
  395. package/src/fields/DatePicker/Calendar.tsx +4 -1
  396. package/src/fields/DatePicker/DatePicker.stories.tsx +22 -1
  397. package/src/fields/DatePicker/DateRangePicker.tsx +4 -2
  398. package/src/fields/DatePicker/DatetimePicker.catalog.tsx +21 -19
  399. package/src/fields/DatePicker/DatetimePicker.native.spec.tsx +144 -0
  400. package/src/fields/DatePicker/DatetimePicker.native.tsx +57 -32
  401. package/src/fields/DatePicker/DatetimePicker.stories.tsx +22 -0
  402. package/src/fields/DatePicker/MonthPicker.tsx +8 -3
  403. package/src/fields/DatePicker/MultiDatePicker.tsx +4 -2
  404. package/src/fields/DatePicker/index.native.tsx +1 -0
  405. package/src/fields/DatePicker/parts.spec.tsx +56 -0
  406. package/src/fields/DatePicker/parts.tsx +33 -12
  407. package/src/fields/FileUpload/FileUpload.spec.tsx +29 -0
  408. package/src/fields/FileUpload/index.tsx +6 -0
  409. package/src/fields/Geolocation/Geolocation.spec.tsx +287 -35
  410. package/src/fields/Geolocation/Geolocation.stories.tsx +141 -7
  411. package/src/fields/Geolocation/GeolocationMap.native.tsx +3 -0
  412. package/src/fields/Geolocation/GeolocationMap.tsx +4 -0
  413. package/src/fields/Geolocation/geocoder.spec.ts +59 -0
  414. package/src/fields/Geolocation/geocoder.ts +84 -0
  415. package/src/fields/Geolocation/geocoderSeam.spec.tsx +203 -0
  416. package/src/fields/Geolocation/index.tsx +912 -180
  417. package/src/fields/Geolocation/nativeSearchFocus.spec.ts +34 -0
  418. package/src/fields/Geolocation/nativeSearchFocus.ts +19 -0
  419. package/src/fields/Geolocation/salvage.spec.tsx +398 -0
  420. package/src/fields/Geolocation/storyProviders.spec.tsx +44 -0
  421. package/src/fields/Icon/Icon.spec.tsx +215 -1
  422. package/src/fields/Icon/Icon.stories.tsx +9 -1
  423. package/src/fields/Icon/drawnSet.tsx +44 -4
  424. package/src/fields/Icon/index.tsx +118 -18
  425. package/src/fields/Input/Input.copy.spec.tsx +1 -0
  426. package/src/fields/Input/Input.spec.tsx +50 -0
  427. package/src/fields/Input/Input.stories.tsx +1 -1
  428. package/src/fields/Input/index.tsx +7 -13
  429. package/src/fields/PhoneInput/index.tsx +2 -2
  430. package/src/fields/RadioGroup/RadioGroup.native.spec.tsx +67 -0
  431. package/src/fields/RadioGroup/index.tsx +82 -8
  432. package/src/fields/SearchInput/SearchInput.spec.tsx +14 -0
  433. package/src/fields/SearchInput/index.tsx +5 -6
  434. package/src/fields/Select/Select.spec.tsx +54 -0
  435. package/src/fields/Select/index.tsx +52 -17
  436. package/src/fields/Stepper/Stepper.spec.tsx +34 -1
  437. package/src/fields/Stepper/index.tsx +193 -33
  438. package/src/fields/ToggleGroup/ToggleGroup.native.spec.tsx +73 -0
  439. package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +49 -0
  440. package/src/fields/ToggleGroup/index.tsx +76 -1
  441. package/src/index.ts +9 -0
  442. package/src/shared/focusManagement.spec.tsx +68 -0
  443. package/src/shared/focusManagement.ts +20 -10
  444. package/src/shared/nativeA11y.spec.ts +64 -0
  445. package/src/shared/nativeA11y.ts +80 -0
  446. package/types/Button/index.d.ts +22 -3
  447. package/types/Button/index.d.ts.map +1 -1
  448. package/types/Chip/index.d.ts.map +1 -1
  449. package/types/FloatingPanel/index.d.ts +11 -1
  450. package/types/FloatingPanel/index.d.ts.map +1 -1
  451. package/types/FloatingPanel/index.native.d.ts +2 -1
  452. package/types/FloatingPanel/index.native.d.ts.map +1 -1
  453. package/types/FloatingPanel/nestedAction.d.ts +13 -0
  454. package/types/FloatingPanel/nestedAction.d.ts.map +1 -0
  455. package/types/InputParts/index.d.ts.map +1 -1
  456. package/types/fields/Checkbox/CheckboxFieldFrame.d.ts +46 -2
  457. package/types/fields/Checkbox/CheckboxFieldFrame.d.ts.map +1 -1
  458. package/types/fields/Checkbox/index.d.ts +3 -3
  459. package/types/fields/Combobox/index.d.ts +3 -1
  460. package/types/fields/Combobox/index.d.ts.map +1 -1
  461. package/types/fields/DatePicker/Calendar.d.ts.map +1 -1
  462. package/types/fields/DatePicker/DateRangePicker.d.ts.map +1 -1
  463. package/types/fields/DatePicker/DatetimePicker.catalog.d.ts.map +1 -1
  464. package/types/fields/DatePicker/DatetimePicker.native.d.ts.map +1 -1
  465. package/types/fields/DatePicker/MonthPicker.d.ts.map +1 -1
  466. package/types/fields/DatePicker/MultiDatePicker.d.ts.map +1 -1
  467. package/types/fields/DatePicker/index.native.d.ts.map +1 -1
  468. package/types/fields/DatePicker/parts.d.ts.map +1 -1
  469. package/types/fields/FileUpload/index.d.ts.map +1 -1
  470. package/types/fields/Geolocation/GeolocationMap.d.ts +4 -0
  471. package/types/fields/Geolocation/GeolocationMap.d.ts.map +1 -1
  472. package/types/fields/Geolocation/GeolocationMap.native.d.ts +3 -0
  473. package/types/fields/Geolocation/GeolocationMap.native.d.ts.map +1 -1
  474. package/types/fields/Geolocation/geocoder.d.ts +53 -0
  475. package/types/fields/Geolocation/geocoder.d.ts.map +1 -0
  476. package/types/fields/Geolocation/index.d.ts +18 -2
  477. package/types/fields/Geolocation/index.d.ts.map +1 -1
  478. package/types/fields/Geolocation/nativeSearchFocus.d.ts +8 -0
  479. package/types/fields/Geolocation/nativeSearchFocus.d.ts.map +1 -0
  480. package/types/fields/Icon/drawnSet.d.ts.map +1 -1
  481. package/types/fields/Icon/index.d.ts.map +1 -1
  482. package/types/fields/Input/index.d.ts.map +1 -1
  483. package/types/fields/PhoneInput/index.d.ts.map +1 -1
  484. package/types/fields/RadioGroup/index.d.ts +30 -3
  485. package/types/fields/RadioGroup/index.d.ts.map +1 -1
  486. package/types/fields/SearchInput/index.d.ts.map +1 -1
  487. package/types/fields/Select/index.d.ts.map +1 -1
  488. package/types/fields/Stepper/index.d.ts.map +1 -1
  489. package/types/fields/ToggleGroup/index.d.ts +31 -2
  490. package/types/fields/ToggleGroup/index.d.ts.map +1 -1
  491. package/types/index.d.ts +2 -0
  492. package/types/index.d.ts.map +1 -1
  493. package/types/shared/focusManagement.d.ts +2 -2
  494. package/types/shared/focusManagement.d.ts.map +1 -1
  495. package/types/shared/nativeA11y.d.ts +61 -0
  496. package/types/shared/nativeA11y.d.ts.map +1 -0
  497. package/src/router.d.ts +0 -16
@@ -0,0 +1,36 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { isNestedPanelAction } from "./nestedAction";
3
+
4
+ describe("independent actions inside panel triggers", () => {
5
+ it("recognizes an SVG descendant of a marked action", () => {
6
+ const wrapper = document.createElement("div");
7
+ wrapper.innerHTML = '<button data-floating-panel-action="true"><svg><path /></svg></button>';
8
+ expect(
9
+ isNestedPanelAction({
10
+ nativeEvent: { target: wrapper.querySelector("path") },
11
+ currentTarget: wrapper,
12
+ }),
13
+ ).toBe(true);
14
+ });
15
+
16
+ it("does not let a marker above the wrapper suppress an ordinary opener", () => {
17
+ const outer = document.createElement("div");
18
+ outer.setAttribute("data-floating-panel-action", "true");
19
+ outer.innerHTML = "<div><button>Open</button></div>";
20
+ expect(
21
+ isNestedPanelAction({
22
+ target: outer.querySelector("button"),
23
+ currentTarget: outer.firstElementChild,
24
+ }),
25
+ ).toBe(false);
26
+ });
27
+
28
+ it("keeps unmarked buttons and non-DOM events as ordinary trigger presses", () => {
29
+ const wrapper = document.createElement("div");
30
+ wrapper.innerHTML = "<button>Open</button>";
31
+ expect(isNestedPanelAction({ target: wrapper.firstElementChild, currentTarget: wrapper })).toBe(
32
+ false,
33
+ );
34
+ expect(isNestedPanelAction({})).toBe(false);
35
+ });
36
+ });
@@ -0,0 +1,15 @@
1
+ export const floatingPanelActionProps = { "data-floating-panel-action": "true" } as const;
2
+
3
+ export interface PanelActionEvent {
4
+ target?: unknown;
5
+ currentTarget?: unknown;
6
+ nativeEvent?: { target?: unknown };
7
+ }
8
+
9
+ /** Marked actions inside a trigger keep their own press and keyboard behavior. */
10
+ export function isNestedPanelAction(event: PanelActionEvent): boolean {
11
+ const target = (event.nativeEvent?.target ?? event.target) as Element | null;
12
+ const wrapper = event.currentTarget as Element | null;
13
+ const action = target?.closest?.('[data-floating-panel-action="true"]');
14
+ return !!action && !!wrapper?.contains?.(action);
15
+ }
@@ -1,6 +1,5 @@
1
1
  /**
2
- * MPO-38 AC: no FloatingPanel consumer renders a panel narrower than its
3
- * trigger.
2
+ * Text listboxes match the field width; intrinsic editors size to their content.
4
3
  *
5
4
  * The runtime half is covered in `useFloatingPanel.spec.tsx`. This is the
6
5
  * source half, and it exists because the defect it guards is invisible at
@@ -8,11 +7,9 @@
8
7
  * DatePicker measured 262px of calendar under a 289px trigger purely because
9
8
  * the call site said `fitContent`.
10
9
  *
11
- * A FIELD-shaped trigger (a control the user reads a value out of) takes
12
- * `at-least-trigger`. A BUTTON-shaped trigger — an icon, a toolbar chip —
13
- * legitimately keeps `fit-content`, because matching a 32px button would be
14
- * absurd; those are listed explicitly so the exemption is a decision rather
15
- * than an oversight.
10
+ * Calendar grids take fit-content (MPO-262): a full-width field wrapper is
11
+ * unrelated to seven day columns and must not create a mostly empty popup.
12
+ * Text listboxes retain at-least-trigger; icon/button launchers may also hug.
16
13
  */
17
14
  import { readFileSync } from "node:fs";
18
15
  import { dirname, resolve } from "node:path";
@@ -22,13 +19,9 @@ import { describe, expect, it } from "vitest";
22
19
  const fieldsDir = resolve(dirname(fileURLToPath(import.meta.url)), "..", "fields");
23
20
 
24
21
  /** Pickers whose trigger is a form FIELD: the panel may never be narrower. */
25
- const fieldShapedPickers = [
26
- "DatePicker/parts.tsx",
27
- "DatePicker/DatetimePicker.catalog.tsx",
28
- "TimePicker/catalog.tsx",
29
- "ColorPicker/parts.tsx",
30
- "Icon/index.tsx",
31
- ];
22
+ const fieldShapedPickers = ["TimePicker/catalog.tsx", "ColorPicker/parts.tsx", "Icon/index.tsx"];
23
+
24
+ const intrinsicGridPickers = ["DatePicker/parts.tsx", "DatePicker/DatetimePicker.catalog.tsx"];
32
25
 
33
26
  /** Panels opened from an icon/button trigger, where fit-content is correct. */
34
27
  const buttonShapedPickers = ["Geolocation/index.tsx"];
@@ -37,7 +30,11 @@ function read(relative: string): string {
37
30
  return readFileSync(resolve(fieldsDir, relative), "utf8");
38
31
  }
39
32
 
40
- describe("FloatingPanel width contract (MPO-38)", () => {
33
+ describe("FloatingPanel width contract (MPO-38, MPO-262)", () => {
34
+ it.each(intrinsicGridPickers)("%s hugs its calendar grid", (relative) => {
35
+ expect(read(relative)).toContain('widthMode="fit-content"');
36
+ });
37
+
41
38
  it.each(fieldShapedPickers)("%s declares at-least-trigger", (relative) => {
42
39
  const source = read(relative);
43
40
  expect(source).toContain('widthMode="at-least-trigger"');
@@ -1,9 +1,9 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
2
- import { Input as TamaguiInput, Paragraph, YStack } from "tamagui";
2
+ import { Paragraph, YStack } from "tamagui";
3
3
  import { FieldGroup } from "./FieldGroup";
4
4
  import { FormGrid } from "./FormGrid";
5
5
  import { FormSection, FormSectionStack } from "./FormSection";
6
- import { FieldLayout } from "./fieldLayout";
6
+ import { Input } from "./fields/Input";
7
7
 
8
8
  const meta: Meta<typeof FormGrid> = {
9
9
  title: "Forms/FormGrid",
@@ -24,11 +24,7 @@ export default meta;
24
24
  type Story = StoryObj<typeof FormGrid>;
25
25
 
26
26
  function GridField({ id, label }: { id: string; label: string }) {
27
- return (
28
- <FieldLayout id={id} label={label}>
29
- <TamaguiInput id={id} placeholder={label} />
30
- </FieldLayout>
31
- );
27
+ return <Input id={id} label={label} placeholder={label} />;
32
28
  }
33
29
 
34
30
  export const Basic: Story = {
@@ -99,13 +95,11 @@ export const LongErrors: Story = {
99
95
  render: () => (
100
96
  <YStack maxWidth={640}>
101
97
  <FormGrid columns={2}>
102
- <FieldLayout
98
+ <Input
103
99
  id="fge-a"
104
100
  label="With long error"
105
101
  error="This validation message is extremely long and should wrap inside its own grid cell without breaking the neighbouring column alignment or overflowing the grid container"
106
- >
107
- <TamaguiInput id="fge-a" />
108
- </FieldLayout>
102
+ />
109
103
  <GridField id="fge-b" label="Neighbour" />
110
104
  </FormGrid>
111
105
  </YStack>
@@ -212,9 +212,7 @@ export const multiStepRegistration: Story = {
212
212
  />
213
213
 
214
214
  <FormActions>
215
- <Button variant="outlined" onPress={() => setStep("personal")}>
216
- Back
217
- </Button>
215
+ <Button onPress={() => setStep("personal")}>Back</Button>
218
216
  <Button onPress={() => setStep("verification")}>Next: Verification</Button>
219
217
  </FormActions>
220
218
  </FormSection>
@@ -240,9 +238,7 @@ export const multiStepRegistration: Story = {
240
238
  />
241
239
 
242
240
  <FormActions>
243
- <Button variant="outlined" onPress={() => setStep("contact")}>
244
- Back
245
- </Button>
241
+ <Button onPress={() => setStep("contact")}>Back</Button>
246
242
  <form.Subscribe selector={(state) => [state.canSubmit, state.isSubmitting]}>
247
243
  {([canSubmit, isSubmitting]) => (
248
244
  <Button action="submit" disabled={!canSubmit || isSubmitting}>
@@ -40,6 +40,22 @@ describe("Input.Button", () => {
40
40
  expect(btn.contains(ring)).toBe(true);
41
41
  });
42
42
 
43
+ it("a bare string child is a LABEL, not an icon type to createElement", () => {
44
+ const result = renderWithProviders(
45
+ <Input size="$4">
46
+ <Input.Box size="$4">
47
+ <Input.Button size="$4" aria-label="cap">
48
+ Scan
49
+ </Input.Button>
50
+ </Input.Box>
51
+ </Input>,
52
+ );
53
+ const btn = result.container.querySelector("[aria-label='cap']") as HTMLElement;
54
+ expect(btn).not.toBeNull();
55
+ expect(btn.textContent).toContain("Scan");
56
+ expect(result.container.querySelector("scan")).toBeNull();
57
+ });
58
+
43
59
  it("end-cap square is generated from the size recipe at every token", () => {
44
60
  for (const token of SIZE_RECIPE_TOKENS) {
45
61
  if (token === "$true") continue;
@@ -1,6 +1,6 @@
1
1
  import { getFontSized } from "@tamagui/get-font-sized";
2
2
  import type { SizeVariantSpreadFunction } from "@tamagui/web";
3
- import { useEffect, useState, type ReactNode } from "react";
3
+ import { useCallback, useEffect, useState, type ReactNode } from "react";
4
4
  import type { ComponentProps, Ref, RefObject } from "react";
5
5
  import { Pressable as RNPressable } from "react-native";
6
6
  import type {
@@ -1035,6 +1035,33 @@ const InputButtonImpl = InputButton.styleable<{ glyphRing?: boolean }>((buttonPr
1035
1035
  size: knobProps.controlIcon.width,
1036
1036
  color: paint as never,
1037
1037
  });
1038
+ // A string/number child is a LABEL, not an icon. `getThemedIcon` treats an
1039
+ // un-elemented child as a component TYPE and `createElement`s it, so "Scan"
1040
+ // becomes an invented `<scan>` element that paints nothing (MPO-208); a bare
1041
+ // string under the glyphRing View is the same category error on native.
1042
+ const textChild =
1043
+ typeof children === "string" || typeof children === "number" ? (
1044
+ <Text
1045
+ {...knobProps.controlType}
1046
+ fontFamily={knobProps.body.fontFamily}
1047
+ fontWeight={knobProps.body.fontWeight}
1048
+ color={paint as never}
1049
+ numberOfLines={1}
1050
+ userSelect="none"
1051
+ >
1052
+ {children}
1053
+ </Text>
1054
+ ) : null;
1055
+ const decorativeRef = useCallback(
1056
+ (node: TamaguiElement | null) => {
1057
+ // Tamagui 2.7.6 Button stamps tabIndex=0 after consumer props.
1058
+ // Correct the host at hydration; decorative caps share the field stop.
1059
+ if (isWeb && node && "tabIndex" in node) node.tabIndex = tabIndexProp ?? -1;
1060
+ if (typeof ref === "function") ref(node);
1061
+ else if (ref) ref.current = node;
1062
+ },
1063
+ [ref, tabIndexProp],
1064
+ );
1038
1065
 
1039
1066
  if (glyphRing) {
1040
1067
  // A real tab stop must square off the token it was HANDED, not the
@@ -1068,7 +1095,7 @@ const InputButtonImpl = InputButton.styleable<{ glyphRing?: boolean }>((buttonPr
1068
1095
  alignItems="center"
1069
1096
  justifyContent="center"
1070
1097
  >
1071
- {children}
1098
+ {textChild ?? children}
1072
1099
  </View>
1073
1100
  </InputGlyphButton>
1074
1101
  );
@@ -1077,7 +1104,7 @@ const InputButtonImpl = InputButton.styleable<{ glyphRing?: boolean }>((buttonPr
1077
1104
  const square = knobProps.control.height;
1078
1105
  return (
1079
1106
  <InputButton
1080
- ref={ref}
1107
+ ref={decorativeRef}
1081
1108
  size={size}
1082
1109
  height={square}
1083
1110
  width={square}
@@ -1091,7 +1118,7 @@ const InputButtonImpl = InputButton.styleable<{ glyphRing?: boolean }>((buttonPr
1091
1118
  data-end-cap={square}
1092
1119
  {...props}
1093
1120
  >
1094
- {getThemedIcon(children)}
1121
+ {textChild ?? getThemedIcon(children)}
1095
1122
  </InputButton>
1096
1123
  );
1097
1124
  });
@@ -1166,9 +1193,8 @@ export const InputContainerFrame = styled(View, {
1166
1193
 
1167
1194
  variants: {
1168
1195
  size: {
1169
- "...size": (val, { tokens }) => ({
1170
- gap: (tokens.space[val] as any)?.val * 0.3,
1171
- }),
1196
+ // Size is shared with the child parts; layout spacing belongs to space.
1197
+ "...size": () => ({}),
1172
1198
  },
1173
1199
  color: {
1174
1200
  "...color": () => ({}),
@@ -1194,6 +1220,7 @@ const InputContainerImpl = InputContainerFrame.styleable((props, forwardedRef) =
1194
1220
  ref={forwardedRef}
1195
1221
  size={knobProps.sizeToken}
1196
1222
  {...knobProps.body}
1223
+ {...knobProps.gap}
1197
1224
  // LC-06/LC-10 (UX-P12): inside a table cell the field root must adopt
1198
1225
  // the cell width — the raw web <input> carries an intrinsic width that
1199
1226
  // otherwise floors the whole column at ~200px and lays out past the
@@ -0,0 +1,43 @@
1
+ import { createRef } from "react";
2
+ import { Preset } from "@multiplatform.one/theme";
3
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
4
+ import { cleanup } from "@testing-library/react";
5
+ import { afterEach, expect, it } from "vitest";
6
+ import { Input } from "./index";
7
+
8
+ afterEach(cleanup);
9
+
10
+ function measure(size: "small" | "medium", space: "small" | "large", gap?: number) {
11
+ const ref = createRef<HTMLElement>();
12
+ const { getByTestId } = renderWithProviders(
13
+ <Preset overrides={{ size, space }}>
14
+ <Input testID="root" ref={ref as never} {...(gap === undefined ? {} : { gap })}>
15
+ <Input.Label>Location</Input.Label>
16
+ <Input.Box>
17
+ <Input.Area placeholder="Location" />
18
+ </Input.Box>
19
+ </Input>
20
+ </Preset>,
21
+ );
22
+ const root = getByTestId("root");
23
+ expect(ref.current).toBe(root);
24
+ // Happy DOM leaves token-backed CSS gaps unresolved; browser coverage reads
25
+ // the actual pixels. Keep this test checking the rendered gap owner.
26
+ const value =
27
+ getComputedStyle(root).gap || [...root.classList].find((name) => name.startsWith("_gap-"));
28
+ expect(value).toBeTruthy();
29
+ cleanup();
30
+ return value;
31
+ }
32
+
33
+ it("lets space change the multi-slot layout gap at a fixed control size", () => {
34
+ expect(measure("medium", "small")).not.toBe(measure("medium", "large"));
35
+ });
36
+
37
+ it("keeps the layout gap stable when only control size changes", () => {
38
+ expect(measure("small", "small")).toBe(measure("medium", "small"));
39
+ });
40
+
41
+ it("preserves the consumer gap eject and forwarded root ref", () => {
42
+ expect(measure("medium", "large", 11)).toBe("11px");
43
+ });
@@ -7,6 +7,22 @@ import { Wheel } from "./index";
7
7
  afterEach(cleanup);
8
8
 
9
9
  describe("Wheel contrast contract", () => {
10
+ it("uses the selected-text weight and keeps rounding on the selection band", () => {
11
+ renderWithProviders(
12
+ <Preset overrides={{ borderRadius: "full" }}>
13
+ <Wheel items={[1, 2, 3, 4, 5]} value={3} visibleItems={5} />
14
+ </Preset>,
15
+ );
16
+ const wheel = screen.getByTestId("wheel");
17
+ const selected = wheel.querySelector('[data-selected="true"]')?.firstElementChild;
18
+ expect(selected).toBeTruthy();
19
+ expect(["700", "bold"]).toContain(getComputedStyle(selected as Element).fontWeight);
20
+ expect(["", "0px"]).toContain(getComputedStyle(wheel).borderTopLeftRadius);
21
+ expect(getComputedStyle(screen.getByTestId("wheel-selection")).borderStartStartRadius).not.toBe(
22
+ "0px",
23
+ );
24
+ });
25
+
10
26
  it("keeps inactive item text on the AA $color11 ramp (not opacity-dimmed)", () => {
11
27
  renderWithProviders(
12
28
  <Wheel items={[1, 2, 3, 4, 5]} value={3} onChange={() => {}} visibleItems={5} />,
@@ -112,7 +112,7 @@ function ensureWheelFocusStyles() {
112
112
  const style = document.createElement("style");
113
113
  style.id = WHEEL_FOCUS_STYLE_ID;
114
114
  style.textContent =
115
- ".mp1-wheel-wrapper:focus-visible { outline: 2px solid var(--outlineColor, rgba(0,0,0,0.5)); outline-offset: -2px; }";
115
+ ".mp1-wheel-wrapper:focus-visible { outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText)); outline-offset: -2px; }";
116
116
  document.head.appendChild(style);
117
117
  }
118
118
 
@@ -847,7 +847,7 @@ export function Wheel<T = string | number>({
847
847
  <Text
848
848
  {...knobProps.body}
849
849
  fontSize={size}
850
- fontWeight={isSelected && !disabled ? "600" : "400"}
850
+ fontWeight={isSelected && !disabled ? "bold" : knobProps.textWeight.fontWeight}
851
851
  color={itemColor(isSelected)}
852
852
  numberOfLines={1}
853
853
  ellipsizeMode="tail"
@@ -865,7 +865,7 @@ export function Wheel<T = string | number>({
865
865
  width={flex ? "100%" : columnWidth}
866
866
  minWidth={flex ? 0 : columnWidth}
867
867
  flex={flex}
868
- {...knobProps.containerRadius}
868
+ borderRadius={0}
869
869
  data-testid="wheel"
870
870
  data-disabled={disabled ? true : undefined}
871
871
  aria-disabled={disabled || undefined}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * The four form LAYOUT stories must mount house field chrome, not a raw
3
+ * tamagui primitive.
4
+ *
5
+ * FieldLayout, FieldGroup, Fieldset and FormGrid paint no radius of their own —
6
+ * they are stacks, a grid and a legend. Whatever radius a probe reads off one
7
+ * of their stories belongs to the CONTROL the story chose to mount. A raw
8
+ * `Input` from "tamagui" consumes no knobs, so it pins one radius at every
9
+ * stop and the axis reads dead against a component that never had a say.
10
+ *
11
+ * The measurement here is therefore the STORY's, not the component's: walk the
12
+ * borderRadius knob and assert the control inside each story tracks it.
13
+ *
14
+ * Under jsdom the providers inject no CSS and the radius atom keeps its token
15
+ * reference (`_btlr-t-radius-4`) rather than resolving to `9px`, so this file
16
+ * gates the token ladder. The pixel ladder (0/5/9/16/50) and the dark scheme
17
+ * are measured for real by scripts/knob-axis-probe.mjs against a browser.
18
+ */
19
+
20
+ import { cleanup } from "@testing-library/react";
21
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
22
+ import { Preset, type BorderRadius } from "@multiplatform.one/theme";
23
+ import type { ReactElement } from "react";
24
+ import { afterEach, describe, expect, it } from "vitest";
25
+
26
+ import * as fieldGroupStories from "./FieldGroup.stories";
27
+ import * as fieldLayoutStories from "./FieldLayout.stories";
28
+ import * as fieldsetStories from "./Fieldset.stories";
29
+ import * as formGridStories from "./FormGrid.stories";
30
+
31
+ afterEach(cleanup);
32
+
33
+ /** Knob stop -> radius token index, the `$N` the resolver hands the frame. */
34
+ const ladder: Record<BorderRadius, string> = {
35
+ none: "0",
36
+ small: "2",
37
+ medium: "4",
38
+ large: "6",
39
+ full: "12",
40
+ };
41
+ const stops = Object.keys(ladder) as BorderRadius[];
42
+
43
+ type StoryLike = { render?: (args: Record<string, unknown>) => ReactElement };
44
+
45
+ /** Every radius token present in the subtree, deduped — the probe's reading. */
46
+ function radiusTokens(container: HTMLElement): string[] {
47
+ const found = new Set<string>();
48
+ for (const el of container.querySelectorAll<HTMLElement>("*")) {
49
+ for (const cls of String(el.className || "").split(/\s+/)) {
50
+ const match = /^_btlr-t-radius-(\d+)$/.exec(cls);
51
+ if (match) found.add(match[1]);
52
+ }
53
+ }
54
+ return [...found].sort();
55
+ }
56
+
57
+ function mountAt(story: StoryLike, meta: { args?: unknown }, stop: BorderRadius) {
58
+ if (!story.render) throw new Error("story has no render");
59
+ return renderWithProviders(
60
+ <Preset overrides={{ borderRadius: stop, elevation: "none" }}>
61
+ {story.render({ ...((meta.args ?? {}) as Record<string, unknown>) })}
62
+ </Preset>,
63
+ );
64
+ }
65
+
66
+ const family = [
67
+ {
68
+ name: "Forms/FieldLayout",
69
+ story: fieldLayoutStories.Basic as StoryLike,
70
+ meta: fieldLayoutStories.default,
71
+ },
72
+ {
73
+ name: "Forms/FieldGroup",
74
+ story: fieldGroupStories.Basic as StoryLike,
75
+ meta: fieldGroupStories.default,
76
+ },
77
+ {
78
+ name: "Forms/Fieldset",
79
+ story: fieldsetStories.Default as StoryLike,
80
+ meta: fieldsetStories.default,
81
+ },
82
+ {
83
+ name: "Forms/FormGrid",
84
+ story: formGridStories.Basic as StoryLike,
85
+ meta: formGridStories.default,
86
+ },
87
+ ];
88
+
89
+ describe("form layout stories mount knob-consuming field chrome", () => {
90
+ for (const { name, story, meta } of family) {
91
+ describe(name, () => {
92
+ // A story that fails to render measures flat on every axis, which reads
93
+ // exactly like a dead knob. Prove there is a control before believing
94
+ // anything measured off it.
95
+ it("renders a text control at all", () => {
96
+ const { container } = mountAt(story, meta as { args?: unknown }, "medium");
97
+ expect(container.querySelectorAll("input").length).toBeGreaterThan(0);
98
+ });
99
+
100
+ for (const stop of stops) {
101
+ it(`takes radius token $${ladder[stop]} at borderRadius:${stop}`, () => {
102
+ const { container } = mountAt(story, meta as { args?: unknown }, stop);
103
+ expect(radiusTokens(container)).toContain(ladder[stop]);
104
+ });
105
+ }
106
+
107
+ it("moves across all five stops instead of pinning one radius", () => {
108
+ const signatures = stops.map((stop) => {
109
+ const result = mountAt(story, meta as { args?: unknown }, stop);
110
+ const tokens = JSON.stringify(radiusTokens(result.container));
111
+ cleanup();
112
+ return tokens;
113
+ });
114
+ expect(new Set(signatures).size).toBe(stops.length);
115
+ });
116
+ });
117
+ }
118
+ });
@@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
2
  import { renderWithProviders } from "@multiplatform.one/test-utils";
3
3
  import { Preset } from "@multiplatform.one/theme";
4
4
  import { Input as TamaguiInput } from "tamagui";
5
- import { FieldLayout } from "./fieldLayout";
5
+ import { FieldLayout, useFieldDescribedBy } from "./fieldLayout";
6
6
  import { __resetDevWarnSeen } from "./shared/devWarn";
7
7
 
8
8
  function classIncludes(container: HTMLElement, fragment: string): boolean {
@@ -188,6 +188,47 @@ describe("FieldLayout error precedence (Axiom 5 eject-last)", () => {
188
188
  });
189
189
  });
190
190
 
191
+ describe("FieldLayout message-before-control anatomy", () => {
192
+ function Control() {
193
+ return <input id="ordered" aria-describedby={useFieldDescribedBy()} />;
194
+ }
195
+
196
+ for (const mode of ["top", "side", "compact"] as const) {
197
+ it(`${mode}: helper and replacement error precede the control and describe only the rendered slot`, () => {
198
+ const renderField = (error?: string) => (
199
+ <Preset overrides={{ fieldLabelPlacement: mode === "side" ? "side" : "top" }}>
200
+ <FieldLayout
201
+ id="ordered"
202
+ label="Email"
203
+ compactSpacing={mode === "compact"}
204
+ helperText="Use your work address"
205
+ error={error}
206
+ >
207
+ <Control />
208
+ </FieldLayout>
209
+ </Preset>
210
+ );
211
+ const result = renderWithProviders(renderField());
212
+ const assertSlot = (id: string, text: string) => {
213
+ const input = result.container.querySelector("input")!;
214
+ const message = result.container.querySelector(`#${id}`)!;
215
+ expect(message.textContent).toBe(text);
216
+ expect(
217
+ message.compareDocumentPosition(input) & Node.DOCUMENT_POSITION_FOLLOWING,
218
+ ).toBeTruthy();
219
+ expect(input.getAttribute("aria-describedby")).toBe(id);
220
+ expect(
221
+ result.container.querySelectorAll("[id$='-description'], [id$='-error']"),
222
+ ).toHaveLength(1);
223
+ };
224
+ assertSlot("ordered-description", "Use your work address");
225
+ result.rerender(renderField("Enter an email address"));
226
+ assertSlot("ordered-error", "Enter an email address");
227
+ expect(result.container.textContent).not.toContain("Use your work address");
228
+ });
229
+ }
230
+ });
231
+
191
232
  describe("FieldLayout banned-error-word DEV warn", () => {
192
233
  let warnSpy: ReturnType<typeof vi.spyOn>;
193
234
 
@@ -218,13 +218,13 @@ export function FieldLayout({
218
218
  ...(width !== undefined ? { width } : {}),
219
219
  };
220
220
 
221
- const describedBy =
222
- [
223
- helperText && id ? `${id}-description` : undefined,
224
- errorMessage && id ? `${id}-error` : undefined,
225
- ]
226
- .filter(Boolean)
227
- .join(" ") || undefined;
221
+ const describedBy = id
222
+ ? errorMessage
223
+ ? `${id}-error`
224
+ : helperText
225
+ ? `${id}-description`
226
+ : undefined
227
+ : undefined;
228
228
 
229
229
  const a11yLabel = typeof label === "string" ? `${label}${requiredSuffix}` : ariaLabel;
230
230
  const a11yDescription = errorMessage ?? helperText;
@@ -293,9 +293,9 @@ export function FieldLayout({
293
293
 
294
294
  const controlColumn = (
295
295
  <YStack flex={sideLabel ? 1 : undefined} {...gapProps}>
296
- {children}
297
296
  {helperNode}
298
297
  {errorNode}
298
+ {children}
299
299
  </YStack>
300
300
  );
301
301
 
@@ -330,9 +330,9 @@ export function FieldLayout({
330
330
  ) : (
331
331
  <>
332
332
  {labelNode}
333
- {children}
334
333
  {helperNode}
335
334
  {errorNode}
335
+ {children}
336
336
  </>
337
337
  )}
338
338
  </YStack>
@@ -102,6 +102,8 @@ describe("Barcode", () => {
102
102
  const button = result.container.querySelector("[aria-label='Scan barcode']");
103
103
  expect(button).not.toBeNull();
104
104
  expect(button?.textContent).toContain("Scan");
105
+ expect(button?.querySelector("scan")).toBeNull();
106
+ expect(result.container.querySelector("scan")).toBeNull();
105
107
  });
106
108
 
107
109
  it("renders readOnly — hides scan button", () => {
@@ -11,6 +11,8 @@
11
11
  import { cleanup } from "@testing-library/react";
12
12
  import { renderWithProviders } from "@multiplatform.one/test-utils";
13
13
  import { afterEach, describe, expect, it } from "vitest";
14
+ import { createRef } from "react";
15
+ import { FieldLayout } from "../../fieldLayout";
14
16
  import { CheckboxFieldFrame } from "./CheckboxFieldFrame";
15
17
 
16
18
  afterEach(cleanup);
@@ -31,6 +33,22 @@ function frame(container: HTMLElement): HTMLElement {
31
33
  }
32
34
 
33
35
  describe("CheckboxFieldFrame", () => {
36
+ it("links the rendered field message, forwards its ref, and preserves an explicit description", () => {
37
+ const ref = createRef<any>();
38
+ const fixture = (override?: { "aria-describedby": string | undefined }) => (
39
+ <FieldLayout id="consent" helperText="Read the terms" error="Accept the terms">
40
+ <CheckboxFieldFrame id="consent" checked={false} ref={ref} {...override} />
41
+ </FieldLayout>
42
+ );
43
+ const result = renderWithProviders(fixture());
44
+ expect(frame(result.container).getAttribute("aria-describedby")).toBe("consent-error");
45
+ expect(ref.current).toBe(frame(result.container));
46
+ result.rerender(fixture({ "aria-describedby": "consumer-description" }));
47
+ expect(frame(result.container).getAttribute("aria-describedby")).toBe("consumer-description");
48
+ result.rerender(fixture({ "aria-describedby": undefined }));
49
+ expect(frame(result.container).getAttribute("aria-describedby")).toBeNull();
50
+ });
51
+
34
52
  it("still renders a real role=checkbox, so the styling never costs the semantics", () => {
35
53
  const { container } = renderWithProviders(<CheckboxFieldFrame checked={false} />);
36
54
  expect(frame(container)).toBeTruthy();
@@ -1,7 +1,8 @@
1
1
  import { Checkbox as TamaguiCheckbox, styled } from "tamagui";
2
+ import { useFieldDescribedBy } from "../../fieldLayout";
2
3
 
3
4
  /** Hit-target frame. The painted box is CheckboxGlyphBox (LC-71). */
4
- export const CheckboxFieldFrame = styled(TamaguiCheckbox, {
5
+ const CheckboxFieldFrameBase = styled(TamaguiCheckbox, {
5
6
  backgroundColor: "transparent",
6
7
  borderColor: "transparent",
7
8
  borderWidth: 0,
@@ -21,3 +22,7 @@ export const CheckboxFieldFrame = styled(TamaguiCheckbox, {
21
22
  },
22
23
  activeStyle: { backgroundColor: "transparent", borderColor: "transparent" },
23
24
  });
25
+
26
+ export const CheckboxFieldFrame = CheckboxFieldFrameBase.styleable((props, ref) => (
27
+ <CheckboxFieldFrameBase aria-describedby={useFieldDescribedBy()} {...props} ref={ref} />
28
+ ));