@multiplatform.one/forms 8.2.2 → 8.4.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 (570) hide show
  1. package/dist/cjs/AdaptivePopup/index.native.js +2 -2
  2. package/dist/cjs/AdaptivePopup/index.native.js.map +1 -1
  3. package/dist/cjs/Button/index.native.js +2 -2
  4. package/dist/cjs/Button/index.native.js.map +1 -1
  5. package/dist/cjs/Composer/index.native.js +1 -1
  6. package/dist/cjs/Composer/index.native.js.map +1 -1
  7. package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js +1 -1
  8. package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
  9. package/dist/cjs/ContextualSaveBar/index.native.js +3 -3
  10. package/dist/cjs/ContextualSaveBar/index.native.js.map +1 -1
  11. package/dist/cjs/ControlGroup/index.cjs +2 -1
  12. package/dist/cjs/ControlGroup/index.native.js +3 -2
  13. package/dist/cjs/ControlGroup/index.native.js.map +1 -1
  14. package/dist/cjs/DescriptionList/index.native.js +2 -2
  15. package/dist/cjs/DescriptionList/index.native.js.map +1 -1
  16. package/dist/cjs/FieldDisplay/index.native.js +1 -1
  17. package/dist/cjs/FieldDisplay/index.native.js.map +1 -1
  18. package/dist/cjs/FloatingPanel/index.native.js +20 -2
  19. package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
  20. package/dist/cjs/FloatingPanel/trailingAction.native.js +1 -1
  21. package/dist/cjs/FloatingPanel/trailingAction.native.js.map +1 -1
  22. package/dist/cjs/Form/index.native.js +1 -1
  23. package/dist/cjs/Form/index.native.js.map +1 -1
  24. package/dist/cjs/InputParts/index.cjs +1 -0
  25. package/dist/cjs/InputParts/index.native.js +1 -0
  26. package/dist/cjs/InputParts/index.native.js.map +1 -1
  27. package/dist/cjs/Wheel/index.cjs +22 -6
  28. package/dist/cjs/Wheel/index.native.js +26 -8
  29. package/dist/cjs/Wheel/index.native.js.map +1 -1
  30. package/dist/cjs/fieldLayout.native.js +1 -1
  31. package/dist/cjs/fieldLayout.native.js.map +1 -1
  32. package/dist/cjs/fields/Barcode/BarcodeScanner.native.js +1 -1
  33. package/dist/cjs/fields/Barcode/index.native.js +2 -2
  34. package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
  35. package/dist/cjs/fields/Checkbox/Checkbox.native.js +1 -1
  36. package/dist/cjs/fields/Checkbox/Checkbox.native.js.map +1 -1
  37. package/dist/cjs/fields/Checkbox/CheckboxGroup.native.js +1 -1
  38. package/dist/cjs/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
  39. package/dist/cjs/fields/ColorPicker/index.native.js +2 -2
  40. package/dist/cjs/fields/ColorPicker/index.native.js.map +1 -1
  41. package/dist/cjs/fields/ColorPicker/parts.native.js +2 -2
  42. package/dist/cjs/fields/ColorPicker/parts.native.js.map +1 -1
  43. package/dist/cjs/fields/Combobox/index.native.js +5 -5
  44. package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
  45. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +2 -2
  46. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  47. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js +3 -3
  48. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  49. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +2 -2
  50. package/dist/cjs/fields/DatePicker/MonthPicker.native.js +2 -2
  51. package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
  52. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +2 -2
  53. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  54. package/dist/cjs/fields/DatePicker/catalog.native.js +2 -2
  55. package/dist/cjs/fields/DatePicker/catalog.native.js.map +1 -1
  56. package/dist/cjs/fields/DatePicker/index.native.js +2 -2
  57. package/dist/cjs/fields/DatePicker/parts.cjs +33 -30
  58. package/dist/cjs/fields/DatePicker/parts.native.js +36 -32
  59. package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
  60. package/dist/cjs/fields/Duration/DurationWheel.native.js +1 -1
  61. package/dist/cjs/fields/Duration/index.native.js +3 -3
  62. package/dist/cjs/fields/Duration/index.native.js.map +1 -1
  63. package/dist/cjs/fields/FileUpload/index.cjs +32 -15
  64. package/dist/cjs/fields/FileUpload/index.native.js +42 -21
  65. package/dist/cjs/fields/FileUpload/index.native.js.map +1 -1
  66. package/dist/cjs/fields/Geolocation/index.native.js +5 -5
  67. package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
  68. package/dist/cjs/fields/Icon/index.native.js +3 -3
  69. package/dist/cjs/fields/Icon/index.native.js.map +1 -1
  70. package/dist/cjs/fields/ImageField/index.cjs +35 -20
  71. package/dist/cjs/fields/ImageField/index.native.js +39 -22
  72. package/dist/cjs/fields/ImageField/index.native.js.map +1 -1
  73. package/dist/cjs/fields/Input/index.native.js +3 -3
  74. package/dist/cjs/fields/Input/index.native.js.map +1 -1
  75. package/dist/cjs/fields/MentionInput/index.native.js +3 -3
  76. package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
  77. package/dist/cjs/fields/OTPInput/index.native.js +3 -3
  78. package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
  79. package/dist/cjs/fields/PhoneInput/index.native.js +3 -3
  80. package/dist/cjs/fields/PhoneInput/index.native.js.map +1 -1
  81. package/dist/cjs/fields/Progress/index.cjs +5 -0
  82. package/dist/cjs/fields/Progress/index.native.js +6 -1
  83. package/dist/cjs/fields/Progress/index.native.js.map +1 -1
  84. package/dist/cjs/fields/RadioGroup/index.native.js +1 -1
  85. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  86. package/dist/cjs/fields/Rating/index.native.js +1 -1
  87. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  88. package/dist/cjs/fields/SearchInput/index.native.js +2 -2
  89. package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
  90. package/dist/cjs/fields/Select/index.native.js +4 -4
  91. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  92. package/dist/cjs/fields/Signature/index.native.js +2 -2
  93. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  94. package/dist/cjs/fields/Slider/index.cjs +38 -12
  95. package/dist/cjs/fields/Slider/index.native.js +40 -12
  96. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  97. package/dist/cjs/fields/Stepper/index.native.js +2 -2
  98. package/dist/cjs/fields/Stepper/index.native.js.map +1 -1
  99. package/dist/cjs/fields/Switch/index.cjs +10 -6
  100. package/dist/cjs/fields/Switch/index.native.js +12 -8
  101. package/dist/cjs/fields/Switch/index.native.js.map +1 -1
  102. package/dist/cjs/fields/TextArea/index.native.js +2 -2
  103. package/dist/cjs/fields/TextArea/index.native.js.map +1 -1
  104. package/dist/cjs/fields/TimePicker/catalog.native.js +3 -3
  105. package/dist/cjs/fields/TimePicker/catalog.native.js.map +1 -1
  106. package/dist/cjs/fields/TimePicker/index.native.js +2 -2
  107. package/dist/cjs/fields/TimePicker/parts.cjs +9 -10
  108. package/dist/cjs/fields/TimePicker/parts.native.js +10 -11
  109. package/dist/cjs/fields/TimePicker/parts.native.js.map +1 -1
  110. package/dist/cjs/fields/TimeRangeScrubber/index.native.js +2 -2
  111. package/dist/cjs/fields/TimeRangeScrubber/index.native.js.map +1 -1
  112. package/dist/cjs/fields/ToggleGroup/index.cjs +1 -0
  113. package/dist/cjs/fields/ToggleGroup/index.native.js +2 -1
  114. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  115. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js +1 -1
  116. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
  117. package/dist/cjs/fields/pickerHandle.cjs +18 -0
  118. package/dist/cjs/fields/pickerHandle.native.js +21 -0
  119. package/dist/cjs/fields/pickerHandle.native.js.map +1 -0
  120. package/dist/cjs/hooks/useHoldCue.cjs +54 -0
  121. package/dist/cjs/hooks/useHoldCue.native.js +62 -0
  122. package/dist/cjs/hooks/useHoldCue.native.js.map +1 -0
  123. package/dist/cjs/index.cjs +4 -0
  124. package/dist/cjs/index.gnome.cjs +4 -0
  125. package/dist/cjs/index.gnome.native.js +41 -37
  126. package/dist/cjs/index.gnome.native.js.map +1 -1
  127. package/dist/cjs/index.native.js +50 -46
  128. package/dist/cjs/index.native.js.map +1 -1
  129. package/dist/cjs/keyboard/KeyboardDoneBar.native.js +1 -1
  130. package/dist/cjs/shared/TimeColumn.native.js +1 -1
  131. package/dist/cjs/shared/TimeColumn.native.js.map +1 -1
  132. package/dist/cjs/shared/colorRamps.cjs +9 -7
  133. package/dist/cjs/shared/colorRamps.native.js +9 -7
  134. package/dist/cjs/shared/colorRamps.native.js.map +1 -1
  135. package/dist/cjs/shared/controlTrack.cjs +32 -0
  136. package/dist/cjs/shared/controlTrack.native.js +35 -0
  137. package/dist/cjs/shared/controlTrack.native.js.map +1 -0
  138. package/dist/cjs/shared/floatingList.native.js +1 -1
  139. package/dist/cjs/shared/floatingList.native.js.map +1 -1
  140. package/dist/cjs/shared/utils.native.js +1 -1
  141. package/dist/cjs/shared/utils.native.js.map +1 -1
  142. package/dist/esm/ControlGroup/index.mjs +2 -1
  143. package/dist/esm/ControlGroup/index.mjs.map +1 -1
  144. package/dist/esm/ControlGroup/index.native.js +2 -1
  145. package/dist/esm/ControlGroup/index.native.js.map +1 -1
  146. package/dist/esm/FloatingPanel/index.native.js +20 -2
  147. package/dist/esm/FloatingPanel/index.native.js.map +1 -1
  148. package/dist/esm/InputParts/index.mjs +1 -0
  149. package/dist/esm/InputParts/index.mjs.map +1 -1
  150. package/dist/esm/InputParts/index.native.js +1 -0
  151. package/dist/esm/InputParts/index.native.js.map +1 -1
  152. package/dist/esm/Wheel/index.mjs +23 -7
  153. package/dist/esm/Wheel/index.mjs.map +1 -1
  154. package/dist/esm/Wheel/index.native.js +27 -9
  155. package/dist/esm/Wheel/index.native.js.map +1 -1
  156. package/dist/esm/fields/DatePicker/parts.mjs +35 -32
  157. package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
  158. package/dist/esm/fields/DatePicker/parts.native.js +36 -32
  159. package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
  160. package/dist/esm/fields/FileUpload/index.mjs +33 -16
  161. package/dist/esm/fields/FileUpload/index.mjs.map +1 -1
  162. package/dist/esm/fields/FileUpload/index.native.js +41 -20
  163. package/dist/esm/fields/FileUpload/index.native.js.map +1 -1
  164. package/dist/esm/fields/ImageField/index.mjs +36 -21
  165. package/dist/esm/fields/ImageField/index.mjs.map +1 -1
  166. package/dist/esm/fields/ImageField/index.native.js +38 -21
  167. package/dist/esm/fields/ImageField/index.native.js.map +1 -1
  168. package/dist/esm/fields/Progress/index.mjs +5 -0
  169. package/dist/esm/fields/Progress/index.mjs.map +1 -1
  170. package/dist/esm/fields/Progress/index.native.js +5 -0
  171. package/dist/esm/fields/Progress/index.native.js.map +1 -1
  172. package/dist/esm/fields/Slider/index.mjs +38 -12
  173. package/dist/esm/fields/Slider/index.mjs.map +1 -1
  174. package/dist/esm/fields/Slider/index.native.js +39 -11
  175. package/dist/esm/fields/Slider/index.native.js.map +1 -1
  176. package/dist/esm/fields/Switch/index.mjs +10 -6
  177. package/dist/esm/fields/Switch/index.mjs.map +1 -1
  178. package/dist/esm/fields/Switch/index.native.js +10 -6
  179. package/dist/esm/fields/Switch/index.native.js.map +1 -1
  180. package/dist/esm/fields/TimePicker/parts.mjs +9 -10
  181. package/dist/esm/fields/TimePicker/parts.mjs.map +1 -1
  182. package/dist/esm/fields/TimePicker/parts.native.js +9 -10
  183. package/dist/esm/fields/TimePicker/parts.native.js.map +1 -1
  184. package/dist/esm/fields/ToggleGroup/index.mjs +2 -1
  185. package/dist/esm/fields/ToggleGroup/index.mjs.map +1 -1
  186. package/dist/esm/fields/ToggleGroup/index.native.js +2 -1
  187. package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
  188. package/dist/esm/fields/pickerHandle.mjs +2 -0
  189. package/dist/esm/fields/pickerHandle.mjs.map +1 -0
  190. package/dist/esm/fields/pickerHandle.native.js +2 -0
  191. package/dist/esm/fields/pickerHandle.native.js.map +1 -0
  192. package/dist/esm/hooks/useHoldCue.mjs +27 -0
  193. package/dist/esm/hooks/useHoldCue.mjs.map +1 -0
  194. package/dist/esm/hooks/useHoldCue.native.js +32 -0
  195. package/dist/esm/hooks/useHoldCue.native.js.map +1 -0
  196. package/dist/esm/index.gnome.mjs +2 -1
  197. package/dist/esm/index.gnome.mjs.map +1 -1
  198. package/dist/esm/index.gnome.native.js +2 -1
  199. package/dist/esm/index.gnome.native.js.map +1 -1
  200. package/dist/esm/index.mjs +2 -1
  201. package/dist/esm/index.mjs.map +1 -1
  202. package/dist/esm/index.native.js +2 -1
  203. package/dist/esm/index.native.js.map +1 -1
  204. package/dist/esm/shared/colorRamps.mjs +9 -7
  205. package/dist/esm/shared/colorRamps.mjs.map +1 -1
  206. package/dist/esm/shared/colorRamps.native.js +9 -7
  207. package/dist/esm/shared/colorRamps.native.js.map +1 -1
  208. package/dist/esm/shared/controlTrack.mjs +7 -0
  209. package/dist/esm/shared/controlTrack.mjs.map +1 -0
  210. package/dist/esm/shared/controlTrack.native.js +7 -0
  211. package/dist/esm/shared/controlTrack.native.js.map +1 -0
  212. package/dist/esm/shared/nativeOverlayWindow.mjs.map +1 -1
  213. package/dist/esm/shared/systemControls.mjs.map +1 -1
  214. package/dist/esm/shared/systemControls.native.js.map +1 -1
  215. package/dist/jsx/AdaptivePopup/index.native.js +2 -2
  216. package/dist/jsx/AdaptivePopup/index.native.js.map +1 -1
  217. package/dist/jsx/Button/IconButtonGroup.native.js.map +1 -1
  218. package/dist/jsx/Button/circleGlyph.native.js.map +1 -1
  219. package/dist/jsx/Button/iconButtonGroupContext.native.js.map +1 -1
  220. package/dist/jsx/Button/index.native.js +2 -2
  221. package/dist/jsx/Button/index.native.js.map +1 -1
  222. package/dist/jsx/Button/webGlass.native.js.map +1 -1
  223. package/dist/jsx/Chip/index.native.js.map +1 -1
  224. package/dist/jsx/Composer/index.native.js +1 -1
  225. package/dist/jsx/Composer/index.native.js.map +1 -1
  226. package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.native.js +1 -1
  227. package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
  228. package/dist/jsx/ContextualSaveBar/clientKnownIdentity.native.js.map +1 -1
  229. package/dist/jsx/ContextualSaveBar/commitImmediateField.native.js.map +1 -1
  230. package/dist/jsx/ContextualSaveBar/index.native.js +3 -3
  231. package/dist/jsx/ContextualSaveBar/index.native.js.map +1 -1
  232. package/dist/jsx/ContextualSaveBar/useUnsavedChangesGuard.native.js.map +1 -1
  233. package/dist/jsx/ControlGroup/index.mjs +2 -1
  234. package/dist/jsx/ControlGroup/index.mjs.map +1 -1
  235. package/dist/jsx/ControlGroup/index.native.js +3 -2
  236. package/dist/jsx/ControlGroup/index.native.js.map +1 -1
  237. package/dist/jsx/DescriptionList/index.native.js +2 -2
  238. package/dist/jsx/DescriptionList/index.native.js.map +1 -1
  239. package/dist/jsx/ErrorSummary.native.js.map +1 -1
  240. package/dist/jsx/FieldDisplay/editMode.native.js.map +1 -1
  241. package/dist/jsx/FieldDisplay/formatters.native.js.map +1 -1
  242. package/dist/jsx/FieldDisplay/index.native.js +1 -1
  243. package/dist/jsx/FieldDisplay/index.native.js.map +1 -1
  244. package/dist/jsx/FieldGroup.native.js.map +1 -1
  245. package/dist/jsx/FloatingPanel/PanelHeader.native.js.map +1 -1
  246. package/dist/jsx/FloatingPanel/RegularPanel.native.js.map +1 -1
  247. package/dist/jsx/FloatingPanel/compactFace.native.js.map +1 -1
  248. package/dist/jsx/FloatingPanel/containingBlock.native.js.map +1 -1
  249. package/dist/jsx/FloatingPanel/coverRect.native.js.map +1 -1
  250. package/dist/jsx/FloatingPanel/echoContext.native.js.map +1 -1
  251. package/dist/jsx/FloatingPanel/index.native.js +20 -2
  252. package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
  253. package/dist/jsx/FloatingPanel/nestedAction.native.js.map +1 -1
  254. package/dist/jsx/FloatingPanel/paintedBox.native.js.map +1 -1
  255. package/dist/jsx/FloatingPanel/panelWidth.native.js.map +1 -1
  256. package/dist/jsx/FloatingPanel/pointAnchor.native.js.map +1 -1
  257. package/dist/jsx/FloatingPanel/regularPlacement.native.js.map +1 -1
  258. package/dist/jsx/FloatingPanel/trailingAction.native.js +1 -1
  259. package/dist/jsx/FloatingPanel/trailingAction.native.js.map +1 -1
  260. package/dist/jsx/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  261. package/dist/jsx/Form/index.native.js +1 -1
  262. package/dist/jsx/Form/index.native.js.map +1 -1
  263. package/dist/jsx/Form/submissionController.native.js.map +1 -1
  264. package/dist/jsx/Form/validateOn.native.js.map +1 -1
  265. package/dist/jsx/FormGrid.native.js.map +1 -1
  266. package/dist/jsx/FormSection.native.js.map +1 -1
  267. package/dist/jsx/InputParts/PasswordReveal.native.js.map +1 -1
  268. package/dist/jsx/InputParts/index.mjs +1 -0
  269. package/dist/jsx/InputParts/index.mjs.map +1 -1
  270. package/dist/jsx/InputParts/index.native.js +1 -0
  271. package/dist/jsx/InputParts/index.native.js.map +1 -1
  272. package/dist/jsx/InputParts/keyboardAppearance.native.js.map +1 -1
  273. package/dist/jsx/Label/index.native.js.map +1 -1
  274. package/dist/jsx/MediaPicker/base64.native.js.map +1 -1
  275. package/dist/jsx/MediaPicker/payload.native.js.map +1 -1
  276. package/dist/jsx/MediaPicker/types.native.js.map +1 -1
  277. package/dist/jsx/MediaPicker/useMediaPicker.native.js.map +1 -1
  278. package/dist/jsx/Skeleton/index.native.js.map +1 -1
  279. package/dist/jsx/Spinner/SpinnerGlyph.native.js.map +1 -1
  280. package/dist/jsx/Spinner/spinnerSize.native.js.map +1 -1
  281. package/dist/jsx/Table/index.native.js.map +1 -1
  282. package/dist/jsx/Wheel/haptic.native.js.map +1 -1
  283. package/dist/jsx/Wheel/index.mjs +23 -7
  284. package/dist/jsx/Wheel/index.mjs.map +1 -1
  285. package/dist/jsx/Wheel/index.native.js +26 -8
  286. package/dist/jsx/Wheel/index.native.js.map +1 -1
  287. package/dist/jsx/Wheel/wheelShared.native.js.map +1 -1
  288. package/dist/jsx/actionLabel.native.js.map +1 -1
  289. package/dist/jsx/fieldDefaults.native.js.map +1 -1
  290. package/dist/jsx/fieldLayout.native.js +1 -1
  291. package/dist/jsx/fieldLayout.native.js.map +1 -1
  292. package/dist/jsx/fields/Barcode/BarcodePreview.native.js.map +1 -1
  293. package/dist/jsx/fields/Barcode/BarcodeScanner.native.js +1 -1
  294. package/dist/jsx/fields/Barcode/code128.native.js.map +1 -1
  295. package/dist/jsx/fields/Barcode/index.native.js +2 -2
  296. package/dist/jsx/fields/Barcode/index.native.js.map +1 -1
  297. package/dist/jsx/fields/Barcode/qr.native.js.map +1 -1
  298. package/dist/jsx/fields/Barcode/scannerTypes.native.js.map +1 -1
  299. package/dist/jsx/fields/Checkbox/Checkbox.native.js +1 -1
  300. package/dist/jsx/fields/Checkbox/Checkbox.native.js.map +1 -1
  301. package/dist/jsx/fields/Checkbox/CheckboxBox.native.js.map +1 -1
  302. package/dist/jsx/fields/Checkbox/CheckboxCard.native.js.map +1 -1
  303. package/dist/jsx/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
  304. package/dist/jsx/fields/Checkbox/CheckboxGroup.native.js +1 -1
  305. package/dist/jsx/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
  306. package/dist/jsx/fields/Checkbox/checkboxGroupContext.native.js.map +1 -1
  307. package/dist/jsx/fields/Checkbox/index.native.js.map +1 -1
  308. package/dist/jsx/fields/ColorPicker/SystemColorField.native.js.map +1 -1
  309. package/dist/jsx/fields/ColorPicker/index.native.js +2 -2
  310. package/dist/jsx/fields/ColorPicker/index.native.js.map +1 -1
  311. package/dist/jsx/fields/ColorPicker/parts.native.js +2 -2
  312. package/dist/jsx/fields/ColorPicker/parts.native.js.map +1 -1
  313. package/dist/jsx/fields/ColorPicker/systemColorWell.gnome.native.js.map +1 -1
  314. package/dist/jsx/fields/Combobox/authorOptions.native.js.map +1 -1
  315. package/dist/jsx/fields/Combobox/index.native.js +5 -5
  316. package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
  317. package/dist/jsx/fields/DatePicker/Calendar.native.js.map +1 -1
  318. package/dist/jsx/fields/DatePicker/DateRangePicker.native.js +2 -2
  319. package/dist/jsx/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  320. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js +3 -3
  321. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  322. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +2 -2
  323. package/dist/jsx/fields/DatePicker/MonthPicker.native.js +2 -2
  324. package/dist/jsx/fields/DatePicker/MonthPicker.native.js.map +1 -1
  325. package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js +2 -2
  326. package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  327. package/dist/jsx/fields/DatePicker/catalog.native.js +2 -2
  328. package/dist/jsx/fields/DatePicker/catalog.native.js.map +1 -1
  329. package/dist/jsx/fields/DatePicker/fieldValueSync.native.js.map +1 -1
  330. package/dist/jsx/fields/DatePicker/index.native.js +2 -2
  331. package/dist/jsx/fields/DatePicker/parts.mjs +35 -32
  332. package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
  333. package/dist/jsx/fields/DatePicker/parts.native.js +36 -32
  334. package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
  335. package/dist/jsx/fields/DatePicker/utils.native.js.map +1 -1
  336. package/dist/jsx/fields/Duration/DurationWheel.native.js +1 -1
  337. package/dist/jsx/fields/Duration/durationMath.native.js.map +1 -1
  338. package/dist/jsx/fields/Duration/durationWheelTypes.native.js.map +1 -1
  339. package/dist/jsx/fields/Duration/index.native.js +3 -3
  340. package/dist/jsx/fields/Duration/index.native.js.map +1 -1
  341. package/dist/jsx/fields/FileUpload/filePickerTypes.native.js.map +1 -1
  342. package/dist/jsx/fields/FileUpload/index.mjs +33 -16
  343. package/dist/jsx/fields/FileUpload/index.mjs.map +1 -1
  344. package/dist/jsx/fields/FileUpload/index.native.js +42 -21
  345. package/dist/jsx/fields/FileUpload/index.native.js.map +1 -1
  346. package/dist/jsx/fields/FileUpload/nativePickerLoader.native.js.map +1 -1
  347. package/dist/jsx/fields/Geolocation/expoMapsLoader.native.js.map +1 -1
  348. package/dist/jsx/fields/Geolocation/geoValue.native.js.map +1 -1
  349. package/dist/jsx/fields/Geolocation/geocoder.native.js.map +1 -1
  350. package/dist/jsx/fields/Geolocation/geocoderContext.native.js.map +1 -1
  351. package/dist/jsx/fields/Geolocation/index.native.js +5 -5
  352. package/dist/jsx/fields/Geolocation/index.native.js.map +1 -1
  353. package/dist/jsx/fields/Geolocation/mapMath.native.js.map +1 -1
  354. package/dist/jsx/fields/Geolocation/mapTypes.native.js.map +1 -1
  355. package/dist/jsx/fields/Geolocation/nativeSearchFocus.native.js.map +1 -1
  356. package/dist/jsx/fields/Geolocation/photonGeocoder.native.js.map +1 -1
  357. package/dist/jsx/fields/Icon/drawnSet.native.js.map +1 -1
  358. package/dist/jsx/fields/Icon/index.native.js +3 -3
  359. package/dist/jsx/fields/Icon/index.native.js.map +1 -1
  360. package/dist/jsx/fields/ImageField/index.mjs +36 -21
  361. package/dist/jsx/fields/ImageField/index.mjs.map +1 -1
  362. package/dist/jsx/fields/ImageField/index.native.js +39 -22
  363. package/dist/jsx/fields/ImageField/index.native.js.map +1 -1
  364. package/dist/jsx/fields/Input/index.native.js +3 -3
  365. package/dist/jsx/fields/Input/index.native.js.map +1 -1
  366. package/dist/jsx/fields/MentionInput/index.native.js +3 -3
  367. package/dist/jsx/fields/MentionInput/index.native.js.map +1 -1
  368. package/dist/jsx/fields/OTPInput/index.native.js +3 -3
  369. package/dist/jsx/fields/OTPInput/index.native.js.map +1 -1
  370. package/dist/jsx/fields/OTPInput/otpCellCss.native.js.map +1 -1
  371. package/dist/jsx/fields/OTPInput/otpCellEdge.native.js.map +1 -1
  372. package/dist/jsx/fields/PhoneInput/dialCodes.native.js.map +1 -1
  373. package/dist/jsx/fields/PhoneInput/index.native.js +3 -3
  374. package/dist/jsx/fields/PhoneInput/index.native.js.map +1 -1
  375. package/dist/jsx/fields/PhoneInput/phone.native.js.map +1 -1
  376. package/dist/jsx/fields/PhoneInput/regionNames.native.js.map +1 -1
  377. package/dist/jsx/fields/Progress/index.mjs +5 -0
  378. package/dist/jsx/fields/Progress/index.mjs.map +1 -1
  379. package/dist/jsx/fields/Progress/index.native.js +6 -1
  380. package/dist/jsx/fields/Progress/index.native.js.map +1 -1
  381. package/dist/jsx/fields/RadioGroup/index.native.js +1 -1
  382. package/dist/jsx/fields/RadioGroup/index.native.js.map +1 -1
  383. package/dist/jsx/fields/Rating/index.native.js +1 -1
  384. package/dist/jsx/fields/Rating/index.native.js.map +1 -1
  385. package/dist/jsx/fields/Rating/ratingMath.native.js.map +1 -1
  386. package/dist/jsx/fields/Rating/types.native.js.map +1 -1
  387. package/dist/jsx/fields/SearchInput/index.native.js +2 -2
  388. package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
  389. package/dist/jsx/fields/Select/InlineChoices.native.js.map +1 -1
  390. package/dist/jsx/fields/Select/SheetPickerRow.native.js.map +1 -1
  391. package/dist/jsx/fields/Select/index.native.js +4 -4
  392. package/dist/jsx/fields/Select/index.native.js.map +1 -1
  393. package/dist/jsx/fields/Select/shouldInlineChoices.native.js.map +1 -1
  394. package/dist/jsx/fields/Signature/index.native.js +2 -2
  395. package/dist/jsx/fields/Signature/index.native.js.map +1 -1
  396. package/dist/jsx/fields/Slider/index.mjs +38 -12
  397. package/dist/jsx/fields/Slider/index.mjs.map +1 -1
  398. package/dist/jsx/fields/Slider/index.native.js +40 -12
  399. package/dist/jsx/fields/Slider/index.native.js.map +1 -1
  400. package/dist/jsx/fields/Slider/jumpMotion.native.js.map +1 -1
  401. package/dist/jsx/fields/Stepper/index.native.js +2 -2
  402. package/dist/jsx/fields/Stepper/index.native.js.map +1 -1
  403. package/dist/jsx/fields/Stepper/resolveStepperPlacement.native.js.map +1 -1
  404. package/dist/jsx/fields/Switch/footprint.native.js.map +1 -1
  405. package/dist/jsx/fields/Switch/index.mjs +10 -6
  406. package/dist/jsx/fields/Switch/index.mjs.map +1 -1
  407. package/dist/jsx/fields/Switch/index.native.js +12 -8
  408. package/dist/jsx/fields/Switch/index.native.js.map +1 -1
  409. package/dist/jsx/fields/TextArea/index.native.js +2 -2
  410. package/dist/jsx/fields/TextArea/index.native.js.map +1 -1
  411. package/dist/jsx/fields/TimePicker/catalog.native.js +3 -3
  412. package/dist/jsx/fields/TimePicker/catalog.native.js.map +1 -1
  413. package/dist/jsx/fields/TimePicker/index.native.js +2 -2
  414. package/dist/jsx/fields/TimePicker/parts.mjs +9 -10
  415. package/dist/jsx/fields/TimePicker/parts.mjs.map +1 -1
  416. package/dist/jsx/fields/TimePicker/parts.native.js +10 -11
  417. package/dist/jsx/fields/TimePicker/parts.native.js.map +1 -1
  418. package/dist/jsx/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
  419. package/dist/jsx/fields/TimeRangeScrubber/index.native.js +2 -2
  420. package/dist/jsx/fields/TimeRangeScrubber/index.native.js.map +1 -1
  421. package/dist/jsx/fields/ToggleGroup/index.mjs +2 -1
  422. package/dist/jsx/fields/ToggleGroup/index.mjs.map +1 -1
  423. package/dist/jsx/fields/ToggleGroup/index.native.js +2 -1
  424. package/dist/jsx/fields/ToggleGroup/index.native.js.map +1 -1
  425. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js +1 -1
  426. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
  427. package/dist/jsx/fields/nativeDateTime/dateTimePickerLoader.native.js.map +1 -1
  428. package/dist/jsx/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -1
  429. package/dist/jsx/fields/nativeDateTime/sheetKeyboard.native.js.map +1 -1
  430. package/dist/jsx/fields/nativeSelect.native.js.map +1 -1
  431. package/dist/jsx/fields/pickerHandle.mjs +2 -0
  432. package/dist/jsx/fields/pickerHandle.mjs.map +1 -0
  433. package/dist/jsx/fields/pickerHandle.native.js +21 -0
  434. package/dist/jsx/fields/pickerHandle.native.js.map +1 -0
  435. package/dist/jsx/fields/selectedOrder.native.js.map +1 -1
  436. package/dist/jsx/formSpacing.native.js.map +1 -1
  437. package/dist/jsx/hooks/useFocusManagement.native.js.map +1 -1
  438. package/dist/jsx/hooks/useHoldCue.mjs +27 -0
  439. package/dist/jsx/hooks/useHoldCue.mjs.map +1 -0
  440. package/dist/jsx/hooks/useHoldCue.native.js +62 -0
  441. package/dist/jsx/hooks/useHoldCue.native.js.map +1 -0
  442. package/dist/jsx/index.gnome.mjs +2 -1
  443. package/dist/jsx/index.gnome.mjs.map +1 -1
  444. package/dist/jsx/index.gnome.native.js +41 -37
  445. package/dist/jsx/index.gnome.native.js.map +1 -1
  446. package/dist/jsx/index.js +2 -1
  447. package/dist/jsx/index.js.map +1 -1
  448. package/dist/jsx/index.mjs +2 -1
  449. package/dist/jsx/index.mjs.map +1 -1
  450. package/dist/jsx/index.native.js +50 -46
  451. package/dist/jsx/index.native.js.map +1 -1
  452. package/dist/jsx/keyboard/KeyboardDoneBar.native.js +1 -1
  453. package/dist/jsx/keyboard/chain.native.js.map +1 -1
  454. package/dist/jsx/keyboard/index.native.js.map +1 -1
  455. package/dist/jsx/keyboard/types.native.js.map +1 -1
  456. package/dist/jsx/nativeTwins.native.js.map +1 -1
  457. package/dist/jsx/requiredMarking.native.js.map +1 -1
  458. package/dist/jsx/shared/CheckGlyph.native.js.map +1 -1
  459. package/dist/jsx/shared/TimeColumn.native.js +1 -1
  460. package/dist/jsx/shared/TimeColumn.native.js.map +1 -1
  461. package/dist/jsx/shared/capabilityPreflight.native.js.map +1 -1
  462. package/dist/jsx/shared/checkedOnField.native.js.map +1 -1
  463. package/dist/jsx/shared/choiceRowPress.native.js.map +1 -1
  464. package/dist/jsx/shared/colorRamps.mjs +9 -7
  465. package/dist/jsx/shared/colorRamps.mjs.map +1 -1
  466. package/dist/jsx/shared/colorRamps.native.js +9 -7
  467. package/dist/jsx/shared/colorRamps.native.js.map +1 -1
  468. package/dist/jsx/shared/controlTrack.mjs +7 -0
  469. package/dist/jsx/shared/controlTrack.mjs.map +1 -0
  470. package/dist/jsx/shared/controlTrack.native.js +35 -0
  471. package/dist/jsx/shared/controlTrack.native.js.map +1 -0
  472. package/dist/jsx/shared/devWarn.native.js.map +1 -1
  473. package/dist/jsx/shared/fieldRowContext.native.js.map +1 -1
  474. package/dist/jsx/shared/floatingList.native.js +1 -1
  475. package/dist/jsx/shared/floatingList.native.js.map +1 -1
  476. package/dist/jsx/shared/focusManagement.native.js.map +1 -1
  477. package/dist/jsx/shared/groupContext.native.js.map +1 -1
  478. package/dist/jsx/shared/i18n.native.js.map +1 -1
  479. package/dist/jsx/shared/instantMotion.native.js.map +1 -1
  480. package/dist/jsx/shared/nativeA11y.native.js.map +1 -1
  481. package/dist/jsx/shared/nativeAutoFocus.native.js.map +1 -1
  482. package/dist/jsx/shared/nativeOverlayWindow.mjs.map +1 -1
  483. package/dist/jsx/shared/nativeOverlayWindow.native.js.map +1 -1
  484. package/dist/jsx/shared/overlaySizeClass.native.js.map +1 -1
  485. package/dist/jsx/shared/overlayStack.native.js.map +1 -1
  486. package/dist/jsx/shared/panelPortal.native.js.map +1 -1
  487. package/dist/jsx/shared/pickerTriggerContract.native.js.map +1 -1
  488. package/dist/jsx/shared/pressSlopProps.native.js.map +1 -1
  489. package/dist/jsx/shared/restoreRetries.native.js.map +1 -1
  490. package/dist/jsx/shared/sheetNavigation.native.js.map +1 -1
  491. package/dist/jsx/shared/systemControlModules.gnome.native.js.map +1 -1
  492. package/dist/jsx/shared/systemControls.mjs.map +1 -1
  493. package/dist/jsx/shared/systemControls.native.js.map +1 -1
  494. package/dist/jsx/shared/t.native.js.map +1 -1
  495. package/dist/jsx/shared/tableCellContext.native.js.map +1 -1
  496. package/dist/jsx/shared/useDragScroll.native.js.map +1 -1
  497. package/dist/jsx/shared/useKeyboardInset.native.js.map +1 -1
  498. package/dist/jsx/shared/useSheetEscapeDismiss.native.js.map +1 -1
  499. package/dist/jsx/shared/useWheelIncrement.native.js.map +1 -1
  500. package/dist/jsx/shared/utils.native.js +1 -1
  501. package/dist/jsx/shared/utils.native.js.map +1 -1
  502. package/dist/jsx/shared/zIndex.native.js.map +1 -1
  503. package/dist/jsx/standardActions.native.js.map +1 -1
  504. package/dist/jsx/themedPrimitives.native.js.map +1 -1
  505. package/dist/jsx/types.native.js.map +1 -1
  506. package/dist/jsx/utils/LinkCell.native.js.map +1 -1
  507. package/package.json +11 -10
  508. package/src/Button/Button.controlTiers.spec.tsx +2 -2
  509. package/src/ControlGroup/index.tsx +2 -1
  510. package/src/FloatingPanel/FloatingPanel.holdCue.native.spec.tsx +72 -0
  511. package/src/FloatingPanel/index.native.tsx +9 -1
  512. package/src/InputParts/index.tsx +1 -0
  513. package/src/Wheel/Wheel.edgeFade.spec.tsx +74 -0
  514. package/src/Wheel/index.tsx +25 -11
  515. package/src/fields/DatePicker/dateFieldMarks.spec.tsx +154 -0
  516. package/src/fields/DatePicker/parts.tsx +33 -30
  517. package/src/fields/FileUpload/index.tsx +45 -16
  518. package/src/fields/ImageField/index.tsx +42 -19
  519. package/src/fields/Progress/index.tsx +3 -0
  520. package/src/fields/Slider/Slider.system.native.spec.tsx +44 -0
  521. package/src/fields/Slider/index.tsx +40 -12
  522. package/src/fields/Stepper/Stepper.stories.tsx +42 -0
  523. package/src/fields/Switch/Switch.spec.tsx +14 -10
  524. package/src/fields/Switch/index.tsx +11 -7
  525. package/src/fields/TimePicker/parts.tsx +8 -8
  526. package/src/fields/ToggleGroup/index.tsx +7 -1
  527. package/src/fields/fieldTriggerSlot.spec.tsx +89 -0
  528. package/src/fields/pickerHandle.ts +13 -0
  529. package/src/hooks/useHoldCue.ts +26 -0
  530. package/src/index.gnome.ts +1 -0
  531. package/src/index.ts +2 -0
  532. package/src/overlayGround.spec.ts +5 -3
  533. package/src/shared/OverlayWindow.tsx +2 -2
  534. package/src/shared/colorRamps.ts +9 -6
  535. package/src/shared/controlTrack.ts +7 -0
  536. package/src/shared/nativeOverlayWindow.tsx +1 -1
  537. package/src/shared/systemControls.ts +10 -2
  538. package/types/ControlGroup/index.d.ts.map +1 -1
  539. package/types/FloatingPanel/index.native.d.ts.map +1 -1
  540. package/types/InputParts/index.d.ts +4 -4
  541. package/types/InputParts/index.d.ts.map +1 -1
  542. package/types/Wheel/index.d.ts.map +1 -1
  543. package/types/fields/DatePicker/parts.d.ts +4 -3
  544. package/types/fields/DatePicker/parts.d.ts.map +1 -1
  545. package/types/fields/FileUpload/index.d.ts +6 -1
  546. package/types/fields/FileUpload/index.d.ts.map +1 -1
  547. package/types/fields/ImageField/index.d.ts +7 -2
  548. package/types/fields/ImageField/index.d.ts.map +1 -1
  549. package/types/fields/Progress/index.d.ts.map +1 -1
  550. package/types/fields/Slider/index.d.ts.map +1 -1
  551. package/types/fields/Switch/index.d.ts.map +1 -1
  552. package/types/fields/ToggleGroup/index.d.ts.map +1 -1
  553. package/types/fields/pickerHandle.d.ts +12 -0
  554. package/types/fields/pickerHandle.d.ts.map +1 -0
  555. package/types/hooks/useHoldCue.d.ts +10 -0
  556. package/types/hooks/useHoldCue.d.ts.map +1 -0
  557. package/types/index.d.ts +2 -0
  558. package/types/index.d.ts.map +1 -1
  559. package/types/index.gnome.d.ts +1 -0
  560. package/types/index.gnome.d.ts.map +1 -1
  561. package/types/shared/OverlayWindow.d.ts +2 -2
  562. package/types/shared/OverlayWindow.d.ts.map +1 -1
  563. package/types/shared/colorRamps.d.ts +8 -6
  564. package/types/shared/colorRamps.d.ts.map +1 -1
  565. package/types/shared/controlTrack.d.ts +3 -0
  566. package/types/shared/controlTrack.d.ts.map +1 -0
  567. package/types/shared/nativeOverlayWindow.d.ts +1 -1
  568. package/types/shared/nativeOverlayWindow.d.ts.map +1 -1
  569. package/types/shared/systemControls.d.ts +2 -1
  570. package/types/shared/systemControls.d.ts.map +1 -1
@@ -0,0 +1,154 @@
1
+ import { CalendarBlankIcon, ClockIcon } from "@phosphor-icons/react";
2
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
3
+ import {
4
+ createThemesBuilder,
5
+ defaultAccentTheme,
6
+ defaultBaseTheme,
7
+ defaultBuilderOptions,
8
+ } from "@multiplatform.one/theme";
9
+ import { configWithoutAnimations } from "@tamagui/config";
10
+ import { animationsCSS } from "@tamagui/config/v5-css";
11
+ import { render } from "@testing-library/react";
12
+ import type { ReactElement } from "react";
13
+ import { renderToStaticMarkup } from "react-dom/server";
14
+ import { TamaguiProvider, createTamagui } from "tamagui";
15
+ import { describe, expect, it, vi } from "vitest";
16
+ import { Input } from "../Input";
17
+ import { TimePicker } from "../TimePicker";
18
+ import { DatePicker, DatetimePicker } from "./index";
19
+ import { CalendarDays, MonthGrid, YearGrid, isSameDay, useCalendarData } from "./parts";
20
+
21
+ vi.mock("@multiplatform.one/storybook", () => ({ action: () => () => {} }));
22
+ vi.mock("@multiplatform.one/table", () => ({ DataTable: () => null }));
23
+
24
+ const houseThemes = createThemesBuilder(
25
+ defaultBaseTheme,
26
+ defaultAccentTheme,
27
+ defaultBuilderOptions,
28
+ ).themes() as Record<string, Record<string, string>>;
29
+
30
+ const houseConfig = createTamagui({
31
+ ...configWithoutAnimations,
32
+ animations: animationsCSS,
33
+ themes: houseThemes as never,
34
+ });
35
+
36
+ function placeholderInk(node: ReactElement) {
37
+ const { container, unmount } = renderWithProviders(node);
38
+ const input = container.querySelector("input");
39
+ expect(input).toBeTruthy();
40
+ const ink = input!.style.getPropertyValue("--t_placeholderColor");
41
+ unmount();
42
+ return ink;
43
+ }
44
+
45
+ function pathOf(icon: ReactElement) {
46
+ return renderToStaticMarkup(icon).match(/ d="([^"]+)"/)![1];
47
+ }
48
+
49
+ function June() {
50
+ const calendarData = useCalendarData(new Date(2024, 5, 15));
51
+ return (
52
+ <CalendarDays
53
+ calendarData={calendarData}
54
+ isSelected={(day) => isSameDay(day, new Date(2024, 5, 15))}
55
+ onSelect={() => {}}
56
+ />
57
+ );
58
+ }
59
+
60
+ function selectedCell(node: ReactElement, scheme: "light" | "dark") {
61
+ const { container } = render(
62
+ <TamaguiProvider config={houseConfig} defaultTheme={scheme} disableInjectCSS>
63
+ {node}
64
+ </TamaguiProvider>,
65
+ );
66
+ const cell = container.querySelector<HTMLElement>("[aria-pressed='true']");
67
+ expect(cell).toBeTruthy();
68
+ return cell!;
69
+ }
70
+
71
+ describe("date and time fields read empty, name their kind and mark the pick (FZ-8433)", () => {
72
+ const stock = placeholderInk(<Input label="Name" placeholder="Your name" />);
73
+
74
+ it.each([
75
+ ["DatePicker", <DatePicker key="d" label="Date" placeholder="Pick a date" />],
76
+ ["DatetimePicker", <DatetimePicker key="dt" label="When" placeholder="Pick a time" />],
77
+ ["TimePicker", <TimePicker key="t" label="Time" placeholder="Select time" />],
78
+ ])("an empty %s draws its placeholder in the theme's placeholder ink", (_name, node) => {
79
+ const ink = placeholderInk(node);
80
+ expect(stock).not.toBe("");
81
+ expect(ink).toBe(stock);
82
+ expect(ink).not.toBe("var(--color11)");
83
+ });
84
+
85
+ it.each([
86
+ [
87
+ "DatetimePicker",
88
+ <DatetimePicker key="dt" label="When" />,
89
+ "date-picker-glyph",
90
+ CalendarBlankIcon,
91
+ ],
92
+ ["DatePicker", <DatePicker key="d" label="Date" />, "date-picker-glyph", CalendarBlankIcon],
93
+ ["TimePicker", <TimePicker key="t" label="Time" />, "time-picker-glyph", ClockIcon],
94
+ [
95
+ "a read-only DatetimePicker",
96
+ <DatetimePicker key="ro" label="When" value={new Date(2026, 9, 31, 9, 30)} readOnly />,
97
+ "date-picker-glyph",
98
+ CalendarBlankIcon,
99
+ ],
100
+ ] as const)("%s draws one glyph, on the input's right", (_name, node, testId, Icon) => {
101
+ const { container, unmount } = renderWithProviders(node);
102
+ const glyphs = container.querySelectorAll(`[data-testid='${testId}']`);
103
+ expect(glyphs).toHaveLength(1);
104
+ const paths = Array.from(glyphs[0]!.querySelectorAll("svg path")).map((p) =>
105
+ p.getAttribute("d"),
106
+ );
107
+ expect(paths).toEqual([pathOf(<Icon />)]);
108
+ const input = container.querySelector("input")!;
109
+ expect(
110
+ input.compareDocumentPosition(glyphs[0]!) & Node.DOCUMENT_POSITION_FOLLOWING,
111
+ ).toBeTruthy();
112
+ unmount();
113
+ });
114
+
115
+ it("a filled web field swaps its glyph for the clear action, so the right holds one icon", () => {
116
+ const { container } = renderWithProviders(
117
+ <DatetimePicker label="When" value={new Date(2026, 9, 31, 9, 30)} />,
118
+ );
119
+ expect(container.querySelector("[data-testid='date-picker-glyph']")).toBeNull();
120
+ expect(container.querySelector("[data-testid='date-picker-clear']")).toBeTruthy();
121
+ });
122
+
123
+ it.each(
124
+ (["light", "dark"] as const).flatMap((scheme) => [
125
+ ["day", scheme, <June key="d" />],
126
+ [
127
+ "month",
128
+ scheme,
129
+ <MonthGrid key="m" currentYear={2024} selectedMonth={5} onSelectMonth={() => {}} />,
130
+ ],
131
+ [
132
+ "year",
133
+ scheme,
134
+ <YearGrid
135
+ key="y"
136
+ yearPageStart={2020}
137
+ selectedYear={2024}
138
+ onSelectYear={() => {}}
139
+ onPrevPage={() => {}}
140
+ onNextPage={() => {}}
141
+ />,
142
+ ],
143
+ ]) as [string, "light" | "dark", ReactElement][],
144
+ )(
145
+ "the picked %s fills with the accent mark in %s, inked for that fill",
146
+ (_name, scheme, node) => {
147
+ const cell = selectedCell(node, scheme);
148
+ expect(cell.className).toMatch(/(?:^|\s)_bg-accentBackg/);
149
+ expect(cell.className).not.toMatch(/t_accent/);
150
+ const ink = cell.querySelector<HTMLElement>("span")!.className;
151
+ expect(ink).toMatch(/(?:^|\s)_col-(?:hsla?|rgba?)/);
152
+ },
153
+ );
154
+ });
@@ -12,6 +12,7 @@ import {
12
12
  getMonthNames,
13
13
  useAccentOnSurface,
14
14
  useGlyphColor,
15
+ useReadableTextOn,
15
16
  useResolvedKnobs,
16
17
  } from "@multiplatform.one/theme";
17
18
  import {
@@ -29,7 +30,7 @@ import { FloatingPanel, floatingPanelActionProps, isNestedPanelAction } from "..
29
30
  import type { PanelActionEvent } from "../../FloatingPanel/nestedAction";
30
31
  import type { PanelWidth } from "../../FloatingPanel/panelWidth";
31
32
  import { Input as InputParts } from "../../InputParts";
32
- import { formCommonColors } from "../../shared/colorRamps";
33
+ import { formCommonColors, formSelectedColors } from "../../shared/colorRamps";
33
34
  import { t } from "../../shared/t";
34
35
 
35
36
  // ---------------------------------------------------------------------------
@@ -341,6 +342,7 @@ export function CalendarDayCell({
341
342
  }) {
342
343
  const { knobProps } = useCalendarKnobs();
343
344
  const accentText = useAccentOnSurface();
345
+ const onMark = useReadableTextOn(formSelectedColors.mark);
344
346
  const { px, hitSlop, box } = splitNestedControl(knobProps.nestedControl);
345
347
 
346
348
  if (!visible) {
@@ -373,8 +375,7 @@ export function CalendarDayCell({
373
375
  // identical to a choosable cell; we do not adopt that.
374
376
  opacity={disabled ? 0.5 : dimmed ? 0.45 : 1}
375
377
  pointerEvents={disabled ? "none" : "auto"}
376
- backgroundColor={selected ? (selectedBackground ?? "$background") : "transparent"}
377
- theme={selected ? ("accent" as any) : undefined}
378
+ backgroundColor={selected ? (selectedBackground ?? formSelectedColors.mark) : "transparent"}
378
379
  borderWidth={showTodayMark ? 2 : 0}
379
380
  borderColor={showTodayMark ? accentText : "transparent"}
380
381
  zIndex={1}
@@ -398,7 +399,7 @@ export function CalendarDayCell({
398
399
  {...knobProps.label}
399
400
  {...knobProps.textWeight}
400
401
  fontWeight={selected ? "bold" : knobProps.textWeight.fontWeight}
401
- color={selected ? undefined : today ? accentText : formCommonColors.text}
402
+ color={selected ? onMark : today ? accentText : formCommonColors.text}
402
403
  >
403
404
  {day.getDate()}
404
405
  </Text>
@@ -675,6 +676,7 @@ interface MonthGridProps {
675
676
 
676
677
  export function MonthGrid({ currentYear, selectedMonth, onSelectMonth }: MonthGridProps) {
677
678
  const { knobProps } = useCalendarKnobs();
679
+ const onMark = useReadableTextOn(formSelectedColors.mark);
678
680
  const { animation, animationKey } = useDateAnimation(currentYear);
679
681
  const { px, hitSlop, box } = splitNestedControl(knobProps.nestedControl);
680
682
  const cellW = (px * 7) / 3;
@@ -706,8 +708,7 @@ export function MonthGrid({ currentYear, selectedMonth, onSelectMonth }: MonthGr
706
708
  cursor="pointer"
707
709
  alignItems="center"
708
710
  justifyContent="center"
709
- theme={isSelected ? ("accent" as any) : undefined}
710
- backgroundColor={isSelected ? "$background" : "transparent"}
711
+ backgroundColor={isSelected ? formSelectedColors.mark : "transparent"}
711
712
  onPress={() => onSelectMonth(index)}
712
713
  outlineWidth={0}
713
714
  focusStyle={{ outlineWidth: 0 }}
@@ -725,7 +726,7 @@ export function MonthGrid({ currentYear, selectedMonth, onSelectMonth }: MonthGr
725
726
  >
726
727
  <Text
727
728
  {...knobProps.label}
728
- color={isSelected ? "$color" : formCommonColors.text}
729
+ color={isSelected ? onMark : formCommonColors.text}
729
730
  fontWeight={isSelected ? "bold" : "400"}
730
731
  >
731
732
  {t(name.slice(0, 3))}
@@ -758,6 +759,7 @@ export function YearGrid({
758
759
  onNextPage,
759
760
  }: YearGridProps) {
760
761
  const { knobProps } = useCalendarKnobs();
762
+ const onMark = useReadableTextOn(formSelectedColors.mark);
761
763
  const glyphColor = useGlyphColor();
762
764
  const { px, hitSlop, box } = splitNestedControl(knobProps.nestedControl);
763
765
  const cellW = (px * 7) / 3;
@@ -810,8 +812,7 @@ export function YearGrid({
810
812
  cursor="pointer"
811
813
  alignItems="center"
812
814
  justifyContent="center"
813
- theme={isSelected ? ("accent" as any) : undefined}
814
- backgroundColor={isSelected ? "$background" : "transparent"}
815
+ backgroundColor={isSelected ? formSelectedColors.mark : "transparent"}
815
816
  onPress={() => onSelectYear(year)}
816
817
  outlineWidth={0}
817
818
  focusStyle={{ outlineWidth: 0 }}
@@ -829,7 +830,7 @@ export function YearGrid({
829
830
  >
830
831
  <Text
831
832
  {...knobProps.label}
832
- color={isSelected ? "$color" : formCommonColors.text}
833
+ color={isSelected ? onMark : formCommonColors.text}
833
834
  fontWeight={isSelected ? "bold" : "400"}
834
835
  >
835
836
  {year}
@@ -855,8 +856,8 @@ interface DatePickerInputTriggerProps {
855
856
  onReset: () => void;
856
857
  onButtonPress: () => void;
857
858
  id?: string;
858
- /** Empty-state glyph. Datetime uses calendar; TimePicker uses clock. */
859
- glyph?: "calendar" | "clock";
859
+ /** Trailing glyph: a clock for a time, else a calendar. */
860
+ glyph?: TriggerGlyphKind;
860
861
  "aria-label"?: string;
861
862
  "aria-labelledby"?: string;
862
863
  "aria-describedby"?: string;
@@ -864,6 +865,16 @@ interface DatePickerInputTriggerProps {
864
865
  "aria-invalid"?: boolean;
865
866
  }
866
867
 
868
+ type TriggerGlyphKind = "calendar" | "clock";
869
+
870
+ function TriggerGlyph({ glyph, ...groupItem }: { glyph: TriggerGlyphKind }) {
871
+ return (
872
+ <InputParts.Icon adornment="trailing" color={formCommonColors.muted} {...groupItem}>
873
+ {glyph === "clock" ? <ClockIcon /> : <CalendarBlankIcon />}
874
+ </InputParts.Icon>
875
+ );
876
+ }
877
+
867
878
  export function DatePickerClearButton({
868
879
  onReset,
869
880
  disabled,
@@ -918,8 +929,6 @@ export function DatePickerInputTrigger({
918
929
  }
919
930
  };
920
931
 
921
- const Glyph = glyph === "clock" ? ClockIcon : CalendarBlankIcon;
922
-
923
932
  return (
924
933
  // LC-40: the disabled Box below is pointerEvents-none, so the cursor
925
934
  // affordance must ride this wrapper — the fragment's not-allowed never
@@ -961,11 +970,6 @@ export function DatePickerInputTrigger({
961
970
  }
962
971
  : undefined)}
963
972
  >
964
- <InputParts.Section data-testid="date-picker-glyph">
965
- <InputParts.Icon adornment="leading" color={formCommonColors.muted}>
966
- <Glyph />
967
- </InputParts.Icon>
968
- </InputParts.Section>
969
973
  <InputParts.Section>
970
974
  <InputParts.Area
971
975
  readOnly
@@ -975,14 +979,17 @@ export function DatePickerInputTrigger({
975
979
  placeholder={placeholder}
976
980
  disabled={disabled}
977
981
  color={formCommonColors.text}
978
- placeholderTextColor={formCommonColors.muted}
979
982
  />
980
983
  </InputParts.Section>
981
- {value && isWeb ? (
984
+ {value && isWeb && !disabled ? (
982
985
  <InputParts.Section>
983
986
  <DatePickerClearButton onReset={onReset} disabled={disabled} />
984
987
  </InputParts.Section>
985
- ) : null}
988
+ ) : (
989
+ <InputParts.Section data-testid="date-picker-glyph">
990
+ <TriggerGlyph glyph={glyph} />
991
+ </InputParts.Section>
992
+ )}
986
993
  </InputParts.Box>
987
994
  </View>
988
995
  );
@@ -992,7 +999,7 @@ interface DatePickerReadOnlyFieldProps {
992
999
  value: string;
993
1000
  placeholder?: string;
994
1001
  id?: string;
995
- glyph?: "calendar" | "clock";
1002
+ glyph?: TriggerGlyphKind;
996
1003
  "aria-label"?: string;
997
1004
  "aria-required"?: boolean;
998
1005
  "aria-invalid"?: boolean;
@@ -1011,7 +1018,6 @@ export function DatePickerReadOnlyField({
1011
1018
  "aria-required": ariaRequired,
1012
1019
  "aria-invalid": ariaInvalid,
1013
1020
  }: DatePickerReadOnlyFieldProps) {
1014
- const Glyph = glyph === "clock" ? ClockIcon : CalendarBlankIcon;
1015
1021
  return (
1016
1022
  <View flexDirection="row" alignItems="center" width="100%">
1017
1023
  <InputParts.Box
@@ -1020,11 +1026,6 @@ export function DatePickerReadOnlyField({
1020
1026
  elevation={undefined}
1021
1027
  data-testid="date-picker-readonly"
1022
1028
  >
1023
- <InputParts.Section data-testid="date-picker-glyph">
1024
- <InputParts.Icon adornment="leading" color={formCommonColors.muted}>
1025
- <Glyph />
1026
- </InputParts.Icon>
1027
- </InputParts.Section>
1028
1029
  <InputParts.Section>
1029
1030
  <InputParts.Area
1030
1031
  readOnly
@@ -1032,13 +1033,15 @@ export function DatePickerReadOnlyField({
1032
1033
  value={value}
1033
1034
  placeholder={placeholder}
1034
1035
  color={formCommonColors.text}
1035
- placeholderTextColor={formCommonColors.muted}
1036
1036
  aria-label={ariaLabel}
1037
1037
  aria-readonly="true"
1038
1038
  aria-required={ariaRequired}
1039
1039
  aria-invalid={ariaInvalid}
1040
1040
  />
1041
1041
  </InputParts.Section>
1042
+ <InputParts.Section data-testid="date-picker-glyph">
1043
+ <TriggerGlyph glyph={glyph} />
1044
+ </InputParts.Section>
1042
1045
  </InputParts.Box>
1043
1046
  </View>
1044
1047
  );
@@ -2,7 +2,16 @@ import { transitionProps } from "@multiplatform.one/theme";
2
2
  import { useTouchSurface } from "@multiplatform.one/theme";
3
3
  import { FileIcon, UploadIcon, XIcon } from "@phosphor-icons/react";
4
4
  import type { DeepKeys, DeepValue } from "@tanstack/form-core";
5
- import { type DragEvent, type ReactNode, useCallback, useEffect, useRef, useState } from "react";
5
+ import {
6
+ type DragEvent,
7
+ type ReactNode,
8
+ type Ref,
9
+ useCallback,
10
+ useEffect,
11
+ useImperativeHandle,
12
+ useRef,
13
+ useState,
14
+ } from "react";
6
15
  import { useMedia, useProps, type SizeTokens } from "tamagui";
7
16
  import { Image, isWeb, Text, XStack, YStack, styled } from "tamagui";
8
17
  import { Button, IconButton, IconButtonGroup } from "../../Button";
@@ -26,6 +35,7 @@ import {
26
35
  import { formCommonColors, formDropzoneColors, formInputColors } from "../../shared/colorRamps";
27
36
  import { t } from "../../shared/t";
28
37
  import type { FieldComponentProps, Validator } from "../../types";
38
+ import type { FieldPickerHandle, FieldPickerTrigger } from "../pickerHandle";
29
39
  import type { NativePickedFile, NativePickerMode } from "./filePickerTypes";
30
40
  // Platform-split: the web twin is inert, the `.native` twin opens
31
41
  // expo-document-picker / expo-image-picker (Geolocation map-surface pattern).
@@ -114,6 +124,10 @@ export type FileUploadProps<
114
124
  existing?: { src: string; name?: string; isImage?: boolean } | null;
115
125
  /** Removes the existing file; given, its tile carries a remove disc. */
116
126
  onExistingRemove?: () => void;
127
+ /** LC-290: `open()` runs the picker from the app's own control. */
128
+ ref?: Ref<FieldPickerHandle>;
129
+ /** LC-290: the app's own control, drawn in place of the dropzone; call `open` from its press. */
130
+ trigger?: FieldPickerTrigger;
117
131
  };
118
132
 
119
133
  const UploadAreaFrame = styled(YStack, {
@@ -203,6 +217,7 @@ export function FileUpload<
203
217
  >(props: FileUploadProps<TParentData, TName, TFieldValidator, TFormValidator, TData>) {
204
218
  const hydrationTouch = useTouchSurface();
205
219
  const media = useMedia();
220
+ const { ref: pickerRef, trigger } = props;
206
221
  const {
207
222
  defaultValue,
208
223
  form,
@@ -230,6 +245,8 @@ export function FileUpload<
230
245
  existing,
231
246
  onExistingRemove,
232
247
  id: idProp,
248
+ ref: _ref,
249
+ trigger: _trigger,
233
250
  ...fieldProps
234
251
  } = useProps(props);
235
252
 
@@ -615,6 +632,9 @@ export function FileUpload<
615
632
  fileInputRef.current?.click();
616
633
  }, [disabled, readOnly]);
617
634
 
635
+ const requestFilesRef = useRef<() => void>(openFileDialog);
636
+ useImperativeHandle(pickerRef, () => ({ open: () => requestFilesRef.current() }), []);
637
+
618
638
  // Native has no <input type="file">. The same press opens the OS picker and
619
639
  // routes its result through the identical validate → setState → field path,
620
640
  // so `accept`, `maxSize`, `multiple` and the removal list behave as on web.
@@ -912,6 +932,29 @@ export function FileUpload<
912
932
  : () => {
913
933
  void openNativePicker(onValueChange, onBlurHandler);
914
934
  };
935
+ requestFilesRef.current = requestFiles;
936
+ const hiddenInput = isWeb ? (
937
+ <input
938
+ ref={fileInputRef}
939
+ type="file"
940
+ accept={accept}
941
+ multiple={multiple}
942
+ tabIndex={-1}
943
+ onChange={(e) => {
944
+ handleFileSelect(e.target.files, onValueChange, e.target.files);
945
+ onBlurHandler?.();
946
+ }}
947
+ style={{ display: "none" }}
948
+ disabled={!canInteract}
949
+ />
950
+ ) : null;
951
+ if (trigger)
952
+ return (
953
+ <YStack data-file-upload="trigger" alignItems="flex-start">
954
+ {trigger(requestFiles)}
955
+ {hiddenInput}
956
+ </YStack>
957
+ );
915
958
 
916
959
  // Drag-and-drop, keyboard activation and the focus ring are DOM concerns;
917
960
  // native gets a plain press target on the same surface instead.
@@ -1150,21 +1193,7 @@ export function FileUpload<
1150
1193
  </Text>
1151
1194
  )}
1152
1195
 
1153
- {isWeb ? (
1154
- <input
1155
- ref={fileInputRef}
1156
- type="file"
1157
- accept={accept}
1158
- multiple={multiple}
1159
- tabIndex={-1}
1160
- onChange={(e) => {
1161
- handleFileSelect(e.target.files, onValueChange, e.target.files);
1162
- onBlurHandler?.();
1163
- }}
1164
- style={{ display: "none" }}
1165
- disabled={!canInteract}
1166
- />
1167
- ) : null}
1196
+ {hiddenInput}
1168
1197
  </YStack>
1169
1198
 
1170
1199
  {((multiple && hasRows) || transfers.length > 0) && (
@@ -18,8 +18,9 @@ import {
18
18
  type DisabledSurfaceProps,
19
19
  type KnobProps,
20
20
  } from "@multiplatform.one/theme";
21
- import type { DragEvent, ReactNode } from "react";
22
- import { useCallback, useEffect, useRef, useState } from "react";
21
+ import type { DragEvent, ReactNode, Ref } from "react";
22
+ import { useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
23
+ import type { FieldPickerHandle, FieldPickerTrigger } from "../pickerHandle";
23
24
  import type { LabelProps, SizeTokens } from "tamagui";
24
25
  import { Image, Text as TamaguiText, View, YStack, isWeb, styled } from "tamagui";
25
26
  import { IconButton } from "../../Button";
@@ -78,6 +79,10 @@ export interface ImageFieldProps {
78
79
  objectFit?: "cover" | "contain" | "fill" | "none";
79
80
  /** When true, renders a skeleton placeholder instead of the image field */
80
81
  skeleton?: boolean;
82
+ /** LC-290: `open()` runs the picker from the app's own control. */
83
+ ref?: Ref<FieldPickerHandle>;
84
+ /** LC-290: the app's own control, drawn in place of the image frame; call `open` from its press. */
85
+ trigger?: FieldPickerTrigger;
81
86
  }
82
87
 
83
88
  const ImageFrame = styled(View, {
@@ -112,6 +117,8 @@ type ImageControlProps = {
112
117
  onChangeProp?: (val: string | File | null) => void;
113
118
  onInvalid?: (message: string | undefined) => void;
114
119
  blurHandler?: (...args: any[]) => void;
120
+ pickerRef?: Ref<FieldPickerHandle>;
121
+ trigger?: FieldPickerTrigger;
115
122
  };
116
123
 
117
124
  function isImageFile(file: File, accept: string): boolean {
@@ -148,6 +155,8 @@ function ImageControl({
148
155
  onChangeProp,
149
156
  onInvalid,
150
157
  blurHandler,
158
+ pickerRef,
159
+ trigger,
151
160
  }: ImageControlProps) {
152
161
  const describedBy = useFieldDescribedBy();
153
162
  const fieldA11y = useFieldA11y();
@@ -230,6 +239,7 @@ function ImageControl({
230
239
  if (!canInteract) return;
231
240
  fileInputRef.current?.click();
232
241
  }, [canInteract]);
242
+ useImperativeHandle(pickerRef, () => ({ open: openFileDialog }), [openFileDialog]);
233
243
 
234
244
  const isInteractiveChild = useCallback((e: { target: unknown; currentTarget: unknown }) => {
235
245
  const target = e.target as HTMLElement | null;
@@ -313,6 +323,31 @@ function ImageControl({
313
323
  const emptyName =
314
324
  typeof label === "string" && label ? t("{{label}}: add image", { label }) : t("Add image");
315
325
 
326
+ const hiddenInput = isWeb ? (
327
+ <input
328
+ ref={fileInputRef}
329
+ type="file"
330
+ accept={accept}
331
+ tabIndex={-1}
332
+ aria-hidden={true}
333
+ onChange={(e) => {
334
+ const files = e.target.files;
335
+ e.target.value = "";
336
+ if (!files || files.length === 0) return;
337
+ applyFile(files[0]);
338
+ }}
339
+ style={{ display: "none" }}
340
+ disabled={!canInteract}
341
+ />
342
+ ) : null;
343
+ if (trigger)
344
+ return (
345
+ <YStack alignItems="flex-start" data-image-field="trigger">
346
+ {trigger(openFileDialog)}
347
+ {hiddenInput}
348
+ </YStack>
349
+ );
350
+
316
351
  return (
317
352
  <YStack alignItems="flex-start" {...knobProps.gap}>
318
353
  <ImageFrame
@@ -398,23 +433,7 @@ function ImageControl({
398
433
  </View>
399
434
  )}
400
435
 
401
- {isWeb && (
402
- <input
403
- ref={fileInputRef}
404
- type="file"
405
- accept={accept}
406
- tabIndex={-1}
407
- aria-hidden={true}
408
- onChange={(e) => {
409
- const files = e.target.files;
410
- e.target.value = "";
411
- if (!files || files.length === 0) return;
412
- applyFile(files[0]);
413
- }}
414
- style={{ display: "none" }}
415
- disabled={!canInteract}
416
- />
417
- )}
436
+ {hiddenInput}
418
437
  </ImageFrame>
419
438
 
420
439
  {showRemove && hasValue && canInteract && !inTableCell && (
@@ -453,6 +472,8 @@ export function ImageField({
453
472
  placeholder,
454
473
  objectFit = "cover",
455
474
  skeleton,
475
+ ref,
476
+ trigger,
456
477
  }: ImageFieldProps) {
457
478
  const { resolvedForm, knobProps, disabledState, id } = useFormField({
458
479
  form: formProp,
@@ -486,6 +507,8 @@ export function ImageField({
486
507
  disabledSurface: disabled ? disabledState.surfaceKnobProps : undefined,
487
508
  onChangeProp,
488
509
  onInvalid: setValidationError,
510
+ pickerRef: ref,
511
+ trigger,
489
512
  };
490
513
 
491
514
  if (!resolvedForm || !name) {
@@ -25,6 +25,7 @@ import {
25
25
  import { Field, FieldLayout, useFieldDescribedBy } from "../../fieldLayout";
26
26
  import { Skeleton } from "../../Skeleton";
27
27
  import { formControlColors, formSelectedColors } from "../../shared/colorRamps";
28
+ import { useControlTrackFill } from "../../shared/controlTrack";
28
29
  import { useIsInTableCell } from "../../shared/tableCellContext";
29
30
  import { bidiIsolate, t } from "../../shared/t";
30
31
  import {
@@ -186,6 +187,7 @@ function ProgressTrack({
186
187
  blurHandler,
187
188
  }: ProgressTrackProps) {
188
189
  const describedBy = useFieldDescribedBy();
190
+ const trackFill = useControlTrackFill();
189
191
  const trackSize = size ?? sizeToken;
190
192
  const percent = Math.round((progressValue / max) * 100);
191
193
  const motion = indicatorMotion(knobProps.motion.slide);
@@ -197,6 +199,7 @@ function ProgressTrack({
197
199
  size={trackSize}
198
200
  overflow="hidden"
199
201
  outlined={knobProps.outlined}
202
+ {...(knobProps.outlined ? undefined : { backgroundColor: trackFill })}
200
203
  {...knobProps.borderRadius}
201
204
  {...(knobProps.outlined ? knobProps.inputSurface : { borderWidth: 0 })}
202
205
  {...(knobProps.outlined ? { borderColor: formControlColors.boundary } : undefined)}
@@ -25,6 +25,17 @@ const SystemSliderProbe = vi.hoisted(
25
25
  data-rail={props.maximumTrackTintColor}
26
26
  data-thumb={props.thumbTintColor ?? ""}
27
27
  data-label={props.accessibilityLabel ?? ""}
28
+ data-accessible={String(props.accessible ?? "")}
29
+ data-role={props.accessibilityRole ?? ""}
30
+ data-a11y-value={JSON.stringify(props.accessibilityValue ?? null)}
31
+ data-actions={(props.accessibilityActions ?? [])
32
+ .map((a: { name: string }) => a.name)
33
+ .join(",")}
34
+ onKeyDown={(event) => {
35
+ const actionName =
36
+ event.key === "ArrowUp" ? "increment" : event.key === "ArrowDown" ? "decrement" : "";
37
+ if (actionName) props.onAccessibilityAction?.({ nativeEvent: { actionName } });
38
+ }}
28
39
  data-min={props.minimumValue}
29
40
  data-max={props.maximumValue}
30
41
  data-step={props.step}
@@ -101,6 +112,39 @@ describe("Slider on iOS and Android", () => {
101
112
  },
102
113
  );
103
114
 
115
+ it("is an adjustable element named by its label, valued, stepping on VoiceOver swipes (FZ-8905)", () => {
116
+ const onChange = vi.fn();
117
+ const result = renderWithProviders(
118
+ <Slider
119
+ label="Brightness"
120
+ defaultValue={[80]}
121
+ min={0}
122
+ max={100}
123
+ step={1}
124
+ onChange={onChange}
125
+ />,
126
+ );
127
+ const view = result.getByTestId("system-slider");
128
+ expect(view.dataset).toMatchObject({
129
+ accessible: "true",
130
+ role: "adjustable",
131
+ label: "Brightness",
132
+ actions: "increment,decrement",
133
+ });
134
+ expect(JSON.parse(view.dataset.a11yValue ?? "null")).toEqual({
135
+ min: 0,
136
+ max: 100,
137
+ now: 80,
138
+ text: "80",
139
+ });
140
+ fireEvent.keyDown(view, { key: "ArrowUp" });
141
+ expect(onChange).toHaveBeenLastCalledWith([81]);
142
+ expect(JSON.parse(view.dataset.a11yValue ?? "null")).toMatchObject({ now: 81 });
143
+ fireEvent.keyDown(view, { key: "ArrowDown" });
144
+ fireEvent.keyDown(view, { key: "ArrowDown" });
145
+ expect(onChange).toHaveBeenLastCalledWith([79]);
146
+ });
147
+
104
148
  it("tints the Android thumb with the fill", () => {
105
149
  system.os = "android";
106
150
  const result = renderInScheme(<Slider label="Volume" />, "light");