@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
@@ -122,10 +122,13 @@ describe("Stepper", () => {
122
122
  });
123
123
  const increase = result.container.querySelector('[aria-label="Increase"]') as HTMLElement;
124
124
  await act(async () => {
125
- fireEvent.pointerDown(increase);
125
+ expect(fireEvent.pointerDown(increase)).toBe(false);
126
+ fireEvent.pointerUp(increase);
126
127
  });
127
128
  expect(increase).not.toBe(document.activeElement);
128
129
  expect(document.activeElement).toBe(input);
130
+ expect(input.value).toBe("5");
131
+ expect(increase.getAttribute("tabindex")).toBe("-1");
129
132
  });
130
133
  });
131
134
 
@@ -245,6 +248,36 @@ describe("Stepper", () => {
245
248
  });
246
249
 
247
250
  describe("bound feedback (LC-71)", () => {
251
+ it("steps from empty into a bounded negative range", async () => {
252
+ const result = renderWithProviders(<Stepper min={-10} max={-5} allowEmpty />);
253
+ const increase = result.container.querySelector('[data-stepper-button="increment"]')!;
254
+ await act(async () => {
255
+ fireEvent.pointerDown(increase);
256
+ fireEvent.pointerUp(increase);
257
+ });
258
+ expect((result.getInput() as HTMLInputElement).value).toBe("-5");
259
+ expect(result.container.textContent).not.toContain("Maximum reached");
260
+ const inner = increase.querySelector("button")!;
261
+ expect(inner.getAttribute("tabindex")).toBe("-1");
262
+ });
263
+
264
+ it("clears failed-step feedback after a successful step and blur", async () => {
265
+ const result = renderWithProviders(
266
+ <Stepper label="Quantity" defaultValue={1} min={1} max={10} helperText="Choose quantity" />,
267
+ );
268
+ const input = result.getInput() as HTMLInputElement;
269
+ await act(async () => fireEvent.keyDown(input, { key: "ArrowDown" }));
270
+ expect(result.container.textContent).toContain("Minimum reached");
271
+ await act(async () => fireEvent.keyDown(input, { key: "ArrowUp" }));
272
+ expect(result.container.textContent).not.toContain("Minimum reached");
273
+ await act(async () => fireEvent.keyDown(input, { key: "Home" }));
274
+ await act(async () => fireEvent.keyDown(input, { key: "ArrowDown" }));
275
+ expect(result.container.textContent).toContain("Minimum reached");
276
+ await act(async () => fireEvent.blur(input));
277
+ expect(result.container.textContent).not.toContain("Minimum reached");
278
+ expect(result.container.textContent).toContain("Choose quantity");
279
+ });
280
+
248
281
  it("does not show Minimum reached at rest when the value is already at min", () => {
249
282
  const result = renderWithProviders(
250
283
  <Stepper label="Quantity" defaultValue={1} min={1} max={10} />,
@@ -9,6 +9,7 @@ import {
9
9
  useRef,
10
10
  useState,
11
11
  } from "react";
12
+ import { Pressable } from "react-native";
12
13
  import { isWeb, useProps, View } from "tamagui";
13
14
  import { Input as TamaguiInput } from "tamagui";
14
15
  import { isTouchSurface, sizeRecipeForToken, useGlyphColor } from "@multiplatform.one/theme";
@@ -28,12 +29,13 @@ import {
28
29
  import { useWheelIncrement } from "../../shared/useWheelIncrement";
29
30
  import type { FormFieldProps } from "../../fieldLayout";
30
31
  import { Input as InputParts } from "../../InputParts";
31
- import { formInputColors } from "../../shared/colorRamps";
32
+ import { formButtonColors, formInputColors } from "../../shared/colorRamps";
32
33
  import { t } from "../../shared/t";
33
34
  import type { FieldComponentProps, Validator } from "../../types";
34
35
 
35
36
  const repeatDelay = 400;
36
37
  const repeatInterval = 80;
38
+ const boundCaptionDuration = 2000;
37
39
  const LARGE_STEP_FACTOR = 10;
38
40
 
39
41
  /** CSS timings for discrete value motion (mirrors theme animationConfig). */
@@ -90,7 +92,7 @@ function useRepeatAction(action: () => void, repeatingRef: MutableRefObject<bool
90
92
 
91
93
  useEffect(() => stop, [stop]);
92
94
 
93
- return { onPressIn: start, onPressOut: stop };
95
+ return { onPressIn: start, onPressOut: stop, stop };
94
96
  }
95
97
 
96
98
  export type StepperProps<
@@ -139,56 +141,125 @@ export type StepperProps<
139
141
  function StepperSpinButton({
140
142
  kind,
141
143
  disabled,
144
+ atBound,
145
+ seamWidth,
142
146
  stacked,
143
147
  seam,
144
148
  onPressIn,
145
149
  onPressOut,
146
150
  onActivate,
151
+ onBoundPress,
147
152
  children,
148
153
  }: {
149
154
  kind: "increment" | "decrement";
150
155
  disabled: boolean;
156
+ atBound: boolean;
157
+ seamWidth: number;
151
158
  stacked?: boolean;
152
159
  seam?: "bottom" | "end" | "start";
153
160
  onPressIn: () => void;
154
161
  onPressOut: () => void;
155
162
  onActivate: () => void;
163
+ onBoundPress: () => void;
156
164
  children: ReactNode;
157
165
  }) {
158
166
  const label = kind === "increment" ? t("Increase") : t("Decrease");
159
- return (
167
+ const [pressed, setPressed] = useState(false);
168
+ const button = (
160
169
  <InputParts.Button
161
170
  tabIndex={-1}
162
171
  disabled={disabled}
163
- aria-disabled={disabled || undefined}
164
- aria-label={label}
165
- data-stepper-button={kind}
166
- cursor={disabled ? "not-allowed" : "pointer"}
167
- opacity={disabled ? 0.4 : 1}
168
- height={stacked ? "50%" : "100%"}
169
- flex={stacked ? 1 : undefined}
172
+ aria-hidden
173
+ importantForAccessibility="no-hide-descendants"
174
+ pointerEvents="none"
175
+ cursor={disabled || atBound ? "not-allowed" : "pointer"}
176
+ opacity={disabled || atBound ? 0.4 : 1}
177
+ backgroundColor={
178
+ pressed && !disabled && !atBound ? formButtonColors.background.active : "transparent"
179
+ }
180
+ height="100%"
170
181
  alignSelf="stretch"
171
- borderBottomWidth={seam === "bottom" ? 1 : 0}
172
- borderInlineEndWidth={seam === "end" ? 1 : 0}
173
- borderInlineStartWidth={seam === "start" ? 1 : 0}
182
+ borderBottomWidth={seam === "bottom" ? seamWidth : 0}
183
+ {...(isWeb
184
+ ? {
185
+ style: {
186
+ borderInlineEndWidth: seam === "end" ? seamWidth : 0,
187
+ borderInlineStartWidth: seam === "start" ? seamWidth : 0,
188
+ borderInlineEndStyle: "solid",
189
+ borderInlineStartStyle: "solid",
190
+ },
191
+ }
192
+ : {
193
+ borderEndWidth: seam === "end" ? seamWidth : 0,
194
+ borderStartWidth: seam === "start" ? seamWidth : 0,
195
+ })}
174
196
  borderColor={formInputColors.border.base}
175
197
  focusStyle={noButtonRing}
176
198
  focusVisibleStyle={noButtonRing}
177
199
  hoverStyle={disabled ? { backgroundColor: "transparent" } : undefined}
178
- onMouseDown={(e: any) => {
179
- preventFocusSteal(e);
180
- onActivate();
181
- }}
182
- onPointerDown={(e: any) => {
183
- preventFocusSteal(e);
184
- onActivate();
185
- }}
186
- onPressIn={disabled ? undefined : onPressIn}
187
- onPressOut={onPressOut}
188
200
  >
189
201
  {children}
190
202
  </InputParts.Button>
191
203
  );
204
+ const start = () => {
205
+ if (disabled) return;
206
+ setPressed(true);
207
+ onActivate();
208
+ if (atBound) onBoundPress();
209
+ else onPressIn();
210
+ };
211
+ const stop = () => {
212
+ setPressed(false);
213
+ onPressOut();
214
+ };
215
+ const hitStyle = {
216
+ display: "flex" as const,
217
+ height: stacked ? ("50%" as const) : ("100%" as const),
218
+ flex: stacked ? 1 : undefined,
219
+ };
220
+ // Keep the press target mounted when a step reaches its bound. Tamagui
221
+ // suppresses aria-disabled presses; the wrapper owns attempted-step feedback.
222
+ return isWeb ? (
223
+ <div
224
+ role="button"
225
+ aria-label={label}
226
+ aria-disabled={disabled || atBound || undefined}
227
+ tabIndex={-1}
228
+ data-stepper-button={kind}
229
+ style={hitStyle}
230
+ onPointerDown={(event) => {
231
+ // This raw wrapper owns the pointer lifecycle. Cancel compatibility
232
+ // mouse events so touch and pen cannot commit the same step twice.
233
+ preventFocusSteal(event);
234
+ start();
235
+ }}
236
+ onMouseDown={preventFocusSteal}
237
+ onPointerUp={stop}
238
+ onPointerCancel={stop}
239
+ onPointerLeave={stop}
240
+ onClick={(event) => {
241
+ if (event.detail !== 0) return;
242
+ start();
243
+ stop();
244
+ }}
245
+ >
246
+ {button}
247
+ </div>
248
+ ) : (
249
+ <Pressable
250
+ accessibilityRole="button"
251
+ accessibilityLabel={label}
252
+ accessibilityState={{ disabled: disabled || atBound }}
253
+ // An explicit false overrides accessibilityState in React Native.
254
+ disabled={disabled || undefined}
255
+ onPressIn={start}
256
+ onPressOut={stop}
257
+ hitSlop={{ top: seamWidth, bottom: seamWidth }}
258
+ style={hitStyle}
259
+ >
260
+ {button}
261
+ </Pressable>
262
+ );
192
263
  }
193
264
 
194
265
  export function Stepper<
@@ -253,6 +324,27 @@ export function Stepper<
253
324
  // LC-25: discrete +/- taps tween the value chrome; hold-repeat / typing stay live.
254
325
  // Opacity (not transform) — Tamagui Input owns transform internally on web.
255
326
  const [valueFlash, setValueFlash] = useState(false);
327
+ const [boundCaption, setBoundCaption] = useState<string | null>(null);
328
+ const boundTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
329
+ const clearBoundCaption = useCallback(() => {
330
+ if (boundTimerRef.current) clearTimeout(boundTimerRef.current);
331
+ boundTimerRef.current = null;
332
+ setBoundCaption(null);
333
+ }, []);
334
+ const showBoundCaption = useCallback((kind: "min" | "max") => {
335
+ if (boundTimerRef.current) clearTimeout(boundTimerRef.current);
336
+ setBoundCaption(kind === "min" ? t("Minimum reached") : t("Maximum reached"));
337
+ boundTimerRef.current = setTimeout(() => {
338
+ boundTimerRef.current = null;
339
+ setBoundCaption(null);
340
+ }, boundCaptionDuration);
341
+ }, []);
342
+ useEffect(
343
+ () => () => {
344
+ if (boundTimerRef.current) clearTimeout(boundTimerRef.current);
345
+ },
346
+ [],
347
+ );
256
348
  const repeatingRef = useRef(false);
257
349
  const typingRef = useRef(false);
258
350
  const incrementRef = useRef<() => void>(() => {});
@@ -316,11 +408,12 @@ export function Stepper<
316
408
  const clamped = clampValue(next);
317
409
  const formatted = formatValue(clamped);
318
410
  if (formatted === inputValue) return;
411
+ clearBoundCaption();
319
412
  if (pulse) pulseDiscreteStep();
320
413
  setInputValue(formatted);
321
414
  if (!name) onChange?.(clamped);
322
415
  },
323
- [clampValue, formatValue, inputValue, name, onChange, pulseDiscreteStep],
416
+ [clampValue, formatValue, inputValue, name, onChange, pulseDiscreteStep, clearBoundCaption],
324
417
  );
325
418
 
326
419
  const applyDelta = useCallback(
@@ -328,11 +421,55 @@ export function Stepper<
328
421
  if (disabled || readOnly) return;
329
422
  const current = parseValue(inputValue);
330
423
  const from = current ?? 0;
424
+ if (current !== null && delta < 0 && boundsLo !== undefined && from <= boundsLo) {
425
+ showBoundCaption("min");
426
+ return;
427
+ }
428
+ if (current !== null && delta > 0 && boundsHi !== undefined && from >= boundsHi) {
429
+ showBoundCaption("max");
430
+ return;
431
+ }
331
432
  commitNumber(from + delta, true);
332
433
  },
333
- [disabled, readOnly, parseValue, inputValue, commitNumber],
434
+ [
435
+ disabled,
436
+ readOnly,
437
+ parseValue,
438
+ inputValue,
439
+ commitNumber,
440
+ boundsLo,
441
+ boundsHi,
442
+ showBoundCaption,
443
+ ],
334
444
  );
335
445
 
446
+ useEffect(() => {
447
+ const current = parseValue(inputValue);
448
+ if (
449
+ disabled ||
450
+ readOnly ||
451
+ (current !== null && boundsHi !== undefined && current >= boundsHi)
452
+ ) {
453
+ repeatIncrement.stop();
454
+ }
455
+ if (
456
+ disabled ||
457
+ readOnly ||
458
+ (current !== null && boundsLo !== undefined && current <= boundsLo)
459
+ ) {
460
+ repeatDecrement.stop();
461
+ }
462
+ }, [
463
+ inputValue,
464
+ parseValue,
465
+ boundsLo,
466
+ boundsHi,
467
+ disabled,
468
+ readOnly,
469
+ repeatIncrement.stop,
470
+ repeatDecrement.stop,
471
+ ]);
472
+
336
473
  const increment = useCallback(() => applyDelta(step), [applyDelta, step]);
337
474
  const decrement = useCallback(() => applyDelta(-step), [applyDelta, step]);
338
475
 
@@ -439,18 +576,20 @@ export function Stepper<
439
576
 
440
577
  const stacked = placement === "left" || placement === "right";
441
578
  const showSpin = showButtons && !readOnly;
442
- const decDisabled = !!(disabled || atMin);
443
- const incDisabled = !!(disabled || atMax);
579
+ const seamWidth = knobProps.borderRadius.borderWidth;
444
580
 
445
581
  const decrementButton = (
446
582
  <StepperSpinButton
447
583
  kind="decrement"
448
- disabled={decDisabled}
584
+ disabled={!!disabled}
585
+ atBound={atMin}
586
+ seamWidth={seamWidth}
449
587
  stacked={stacked}
450
588
  seam={placement === "both" ? "end" : undefined}
451
589
  onPressIn={repeatDecrement.onPressIn}
452
590
  onPressOut={repeatDecrement.onPressOut}
453
591
  onActivate={focusArea}
592
+ onBoundPress={() => showBoundCaption("min")}
454
593
  >
455
594
  {stacked ? (
456
595
  <CaretDownIcon size={iconPx} weight="bold" color={glyphColor} aria-hidden />
@@ -462,12 +601,15 @@ export function Stepper<
462
601
  const incrementButton = (
463
602
  <StepperSpinButton
464
603
  kind="increment"
465
- disabled={incDisabled}
604
+ disabled={!!disabled}
605
+ atBound={atMax}
606
+ seamWidth={seamWidth}
466
607
  stacked={stacked}
467
608
  seam={stacked ? "bottom" : placement === "both" ? "start" : undefined}
468
609
  onPressIn={repeatIncrement.onPressIn}
469
610
  onPressOut={repeatIncrement.onPressOut}
470
611
  onActivate={focusArea}
612
+ onBoundPress={() => showBoundCaption("max")}
471
613
  >
472
614
  {stacked ? (
473
615
  <CaretUpIcon size={iconPx} weight="bold" color={glyphColor} aria-hidden />
@@ -483,8 +625,17 @@ export function Stepper<
483
625
  alignSelf="stretch"
484
626
  flexShrink={0}
485
627
  width={controlSize}
486
- borderInlineStartWidth={edge === "end" ? 1 : 0}
487
- borderInlineEndWidth={edge === "start" ? 1 : 0}
628
+ {...(isWeb
629
+ ? {
630
+ borderInlineStartWidth: edge === "end" ? seamWidth : 0,
631
+ borderInlineEndWidth: edge === "start" ? seamWidth : 0,
632
+ borderInlineStartStyle: "solid",
633
+ borderInlineEndStyle: "solid",
634
+ }
635
+ : {
636
+ borderStartWidth: edge === "end" ? seamWidth : 0,
637
+ borderEndWidth: edge === "start" ? seamWidth : 0,
638
+ })}
488
639
  borderColor={formInputColors.border.base}
489
640
  >
490
641
  {incrementButton}
@@ -541,12 +692,14 @@ export function Stepper<
541
692
  ? {
542
693
  onBlur: () => {
543
694
  typingRef.current = false;
695
+ clearBoundCaption();
544
696
  onBlurHandler();
545
697
  },
546
698
  }
547
699
  : {
548
700
  onBlur: () => {
549
701
  typingRef.current = false;
702
+ clearBoundCaption();
550
703
  },
551
704
  })}
552
705
  {...(onFocusHandler ? { onFocus: onFocusHandler } : undefined)}
@@ -559,7 +712,14 @@ export function Stepper<
559
712
  size={controlSize}
560
713
  disabled={disabled}
561
714
  data-stepper="true"
715
+ data-stepper-control="true"
562
716
  data-stepper-placement={placement}
717
+ {...(showSpin
718
+ ? {
719
+ paddingHorizontal: 0,
720
+ sizeRecipeEscape: "LC-81 stepper segments reach the compound frame edges",
721
+ }
722
+ : undefined)}
563
723
  >
564
724
  {showSpin && placement === "both" ? decrementButton : null}
565
725
  {showSpin && placement === "left" ? spinColumn("start") : null}
@@ -602,7 +762,7 @@ export function Stepper<
602
762
  label={label}
603
763
  labelProps={labelProps}
604
764
  error={errorProp}
605
- helperText={helperText}
765
+ helperText={boundCaption ?? helperText}
606
766
  required={required}
607
767
  size={size}
608
768
  knobProps={knobProps}
@@ -635,7 +795,7 @@ export function Stepper<
635
795
  label,
636
796
  labelProps,
637
797
  error: errorProp,
638
- helperText,
798
+ helperText: boundCaption ?? helperText,
639
799
  required,
640
800
  size,
641
801
  readOnly,
@@ -0,0 +1,73 @@
1
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { ToggleGroup } from "./index";
4
+
5
+ // MPO-283. Before this the whole segmented control was absent from the iOS
6
+ // tree. See RadioGroup.native.spec.tsx for why the state object is pinned in
7
+ // shared/nativeA11y.spec.ts rather than here.
8
+ vi.mock("tamagui", async (importOriginal) => ({
9
+ ...(await importOriginal<typeof import("tamagui")>()),
10
+ isWeb: false,
11
+ }));
12
+
13
+ const severity = [
14
+ { label: "error", value: "error" },
15
+ { label: "warning", value: "warning" },
16
+ { label: "info", value: "info", disabled: true },
17
+ ];
18
+
19
+ const names = (container: HTMLElement) =>
20
+ Array.from(container.querySelectorAll("[accessibilityrole]")).map((el) => [
21
+ el.getAttribute("accessibilityrole"),
22
+ el.getAttribute("accessibilitylabel"),
23
+ ]);
24
+
25
+ describe("native ToggleGroup accessibility contract", () => {
26
+ it("puts every segment in the tree as a named control", () => {
27
+ const { container } = renderWithProviders(
28
+ <ToggleGroup label="Severity" options={severity} value="warning" />,
29
+ );
30
+ expect(names(container)).toEqual([
31
+ ["button", "error"],
32
+ ["button", "warning"],
33
+ ["button", "info"],
34
+ ]);
35
+ });
36
+
37
+ // The platform role is `button` for both kinds, measured: a radio/checkbox
38
+ // accessibilityRole takes the element out of the iOS tree entirely.
39
+ it("keeps every segment in the tree when the group takes several values", () => {
40
+ const { container } = renderWithProviders(
41
+ <ToggleGroup type="multiple" options={severity} value={["error"]} />,
42
+ );
43
+ expect(names(container)).toEqual([
44
+ ["button", "error"],
45
+ ["button", "warning"],
46
+ ["button", "info"],
47
+ ]);
48
+ });
49
+
50
+ it("prefixes a group accessibilityLabel onto each segment, because iOS never reads a container", () => {
51
+ const { container } = renderWithProviders(
52
+ <ToggleGroup accessibilityLabel="Severity" options={severity} value="warning" />,
53
+ );
54
+ expect(names(container)).toContainEqual(["button", "Severity, warning"]);
55
+ });
56
+
57
+ it("takes aria-label as an alias, since tamagui never maps it onto native", () => {
58
+ const { container } = renderWithProviders(
59
+ <ToggleGroup aria-label="Severity" options={severity} value="warning" />,
60
+ );
61
+ expect(names(container)).toContainEqual(["button", "Severity, warning"]);
62
+ });
63
+
64
+ it("lets a segment override its own name", () => {
65
+ const { container } = renderWithProviders(
66
+ <ToggleGroup
67
+ options={[{ label: "●", value: "on", accessibilityLabel: "Filled" }]}
68
+ value="on"
69
+ />,
70
+ );
71
+ expect(names(container)).toEqual([["button", "Filled"]]);
72
+ });
73
+ });
@@ -294,6 +294,55 @@ describe("ToggleGroup", () => {
294
294
  });
295
295
  });
296
296
 
297
+ describe("per-segment elevation wrapper (MPO-133)", () => {
298
+ function elevationWrapperFor(segment: HTMLElement): HTMLElement {
299
+ const wrapper = segment.parentElement as HTMLElement;
300
+ expect(wrapper?.getAttribute("style") ?? "").toMatch(/box-shadow/);
301
+ return wrapper;
302
+ }
303
+
304
+ it("lays the wrapper out as a row so the segment's zero flex-basis sizes width, not height", () => {
305
+ const { container } = renderWithHouseThemes(
306
+ <ToggleGroup label="Alignment" options={options} defaultValue="left" />,
307
+ );
308
+ const segments = [...container.querySelectorAll("[data-state]")] as HTMLElement[];
309
+ expect(segments).toHaveLength(3);
310
+ for (const segment of segments) {
311
+ expect(segment.className).toContain("_fb-0px");
312
+ const wrapper = elevationWrapperFor(segment);
313
+ expect(wrapper.className).toContain("_fd-row");
314
+ expect(wrapper.className).toContain("_fg-1");
315
+ }
316
+ });
317
+
318
+ it("keeps the row wrapper in the vertical orientation", () => {
319
+ const { container } = renderWithHouseThemes(
320
+ <ToggleGroup
321
+ label="Alignment"
322
+ options={options}
323
+ defaultValue="left"
324
+ orientation="vertical"
325
+ />,
326
+ );
327
+ const segments = [...container.querySelectorAll("[data-state]")] as HTMLElement[];
328
+ expect(segments).toHaveLength(3);
329
+ for (const segment of segments) {
330
+ expect(segment.className).toContain("_fb-0px");
331
+ expect(elevationWrapperFor(segment).className).toContain("_fd-row");
332
+ }
333
+ });
334
+
335
+ it("leaves the group frame flat while the segments carry the shadow (E-FLAT)", () => {
336
+ const { container } = renderWithHouseThemes(
337
+ <ToggleGroup label="Alignment" options={options} defaultValue="left" />,
338
+ );
339
+ const group = container.querySelector('[role="group"]') as HTMLElement;
340
+ expect(group).toBeTruthy();
341
+ expect(group.className).not.toMatch(/_bxsh-/);
342
+ expect(group.getAttribute("style") ?? "").not.toMatch(/box-shadow/);
343
+ });
344
+ });
345
+
297
346
  describe("one tab stop (LC-49 / SB-M-217)", () => {
298
347
  it("exposes exactly one tab stop among the segments", () => {
299
348
  const { container } = renderWithHouseThemes(