@multiplatform.one/forms 6.4.3 → 6.7.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 (320) 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/Skeleton/index.cjs +1 -0
  5. package/dist/cjs/Skeleton/index.native.js +4 -0
  6. package/dist/cjs/Skeleton/index.native.js.map +1 -1
  7. package/dist/cjs/fields/Checkbox/Checkbox.cjs +22 -15
  8. package/dist/cjs/fields/Checkbox/Checkbox.native.js +11 -6
  9. package/dist/cjs/fields/Checkbox/Checkbox.native.js.map +1 -1
  10. package/dist/cjs/fields/Checkbox/index.cjs +9 -3
  11. package/dist/cjs/fields/Checkbox/index.native.js +9 -3
  12. package/dist/cjs/fields/Checkbox/index.native.js.map +1 -1
  13. package/dist/cjs/fields/Combobox/index.cjs +9 -4
  14. package/dist/cjs/fields/Combobox/index.native.js +9 -4
  15. package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
  16. package/dist/cjs/fields/DatePicker/DateRangePicker.cjs +30 -20
  17. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +36 -21
  18. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  19. package/dist/cjs/fields/DatePicker/DatetimePicker.cjs +1 -1
  20. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +1 -1
  21. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  22. package/dist/cjs/fields/DatePicker/MonthPicker.cjs +24 -14
  23. package/dist/cjs/fields/DatePicker/MonthPicker.native.js +36 -15
  24. package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
  25. package/dist/cjs/fields/DatePicker/MultiDatePicker.cjs +27 -18
  26. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +32 -19
  27. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  28. package/dist/cjs/fields/DatePicker/fieldValueSync.cjs +11 -1
  29. package/dist/cjs/fields/DatePicker/fieldValueSync.native.js +12 -1
  30. package/dist/cjs/fields/DatePicker/fieldValueSync.native.js.map +1 -1
  31. package/dist/cjs/fields/Geolocation/GeolocationMap.native.js +2 -2
  32. package/dist/cjs/fields/RadioGroup/index.cjs +2 -2
  33. package/dist/cjs/fields/RadioGroup/index.native.js +2 -2
  34. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  35. package/dist/cjs/fields/Rating/index.cjs +17 -2
  36. package/dist/cjs/fields/Rating/index.native.js +25 -2
  37. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  38. package/dist/cjs/fields/SearchInput/index.cjs +5 -1
  39. package/dist/cjs/fields/SearchInput/index.native.js +5 -1
  40. package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
  41. package/dist/cjs/fields/Select/index.cjs +6 -10
  42. package/dist/cjs/fields/Select/index.native.js +12 -10
  43. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  44. package/dist/cjs/fields/Signature/index.cjs +1 -1
  45. package/dist/cjs/fields/Signature/index.native.js +1 -1
  46. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  47. package/dist/cjs/fields/Slider/index.cjs +1 -0
  48. package/dist/cjs/fields/Slider/index.native.js +4 -0
  49. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  50. package/dist/cjs/fields/TextArea/index.cjs +3 -2
  51. package/dist/cjs/fields/TextArea/index.native.js +5 -2
  52. package/dist/cjs/fields/TextArea/index.native.js.map +1 -1
  53. package/dist/cjs/fields/TimePicker/index.cjs +1 -1
  54. package/dist/cjs/fields/TimePicker/index.native.js +1 -1
  55. package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
  56. package/dist/cjs/fields/ToggleGroup/index.cjs +6 -22
  57. package/dist/cjs/fields/ToggleGroup/index.native.js +11 -28
  58. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  59. package/dist/cjs/shared/TimeColumn.cjs +1 -1
  60. package/dist/cjs/shared/TimeColumn.native.js +1 -1
  61. package/dist/cjs/shared/TimeColumn.native.js.map +1 -1
  62. package/dist/cjs/shared/focusManagement.cjs +7 -1
  63. package/dist/cjs/shared/focusManagement.native.js +5 -1
  64. package/dist/cjs/shared/focusManagement.native.js.map +1 -1
  65. package/dist/cjs/shared/t.cjs +5 -0
  66. package/dist/cjs/shared/t.native.js +5 -0
  67. package/dist/cjs/shared/t.native.js.map +1 -1
  68. package/dist/esm/Button/index.mjs +24 -9
  69. package/dist/esm/Button/index.mjs.map +1 -1
  70. package/dist/esm/Button/index.native.js +24 -9
  71. package/dist/esm/Button/index.native.js.map +1 -1
  72. package/dist/esm/Skeleton/index.mjs +2 -1
  73. package/dist/esm/Skeleton/index.mjs.map +1 -1
  74. package/dist/esm/Skeleton/index.native.js +5 -1
  75. package/dist/esm/Skeleton/index.native.js.map +1 -1
  76. package/dist/esm/fields/Checkbox/Checkbox.mjs +24 -17
  77. package/dist/esm/fields/Checkbox/Checkbox.mjs.map +1 -1
  78. package/dist/esm/fields/Checkbox/Checkbox.native.js +13 -8
  79. package/dist/esm/fields/Checkbox/Checkbox.native.js.map +1 -1
  80. package/dist/esm/fields/Checkbox/index.mjs +11 -5
  81. package/dist/esm/fields/Checkbox/index.mjs.map +1 -1
  82. package/dist/esm/fields/Checkbox/index.native.js +11 -5
  83. package/dist/esm/fields/Checkbox/index.native.js.map +1 -1
  84. package/dist/esm/fields/Combobox/index.mjs +9 -4
  85. package/dist/esm/fields/Combobox/index.mjs.map +1 -1
  86. package/dist/esm/fields/Combobox/index.native.js +9 -4
  87. package/dist/esm/fields/Combobox/index.native.js.map +1 -1
  88. package/dist/esm/fields/DatePicker/DateRangePicker.mjs +31 -21
  89. package/dist/esm/fields/DatePicker/DateRangePicker.mjs.map +1 -1
  90. package/dist/esm/fields/DatePicker/DateRangePicker.native.js +37 -22
  91. package/dist/esm/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  92. package/dist/esm/fields/DatePicker/DatetimePicker.mjs +1 -1
  93. package/dist/esm/fields/DatePicker/DatetimePicker.mjs.map +1 -1
  94. package/dist/esm/fields/DatePicker/DatetimePicker.native.js +1 -1
  95. package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  96. package/dist/esm/fields/DatePicker/MonthPicker.mjs +25 -15
  97. package/dist/esm/fields/DatePicker/MonthPicker.mjs.map +1 -1
  98. package/dist/esm/fields/DatePicker/MonthPicker.native.js +37 -16
  99. package/dist/esm/fields/DatePicker/MonthPicker.native.js.map +1 -1
  100. package/dist/esm/fields/DatePicker/MultiDatePicker.mjs +28 -19
  101. package/dist/esm/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
  102. package/dist/esm/fields/DatePicker/MultiDatePicker.native.js +33 -20
  103. package/dist/esm/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  104. package/dist/esm/fields/DatePicker/fieldValueSync.mjs +10 -1
  105. package/dist/esm/fields/DatePicker/fieldValueSync.mjs.map +1 -1
  106. package/dist/esm/fields/DatePicker/fieldValueSync.native.js +11 -1
  107. package/dist/esm/fields/DatePicker/fieldValueSync.native.js.map +1 -1
  108. package/dist/esm/fields/Geolocation/GeolocationMap.native.js +2 -2
  109. package/dist/esm/fields/RadioGroup/index.mjs +2 -2
  110. package/dist/esm/fields/RadioGroup/index.mjs.map +1 -1
  111. package/dist/esm/fields/RadioGroup/index.native.js +2 -2
  112. package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
  113. package/dist/esm/fields/Rating/index.mjs +17 -2
  114. package/dist/esm/fields/Rating/index.mjs.map +1 -1
  115. package/dist/esm/fields/Rating/index.native.js +25 -2
  116. package/dist/esm/fields/Rating/index.native.js.map +1 -1
  117. package/dist/esm/fields/SearchInput/index.mjs +6 -2
  118. package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
  119. package/dist/esm/fields/SearchInput/index.native.js +6 -2
  120. package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
  121. package/dist/esm/fields/Select/index.mjs +6 -10
  122. package/dist/esm/fields/Select/index.mjs.map +1 -1
  123. package/dist/esm/fields/Select/index.native.js +12 -10
  124. package/dist/esm/fields/Select/index.native.js.map +1 -1
  125. package/dist/esm/fields/Signature/index.mjs +1 -1
  126. package/dist/esm/fields/Signature/index.mjs.map +1 -1
  127. package/dist/esm/fields/Signature/index.native.js +1 -1
  128. package/dist/esm/fields/Signature/index.native.js.map +1 -1
  129. package/dist/esm/fields/Slider/index.mjs +1 -0
  130. package/dist/esm/fields/Slider/index.mjs.map +1 -1
  131. package/dist/esm/fields/Slider/index.native.js +4 -0
  132. package/dist/esm/fields/Slider/index.native.js.map +1 -1
  133. package/dist/esm/fields/TextArea/index.mjs +3 -2
  134. package/dist/esm/fields/TextArea/index.mjs.map +1 -1
  135. package/dist/esm/fields/TextArea/index.native.js +5 -2
  136. package/dist/esm/fields/TextArea/index.native.js.map +1 -1
  137. package/dist/esm/fields/TimePicker/index.mjs +1 -1
  138. package/dist/esm/fields/TimePicker/index.mjs.map +1 -1
  139. package/dist/esm/fields/TimePicker/index.native.js +1 -1
  140. package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
  141. package/dist/esm/fields/ToggleGroup/index.mjs +7 -23
  142. package/dist/esm/fields/ToggleGroup/index.mjs.map +1 -1
  143. package/dist/esm/fields/ToggleGroup/index.native.js +12 -29
  144. package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
  145. package/dist/esm/shared/TimeColumn.mjs +1 -1
  146. package/dist/esm/shared/TimeColumn.mjs.map +1 -1
  147. package/dist/esm/shared/TimeColumn.native.js +1 -1
  148. package/dist/esm/shared/TimeColumn.native.js.map +1 -1
  149. package/dist/esm/shared/focusManagement.mjs +7 -1
  150. package/dist/esm/shared/focusManagement.mjs.map +1 -1
  151. package/dist/esm/shared/focusManagement.native.js +5 -1
  152. package/dist/esm/shared/focusManagement.native.js.map +1 -1
  153. package/dist/esm/shared/t.mjs +5 -1
  154. package/dist/esm/shared/t.mjs.map +1 -1
  155. package/dist/esm/shared/t.native.js +5 -1
  156. package/dist/esm/shared/t.native.js.map +1 -1
  157. package/dist/jsx/Button/index.mjs +24 -9
  158. package/dist/jsx/Button/index.mjs.map +1 -1
  159. package/dist/jsx/Button/index.native.js +23 -8
  160. package/dist/jsx/Button/index.native.js.map +1 -1
  161. package/dist/jsx/Skeleton/index.mjs +2 -1
  162. package/dist/jsx/Skeleton/index.mjs.map +1 -1
  163. package/dist/jsx/Skeleton/index.native.js +4 -0
  164. package/dist/jsx/Skeleton/index.native.js.map +1 -1
  165. package/dist/jsx/fields/Checkbox/Checkbox.mjs +24 -17
  166. package/dist/jsx/fields/Checkbox/Checkbox.mjs.map +1 -1
  167. package/dist/jsx/fields/Checkbox/Checkbox.native.js +11 -6
  168. package/dist/jsx/fields/Checkbox/Checkbox.native.js.map +1 -1
  169. package/dist/jsx/fields/Checkbox/index.mjs +11 -5
  170. package/dist/jsx/fields/Checkbox/index.mjs.map +1 -1
  171. package/dist/jsx/fields/Checkbox/index.native.js +9 -3
  172. package/dist/jsx/fields/Checkbox/index.native.js.map +1 -1
  173. package/dist/jsx/fields/Combobox/index.mjs +9 -4
  174. package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
  175. package/dist/jsx/fields/Combobox/index.native.js +9 -4
  176. package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
  177. package/dist/jsx/fields/DatePicker/DateRangePicker.mjs +31 -21
  178. package/dist/jsx/fields/DatePicker/DateRangePicker.mjs.map +1 -1
  179. package/dist/jsx/fields/DatePicker/DateRangePicker.native.js +36 -21
  180. package/dist/jsx/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  181. package/dist/jsx/fields/DatePicker/DatetimePicker.mjs +1 -1
  182. package/dist/jsx/fields/DatePicker/DatetimePicker.mjs.map +1 -1
  183. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +1 -1
  184. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  185. package/dist/jsx/fields/DatePicker/MonthPicker.mjs +25 -15
  186. package/dist/jsx/fields/DatePicker/MonthPicker.mjs.map +1 -1
  187. package/dist/jsx/fields/DatePicker/MonthPicker.native.js +36 -15
  188. package/dist/jsx/fields/DatePicker/MonthPicker.native.js.map +1 -1
  189. package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs +28 -19
  190. package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
  191. package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js +32 -19
  192. package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  193. package/dist/jsx/fields/DatePicker/fieldValueSync.mjs +10 -1
  194. package/dist/jsx/fields/DatePicker/fieldValueSync.mjs.map +1 -1
  195. package/dist/jsx/fields/DatePicker/fieldValueSync.native.js +12 -1
  196. package/dist/jsx/fields/DatePicker/fieldValueSync.native.js.map +1 -1
  197. package/dist/jsx/fields/Geolocation/GeolocationMap.native.js +2 -2
  198. package/dist/jsx/fields/RadioGroup/index.mjs +2 -2
  199. package/dist/jsx/fields/RadioGroup/index.mjs.map +1 -1
  200. package/dist/jsx/fields/RadioGroup/index.native.js +2 -2
  201. package/dist/jsx/fields/RadioGroup/index.native.js.map +1 -1
  202. package/dist/jsx/fields/Rating/index.mjs +17 -2
  203. package/dist/jsx/fields/Rating/index.mjs.map +1 -1
  204. package/dist/jsx/fields/Rating/index.native.js +25 -2
  205. package/dist/jsx/fields/Rating/index.native.js.map +1 -1
  206. package/dist/jsx/fields/SearchInput/index.mjs +6 -2
  207. package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
  208. package/dist/jsx/fields/SearchInput/index.native.js +5 -1
  209. package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
  210. package/dist/jsx/fields/Select/index.mjs +6 -10
  211. package/dist/jsx/fields/Select/index.mjs.map +1 -1
  212. package/dist/jsx/fields/Select/index.native.js +12 -10
  213. package/dist/jsx/fields/Select/index.native.js.map +1 -1
  214. package/dist/jsx/fields/Signature/index.mjs +1 -1
  215. package/dist/jsx/fields/Signature/index.mjs.map +1 -1
  216. package/dist/jsx/fields/Signature/index.native.js +1 -1
  217. package/dist/jsx/fields/Signature/index.native.js.map +1 -1
  218. package/dist/jsx/fields/Slider/index.mjs +1 -0
  219. package/dist/jsx/fields/Slider/index.mjs.map +1 -1
  220. package/dist/jsx/fields/Slider/index.native.js +4 -0
  221. package/dist/jsx/fields/Slider/index.native.js.map +1 -1
  222. package/dist/jsx/fields/TextArea/index.mjs +3 -2
  223. package/dist/jsx/fields/TextArea/index.mjs.map +1 -1
  224. package/dist/jsx/fields/TextArea/index.native.js +5 -2
  225. package/dist/jsx/fields/TextArea/index.native.js.map +1 -1
  226. package/dist/jsx/fields/TimePicker/index.mjs +1 -1
  227. package/dist/jsx/fields/TimePicker/index.mjs.map +1 -1
  228. package/dist/jsx/fields/TimePicker/index.native.js +1 -1
  229. package/dist/jsx/fields/TimePicker/index.native.js.map +1 -1
  230. package/dist/jsx/fields/ToggleGroup/index.mjs +7 -23
  231. package/dist/jsx/fields/ToggleGroup/index.mjs.map +1 -1
  232. package/dist/jsx/fields/ToggleGroup/index.native.js +11 -28
  233. package/dist/jsx/fields/ToggleGroup/index.native.js.map +1 -1
  234. package/dist/jsx/shared/TimeColumn.mjs +1 -1
  235. package/dist/jsx/shared/TimeColumn.mjs.map +1 -1
  236. package/dist/jsx/shared/TimeColumn.native.js +1 -1
  237. package/dist/jsx/shared/TimeColumn.native.js.map +1 -1
  238. package/dist/jsx/shared/focusManagement.mjs +7 -1
  239. package/dist/jsx/shared/focusManagement.mjs.map +1 -1
  240. package/dist/jsx/shared/focusManagement.native.js +5 -1
  241. package/dist/jsx/shared/focusManagement.native.js.map +1 -1
  242. package/dist/jsx/shared/t.mjs +5 -1
  243. package/dist/jsx/shared/t.mjs.map +1 -1
  244. package/dist/jsx/shared/t.native.js +5 -0
  245. package/dist/jsx/shared/t.native.js.map +1 -1
  246. package/package.json +9 -8
  247. package/src/Button/Button.stories.tsx +19 -0
  248. package/src/Button/index.tsx +45 -12
  249. package/src/ControlGroup/ControlGroup.stories.tsx +12 -0
  250. package/src/FieldLayout.stories.tsx +3 -2
  251. package/src/Form/Form.stories.tsx +13 -0
  252. package/src/Skeleton/index.tsx +5 -1
  253. package/src/fields/Checkbox/Checkbox.spec.tsx +50 -1
  254. package/src/fields/Checkbox/Checkbox.tsx +47 -19
  255. package/src/fields/Checkbox/index.tsx +23 -5
  256. package/src/fields/ColorPicker/ColorPicker.stories.tsx +2 -1
  257. package/src/fields/Combobox/index.tsx +8 -3
  258. package/src/fields/DatePicker/DatePicker.spec.tsx +93 -0
  259. package/src/fields/DatePicker/DatePicker.stories.tsx +2 -1
  260. package/src/fields/DatePicker/DateRangePicker.spec.tsx +72 -0
  261. package/src/fields/DatePicker/DateRangePicker.tsx +44 -30
  262. package/src/fields/DatePicker/DatetimePicker.spec.tsx +39 -0
  263. package/src/fields/DatePicker/DatetimePicker.tsx +1 -1
  264. package/src/fields/DatePicker/MonthPicker.spec.tsx +61 -0
  265. package/src/fields/DatePicker/MonthPicker.tsx +47 -21
  266. package/src/fields/DatePicker/MultiDatePicker.spec.tsx +34 -0
  267. package/src/fields/DatePicker/MultiDatePicker.tsx +39 -27
  268. package/src/fields/DatePicker/fieldValueSync.tsx +23 -0
  269. package/src/fields/FileUpload/FileUpload.stories.tsx +11 -1
  270. package/src/fields/Geolocation/Geolocation.stories.tsx +9 -0
  271. package/src/fields/Geolocation/GeolocationMap.native.tsx +2 -2
  272. package/src/fields/ImageField/ImageField.stories.tsx +2 -1
  273. package/src/fields/Input/Input.stories.tsx +19 -0
  274. package/src/fields/Progress/Progress.stories.tsx +19 -0
  275. package/src/fields/RadioGroup/RadioGroup.spec.tsx +139 -2
  276. package/src/fields/RadioGroup/index.tsx +2 -2
  277. package/src/fields/Rating/Rating.spec.tsx +43 -1
  278. package/src/fields/Rating/index.tsx +43 -4
  279. package/src/fields/SearchInput/SearchInput.spec.tsx +11 -0
  280. package/src/fields/SearchInput/index.tsx +6 -2
  281. package/src/fields/Select/Select.stories.tsx +19 -0
  282. package/src/fields/Select/index.tsx +12 -5
  283. package/src/fields/Signature/index.tsx +1 -1
  284. package/src/fields/Slider/Slider.spec.tsx +89 -4
  285. package/src/fields/Slider/Slider.stories.tsx +19 -0
  286. package/src/fields/Slider/index.tsx +4 -0
  287. package/src/fields/Stepper/Stepper.stories.tsx +12 -0
  288. package/src/fields/Switch/Switch.spec.tsx +50 -2
  289. package/src/fields/TextArea/TextArea.spec.tsx +57 -0
  290. package/src/fields/TextArea/TextArea.stories.tsx +19 -0
  291. package/src/fields/TextArea/index.tsx +10 -2
  292. package/src/fields/TimePicker/index.tsx +1 -1
  293. package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +64 -1
  294. package/src/fields/ToggleGroup/ToggleGroup.stories.tsx +19 -0
  295. package/src/fields/ToggleGroup/index.tsx +31 -29
  296. package/src/shared/FloatingListScrollArrows.stories.tsx +4 -2
  297. package/src/shared/TimeColumn.tsx +1 -1
  298. package/src/shared/focusManagement.ts +12 -1
  299. package/src/shared/t.spec.ts +39 -0
  300. package/src/shared/t.ts +20 -0
  301. package/types/Button/index.d.ts +9 -1
  302. package/types/Button/index.d.ts.map +1 -1
  303. package/types/Skeleton/index.d.ts.map +1 -1
  304. package/types/fields/Checkbox/Checkbox.d.ts.map +1 -1
  305. package/types/fields/Checkbox/index.d.ts.map +1 -1
  306. package/types/fields/Combobox/index.d.ts.map +1 -1
  307. package/types/fields/DatePicker/DateRangePicker.d.ts.map +1 -1
  308. package/types/fields/DatePicker/MonthPicker.d.ts.map +1 -1
  309. package/types/fields/DatePicker/MultiDatePicker.d.ts.map +1 -1
  310. package/types/fields/DatePicker/fieldValueSync.d.ts +14 -0
  311. package/types/fields/DatePicker/fieldValueSync.d.ts.map +1 -1
  312. package/types/fields/Rating/index.d.ts.map +1 -1
  313. package/types/fields/SearchInput/index.d.ts.map +1 -1
  314. package/types/fields/Select/index.d.ts.map +1 -1
  315. package/types/fields/Slider/index.d.ts.map +1 -1
  316. package/types/fields/TextArea/index.d.ts.map +1 -1
  317. package/types/fields/ToggleGroup/index.d.ts.map +1 -1
  318. package/types/shared/focusManagement.d.ts.map +1 -1
  319. package/types/shared/t.d.ts +16 -0
  320. package/types/shared/t.d.ts.map +1 -1
@@ -333,7 +333,7 @@ const ComboboxItem = memo(function ComboboxItem({
333
333
  ? // Two-line rows need to grow past the size-variant height.
334
334
  { height: "auto", paddingVertical: "$2" }
335
335
  : undefined)}
336
- {...(ctx.knobProps.transition ? { animation: ctx.knobProps.transition } : undefined)}
336
+ {...(ctx.knobProps.transition ? { transition: ctx.knobProps.transition } : undefined)}
337
337
  >
338
338
  {option.description ? (
339
339
  <YStack flex={1} minWidth={0}>
@@ -1258,6 +1258,11 @@ function FloatingComboboxCore({
1258
1258
  : {
1259
1259
  borderRadius: knobProps.borderRadius.borderRadius,
1260
1260
  borderWidth: knobProps.borderRadius.borderWidth,
1261
+ // LC-54 PRESS-FLOOR: compact/small size tokens render a sub-44
1262
+ // trigger (the 36px "Allocated To" quick filter breaking the
1263
+ // list's 44px control row) — same floor the house Select holds
1264
+ // on both its trigger variants.
1265
+ minHeight: 44,
1261
1266
  })}
1262
1267
  >
1263
1268
  <SyncFocusToOpen open={open} />
@@ -1497,7 +1502,7 @@ function FloatingComboboxCore({
1497
1502
  : undefined
1498
1503
  }
1499
1504
  onPress={handleCreate}
1500
- {...(knobProps.transition ? { animation: knobProps.transition } : undefined)}
1505
+ {...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
1501
1506
  >
1502
1507
  <PlusIcon size={14} color={knobProps.textAccentColor} />
1503
1508
  <Text
@@ -1538,7 +1543,7 @@ function FloatingComboboxCore({
1538
1543
  : "transparent"
1539
1544
  }
1540
1545
  pressStyle={{ backgroundColor: formInputColors.background.focus }}
1541
- {...(knobProps.transition ? { animation: knobProps.transition } : undefined)}
1546
+ {...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
1542
1547
  >
1543
1548
  <PlusIcon size={14} color={knobProps.textAccentColor} />
1544
1549
  <Text
@@ -223,6 +223,99 @@ describe("DatePicker", () => {
223
223
  });
224
224
  });
225
225
 
226
+ describe("late-arriving value display (create-mode seeding)", () => {
227
+ // The form branch only ever displayed the mount-time value (`selectedDate`
228
+ // was never re-synced from field state), so a value applied AFTER first
229
+ // paint — create-mode engine seeding, form.setFieldValue, live server
230
+ // merge — never rendered. Adopting a programmatic value must not emit
231
+ // onChange (LC-14: a seeded value is not a user edit).
232
+ const getDisplayInput = (container: ParentNode) =>
233
+ container.querySelector("input") as HTMLInputElement | null;
234
+
235
+ it("standalone controlled: a value arriving after mount displays, without onChange", async () => {
236
+ const DatePicker = await loadDatePicker();
237
+ const onChange = vi.fn();
238
+ const onValueChange = vi.fn();
239
+ const result = renderWithProviders(
240
+ <DatePicker
241
+ label="Due Date"
242
+ value={null}
243
+ onChange={onChange}
244
+ onValueChange={onValueChange}
245
+ />,
246
+ );
247
+ expect(getDisplayInput(result.container)?.value ?? "").toBe("");
248
+
249
+ // Late seed: the upstream doc value (frappe wire string) arrives after
250
+ // first paint.
251
+ result.rerender(
252
+ <DatePicker
253
+ label="Due Date"
254
+ value="2026-03-05"
255
+ onChange={onChange}
256
+ onValueChange={onValueChange}
257
+ />,
258
+ );
259
+ await waitFor(() => {
260
+ expect(getDisplayInput(result.container)?.value).toBe("Mar 5, 2026");
261
+ });
262
+ expect(onChange).not.toHaveBeenCalled();
263
+ expect(onValueChange).not.toHaveBeenCalled();
264
+ });
265
+
266
+ it("form-integrated: a field value set after mount displays, without onChange", async () => {
267
+ const DatePicker = await loadDatePicker();
268
+ const onChange = vi.fn();
269
+ let formApi: { setFieldValue: (name: "date", value: string | null) => void } | undefined;
270
+ const TestComponent = () => {
271
+ const form = useForm({ defaultValues: { date: null as string | null } });
272
+ formApi = form as unknown as typeof formApi;
273
+ return (
274
+ <Form form={form}>
275
+ <DatePicker label="Due Date" name="date" onChange={onChange} />
276
+ </Form>
277
+ );
278
+ };
279
+ const result = renderWithProviders(<TestComponent />);
280
+ expect(getDisplayInput(result.container)?.value ?? "").toBe("");
281
+
282
+ await act(async () => {
283
+ formApi?.setFieldValue("date", "2026-03-05");
284
+ });
285
+ await waitFor(() => {
286
+ expect(getDisplayInput(result.container)?.value).toBe("Mar 5, 2026");
287
+ });
288
+ expect(onChange).not.toHaveBeenCalled();
289
+ });
290
+
291
+ it("form-integrated: clearing the field value programmatically clears the display", async () => {
292
+ const DatePicker = await loadDatePicker();
293
+ const onChange = vi.fn();
294
+ let formApi: { setFieldValue: (name: "date", value: string | null) => void } | undefined;
295
+ const TestComponent = () => {
296
+ const form = useForm({ defaultValues: { date: "2026-03-05" as string | null } });
297
+ formApi = form as unknown as typeof formApi;
298
+ return (
299
+ <Form form={form}>
300
+ <DatePicker label="Due Date" name="date" onChange={onChange} />
301
+ </Form>
302
+ );
303
+ };
304
+ const result = renderWithProviders(<TestComponent />);
305
+ await waitFor(() => {
306
+ expect(getDisplayInput(result.container)?.value).toBe("Mar 5, 2026");
307
+ });
308
+
309
+ await act(async () => {
310
+ formApi?.setFieldValue("date", null);
311
+ });
312
+ await waitFor(() => {
313
+ expect(getDisplayInput(result.container)?.value ?? "").toBe("");
314
+ });
315
+ expect(onChange).not.toHaveBeenCalled();
316
+ });
317
+ });
318
+
226
319
  describe("date utilities", () => {
227
320
  it("formats display values in the house absolute register and handles null", () => {
228
321
  expect(formatDateDisplay(null)).toBe("");
@@ -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
  });