@multiplatform.one/forms 6.4.2 → 6.6.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 (405) hide show
  1. package/dist/cjs/Button/index.cjs +23 -8
  2. package/dist/cjs/Button/index.native.js +23 -8
  3. package/dist/cjs/Button/index.native.js.map +1 -1
  4. package/dist/cjs/FieldDisplay/formatters.cjs +7 -12
  5. package/dist/cjs/FieldDisplay/formatters.native.js +7 -12
  6. package/dist/cjs/FieldDisplay/formatters.native.js.map +1 -1
  7. package/dist/cjs/Skeleton/index.cjs +1 -0
  8. package/dist/cjs/Skeleton/index.native.js +4 -0
  9. package/dist/cjs/Skeleton/index.native.js.map +1 -1
  10. package/dist/cjs/Wheel/index.cjs +1 -1
  11. package/dist/cjs/Wheel/index.native.js +1 -1
  12. package/dist/cjs/Wheel/index.native.js.map +1 -1
  13. package/dist/cjs/fields/Checkbox/Checkbox.cjs +22 -15
  14. package/dist/cjs/fields/Checkbox/Checkbox.native.js +11 -6
  15. package/dist/cjs/fields/Checkbox/Checkbox.native.js.map +1 -1
  16. package/dist/cjs/fields/Checkbox/index.cjs +9 -3
  17. package/dist/cjs/fields/Checkbox/index.native.js +9 -3
  18. package/dist/cjs/fields/Checkbox/index.native.js.map +1 -1
  19. package/dist/cjs/fields/ColorPicker/parts.native.js.map +1 -1
  20. package/dist/cjs/fields/Combobox/index.cjs +9 -4
  21. package/dist/cjs/fields/Combobox/index.native.js +9 -4
  22. package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
  23. package/dist/cjs/fields/DatePicker/DateRangePicker.cjs +30 -20
  24. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +36 -21
  25. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  26. package/dist/cjs/fields/DatePicker/DatetimePicker.cjs +21 -15
  27. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +26 -16
  28. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  29. package/dist/cjs/fields/DatePicker/MonthPicker.cjs +24 -14
  30. package/dist/cjs/fields/DatePicker/MonthPicker.native.js +36 -15
  31. package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
  32. package/dist/cjs/fields/DatePicker/MultiDatePicker.cjs +27 -18
  33. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +32 -19
  34. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  35. package/dist/cjs/fields/DatePicker/fieldValueSync.cjs +49 -0
  36. package/dist/cjs/fields/DatePicker/fieldValueSync.native.js +56 -0
  37. package/dist/cjs/fields/DatePicker/fieldValueSync.native.js.map +1 -0
  38. package/dist/cjs/fields/DatePicker/index.cjs +20 -14
  39. package/dist/cjs/fields/DatePicker/index.native.js +25 -15
  40. package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
  41. package/dist/cjs/fields/DatePicker/parts.cjs +2 -3
  42. package/dist/cjs/fields/DatePicker/parts.native.js +2 -3
  43. package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
  44. package/dist/cjs/fields/Geolocation/GeolocationMap.native.js +2 -2
  45. package/dist/cjs/fields/RadioGroup/index.cjs +4 -6
  46. package/dist/cjs/fields/RadioGroup/index.native.js +7 -6
  47. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  48. package/dist/cjs/fields/Rating/index.cjs +20 -3
  49. package/dist/cjs/fields/Rating/index.native.js +31 -6
  50. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  51. package/dist/cjs/fields/SearchInput/index.cjs +5 -1
  52. package/dist/cjs/fields/SearchInput/index.native.js +5 -1
  53. package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
  54. package/dist/cjs/fields/Select/index.cjs +6 -10
  55. package/dist/cjs/fields/Select/index.native.js +12 -10
  56. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  57. package/dist/cjs/fields/Signature/index.cjs +1 -1
  58. package/dist/cjs/fields/Signature/index.native.js +1 -1
  59. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  60. package/dist/cjs/fields/Slider/index.cjs +16 -4
  61. package/dist/cjs/fields/Slider/index.native.js +24 -4
  62. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  63. package/dist/cjs/fields/TextArea/index.cjs +3 -2
  64. package/dist/cjs/fields/TextArea/index.native.js +5 -2
  65. package/dist/cjs/fields/TextArea/index.native.js.map +1 -1
  66. package/dist/cjs/fields/TimePicker/index.cjs +1 -1
  67. package/dist/cjs/fields/TimePicker/index.native.js +1 -1
  68. package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
  69. package/dist/cjs/fields/ToggleGroup/index.cjs +6 -22
  70. package/dist/cjs/fields/ToggleGroup/index.native.js +11 -28
  71. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  72. package/dist/cjs/shared/TimeColumn.cjs +1 -1
  73. package/dist/cjs/shared/TimeColumn.native.js +1 -1
  74. package/dist/cjs/shared/TimeColumn.native.js.map +1 -1
  75. package/dist/cjs/shared/colorRamps.cjs +5 -1
  76. package/dist/cjs/shared/colorRamps.native.js +5 -1
  77. package/dist/cjs/shared/colorRamps.native.js.map +1 -1
  78. package/dist/cjs/shared/focusManagement.cjs +7 -1
  79. package/dist/cjs/shared/focusManagement.native.js +5 -1
  80. package/dist/cjs/shared/focusManagement.native.js.map +1 -1
  81. package/dist/cjs/shared/t.cjs +5 -0
  82. package/dist/cjs/shared/t.native.js +5 -0
  83. package/dist/cjs/shared/t.native.js.map +1 -1
  84. package/dist/esm/Button/index.mjs +24 -9
  85. package/dist/esm/Button/index.mjs.map +1 -1
  86. package/dist/esm/Button/index.native.js +24 -9
  87. package/dist/esm/Button/index.native.js.map +1 -1
  88. package/dist/esm/FieldDisplay/formatters.mjs +8 -13
  89. package/dist/esm/FieldDisplay/formatters.mjs.map +1 -1
  90. package/dist/esm/FieldDisplay/formatters.native.js +8 -13
  91. package/dist/esm/FieldDisplay/formatters.native.js.map +1 -1
  92. package/dist/esm/FieldDisplay/index.mjs.map +1 -1
  93. package/dist/esm/FloatingPanel/index.mjs.map +1 -1
  94. package/dist/esm/Skeleton/index.mjs +2 -1
  95. package/dist/esm/Skeleton/index.mjs.map +1 -1
  96. package/dist/esm/Skeleton/index.native.js +5 -1
  97. package/dist/esm/Skeleton/index.native.js.map +1 -1
  98. package/dist/esm/Wheel/index.mjs +1 -1
  99. package/dist/esm/Wheel/index.mjs.map +1 -1
  100. package/dist/esm/Wheel/index.native.js +1 -1
  101. package/dist/esm/Wheel/index.native.js.map +1 -1
  102. package/dist/esm/fields/Checkbox/Checkbox.mjs +24 -17
  103. package/dist/esm/fields/Checkbox/Checkbox.mjs.map +1 -1
  104. package/dist/esm/fields/Checkbox/Checkbox.native.js +13 -8
  105. package/dist/esm/fields/Checkbox/Checkbox.native.js.map +1 -1
  106. package/dist/esm/fields/Checkbox/index.mjs +11 -5
  107. package/dist/esm/fields/Checkbox/index.mjs.map +1 -1
  108. package/dist/esm/fields/Checkbox/index.native.js +11 -5
  109. package/dist/esm/fields/Checkbox/index.native.js.map +1 -1
  110. package/dist/esm/fields/ColorPicker/index.mjs.map +1 -1
  111. package/dist/esm/fields/ColorPicker/parts.mjs.map +1 -1
  112. package/dist/esm/fields/ColorPicker/parts.native.js.map +1 -1
  113. package/dist/esm/fields/Combobox/index.mjs +9 -4
  114. package/dist/esm/fields/Combobox/index.mjs.map +1 -1
  115. package/dist/esm/fields/Combobox/index.native.js +9 -4
  116. package/dist/esm/fields/Combobox/index.native.js.map +1 -1
  117. package/dist/esm/fields/DatePicker/DateRangePicker.mjs +31 -21
  118. package/dist/esm/fields/DatePicker/DateRangePicker.mjs.map +1 -1
  119. package/dist/esm/fields/DatePicker/DateRangePicker.native.js +37 -22
  120. package/dist/esm/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  121. package/dist/esm/fields/DatePicker/DatetimePicker.mjs +21 -15
  122. package/dist/esm/fields/DatePicker/DatetimePicker.mjs.map +1 -1
  123. package/dist/esm/fields/DatePicker/DatetimePicker.native.js +26 -16
  124. package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  125. package/dist/esm/fields/DatePicker/MonthPicker.mjs +25 -15
  126. package/dist/esm/fields/DatePicker/MonthPicker.mjs.map +1 -1
  127. package/dist/esm/fields/DatePicker/MonthPicker.native.js +37 -16
  128. package/dist/esm/fields/DatePicker/MonthPicker.native.js.map +1 -1
  129. package/dist/esm/fields/DatePicker/MultiDatePicker.mjs +28 -19
  130. package/dist/esm/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
  131. package/dist/esm/fields/DatePicker/MultiDatePicker.native.js +33 -20
  132. package/dist/esm/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  133. package/dist/esm/fields/DatePicker/fieldValueSync.mjs +23 -0
  134. package/dist/esm/fields/DatePicker/fieldValueSync.mjs.map +1 -0
  135. package/dist/esm/fields/DatePicker/fieldValueSync.native.js +27 -0
  136. package/dist/esm/fields/DatePicker/fieldValueSync.native.js.map +1 -0
  137. package/dist/esm/fields/DatePicker/index.mjs +21 -15
  138. package/dist/esm/fields/DatePicker/index.mjs.map +1 -1
  139. package/dist/esm/fields/DatePicker/index.native.js +26 -16
  140. package/dist/esm/fields/DatePicker/index.native.js.map +1 -1
  141. package/dist/esm/fields/DatePicker/parts.mjs +3 -4
  142. package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
  143. package/dist/esm/fields/DatePicker/parts.native.js +3 -4
  144. package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
  145. package/dist/esm/fields/DatePicker/utils.mjs.map +1 -1
  146. package/dist/esm/fields/Geolocation/GeolocationMap.native.js +2 -2
  147. package/dist/esm/fields/ImageField/index.mjs.map +1 -1
  148. package/dist/esm/fields/OTPInput/index.mjs.map +1 -1
  149. package/dist/esm/fields/RadioGroup/index.mjs +5 -7
  150. package/dist/esm/fields/RadioGroup/index.mjs.map +1 -1
  151. package/dist/esm/fields/RadioGroup/index.native.js +8 -7
  152. package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
  153. package/dist/esm/fields/Rating/index.mjs +20 -3
  154. package/dist/esm/fields/Rating/index.mjs.map +1 -1
  155. package/dist/esm/fields/Rating/index.native.js +31 -6
  156. package/dist/esm/fields/Rating/index.native.js.map +1 -1
  157. package/dist/esm/fields/SearchInput/index.mjs +6 -2
  158. package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
  159. package/dist/esm/fields/SearchInput/index.native.js +6 -2
  160. package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
  161. package/dist/esm/fields/Select/index.mjs +6 -10
  162. package/dist/esm/fields/Select/index.mjs.map +1 -1
  163. package/dist/esm/fields/Select/index.native.js +12 -10
  164. package/dist/esm/fields/Select/index.native.js.map +1 -1
  165. package/dist/esm/fields/Signature/index.mjs +1 -1
  166. package/dist/esm/fields/Signature/index.mjs.map +1 -1
  167. package/dist/esm/fields/Signature/index.native.js +1 -1
  168. package/dist/esm/fields/Signature/index.native.js.map +1 -1
  169. package/dist/esm/fields/Slider/index.mjs +16 -4
  170. package/dist/esm/fields/Slider/index.mjs.map +1 -1
  171. package/dist/esm/fields/Slider/index.native.js +24 -4
  172. package/dist/esm/fields/Slider/index.native.js.map +1 -1
  173. package/dist/esm/fields/TextArea/index.mjs +3 -2
  174. package/dist/esm/fields/TextArea/index.mjs.map +1 -1
  175. package/dist/esm/fields/TextArea/index.native.js +5 -2
  176. package/dist/esm/fields/TextArea/index.native.js.map +1 -1
  177. package/dist/esm/fields/TimePicker/index.mjs +1 -1
  178. package/dist/esm/fields/TimePicker/index.mjs.map +1 -1
  179. package/dist/esm/fields/TimePicker/index.native.js +1 -1
  180. package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
  181. package/dist/esm/fields/ToggleGroup/index.mjs +7 -23
  182. package/dist/esm/fields/ToggleGroup/index.mjs.map +1 -1
  183. package/dist/esm/fields/ToggleGroup/index.native.js +12 -29
  184. package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
  185. package/dist/esm/shared/TimeColumn.mjs +1 -1
  186. package/dist/esm/shared/TimeColumn.mjs.map +1 -1
  187. package/dist/esm/shared/TimeColumn.native.js +1 -1
  188. package/dist/esm/shared/TimeColumn.native.js.map +1 -1
  189. package/dist/esm/shared/colorRamps.mjs +5 -2
  190. package/dist/esm/shared/colorRamps.mjs.map +1 -1
  191. package/dist/esm/shared/colorRamps.native.js +5 -2
  192. package/dist/esm/shared/colorRamps.native.js.map +1 -1
  193. package/dist/esm/shared/focusManagement.mjs +7 -1
  194. package/dist/esm/shared/focusManagement.mjs.map +1 -1
  195. package/dist/esm/shared/focusManagement.native.js +5 -1
  196. package/dist/esm/shared/focusManagement.native.js.map +1 -1
  197. package/dist/esm/shared/t.mjs +5 -1
  198. package/dist/esm/shared/t.mjs.map +1 -1
  199. package/dist/esm/shared/t.native.js +5 -1
  200. package/dist/esm/shared/t.native.js.map +1 -1
  201. package/dist/jsx/Button/index.mjs +24 -9
  202. package/dist/jsx/Button/index.mjs.map +1 -1
  203. package/dist/jsx/Button/index.native.js +23 -8
  204. package/dist/jsx/Button/index.native.js.map +1 -1
  205. package/dist/jsx/FieldDisplay/formatters.mjs +8 -13
  206. package/dist/jsx/FieldDisplay/formatters.mjs.map +1 -1
  207. package/dist/jsx/FieldDisplay/formatters.native.js +7 -12
  208. package/dist/jsx/FieldDisplay/formatters.native.js.map +1 -1
  209. package/dist/jsx/FieldDisplay/index.mjs.map +1 -1
  210. package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
  211. package/dist/jsx/Skeleton/index.mjs +2 -1
  212. package/dist/jsx/Skeleton/index.mjs.map +1 -1
  213. package/dist/jsx/Skeleton/index.native.js +4 -0
  214. package/dist/jsx/Skeleton/index.native.js.map +1 -1
  215. package/dist/jsx/Wheel/index.mjs +1 -1
  216. package/dist/jsx/Wheel/index.mjs.map +1 -1
  217. package/dist/jsx/Wheel/index.native.js +1 -1
  218. package/dist/jsx/Wheel/index.native.js.map +1 -1
  219. package/dist/jsx/fields/Checkbox/Checkbox.mjs +24 -17
  220. package/dist/jsx/fields/Checkbox/Checkbox.mjs.map +1 -1
  221. package/dist/jsx/fields/Checkbox/Checkbox.native.js +11 -6
  222. package/dist/jsx/fields/Checkbox/Checkbox.native.js.map +1 -1
  223. package/dist/jsx/fields/Checkbox/index.mjs +11 -5
  224. package/dist/jsx/fields/Checkbox/index.mjs.map +1 -1
  225. package/dist/jsx/fields/Checkbox/index.native.js +9 -3
  226. package/dist/jsx/fields/Checkbox/index.native.js.map +1 -1
  227. package/dist/jsx/fields/ColorPicker/index.mjs.map +1 -1
  228. package/dist/jsx/fields/ColorPicker/parts.mjs.map +1 -1
  229. package/dist/jsx/fields/ColorPicker/parts.native.js.map +1 -1
  230. package/dist/jsx/fields/Combobox/index.mjs +9 -4
  231. package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
  232. package/dist/jsx/fields/Combobox/index.native.js +9 -4
  233. package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
  234. package/dist/jsx/fields/DatePicker/DateRangePicker.mjs +31 -21
  235. package/dist/jsx/fields/DatePicker/DateRangePicker.mjs.map +1 -1
  236. package/dist/jsx/fields/DatePicker/DateRangePicker.native.js +36 -21
  237. package/dist/jsx/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  238. package/dist/jsx/fields/DatePicker/DatetimePicker.mjs +21 -15
  239. package/dist/jsx/fields/DatePicker/DatetimePicker.mjs.map +1 -1
  240. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +26 -16
  241. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  242. package/dist/jsx/fields/DatePicker/MonthPicker.mjs +25 -15
  243. package/dist/jsx/fields/DatePicker/MonthPicker.mjs.map +1 -1
  244. package/dist/jsx/fields/DatePicker/MonthPicker.native.js +36 -15
  245. package/dist/jsx/fields/DatePicker/MonthPicker.native.js.map +1 -1
  246. package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs +28 -19
  247. package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
  248. package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js +32 -19
  249. package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  250. package/dist/jsx/fields/DatePicker/fieldValueSync.mjs +23 -0
  251. package/dist/jsx/fields/DatePicker/fieldValueSync.mjs.map +1 -0
  252. package/dist/jsx/fields/DatePicker/fieldValueSync.native.js +56 -0
  253. package/dist/jsx/fields/DatePicker/fieldValueSync.native.js.map +1 -0
  254. package/dist/jsx/fields/DatePicker/index.mjs +21 -15
  255. package/dist/jsx/fields/DatePicker/index.mjs.map +1 -1
  256. package/dist/jsx/fields/DatePicker/index.native.js +25 -15
  257. package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
  258. package/dist/jsx/fields/DatePicker/parts.mjs +3 -4
  259. package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
  260. package/dist/jsx/fields/DatePicker/parts.native.js +2 -3
  261. package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
  262. package/dist/jsx/fields/DatePicker/utils.mjs.map +1 -1
  263. package/dist/jsx/fields/Geolocation/GeolocationMap.native.js +2 -2
  264. package/dist/jsx/fields/ImageField/index.mjs.map +1 -1
  265. package/dist/jsx/fields/OTPInput/index.mjs.map +1 -1
  266. package/dist/jsx/fields/RadioGroup/index.mjs +5 -7
  267. package/dist/jsx/fields/RadioGroup/index.mjs.map +1 -1
  268. package/dist/jsx/fields/RadioGroup/index.native.js +7 -6
  269. package/dist/jsx/fields/RadioGroup/index.native.js.map +1 -1
  270. package/dist/jsx/fields/Rating/index.mjs +20 -3
  271. package/dist/jsx/fields/Rating/index.mjs.map +1 -1
  272. package/dist/jsx/fields/Rating/index.native.js +31 -6
  273. package/dist/jsx/fields/Rating/index.native.js.map +1 -1
  274. package/dist/jsx/fields/SearchInput/index.mjs +6 -2
  275. package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
  276. package/dist/jsx/fields/SearchInput/index.native.js +5 -1
  277. package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
  278. package/dist/jsx/fields/Select/index.mjs +6 -10
  279. package/dist/jsx/fields/Select/index.mjs.map +1 -1
  280. package/dist/jsx/fields/Select/index.native.js +12 -10
  281. package/dist/jsx/fields/Select/index.native.js.map +1 -1
  282. package/dist/jsx/fields/Signature/index.mjs +1 -1
  283. package/dist/jsx/fields/Signature/index.mjs.map +1 -1
  284. package/dist/jsx/fields/Signature/index.native.js +1 -1
  285. package/dist/jsx/fields/Signature/index.native.js.map +1 -1
  286. package/dist/jsx/fields/Slider/index.mjs +16 -4
  287. package/dist/jsx/fields/Slider/index.mjs.map +1 -1
  288. package/dist/jsx/fields/Slider/index.native.js +24 -4
  289. package/dist/jsx/fields/Slider/index.native.js.map +1 -1
  290. package/dist/jsx/fields/TextArea/index.mjs +3 -2
  291. package/dist/jsx/fields/TextArea/index.mjs.map +1 -1
  292. package/dist/jsx/fields/TextArea/index.native.js +5 -2
  293. package/dist/jsx/fields/TextArea/index.native.js.map +1 -1
  294. package/dist/jsx/fields/TimePicker/index.mjs +1 -1
  295. package/dist/jsx/fields/TimePicker/index.mjs.map +1 -1
  296. package/dist/jsx/fields/TimePicker/index.native.js +1 -1
  297. package/dist/jsx/fields/TimePicker/index.native.js.map +1 -1
  298. package/dist/jsx/fields/ToggleGroup/index.mjs +7 -23
  299. package/dist/jsx/fields/ToggleGroup/index.mjs.map +1 -1
  300. package/dist/jsx/fields/ToggleGroup/index.native.js +11 -28
  301. package/dist/jsx/fields/ToggleGroup/index.native.js.map +1 -1
  302. package/dist/jsx/shared/TimeColumn.mjs +1 -1
  303. package/dist/jsx/shared/TimeColumn.mjs.map +1 -1
  304. package/dist/jsx/shared/TimeColumn.native.js +1 -1
  305. package/dist/jsx/shared/TimeColumn.native.js.map +1 -1
  306. package/dist/jsx/shared/colorRamps.mjs +5 -2
  307. package/dist/jsx/shared/colorRamps.mjs.map +1 -1
  308. package/dist/jsx/shared/colorRamps.native.js +5 -1
  309. package/dist/jsx/shared/colorRamps.native.js.map +1 -1
  310. package/dist/jsx/shared/focusManagement.mjs +7 -1
  311. package/dist/jsx/shared/focusManagement.mjs.map +1 -1
  312. package/dist/jsx/shared/focusManagement.native.js +5 -1
  313. package/dist/jsx/shared/focusManagement.native.js.map +1 -1
  314. package/dist/jsx/shared/t.mjs +5 -1
  315. package/dist/jsx/shared/t.mjs.map +1 -1
  316. package/dist/jsx/shared/t.native.js +5 -0
  317. package/dist/jsx/shared/t.native.js.map +1 -1
  318. package/package.json +8 -7
  319. package/src/Button/Button.stories.tsx +19 -0
  320. package/src/Button/index.tsx +45 -12
  321. package/src/ControlGroup/ControlGroup.stories.tsx +12 -0
  322. package/src/FieldDisplay/formatters.ts +10 -14
  323. package/src/FieldLayout.stories.tsx +3 -2
  324. package/src/Form/Form.stories.tsx +13 -0
  325. package/src/Skeleton/index.tsx +5 -1
  326. package/src/fields/Checkbox/Checkbox.spec.tsx +50 -1
  327. package/src/fields/Checkbox/Checkbox.tsx +47 -19
  328. package/src/fields/Checkbox/index.tsx +23 -5
  329. package/src/fields/ColorPicker/ColorPicker.stories.tsx +2 -1
  330. package/src/fields/Combobox/index.tsx +8 -3
  331. package/src/fields/DatePicker/DatePicker.spec.tsx +93 -0
  332. package/src/fields/DatePicker/DatePicker.stories.tsx +2 -1
  333. package/src/fields/DatePicker/DateRangePicker.spec.tsx +72 -0
  334. package/src/fields/DatePicker/DateRangePicker.tsx +44 -30
  335. package/src/fields/DatePicker/DatetimePicker.spec.tsx +39 -0
  336. package/src/fields/DatePicker/DatetimePicker.tsx +1 -1
  337. package/src/fields/DatePicker/MonthPicker.spec.tsx +61 -0
  338. package/src/fields/DatePicker/MonthPicker.tsx +47 -21
  339. package/src/fields/DatePicker/MultiDatePicker.spec.tsx +34 -0
  340. package/src/fields/DatePicker/MultiDatePicker.tsx +39 -27
  341. package/src/fields/DatePicker/fieldValueSync.tsx +23 -0
  342. package/src/fields/DatePicker/parts.tsx +6 -1
  343. package/src/fields/FileUpload/FileUpload.stories.tsx +11 -1
  344. package/src/fields/Geolocation/Geolocation.stories.tsx +9 -0
  345. package/src/fields/Geolocation/GeolocationMap.native.tsx +2 -2
  346. package/src/fields/ImageField/ImageField.stories.tsx +2 -1
  347. package/src/fields/Input/Input.stories.tsx +19 -0
  348. package/src/fields/Progress/Progress.stories.tsx +19 -0
  349. package/src/fields/RadioGroup/RadioGroup.spec.tsx +139 -2
  350. package/src/fields/RadioGroup/index.tsx +2 -2
  351. package/src/fields/Rating/Rating.spec.tsx +43 -1
  352. package/src/fields/Rating/index.tsx +43 -4
  353. package/src/fields/SearchInput/SearchInput.spec.tsx +11 -0
  354. package/src/fields/SearchInput/index.tsx +6 -2
  355. package/src/fields/Select/Select.stories.tsx +19 -0
  356. package/src/fields/Select/index.tsx +12 -5
  357. package/src/fields/Signature/index.tsx +1 -1
  358. package/src/fields/Slider/Slider.spec.tsx +89 -4
  359. package/src/fields/Slider/Slider.stories.tsx +19 -0
  360. package/src/fields/Slider/index.tsx +4 -0
  361. package/src/fields/Stepper/Stepper.stories.tsx +12 -0
  362. package/src/fields/Switch/Switch.spec.tsx +50 -2
  363. package/src/fields/TextArea/TextArea.spec.tsx +57 -0
  364. package/src/fields/TextArea/TextArea.stories.tsx +19 -0
  365. package/src/fields/TextArea/index.tsx +10 -2
  366. package/src/fields/TimePicker/index.tsx +1 -1
  367. package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +64 -1
  368. package/src/fields/ToggleGroup/ToggleGroup.stories.tsx +19 -0
  369. package/src/fields/ToggleGroup/index.tsx +31 -29
  370. package/src/shared/FloatingListScrollArrows.stories.tsx +4 -2
  371. package/src/shared/TimeColumn.tsx +1 -1
  372. package/src/shared/focusManagement.ts +12 -1
  373. package/src/shared/t.spec.ts +39 -0
  374. package/src/shared/t.ts +20 -0
  375. package/types/Button/index.d.ts +9 -1
  376. package/types/Button/index.d.ts.map +1 -1
  377. package/types/FieldDisplay/formatters.d.ts +7 -1
  378. package/types/FieldDisplay/formatters.d.ts.map +1 -1
  379. package/types/InputParts/index.d.ts +4 -4
  380. package/types/Skeleton/index.d.ts.map +1 -1
  381. package/types/fields/Checkbox/Checkbox.d.ts.map +1 -1
  382. package/types/fields/Checkbox/index.d.ts +3 -3
  383. package/types/fields/Checkbox/index.d.ts.map +1 -1
  384. package/types/fields/Combobox/index.d.ts.map +1 -1
  385. package/types/fields/DatePicker/DateRangePicker.d.ts.map +1 -1
  386. package/types/fields/DatePicker/DatetimePicker.d.ts.map +1 -1
  387. package/types/fields/DatePicker/MonthPicker.d.ts.map +1 -1
  388. package/types/fields/DatePicker/MultiDatePicker.d.ts.map +1 -1
  389. package/types/fields/DatePicker/fieldValueSync.d.ts +31 -0
  390. package/types/fields/DatePicker/fieldValueSync.d.ts.map +1 -0
  391. package/types/fields/DatePicker/index.d.ts.map +1 -1
  392. package/types/fields/DatePicker/parts.d.ts.map +1 -1
  393. package/types/fields/Input/index.d.ts +2 -2
  394. package/types/fields/RadioGroup/index.d.ts.map +1 -1
  395. package/types/fields/Rating/index.d.ts.map +1 -1
  396. package/types/fields/SearchInput/index.d.ts.map +1 -1
  397. package/types/fields/Select/index.d.ts.map +1 -1
  398. package/types/fields/Slider/index.d.ts.map +1 -1
  399. package/types/fields/TextArea/index.d.ts.map +1 -1
  400. package/types/fields/ToggleGroup/index.d.ts.map +1 -1
  401. package/types/shared/colorRamps.d.ts +14 -0
  402. package/types/shared/colorRamps.d.ts.map +1 -1
  403. package/types/shared/focusManagement.d.ts.map +1 -1
  404. package/types/shared/t.d.ts +16 -0
  405. package/types/shared/t.d.ts.map +1 -1
@@ -116,7 +116,8 @@ export const Disabled: Story = {
116
116
  export const WithError: Story = {
117
117
  args: {
118
118
  label: "Required Date",
119
- error: "Please select a date",
119
+ // DG-COPY-02: error copy states the rule broken — never "please"/"invalid"/"error".
120
+ error: "A date is required",
120
121
  required: true,
121
122
  },
122
123
  };
@@ -1,6 +1,8 @@
1
+ import { useForm } from "@tanstack/react-form";
1
2
  import { act, fireEvent, waitFor } from "@testing-library/react";
2
3
  import { describe, expect, it, vi } from "vitest";
3
4
  import { renderWithProviders } from "@multiplatform.one/test-utils";
5
+ import { Form } from "../../Form";
4
6
 
5
7
  vi.mock("react-native", () => ({
6
8
  Platform: {
@@ -87,4 +89,74 @@ describe("DateRangePicker", () => {
87
89
  expect(input?.value ?? "").toContain("–");
88
90
  });
89
91
  });
92
+
93
+ describe("late-arriving value display (create-mode seeding)", () => {
94
+ // The form branch displays from `rangeStart`/`rangeEnd`, which only user
95
+ // picks and the standalone `value` prop used to update — a field value
96
+ // applied AFTER first paint (create-mode engine seeding, setFieldValue)
97
+ // never rendered. Adopting a programmatic value must not emit onChange
98
+ // (LC-14: a seeded value is not a user edit).
99
+ it("form-integrated: a field value set after mount displays, without onChange", async () => {
100
+ const DateRangePicker = await loadDateRangePicker();
101
+ const onChange = vi.fn();
102
+ type Range = { start: Date; end: Date } | null;
103
+ let formApi: { setFieldValue: (name: "range", value: Range) => void } | undefined;
104
+ const TestComponent = () => {
105
+ const form = useForm({ defaultValues: { range: null as Range } });
106
+ formApi = form as unknown as typeof formApi;
107
+ return (
108
+ <Form form={form}>
109
+ <DateRangePicker label="Range" name="range" onChange={onChange} />
110
+ </Form>
111
+ );
112
+ };
113
+ const result = renderWithProviders(<TestComponent />);
114
+ const getInput = () => result.container.querySelector("input") as HTMLInputElement | null;
115
+ expect(getInput()?.value ?? "").toBe("");
116
+
117
+ await act(async () => {
118
+ formApi?.setFieldValue("range", {
119
+ start: new Date(2026, 2, 5),
120
+ end: new Date(2026, 2, 12),
121
+ });
122
+ });
123
+ await waitFor(() => {
124
+ expect(getInput()?.value).toBe("Mar 5, 2026 – Mar 12, 2026");
125
+ });
126
+ expect(onChange).not.toHaveBeenCalled();
127
+ });
128
+
129
+ it("form-integrated: clearing the field value programmatically clears the display", async () => {
130
+ const DateRangePicker = await loadDateRangePicker();
131
+ const onChange = vi.fn();
132
+ type Range = { start: Date; end: Date } | null;
133
+ let formApi: { setFieldValue: (name: "range", value: Range) => void } | undefined;
134
+ const TestComponent = () => {
135
+ const form = useForm({
136
+ defaultValues: {
137
+ range: { start: new Date(2026, 2, 5), end: new Date(2026, 2, 12) } as Range,
138
+ },
139
+ });
140
+ formApi = form as unknown as typeof formApi;
141
+ return (
142
+ <Form form={form}>
143
+ <DateRangePicker label="Range" name="range" onChange={onChange} />
144
+ </Form>
145
+ );
146
+ };
147
+ const result = renderWithProviders(<TestComponent />);
148
+ const getInput = () => result.container.querySelector("input") as HTMLInputElement | null;
149
+ await waitFor(() => {
150
+ expect(getInput()?.value).toBe("Mar 5, 2026 – Mar 12, 2026");
151
+ });
152
+
153
+ await act(async () => {
154
+ formApi?.setFieldValue("range", null);
155
+ });
156
+ await waitFor(() => {
157
+ expect(getInput()?.value ?? "").toBe("");
158
+ });
159
+ expect(onChange).not.toHaveBeenCalled();
160
+ });
161
+ });
90
162
  });
@@ -32,6 +32,7 @@ import {
32
32
  useDateNavigation,
33
33
  yearPageSize,
34
34
  } from "./parts";
35
+ import { FieldValueSync } from "./fieldValueSync";
35
36
 
36
37
  import type { ViewMode } from "./parts";
37
38
 
@@ -471,24 +472,31 @@ export function DateRangePicker<
471
472
  setOpen(true);
472
473
  }, [setDisplayDate]);
473
474
 
474
- // Keep standalone/controlled state in sync when the parent value changes.
475
- // Skip while a range is half-picked (start set, end pending): the first click
476
- // of a new range used to call onChange(null), and syncing that null wiped
477
- // rangeStart so the second click could never complete (SB-T2-03).
475
+ // Adopt an externally-applied value (controlled `value` prop or the live
476
+ // TanStack field value) into the display state without emitting onChange
477
+ // (LC-14). Skip while a range is half-picked (start set, end pending): the
478
+ // first click of a new range used to call onChange(null), and syncing that
479
+ // null wiped rangeStart so the second click could never complete (SB-T2-03).
478
480
  const pickingRangeRef = useRef(false);
479
- useEffect(() => {
480
- if (valueProp === undefined) return;
481
- if (pickingRangeRef.current && valueProp == null) return;
481
+ const adoptExternalValue = useCallback((raw: unknown) => {
482
+ const next = (raw ?? null) as DateRange | null;
483
+ if (pickingRangeRef.current && next == null) return;
482
484
  pickingRangeRef.current = false;
483
- const nextStart = valueProp?.start ?? null;
484
- const nextEnd = valueProp?.end ?? null;
485
+ const nextStart = next?.start ?? null;
486
+ const nextEnd = next?.end ?? null;
485
487
  setRangeStart((prev) =>
486
488
  prev === nextStart || (prev && nextStart && isSameDay(prev, nextStart)) ? prev : nextStart,
487
489
  );
488
490
  setRangeEnd((prev) =>
489
491
  prev === nextEnd || (prev && nextEnd && isSameDay(prev, nextEnd)) ? prev : nextEnd,
490
492
  );
491
- }, [valueProp]);
493
+ }, []);
494
+
495
+ // Keep standalone/controlled state in sync when the parent value changes.
496
+ useEffect(() => {
497
+ if (valueProp === undefined) return;
498
+ adoptExternalValue(valueProp);
499
+ }, [valueProp, adoptExternalValue]);
492
500
 
493
501
  const closePopover = useCallback(() => {
494
502
  setOpen(false);
@@ -647,26 +655,32 @@ export function DateRangePicker<
647
655
  const resolvedError = getFieldError(field, errorProp);
648
656
 
649
657
  return (
650
- <FieldLayout
651
- id={id}
652
- label={label}
653
- labelProps={labelProps}
654
- error={resolvedError}
655
- helperText={helperText}
656
- required={required}
657
- size={size}
658
- knobProps={knobProps}
659
- // LC-40: see standalone branch — FieldLayout carries dimWhole.
660
- disabled={disabled}
661
- >
662
- <InputParts size={size || knobProps.sizeToken}>
663
- {renderPopover(
664
- !!resolvedError,
665
- mergeFieldHandler(field, "handleBlur", _onBlur),
666
- mergeFieldHandler(field, "handleChange"),
667
- )}
668
- </InputParts>
669
- </FieldLayout>
658
+ <>
659
+ {/* Form branch displays from `rangeStart`/`rangeEnd` — keep them
660
+ synced to the live field value (late seeds / programmatic
661
+ updates). */}
662
+ <FieldValueSync value={field.state.value} onSync={adoptExternalValue} />
663
+ <FieldLayout
664
+ id={id}
665
+ label={label}
666
+ labelProps={labelProps}
667
+ error={resolvedError}
668
+ helperText={helperText}
669
+ required={required}
670
+ size={size}
671
+ knobProps={knobProps}
672
+ // LC-40: see standalone branch — FieldLayout carries dimWhole.
673
+ disabled={disabled}
674
+ >
675
+ <InputParts size={size || knobProps.sizeToken}>
676
+ {renderPopover(
677
+ !!resolvedError,
678
+ mergeFieldHandler(field, "handleBlur", _onBlur),
679
+ mergeFieldHandler(field, "handleChange"),
680
+ )}
681
+ </InputParts>
682
+ </FieldLayout>
683
+ </>
670
684
  );
671
685
  }}
672
686
  </Field>
@@ -146,4 +146,43 @@ describe("DatetimePicker", () => {
146
146
  expect(onSubmit.mock.calls[0][0].appt).toBeInstanceOf(Date);
147
147
  });
148
148
  });
149
+
150
+ describe("late-arriving value display (create-mode seeding)", () => {
151
+ // The form branch displays from `selectedDatetime`, kept synced to the
152
+ // live field value by DatePickerFieldValueSync — a value applied AFTER
153
+ // first paint (create-mode engine seeding, setFieldValue, live server
154
+ // merge) must render. Adopting a programmatic value must not emit
155
+ // onChange (LC-14: a seeded value is not a user edit).
156
+ it("form-integrated: a field value set after mount displays, without onChange", async () => {
157
+ const onChange = vi.fn();
158
+ const onValueChange = vi.fn();
159
+ let formApi: { setFieldValue: (name: "appt", value: Date | null) => void } | undefined;
160
+ const TestComponent = () => {
161
+ const form = useForm({ defaultValues: { appt: null as Date | null } });
162
+ formApi = form as unknown as typeof formApi;
163
+ return (
164
+ <Form form={form}>
165
+ <DatetimePicker
166
+ name="appt"
167
+ label="Appointment"
168
+ onChange={onChange}
169
+ onValueChange={onValueChange}
170
+ />
171
+ </Form>
172
+ );
173
+ };
174
+ const result = renderWithProviders(<TestComponent />);
175
+ const getInput = () => result.container.querySelector("input") as HTMLInputElement | null;
176
+ expect(getInput()?.value ?? "").toBe("");
177
+
178
+ await act(async () => {
179
+ formApi?.setFieldValue("appt", new Date(2026, 2, 5, 14, 30));
180
+ });
181
+ await waitFor(() => {
182
+ expect(getInput()?.value ?? "").toContain("Mar 5, 2026");
183
+ });
184
+ expect(onChange).not.toHaveBeenCalled();
185
+ expect(onValueChange).not.toHaveBeenCalled();
186
+ });
187
+ });
149
188
  });
@@ -368,7 +368,7 @@ function TimeSection({
368
368
  backgroundColor={isSelected ? formInputColors.background.focus : "transparent"}
369
369
  hoverStyle={{ backgroundColor: formInputColors.background.focus }}
370
370
  onPress={() => handlePeriodChange(p)}
371
- {...(knobProps.transition ? { animation: knobProps.transition } : undefined)}
371
+ {...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
372
372
  >
373
373
  <Text
374
374
  fontSize="$3"
@@ -142,4 +142,65 @@ describe("MonthPicker", () => {
142
142
  );
143
143
  });
144
144
  });
145
+
146
+ describe("late-arriving value display (create-mode seeding)", () => {
147
+ // `selectedValue` was hardcoded to null at mount and only user picks set
148
+ // it, so a field value applied at ANY point (even the Field-level
149
+ // defaultValue) never displayed. The form branch now adopts the live
150
+ // field value — without emitting onChange (LC-14: a seeded value is not
151
+ // a user edit).
152
+ it("form-integrated: a field value set after mount displays, without onChange", async () => {
153
+ const onChange = vi.fn();
154
+ let formApi:
155
+ | { setFieldValue: (name: "month", value: { month: number; year: number } | null) => void }
156
+ | undefined;
157
+ const TestComponent = () => {
158
+ const form = useForm({
159
+ defaultValues: { month: null as { month: number; year: number } | null },
160
+ });
161
+ formApi = form as unknown as typeof formApi;
162
+ return (
163
+ <Form form={form}>
164
+ <MonthPicker name="month" label="Month" onChange={onChange} />
165
+ </Form>
166
+ );
167
+ };
168
+ const result = renderWithProviders(<TestComponent />);
169
+ const getInput = () => result.container.querySelector("input") as HTMLInputElement | null;
170
+ expect(getInput()?.value ?? "").toBe("");
171
+
172
+ await act(async () => {
173
+ formApi?.setFieldValue("month", { month: 2, year: 2026 });
174
+ });
175
+ await waitFor(() => {
176
+ expect(getInput()?.value).toBe("March 2026");
177
+ });
178
+ expect(onChange).not.toHaveBeenCalled();
179
+ });
180
+
181
+ it("form-integrated: a Field-level defaultValue displays at mount", async () => {
182
+ const onChange = vi.fn();
183
+ const TestComponent = () => {
184
+ const form = useForm({
185
+ defaultValues: { month: undefined as { month: number; year: number } | undefined },
186
+ });
187
+ return (
188
+ <Form form={form}>
189
+ <MonthPicker
190
+ name="month"
191
+ label="Month"
192
+ defaultValue={{ month: 6, year: 2025 }}
193
+ onChange={onChange}
194
+ />
195
+ </Form>
196
+ );
197
+ };
198
+ const result = renderWithProviders(<TestComponent />);
199
+ await waitFor(() => {
200
+ const input = result.container.querySelector("input") as HTMLInputElement | null;
201
+ expect(input?.value).toBe("July 2025");
202
+ });
203
+ expect(onChange).not.toHaveBeenCalled();
204
+ });
205
+ });
145
206
  });
@@ -5,7 +5,6 @@ import { Text, View, useProps, type Popover } from "tamagui";
5
5
 
6
6
  import { Button } from "../../Button";
7
7
  import { Field, FieldLayout } from "../../fieldLayout";
8
- import { formCommonColors } from "../../shared/colorRamps";
9
8
  import { t } from "../../shared/t";
10
9
  import {
11
10
  getFieldError,
@@ -28,6 +27,7 @@ import {
28
27
  useDateNavigation,
29
28
  yearPageSize,
30
29
  } from "./parts";
30
+ import { FieldValueSync } from "./fieldValueSync";
31
31
 
32
32
  // ---------------------------------------------------------------------------
33
33
  // Types
@@ -264,6 +264,27 @@ export function MonthPicker<
264
264
  const { displayDate, setDisplayDate } = useDateNavigation();
265
265
  const popoverRef = useRef<Popover>(null);
266
266
 
267
+ // Display comes from `selectedValue`, which only user picks used to set —
268
+ // a field value applied AFTER mount (create-mode seeding, setFieldValue,
269
+ // even the Field-level defaultValue) never rendered. Adopt the live field
270
+ // value without emitting onChange (LC-14). Identity is preserved when the
271
+ // month is unchanged so the close-on-select effect never re-fires.
272
+ const adoptFieldValue = useCallback((raw: unknown) => {
273
+ const next =
274
+ raw !== null &&
275
+ typeof raw === "object" &&
276
+ typeof (raw as MonthPickerValue).month === "number" &&
277
+ typeof (raw as MonthPickerValue).year === "number"
278
+ ? (raw as MonthPickerValue)
279
+ : null;
280
+ setSelectedValue((prev) =>
281
+ prev === next ||
282
+ (prev !== null && next !== null && prev.month === next.month && prev.year === next.year)
283
+ ? prev
284
+ : next,
285
+ );
286
+ }, []);
287
+
267
288
  const closePopover = useCallback(() => {
268
289
  setOpen(false);
269
290
  popoverRef.current?.close();
@@ -395,26 +416,31 @@ export function MonthPicker<
395
416
  const resolvedError = getFieldError(field, errorProp);
396
417
 
397
418
  return (
398
- <FieldLayout
399
- id={id}
400
- label={label}
401
- labelProps={labelProps}
402
- error={resolvedError}
403
- helperText={helperText}
404
- required={required}
405
- size={size}
406
- knobProps={knobProps}
407
- // LC-40: see standalone branch — FieldLayout carries dimWhole.
408
- disabled={disabled}
409
- >
410
- <InputParts size={size || knobProps.sizeToken}>
411
- {renderPopover(
412
- !!resolvedError,
413
- mergeFieldHandler(field, "handleBlur", _onBlur),
414
- mergeFieldHandler(field, "handleChange"),
415
- )}
416
- </InputParts>
417
- </FieldLayout>
419
+ <>
420
+ {/* Form branch displays from `selectedValue` — keep it synced to
421
+ the live field value (late seeds / programmatic updates). */}
422
+ <FieldValueSync value={field.state.value} onSync={adoptFieldValue} />
423
+ <FieldLayout
424
+ id={id}
425
+ label={label}
426
+ labelProps={labelProps}
427
+ error={resolvedError}
428
+ helperText={helperText}
429
+ required={required}
430
+ size={size}
431
+ knobProps={knobProps}
432
+ // LC-40: see standalone branch — FieldLayout carries dimWhole.
433
+ disabled={disabled}
434
+ >
435
+ <InputParts size={size || knobProps.sizeToken}>
436
+ {renderPopover(
437
+ !!resolvedError,
438
+ mergeFieldHandler(field, "handleBlur", _onBlur),
439
+ mergeFieldHandler(field, "handleChange"),
440
+ )}
441
+ </InputParts>
442
+ </FieldLayout>
443
+ </>
418
444
  );
419
445
  }}
420
446
  </Field>
@@ -1,6 +1,8 @@
1
+ import { useForm } from "@tanstack/react-form";
1
2
  import { act, fireEvent, waitFor } from "@testing-library/react";
2
3
  import { describe, expect, it, vi } from "vitest";
3
4
  import { renderWithProviders } from "@multiplatform.one/test-utils";
5
+ import { Form } from "../../Form";
4
6
 
5
7
  vi.mock("react-native", () => ({
6
8
  Platform: {
@@ -90,4 +92,36 @@ describe("MultiDatePicker", () => {
90
92
  expect(input?.value ?? "").toBe("");
91
93
  });
92
94
  });
95
+
96
+ describe("late-arriving value display (create-mode seeding)", () => {
97
+ // The form branch displays from `selectedDates`, which only user picks
98
+ // and the standalone `value` prop used to update — a field value applied
99
+ // AFTER first paint (create-mode engine seeding, setFieldValue) never
100
+ // rendered. Adopting a programmatic value must not emit onChange (LC-14).
101
+ it("form-integrated: a field value set after mount displays, without onChange", async () => {
102
+ const MultiDatePicker = await loadMultiDatePicker();
103
+ const onChange = vi.fn();
104
+ let formApi: { setFieldValue: (name: "dates", value: Date[]) => void } | undefined;
105
+ const TestComponent = () => {
106
+ const form = useForm({ defaultValues: { dates: [] as Date[] } });
107
+ formApi = form as unknown as typeof formApi;
108
+ return (
109
+ <Form form={form}>
110
+ <MultiDatePicker label="Dates" name="dates" onChange={onChange} />
111
+ </Form>
112
+ );
113
+ };
114
+ const result = renderWithProviders(<TestComponent />);
115
+ const getInput = () => result.container.querySelector("input") as HTMLInputElement | null;
116
+ expect(getInput()?.value ?? "").toBe("");
117
+
118
+ await act(async () => {
119
+ formApi?.setFieldValue("dates", [new Date(2026, 2, 5)]);
120
+ });
121
+ await waitFor(() => {
122
+ expect(getInput()?.value).toBe("Mar 5, 2026");
123
+ });
124
+ expect(onChange).not.toHaveBeenCalled();
125
+ });
126
+ });
93
127
  });
@@ -32,6 +32,7 @@ import {
32
32
  useDateNavigation,
33
33
  yearPageSize,
34
34
  } from "./parts";
35
+ import { FieldValueSync } from "./fieldValueSync";
35
36
 
36
37
  import type { ViewMode } from "./parts";
37
38
 
@@ -414,19 +415,25 @@ export function MultiDatePicker<
414
415
  setOpen(true);
415
416
  }, [setDisplayDate]);
416
417
 
417
- // Keep standalone/controlled state in sync when the parent value changes.
418
- // Skip setState when the calendar days are unchanged so a new array identity
419
- // from the parent cannot force a render storm.
420
- useEffect(() => {
421
- if (valueProp === undefined) return;
422
- const next = Array.isArray(valueProp) ? valueProp : [];
418
+ // Adopt an externally-applied value (controlled `value` prop or the live
419
+ // TanStack field value) into the display state without emitting onChange
420
+ // (LC-14). Skip setState when the calendar days are unchanged so a new
421
+ // array identity from the parent cannot force a render storm.
422
+ const adoptExternalValue = useCallback((raw: unknown) => {
423
+ const next = Array.isArray(raw) ? (raw as Date[]) : [];
423
424
  const prev = selectedDatesRef.current;
424
425
  const same =
425
426
  prev.length === next.length && prev.every((d, i) => next[i] != null && isSameDay(d, next[i]));
426
427
  if (same) return;
427
428
  selectedDatesRef.current = next;
428
429
  setSelectedDates(next);
429
- }, [valueProp]);
430
+ }, []);
431
+
432
+ // Keep standalone/controlled state in sync when the parent value changes.
433
+ useEffect(() => {
434
+ if (valueProp === undefined) return;
435
+ adoptExternalValue(valueProp);
436
+ }, [valueProp, adoptExternalValue]);
430
437
 
431
438
  const handleToggleDate = useCallback(
432
439
  (date: Date, fieldChange?: (value: any) => void) => {
@@ -560,26 +567,31 @@ export function MultiDatePicker<
560
567
  const resolvedError = getFieldError(field, errorProp);
561
568
 
562
569
  return (
563
- <FieldLayout
564
- id={id}
565
- label={label}
566
- labelProps={labelProps}
567
- error={resolvedError}
568
- helperText={helperText}
569
- required={required}
570
- size={size}
571
- knobProps={knobProps}
572
- // LC-40: see standalone branch — FieldLayout carries dimWhole.
573
- disabled={disabled}
574
- >
575
- <InputParts size={size || knobProps.sizeToken}>
576
- {renderPopover(
577
- !!resolvedError,
578
- mergeFieldHandler(field, "handleBlur", _onBlur),
579
- mergeFieldHandler(field, "handleChange"),
580
- )}
581
- </InputParts>
582
- </FieldLayout>
570
+ <>
571
+ {/* Form branch displays from `selectedDates` — keep it synced to
572
+ the live field value (late seeds / programmatic updates). */}
573
+ <FieldValueSync value={field.state.value} onSync={adoptExternalValue} />
574
+ <FieldLayout
575
+ id={id}
576
+ label={label}
577
+ labelProps={labelProps}
578
+ error={resolvedError}
579
+ helperText={helperText}
580
+ required={required}
581
+ size={size}
582
+ knobProps={knobProps}
583
+ // LC-40: see standalone branch — FieldLayout carries dimWhole.
584
+ disabled={disabled}
585
+ >
586
+ <InputParts size={size || knobProps.sizeToken}>
587
+ {renderPopover(
588
+ !!resolvedError,
589
+ mergeFieldHandler(field, "handleBlur", _onBlur),
590
+ mergeFieldHandler(field, "handleChange"),
591
+ )}
592
+ </InputParts>
593
+ </FieldLayout>
594
+ </>
583
595
  );
584
596
  }}
585
597
  </Field>
@@ -32,3 +32,26 @@ export function DatePickerFieldValueSync({
32
32
  }, [value, onSync]);
33
33
  return null;
34
34
  }
35
+
36
+ /**
37
+ * Shape-agnostic variant for pickers whose display state is not a single
38
+ * Date (MonthPicker's {month,year}, MultiDatePicker's Date[],
39
+ * DateRangePicker's {start,end}): mirrors the live TanStack field value into
40
+ * the picker's adoption callback whenever it changes (including mount, so a
41
+ * Field-level defaultValue displays too). Each picker's `onSync` owns its
42
+ * coercion + identity-preserving equality guard, and must never emit
43
+ * onChange from this path (LC-14 — a programmatic value application is not
44
+ * a user edit).
45
+ */
46
+ export function FieldValueSync({
47
+ value,
48
+ onSync,
49
+ }: {
50
+ value: unknown;
51
+ onSync: (value: unknown) => void;
52
+ }) {
53
+ useEffect(() => {
54
+ onSync(value);
55
+ }, [value, onSync]);
56
+ return null;
57
+ }
@@ -2,6 +2,7 @@ import { Calendar, ChevronLeft, ChevronRight, X } from "@tamagui/lucide-icons-2"
2
2
  import {
3
3
  ensureFocusVisibleRing,
4
4
  formatAbsoluteDate,
5
+ getMonthNames,
5
6
  useResolvedKnobs,
6
7
  } from "@multiplatform.one/theme";
7
8
  import {
@@ -100,6 +101,10 @@ export function useDateAnimation(current: string | number) {
100
101
  // useCalendarData — compute calendar grid for a given month
101
102
  // ---------------------------------------------------------------------------
102
103
 
104
+ // Picker headers speak the house month register (LC-12 render channel), not
105
+ // a locale pinned to en-US at the call site.
106
+ const monthNames = getMonthNames();
107
+
103
108
  export function useCalendarData(displayDate: Date): CalendarData {
104
109
  return useMemo(() => {
105
110
  const year = displayDate.getFullYear();
@@ -122,7 +127,7 @@ export function useCalendarData(displayDate: Date): CalendarData {
122
127
  return {
123
128
  year,
124
129
  month,
125
- monthName: displayDate.toLocaleDateString("en-US", { month: "long" }),
130
+ monthName: monthNames[month],
126
131
  days,
127
132
  today: new Date(),
128
133
  };
@@ -107,6 +107,15 @@ export const Basic: Story = {
107
107
  };
108
108
 
109
109
  export const Disabled: Story = {
110
+ parameters: {
111
+ // LC-57 allowlist: disabled-dial demo; FileUpload's internal upload Button
112
+ // has no disabledReason plumbing yet (component-contract follow-up).
113
+ guardrailSpecimen: {
114
+ warns: ["bare-disabled"],
115
+ reason:
116
+ "Disabled-dial specimen: FileUpload's internal upload Button has no disabledReason plumbing yet.",
117
+ },
118
+ },
110
119
  render: (args) => <FileUpload {...args} />,
111
120
  args: {
112
121
  label: "Disabled Upload",
@@ -119,7 +128,8 @@ export const WithError: Story = {
119
128
  render: (args) => <FileUpload {...args} />,
120
129
  args: {
121
130
  label: "Required File",
122
- error: "Please upload a file",
131
+ // DG-COPY-02: error copy states the rule broken — never "please"/"invalid"/"error".
132
+ error: "A file is required",
123
133
  required: true,
124
134
  },
125
135
  };
@@ -95,6 +95,15 @@ export const Basic: Story = {
95
95
  };
96
96
 
97
97
  export const Disabled: Story = {
98
+ parameters: {
99
+ // LC-57 allowlist: disabled-dial demo; Geolocation's internal action
100
+ // Buttons have no disabledReason plumbing yet (component-contract follow-up).
101
+ guardrailSpecimen: {
102
+ warns: ["bare-disabled"],
103
+ reason:
104
+ "Disabled-dial specimen: Geolocation's internal action Buttons have no disabledReason plumbing yet.",
105
+ },
106
+ },
98
107
  args: {
99
108
  label: "Location",
100
109
  helperText: "This field is disabled",