@multiplatform.one/forms 7.6.2 → 7.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 (492) hide show
  1. package/dist/cjs/Button/index.cjs +7 -1
  2. package/dist/cjs/Button/index.native.js +7 -1
  3. package/dist/cjs/Button/index.native.js.map +1 -1
  4. package/dist/cjs/Chip/index.cjs +1 -3
  5. package/dist/cjs/Chip/index.native.js +5 -3
  6. package/dist/cjs/Chip/index.native.js.map +1 -1
  7. package/dist/cjs/ContextualSaveBar/index.cjs +19 -3
  8. package/dist/cjs/ContextualSaveBar/index.native.js +19 -3
  9. package/dist/cjs/ContextualSaveBar/index.native.js.map +1 -1
  10. package/dist/cjs/DescriptionList/index.cjs +38 -12
  11. package/dist/cjs/DescriptionList/index.native.js +38 -12
  12. package/dist/cjs/DescriptionList/index.native.js.map +1 -1
  13. package/dist/cjs/ErrorSummary.cjs +4 -1
  14. package/dist/cjs/ErrorSummary.native.js +4 -1
  15. package/dist/cjs/ErrorSummary.native.js.map +1 -1
  16. package/dist/cjs/FloatingPanel/useFloatingPanel.cjs +24 -2
  17. package/dist/cjs/FloatingPanel/useFloatingPanel.native.js +43 -2
  18. package/dist/cjs/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  19. package/dist/cjs/InputParts/index.cjs +42 -2
  20. package/dist/cjs/InputParts/index.native.js +42 -2
  21. package/dist/cjs/InputParts/index.native.js.map +1 -1
  22. package/dist/cjs/fields/Checkbox/Checkbox.cjs +5 -2
  23. package/dist/cjs/fields/Checkbox/Checkbox.native.js +6 -3
  24. package/dist/cjs/fields/Checkbox/Checkbox.native.js.map +1 -1
  25. package/dist/cjs/fields/Checkbox/CheckboxGroup.cjs +69 -59
  26. package/dist/cjs/fields/Checkbox/CheckboxGroup.native.js +75 -65
  27. package/dist/cjs/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
  28. package/dist/cjs/fields/Checkbox/checkboxGroupContext.cjs +33 -0
  29. package/dist/cjs/fields/Checkbox/checkboxGroupContext.native.js +36 -0
  30. package/dist/cjs/fields/Checkbox/checkboxGroupContext.native.js.map +1 -0
  31. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.cjs +402 -0
  32. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js +441 -0
  33. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -0
  34. package/dist/cjs/fields/DatePicker/DatetimePicker.cjs +2 -376
  35. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +69 -297
  36. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  37. package/dist/cjs/fields/DatePicker/catalog.cjs +306 -0
  38. package/dist/cjs/fields/DatePicker/catalog.native.js +350 -0
  39. package/dist/cjs/fields/DatePicker/catalog.native.js.map +1 -0
  40. package/dist/cjs/fields/DatePicker/index.cjs +7 -280
  41. package/dist/cjs/fields/DatePicker/index.native.js +66 -185
  42. package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
  43. package/dist/cjs/fields/DatePicker/parts.cjs +12 -9
  44. package/dist/cjs/fields/DatePicker/parts.native.js +12 -9
  45. package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
  46. package/dist/cjs/fields/Duration/index.cjs +29 -3
  47. package/dist/cjs/fields/Duration/index.native.js +29 -3
  48. package/dist/cjs/fields/Duration/index.native.js.map +1 -1
  49. package/dist/cjs/fields/PhoneInput/index.cjs +9 -4
  50. package/dist/cjs/fields/PhoneInput/index.native.js +13 -6
  51. package/dist/cjs/fields/PhoneInput/index.native.js.map +1 -1
  52. package/dist/cjs/fields/Rating/index.cjs +1 -1
  53. package/dist/cjs/fields/Rating/index.native.js +4 -1
  54. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  55. package/dist/cjs/fields/SearchInput/index.cjs +6 -0
  56. package/dist/cjs/fields/SearchInput/index.native.js +6 -0
  57. package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
  58. package/dist/cjs/fields/Select/index.cjs +75 -2
  59. package/dist/cjs/fields/Select/index.native.js +77 -2
  60. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  61. package/dist/cjs/fields/Signature/index.cjs +9 -5
  62. package/dist/cjs/fields/Signature/index.native.js +9 -5
  63. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  64. package/dist/cjs/fields/Slider/index.cjs +3 -1
  65. package/dist/cjs/fields/Slider/index.native.js +3 -1
  66. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  67. package/dist/cjs/fields/Switch/index.cjs +5 -18
  68. package/dist/cjs/fields/Switch/index.native.js +5 -18
  69. package/dist/cjs/fields/Switch/index.native.js.map +1 -1
  70. package/dist/cjs/fields/TextArea/index.cjs +19 -5
  71. package/dist/cjs/fields/TextArea/index.native.js +23 -5
  72. package/dist/cjs/fields/TextArea/index.native.js.map +1 -1
  73. package/dist/cjs/fields/TimePicker/catalog.cjs +203 -0
  74. package/dist/cjs/fields/TimePicker/catalog.native.js +227 -0
  75. package/dist/cjs/fields/TimePicker/catalog.native.js.map +1 -0
  76. package/dist/cjs/fields/TimePicker/index.cjs +6 -177
  77. package/dist/cjs/fields/TimePicker/index.native.js +74 -85
  78. package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
  79. package/dist/cjs/fields/TimeRangeScrubber/geometry.cjs +6 -0
  80. package/dist/cjs/fields/TimeRangeScrubber/geometry.native.js +6 -0
  81. package/dist/cjs/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
  82. package/dist/cjs/fields/TimeRangeScrubber/index.cjs +34 -14
  83. package/dist/cjs/fields/TimeRangeScrubber/index.native.js +38 -14
  84. package/dist/cjs/fields/TimeRangeScrubber/index.native.js.map +1 -1
  85. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.cjs +202 -0
  86. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js +211 -0
  87. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -0
  88. package/dist/cjs/fields/nativeDateTime/osDateTimeIosDisplay.cjs +30 -0
  89. package/dist/cjs/fields/nativeDateTime/osDateTimeIosDisplay.native.js +33 -0
  90. package/dist/cjs/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -0
  91. package/dist/cjs/fields/nativeSelect.cjs +30 -0
  92. package/dist/cjs/fields/nativeSelect.native.js +33 -0
  93. package/dist/cjs/fields/nativeSelect.native.js.map +1 -0
  94. package/dist/cjs/index.cjs +1 -0
  95. package/dist/cjs/index.native.js +1 -0
  96. package/dist/cjs/index.native.js.map +1 -1
  97. package/dist/cjs/themedPrimitives.cjs +5 -0
  98. package/dist/cjs/themedPrimitives.native.js +5 -0
  99. package/dist/cjs/themedPrimitives.native.js.map +1 -1
  100. package/dist/esm/Button/index.mjs +8 -2
  101. package/dist/esm/Button/index.mjs.map +1 -1
  102. package/dist/esm/Button/index.native.js +8 -2
  103. package/dist/esm/Button/index.native.js.map +1 -1
  104. package/dist/esm/Chip/index.mjs +1 -3
  105. package/dist/esm/Chip/index.mjs.map +1 -1
  106. package/dist/esm/Chip/index.native.js +5 -3
  107. package/dist/esm/Chip/index.native.js.map +1 -1
  108. package/dist/esm/ContextualSaveBar/index.mjs +19 -3
  109. package/dist/esm/ContextualSaveBar/index.mjs.map +1 -1
  110. package/dist/esm/ContextualSaveBar/index.native.js +19 -3
  111. package/dist/esm/ContextualSaveBar/index.native.js.map +1 -1
  112. package/dist/esm/DescriptionList/index.mjs +38 -12
  113. package/dist/esm/DescriptionList/index.mjs.map +1 -1
  114. package/dist/esm/DescriptionList/index.native.js +38 -12
  115. package/dist/esm/DescriptionList/index.native.js.map +1 -1
  116. package/dist/esm/ErrorSummary.mjs +5 -2
  117. package/dist/esm/ErrorSummary.mjs.map +1 -1
  118. package/dist/esm/ErrorSummary.native.js +5 -2
  119. package/dist/esm/ErrorSummary.native.js.map +1 -1
  120. package/dist/esm/FloatingPanel/useFloatingPanel.mjs +24 -3
  121. package/dist/esm/FloatingPanel/useFloatingPanel.mjs.map +1 -1
  122. package/dist/esm/FloatingPanel/useFloatingPanel.native.js +43 -3
  123. package/dist/esm/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  124. package/dist/esm/InputParts/index.mjs +43 -3
  125. package/dist/esm/InputParts/index.mjs.map +1 -1
  126. package/dist/esm/InputParts/index.native.js +43 -3
  127. package/dist/esm/InputParts/index.native.js.map +1 -1
  128. package/dist/esm/fields/Checkbox/Checkbox.mjs +5 -2
  129. package/dist/esm/fields/Checkbox/Checkbox.mjs.map +1 -1
  130. package/dist/esm/fields/Checkbox/Checkbox.native.js +6 -3
  131. package/dist/esm/fields/Checkbox/Checkbox.native.js.map +1 -1
  132. package/dist/esm/fields/Checkbox/CheckboxGroup.mjs +69 -59
  133. package/dist/esm/fields/Checkbox/CheckboxGroup.mjs.map +1 -1
  134. package/dist/esm/fields/Checkbox/CheckboxGroup.native.js +75 -65
  135. package/dist/esm/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
  136. package/dist/esm/fields/Checkbox/checkboxGroupContext.mjs +7 -0
  137. package/dist/esm/fields/Checkbox/checkboxGroupContext.mjs.map +1 -0
  138. package/dist/esm/fields/Checkbox/checkboxGroupContext.native.js +7 -0
  139. package/dist/esm/fields/Checkbox/checkboxGroupContext.native.js.map +1 -0
  140. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs +377 -0
  141. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -0
  142. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js +413 -0
  143. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -0
  144. package/dist/esm/fields/DatePicker/DatetimePicker.mjs +1 -375
  145. package/dist/esm/fields/DatePicker/DatetimePicker.mjs.map +1 -1
  146. package/dist/esm/fields/DatePicker/DatetimePicker.native.js +65 -293
  147. package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  148. package/dist/esm/fields/DatePicker/catalog.mjs +276 -0
  149. package/dist/esm/fields/DatePicker/catalog.mjs.map +1 -0
  150. package/dist/esm/fields/DatePicker/catalog.native.js +317 -0
  151. package/dist/esm/fields/DatePicker/catalog.native.js.map +1 -0
  152. package/dist/esm/fields/DatePicker/index.mjs +1 -274
  153. package/dist/esm/fields/DatePicker/index.mjs.map +1 -1
  154. package/dist/esm/fields/DatePicker/index.native.js +60 -179
  155. package/dist/esm/fields/DatePicker/index.native.js.map +1 -1
  156. package/dist/esm/fields/DatePicker/parts.mjs +13 -10
  157. package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
  158. package/dist/esm/fields/DatePicker/parts.native.js +13 -10
  159. package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
  160. package/dist/esm/fields/Duration/index.mjs +29 -4
  161. package/dist/esm/fields/Duration/index.mjs.map +1 -1
  162. package/dist/esm/fields/Duration/index.native.js +29 -4
  163. package/dist/esm/fields/Duration/index.native.js.map +1 -1
  164. package/dist/esm/fields/PhoneInput/index.mjs +9 -4
  165. package/dist/esm/fields/PhoneInput/index.mjs.map +1 -1
  166. package/dist/esm/fields/PhoneInput/index.native.js +13 -6
  167. package/dist/esm/fields/PhoneInput/index.native.js.map +1 -1
  168. package/dist/esm/fields/Rating/index.mjs +2 -2
  169. package/dist/esm/fields/Rating/index.mjs.map +1 -1
  170. package/dist/esm/fields/Rating/index.native.js +5 -2
  171. package/dist/esm/fields/Rating/index.native.js.map +1 -1
  172. package/dist/esm/fields/SearchInput/index.mjs +6 -0
  173. package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
  174. package/dist/esm/fields/SearchInput/index.native.js +6 -0
  175. package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
  176. package/dist/esm/fields/Select/index.mjs +76 -3
  177. package/dist/esm/fields/Select/index.mjs.map +1 -1
  178. package/dist/esm/fields/Select/index.native.js +78 -3
  179. package/dist/esm/fields/Select/index.native.js.map +1 -1
  180. package/dist/esm/fields/Signature/index.mjs +10 -6
  181. package/dist/esm/fields/Signature/index.mjs.map +1 -1
  182. package/dist/esm/fields/Signature/index.native.js +10 -6
  183. package/dist/esm/fields/Signature/index.native.js.map +1 -1
  184. package/dist/esm/fields/Slider/index.mjs +4 -2
  185. package/dist/esm/fields/Slider/index.mjs.map +1 -1
  186. package/dist/esm/fields/Slider/index.native.js +4 -2
  187. package/dist/esm/fields/Slider/index.native.js.map +1 -1
  188. package/dist/esm/fields/Switch/index.mjs +6 -19
  189. package/dist/esm/fields/Switch/index.mjs.map +1 -1
  190. package/dist/esm/fields/Switch/index.native.js +6 -19
  191. package/dist/esm/fields/Switch/index.native.js.map +1 -1
  192. package/dist/esm/fields/TextArea/index.mjs +19 -5
  193. package/dist/esm/fields/TextArea/index.mjs.map +1 -1
  194. package/dist/esm/fields/TextArea/index.native.js +23 -5
  195. package/dist/esm/fields/TextArea/index.native.js.map +1 -1
  196. package/dist/esm/fields/TimePicker/catalog.mjs +174 -0
  197. package/dist/esm/fields/TimePicker/catalog.mjs.map +1 -0
  198. package/dist/esm/fields/TimePicker/catalog.native.js +195 -0
  199. package/dist/esm/fields/TimePicker/catalog.native.js.map +1 -0
  200. package/dist/esm/fields/TimePicker/index.mjs +2 -173
  201. package/dist/esm/fields/TimePicker/index.mjs.map +1 -1
  202. package/dist/esm/fields/TimePicker/index.native.js +76 -87
  203. package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
  204. package/dist/esm/fields/TimeRangeScrubber/geometry.mjs +6 -1
  205. package/dist/esm/fields/TimeRangeScrubber/geometry.mjs.map +1 -1
  206. package/dist/esm/fields/TimeRangeScrubber/geometry.native.js +6 -1
  207. package/dist/esm/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
  208. package/dist/esm/fields/TimeRangeScrubber/index.mjs +37 -18
  209. package/dist/esm/fields/TimeRangeScrubber/index.mjs.map +1 -1
  210. package/dist/esm/fields/TimeRangeScrubber/index.native.js +41 -18
  211. package/dist/esm/fields/TimeRangeScrubber/index.native.js.map +1 -1
  212. package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.mjs +166 -0
  213. package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.mjs.map +1 -0
  214. package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js +172 -0
  215. package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -0
  216. package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.mjs +5 -0
  217. package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.mjs.map +1 -0
  218. package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.native.js +5 -0
  219. package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -0
  220. package/dist/esm/fields/nativeSelect.mjs +5 -0
  221. package/dist/esm/fields/nativeSelect.mjs.map +1 -0
  222. package/dist/esm/fields/nativeSelect.native.js +5 -0
  223. package/dist/esm/fields/nativeSelect.native.js.map +1 -0
  224. package/dist/esm/index.mjs +2 -2
  225. package/dist/esm/index.mjs.map +1 -1
  226. package/dist/esm/index.native.js +2 -2
  227. package/dist/esm/index.native.js.map +1 -1
  228. package/dist/esm/themedPrimitives.mjs +5 -0
  229. package/dist/esm/themedPrimitives.mjs.map +1 -1
  230. package/dist/esm/themedPrimitives.native.js +5 -0
  231. package/dist/esm/themedPrimitives.native.js.map +1 -1
  232. package/dist/jsx/Button/index.mjs +8 -2
  233. package/dist/jsx/Button/index.mjs.map +1 -1
  234. package/dist/jsx/Button/index.native.js +7 -1
  235. package/dist/jsx/Button/index.native.js.map +1 -1
  236. package/dist/jsx/Chip/index.mjs +1 -3
  237. package/dist/jsx/Chip/index.mjs.map +1 -1
  238. package/dist/jsx/Chip/index.native.js +5 -3
  239. package/dist/jsx/Chip/index.native.js.map +1 -1
  240. package/dist/jsx/ContextualSaveBar/index.mjs +19 -3
  241. package/dist/jsx/ContextualSaveBar/index.mjs.map +1 -1
  242. package/dist/jsx/ContextualSaveBar/index.native.js +19 -3
  243. package/dist/jsx/ContextualSaveBar/index.native.js.map +1 -1
  244. package/dist/jsx/DescriptionList/index.mjs +38 -12
  245. package/dist/jsx/DescriptionList/index.mjs.map +1 -1
  246. package/dist/jsx/DescriptionList/index.native.js +38 -12
  247. package/dist/jsx/DescriptionList/index.native.js.map +1 -1
  248. package/dist/jsx/ErrorSummary.mjs +5 -2
  249. package/dist/jsx/ErrorSummary.mjs.map +1 -1
  250. package/dist/jsx/ErrorSummary.native.js +4 -1
  251. package/dist/jsx/ErrorSummary.native.js.map +1 -1
  252. package/dist/jsx/FloatingPanel/useFloatingPanel.mjs +24 -3
  253. package/dist/jsx/FloatingPanel/useFloatingPanel.mjs.map +1 -1
  254. package/dist/jsx/FloatingPanel/useFloatingPanel.native.js +43 -2
  255. package/dist/jsx/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  256. package/dist/jsx/InputParts/index.mjs +43 -3
  257. package/dist/jsx/InputParts/index.mjs.map +1 -1
  258. package/dist/jsx/InputParts/index.native.js +42 -2
  259. package/dist/jsx/InputParts/index.native.js.map +1 -1
  260. package/dist/jsx/fields/Checkbox/Checkbox.mjs +5 -2
  261. package/dist/jsx/fields/Checkbox/Checkbox.mjs.map +1 -1
  262. package/dist/jsx/fields/Checkbox/Checkbox.native.js +6 -3
  263. package/dist/jsx/fields/Checkbox/Checkbox.native.js.map +1 -1
  264. package/dist/jsx/fields/Checkbox/CheckboxGroup.mjs +69 -59
  265. package/dist/jsx/fields/Checkbox/CheckboxGroup.mjs.map +1 -1
  266. package/dist/jsx/fields/Checkbox/CheckboxGroup.native.js +75 -65
  267. package/dist/jsx/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
  268. package/dist/jsx/fields/Checkbox/checkboxGroupContext.mjs +7 -0
  269. package/dist/jsx/fields/Checkbox/checkboxGroupContext.mjs.map +1 -0
  270. package/dist/jsx/fields/Checkbox/checkboxGroupContext.native.js +36 -0
  271. package/dist/jsx/fields/Checkbox/checkboxGroupContext.native.js.map +1 -0
  272. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs +377 -0
  273. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -0
  274. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js +441 -0
  275. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -0
  276. package/dist/jsx/fields/DatePicker/DatetimePicker.mjs +1 -375
  277. package/dist/jsx/fields/DatePicker/DatetimePicker.mjs.map +1 -1
  278. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +69 -297
  279. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  280. package/dist/jsx/fields/DatePicker/catalog.mjs +276 -0
  281. package/dist/jsx/fields/DatePicker/catalog.mjs.map +1 -0
  282. package/dist/jsx/fields/DatePicker/catalog.native.js +350 -0
  283. package/dist/jsx/fields/DatePicker/catalog.native.js.map +1 -0
  284. package/dist/jsx/fields/DatePicker/index.mjs +1 -274
  285. package/dist/jsx/fields/DatePicker/index.mjs.map +1 -1
  286. package/dist/jsx/fields/DatePicker/index.native.js +66 -185
  287. package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
  288. package/dist/jsx/fields/DatePicker/parts.mjs +13 -10
  289. package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
  290. package/dist/jsx/fields/DatePicker/parts.native.js +12 -9
  291. package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
  292. package/dist/jsx/fields/Duration/index.mjs +29 -4
  293. package/dist/jsx/fields/Duration/index.mjs.map +1 -1
  294. package/dist/jsx/fields/Duration/index.native.js +29 -3
  295. package/dist/jsx/fields/Duration/index.native.js.map +1 -1
  296. package/dist/jsx/fields/PhoneInput/index.mjs +9 -4
  297. package/dist/jsx/fields/PhoneInput/index.mjs.map +1 -1
  298. package/dist/jsx/fields/PhoneInput/index.native.js +13 -6
  299. package/dist/jsx/fields/PhoneInput/index.native.js.map +1 -1
  300. package/dist/jsx/fields/Rating/index.mjs +2 -2
  301. package/dist/jsx/fields/Rating/index.mjs.map +1 -1
  302. package/dist/jsx/fields/Rating/index.native.js +4 -1
  303. package/dist/jsx/fields/Rating/index.native.js.map +1 -1
  304. package/dist/jsx/fields/SearchInput/index.mjs +6 -0
  305. package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
  306. package/dist/jsx/fields/SearchInput/index.native.js +6 -0
  307. package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
  308. package/dist/jsx/fields/Select/index.mjs +76 -3
  309. package/dist/jsx/fields/Select/index.mjs.map +1 -1
  310. package/dist/jsx/fields/Select/index.native.js +77 -2
  311. package/dist/jsx/fields/Select/index.native.js.map +1 -1
  312. package/dist/jsx/fields/Signature/index.mjs +10 -6
  313. package/dist/jsx/fields/Signature/index.mjs.map +1 -1
  314. package/dist/jsx/fields/Signature/index.native.js +9 -5
  315. package/dist/jsx/fields/Signature/index.native.js.map +1 -1
  316. package/dist/jsx/fields/Slider/index.mjs +4 -2
  317. package/dist/jsx/fields/Slider/index.mjs.map +1 -1
  318. package/dist/jsx/fields/Slider/index.native.js +3 -1
  319. package/dist/jsx/fields/Slider/index.native.js.map +1 -1
  320. package/dist/jsx/fields/Switch/index.mjs +6 -19
  321. package/dist/jsx/fields/Switch/index.mjs.map +1 -1
  322. package/dist/jsx/fields/Switch/index.native.js +5 -18
  323. package/dist/jsx/fields/Switch/index.native.js.map +1 -1
  324. package/dist/jsx/fields/TextArea/index.mjs +19 -5
  325. package/dist/jsx/fields/TextArea/index.mjs.map +1 -1
  326. package/dist/jsx/fields/TextArea/index.native.js +23 -5
  327. package/dist/jsx/fields/TextArea/index.native.js.map +1 -1
  328. package/dist/jsx/fields/TimePicker/catalog.mjs +174 -0
  329. package/dist/jsx/fields/TimePicker/catalog.mjs.map +1 -0
  330. package/dist/jsx/fields/TimePicker/catalog.native.js +227 -0
  331. package/dist/jsx/fields/TimePicker/catalog.native.js.map +1 -0
  332. package/dist/jsx/fields/TimePicker/index.mjs +2 -173
  333. package/dist/jsx/fields/TimePicker/index.mjs.map +1 -1
  334. package/dist/jsx/fields/TimePicker/index.native.js +74 -85
  335. package/dist/jsx/fields/TimePicker/index.native.js.map +1 -1
  336. package/dist/jsx/fields/TimeRangeScrubber/geometry.mjs +6 -1
  337. package/dist/jsx/fields/TimeRangeScrubber/geometry.mjs.map +1 -1
  338. package/dist/jsx/fields/TimeRangeScrubber/geometry.native.js +6 -0
  339. package/dist/jsx/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
  340. package/dist/jsx/fields/TimeRangeScrubber/index.mjs +37 -18
  341. package/dist/jsx/fields/TimeRangeScrubber/index.mjs.map +1 -1
  342. package/dist/jsx/fields/TimeRangeScrubber/index.native.js +38 -14
  343. package/dist/jsx/fields/TimeRangeScrubber/index.native.js.map +1 -1
  344. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.mjs +166 -0
  345. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.mjs.map +1 -0
  346. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js +211 -0
  347. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -0
  348. package/dist/jsx/fields/nativeDateTime/osDateTimeIosDisplay.mjs +5 -0
  349. package/dist/jsx/fields/nativeDateTime/osDateTimeIosDisplay.mjs.map +1 -0
  350. package/dist/jsx/fields/nativeDateTime/osDateTimeIosDisplay.native.js +33 -0
  351. package/dist/jsx/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -0
  352. package/dist/jsx/fields/nativeSelect.mjs +5 -0
  353. package/dist/jsx/fields/nativeSelect.mjs.map +1 -0
  354. package/dist/jsx/fields/nativeSelect.native.js +33 -0
  355. package/dist/jsx/fields/nativeSelect.native.js.map +1 -0
  356. package/dist/jsx/index.js +2 -2
  357. package/dist/jsx/index.js.map +1 -1
  358. package/dist/jsx/index.mjs +2 -2
  359. package/dist/jsx/index.mjs.map +1 -1
  360. package/dist/jsx/index.native.js +1 -0
  361. package/dist/jsx/index.native.js.map +1 -1
  362. package/dist/jsx/themedPrimitives.mjs +5 -0
  363. package/dist/jsx/themedPrimitives.mjs.map +1 -1
  364. package/dist/jsx/themedPrimitives.native.js +5 -0
  365. package/dist/jsx/themedPrimitives.native.js.map +1 -1
  366. package/package.json +12 -9
  367. package/src/Button/Button.labelInk.spec.tsx +1 -1
  368. package/src/Button/Button.sizeLadder.spec.tsx +124 -0
  369. package/src/Button/Button.spec.tsx +7 -17
  370. package/src/Button/Button.stories.tsx +14 -0
  371. package/src/Button/index.tsx +18 -3
  372. package/src/Chip/Chip.spec.tsx +15 -0
  373. package/src/Chip/Chip.stories.tsx +251 -0
  374. package/src/Chip/index.tsx +5 -1
  375. package/src/ContextualSaveBar/ContextualSaveBar.spec.tsx +51 -0
  376. package/src/ContextualSaveBar/ContextualSaveBar.stories.tsx +42 -23
  377. package/src/ContextualSaveBar/UnsavedChangesDialog.spec.tsx +167 -0
  378. package/src/ContextualSaveBar/index.tsx +14 -5
  379. package/src/DescriptionList/DescriptionList.spec.tsx +19 -1
  380. package/src/DescriptionList/DescriptionList.stories.tsx +5 -1
  381. package/src/DescriptionList/index.tsx +57 -19
  382. package/src/ErrorSummary.tsx +5 -2
  383. package/src/FloatingPanel/panelWidthContract.spec.ts +2 -2
  384. package/src/FloatingPanel/useFloatingPanel.spec.tsx +199 -1
  385. package/src/FloatingPanel/useFloatingPanel.ts +45 -3
  386. package/src/InputParts/index.tsx +56 -2
  387. package/src/Spinner/SpinnerGlyph.spec.tsx +132 -0
  388. package/src/Wheel/WheelEdgeFade.spec.tsx +141 -0
  389. package/src/fields/Checkbox/Checkbox.spec.tsx +24 -0
  390. package/src/fields/Checkbox/Checkbox.tsx +8 -3
  391. package/src/fields/Checkbox/CheckboxBox.spec.tsx +395 -0
  392. package/src/fields/Checkbox/CheckboxCard.spec.tsx +197 -0
  393. package/src/fields/Checkbox/CheckboxFieldFrame.spec.tsx +116 -0
  394. package/src/fields/Checkbox/CheckboxGroup.stories.tsx +15 -0
  395. package/src/fields/Checkbox/CheckboxGroup.tsx +77 -70
  396. package/src/fields/Checkbox/checkboxGroupContext.ts +12 -0
  397. package/src/fields/DatePicker/Calendar.spec.tsx +6 -5
  398. package/src/fields/DatePicker/DatePicker.stories.tsx +13 -0
  399. package/src/fields/DatePicker/DatetimePicker.catalog.tsx +586 -0
  400. package/src/fields/DatePicker/DatetimePicker.native.tsx +243 -0
  401. package/src/fields/DatePicker/DatetimePicker.tsx +2 -584
  402. package/src/fields/DatePicker/catalog.tsx +450 -0
  403. package/src/fields/DatePicker/index.native.tsx +261 -0
  404. package/src/fields/DatePicker/index.tsx +20 -448
  405. package/src/fields/DatePicker/parts.tsx +11 -6
  406. package/src/fields/Duration/Duration.spec.tsx +50 -0
  407. package/src/fields/Duration/Duration.stories.tsx +21 -0
  408. package/src/fields/Duration/index.tsx +43 -5
  409. package/src/fields/PhoneInput/PhoneInput.spec.tsx +16 -63
  410. package/src/fields/PhoneInput/PhoneInput.tvalue-source.spec.ts +23 -0
  411. package/src/fields/PhoneInput/index.tsx +10 -3
  412. package/src/fields/Rating/index.tsx +9 -1
  413. package/src/fields/SearchInput/SearchInput.spec.tsx +20 -0
  414. package/src/fields/SearchInput/index.tsx +6 -0
  415. package/src/fields/Select/Select.stories.tsx +23 -1
  416. package/src/fields/Select/index.tsx +77 -1
  417. package/src/fields/Signature/Signature.spec.tsx +22 -3
  418. package/src/fields/Signature/index.tsx +16 -7
  419. package/src/fields/Slider/index.tsx +4 -1
  420. package/src/fields/Switch/index.tsx +14 -12
  421. package/src/fields/TextArea/TextArea.spec.tsx +68 -0
  422. package/src/fields/TextArea/index.tsx +23 -5
  423. package/src/fields/TimePicker/TimePicker.stories.tsx +13 -0
  424. package/src/fields/TimePicker/catalog.tsx +265 -0
  425. package/src/fields/TimePicker/index.native.tsx +229 -0
  426. package/src/fields/TimePicker/index.tsx +6 -261
  427. package/src/fields/TimeRangeScrubber/TimeRangeScrubber.spec.tsx +36 -0
  428. package/src/fields/TimeRangeScrubber/geometry.ts +13 -0
  429. package/src/fields/TimeRangeScrubber/index.tsx +49 -8
  430. package/src/fields/nativeDateTime/OsDateTimeSheet.spec.ts +12 -0
  431. package/src/fields/nativeDateTime/OsDateTimeSheet.tsx +197 -0
  432. package/src/fields/nativeDateTime/osDateTimeIosDisplay.ts +4 -0
  433. package/src/fields/nativeSelect.spec.ts +28 -0
  434. package/src/fields/nativeSelect.ts +13 -0
  435. package/src/index.ts +2 -2
  436. package/src/themedPrimitives.tsx +10 -6
  437. package/types/Button/index.d.ts +3 -2
  438. package/types/Button/index.d.ts.map +1 -1
  439. package/types/Chip/index.d.ts.map +1 -1
  440. package/types/ContextualSaveBar/index.d.ts.map +1 -1
  441. package/types/DescriptionList/index.d.ts.map +1 -1
  442. package/types/ErrorSummary.d.ts.map +1 -1
  443. package/types/FloatingPanel/useFloatingPanel.d.ts +13 -0
  444. package/types/FloatingPanel/useFloatingPanel.d.ts.map +1 -1
  445. package/types/InputParts/index.d.ts.map +1 -1
  446. package/types/fields/Checkbox/Checkbox.d.ts.map +1 -1
  447. package/types/fields/Checkbox/CheckboxGroup.d.ts.map +1 -1
  448. package/types/fields/Checkbox/checkboxGroupContext.d.ts +8 -0
  449. package/types/fields/Checkbox/checkboxGroupContext.d.ts.map +1 -0
  450. package/types/fields/DatePicker/DatetimePicker.catalog.d.ts +35 -0
  451. package/types/fields/DatePicker/DatetimePicker.catalog.d.ts.map +1 -0
  452. package/types/fields/DatePicker/DatetimePicker.d.ts +2 -32
  453. package/types/fields/DatePicker/DatetimePicker.d.ts.map +1 -1
  454. package/types/fields/DatePicker/DatetimePicker.native.d.ts +26 -0
  455. package/types/fields/DatePicker/DatetimePicker.native.d.ts.map +1 -0
  456. package/types/fields/DatePicker/catalog.d.ts +42 -0
  457. package/types/fields/DatePicker/catalog.d.ts.map +1 -0
  458. package/types/fields/DatePicker/index.d.ts +2 -39
  459. package/types/fields/DatePicker/index.d.ts.map +1 -1
  460. package/types/fields/DatePicker/index.native.d.ts +40 -0
  461. package/types/fields/DatePicker/index.native.d.ts.map +1 -0
  462. package/types/fields/DatePicker/parts.d.ts.map +1 -1
  463. package/types/fields/Duration/index.d.ts +2 -0
  464. package/types/fields/Duration/index.d.ts.map +1 -1
  465. package/types/fields/PhoneInput/index.d.ts.map +1 -1
  466. package/types/fields/Rating/index.d.ts.map +1 -1
  467. package/types/fields/SearchInput/index.d.ts.map +1 -1
  468. package/types/fields/Select/index.d.ts +6 -1
  469. package/types/fields/Select/index.d.ts.map +1 -1
  470. package/types/fields/Signature/index.d.ts.map +1 -1
  471. package/types/fields/Slider/index.d.ts.map +1 -1
  472. package/types/fields/Switch/index.d.ts.map +1 -1
  473. package/types/fields/TextArea/index.d.ts.map +1 -1
  474. package/types/fields/TimePicker/catalog.d.ts +41 -0
  475. package/types/fields/TimePicker/catalog.d.ts.map +1 -0
  476. package/types/fields/TimePicker/index.d.ts +2 -38
  477. package/types/fields/TimePicker/index.d.ts.map +1 -1
  478. package/types/fields/TimePicker/index.native.d.ts +31 -0
  479. package/types/fields/TimePicker/index.native.d.ts.map +1 -0
  480. package/types/fields/TimeRangeScrubber/geometry.d.ts +8 -0
  481. package/types/fields/TimeRangeScrubber/geometry.d.ts.map +1 -1
  482. package/types/fields/TimeRangeScrubber/index.d.ts +1 -1
  483. package/types/fields/TimeRangeScrubber/index.d.ts.map +1 -1
  484. package/types/fields/nativeDateTime/OsDateTimeSheet.d.ts +12 -0
  485. package/types/fields/nativeDateTime/OsDateTimeSheet.d.ts.map +1 -0
  486. package/types/fields/nativeDateTime/osDateTimeIosDisplay.d.ts +3 -0
  487. package/types/fields/nativeDateTime/osDateTimeIosDisplay.d.ts.map +1 -0
  488. package/types/fields/nativeSelect.d.ts +12 -0
  489. package/types/fields/nativeSelect.d.ts.map +1 -0
  490. package/types/index.d.ts +2 -2
  491. package/types/index.d.ts.map +1 -1
  492. package/types/themedPrimitives.d.ts.map +1 -1
@@ -8,15 +8,32 @@ import { Switch } from "../fields/Switch";
8
8
  import { Form } from "../Form";
9
9
  import { ContextualSaveBar } from "./index";
10
10
 
11
+ const fields = (
12
+ <YStack gap="$4" width="100%" maxWidth={640} padding="$4" minHeight={360}>
13
+ <Input name="name" label="Service name" />
14
+ <Checkbox name="agree" label="Notify on deploy" />
15
+ <RadioGroup
16
+ name="env"
17
+ label="Environment"
18
+ options={[
19
+ { label: "Prod", value: "prod" },
20
+ { label: "Stage", value: "stage" },
21
+ ]}
22
+ />
23
+ <Switch name="live" label="Live" />
24
+ </YStack>
25
+ );
26
+
11
27
  const meta: Meta<typeof ContextualSaveBar> = {
12
28
  title: "Forms/ContextualSaveBar",
13
29
  component: ContextualSaveBar,
14
30
  parameters: {
15
- status: { type: "beta" },
31
+ layout: "fullscreen",
32
+ status: { type: "stable" },
16
33
  docs: {
17
34
  description: {
18
35
  component:
19
- "Declarative dirty-state Save/Discard bar (DG-ACT-06). Text, checkbox, and radio stage; Switch auto-commits and never raises the bar. Discard is never disabled (LC-30).",
36
+ "Declarative dirty-state Save/Discard bar (DG-ACT-06). Text, checkbox, and radio stage; Switch auto-commits and never raises the bar. Discard is never disabled (LC-30). Frame is CONTAINER-CAP on the top pair only; bottom pair stays 0 (bottom-docked sheet).",
20
37
  },
21
38
  },
22
39
  },
@@ -29,7 +46,11 @@ export const Main: Story = {
29
46
  name: "Main",
30
47
  render: () => (
31
48
  <Form
32
- saveBar={{ onSaved: action("onSaved"), onAutoCommit: action("onAutoCommit") }}
49
+ saveBar={{
50
+ forceVisible: true,
51
+ onSaved: action("onSaved"),
52
+ onAutoCommit: action("onAutoCommit"),
53
+ }}
33
54
  formOptions={{
34
55
  defaultValues: {
35
56
  name: "svc",
@@ -42,31 +63,29 @@ export const Main: Story = {
42
63
  action("onSubmit")(values);
43
64
  }}
44
65
  >
45
- <YStack gap="$4" width="100%" maxWidth={640} padding="$4">
46
- <Input name="name" label="Service name" />
47
- <Checkbox name="agree" label="Notify on deploy" />
48
- <RadioGroup
49
- name="env"
50
- label="Environment"
51
- options={[
52
- { label: "Prod", value: "prod" },
53
- { label: "Stage", value: "stage" },
54
- ]}
55
- />
56
- <Switch name="live" label="Live" />
57
- </YStack>
66
+ {fields}
58
67
  </Form>
59
68
  ),
60
69
  };
61
70
 
62
- export const ForceVisible: Story = {
63
- name: "Force visible",
71
+ export const Dirty: Story = {
72
+ name: "Dirty",
64
73
  render: () => (
65
- <Form formOptions={{ defaultValues: { name: "svc" } }}>
66
- <YStack gap="$4" width="100%" maxWidth={640} padding="$4">
67
- <Input name="name" label="Service name" />
68
- <ContextualSaveBar forceVisible />
69
- </YStack>
74
+ <Form
75
+ saveBar={{ onSaved: action("onSaved"), onAutoCommit: action("onAutoCommit") }}
76
+ formOptions={{
77
+ defaultValues: {
78
+ name: "svc",
79
+ agree: false,
80
+ env: "prod",
81
+ live: false,
82
+ },
83
+ }}
84
+ onSubmit={async (values) => {
85
+ action("onSubmit")(values);
86
+ }}
87
+ >
88
+ {fields}
70
89
  </Form>
71
90
  ),
72
91
  };
@@ -0,0 +1,167 @@
1
+ /**
2
+ * UnsavedChangesDialog — the route-leave confirm (DG-OVL-02), MPO-143.
3
+ *
4
+ * ContextualSaveBar.spec.tsx reaches this dialog through the save bar, which
5
+ * proves the wiring but never exercises the dialog's own contract: the two
6
+ * copy branches, which button calls which callback, and the guard that stops an
7
+ * outside click from dismissing a destructive confirm. Those are the parts a
8
+ * refactor of the save bar would carry away without noticing.
9
+ */
10
+ import { cleanup, fireEvent } from "@testing-library/react";
11
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
12
+ import { afterEach, describe, expect, it, vi } from "vitest";
13
+ import { UnsavedChangesDialog } from "./UnsavedChangesDialog";
14
+
15
+ afterEach(cleanup);
16
+
17
+ function dialog(): HTMLElement | null {
18
+ return document.body.querySelector('[role="alertdialog"]');
19
+ }
20
+
21
+ function button(marker: string): HTMLElement {
22
+ const node = document.body.querySelector(`[${marker}]`);
23
+ if (!node) throw new Error(`No button carrying ${marker}`);
24
+ return node as HTMLElement;
25
+ }
26
+
27
+ function noop() {}
28
+
29
+ /** Tamagui paints through atomic classes; read the inline channel first. */
30
+ function cssOf(node: HTMLElement, prop: string): string {
31
+ const inline = node.style.getPropertyValue(prop);
32
+ if (inline) return inline;
33
+ return getComputedStyle(node).getPropertyValue(prop) || "";
34
+ }
35
+
36
+ describe("UnsavedChangesDialog", () => {
37
+ it("renders nothing while closed", () => {
38
+ renderWithProviders(
39
+ <UnsavedChangesDialog open={false} fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
40
+ );
41
+ expect(dialog()).toBeNull();
42
+ });
43
+
44
+ it("announces as an alertdialog, not a plain dialog, because the choice is destructive", () => {
45
+ renderWithProviders(
46
+ <UnsavedChangesDialog open fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
47
+ );
48
+ expect(dialog()).toBeTruthy();
49
+ expect(document.body.querySelector('[role="dialog"][data-mp-savebar-guard]')).toBeNull();
50
+ });
51
+
52
+ it("leads with the question, so the title carries the decision", () => {
53
+ renderWithProviders(
54
+ <UnsavedChangesDialog open fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
55
+ );
56
+ expect(dialog()?.textContent).toContain("Discard unsaved changes?");
57
+ });
58
+
59
+ it("uses the singular sentence for exactly one edited field", () => {
60
+ renderWithProviders(
61
+ <UnsavedChangesDialog open fieldCount={1} onKeepEditing={noop} onDiscard={noop} />,
62
+ );
63
+ const text = dialog()?.textContent ?? "";
64
+ expect(text).toContain("1 field on this page has edits");
65
+ expect(text).not.toContain("fields on this page have");
66
+ });
67
+
68
+ it("uses the plural sentence, with the count interpolated, for more than one", () => {
69
+ renderWithProviders(
70
+ <UnsavedChangesDialog open fieldCount={4} onKeepEditing={noop} onDiscard={noop} />,
71
+ );
72
+ const text = dialog()?.textContent ?? "";
73
+ expect(text).toContain("4 fields on this page have edits");
74
+ expect(text).not.toContain("1 field on this page has");
75
+ });
76
+
77
+ it("says plainly that leaving discards the edits", () => {
78
+ renderWithProviders(
79
+ <UnsavedChangesDialog open fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
80
+ );
81
+ expect(dialog()?.textContent).toContain("Leaving discards them");
82
+ });
83
+
84
+ it("offers both a way back and a way out", () => {
85
+ renderWithProviders(
86
+ <UnsavedChangesDialog open fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
87
+ );
88
+ expect(button("data-mp-savebar-keep").textContent).toContain("Keep editing");
89
+ expect(button("data-mp-savebar-discard-confirm").textContent).toContain("Discard changes");
90
+ });
91
+
92
+ it("calls onKeepEditing, and only that, when the safe button is pressed", () => {
93
+ const onKeepEditing = vi.fn();
94
+ const onDiscard = vi.fn();
95
+ renderWithProviders(
96
+ <UnsavedChangesDialog
97
+ open
98
+ fieldCount={2}
99
+ onKeepEditing={onKeepEditing}
100
+ onDiscard={onDiscard}
101
+ />,
102
+ );
103
+ fireEvent.click(button("data-mp-savebar-keep"));
104
+ expect(onKeepEditing).toHaveBeenCalledTimes(1);
105
+ expect(onDiscard).not.toHaveBeenCalled();
106
+ });
107
+
108
+ it("calls onDiscard, and only that, when the destructive button is pressed", () => {
109
+ const onKeepEditing = vi.fn();
110
+ const onDiscard = vi.fn();
111
+ renderWithProviders(
112
+ <UnsavedChangesDialog
113
+ open
114
+ fieldCount={2}
115
+ onKeepEditing={onKeepEditing}
116
+ onDiscard={onDiscard}
117
+ />,
118
+ );
119
+ fireEvent.click(button("data-mp-savebar-discard-confirm"));
120
+ expect(onDiscard).toHaveBeenCalledTimes(1);
121
+ expect(onKeepEditing).not.toHaveBeenCalled();
122
+ });
123
+
124
+ it("treats any dismissal as keep-editing, never as a silent discard", () => {
125
+ const onKeepEditing = vi.fn();
126
+ const onDiscard = vi.fn();
127
+ renderWithProviders(
128
+ <UnsavedChangesDialog
129
+ open
130
+ fieldCount={2}
131
+ onKeepEditing={onKeepEditing}
132
+ onDiscard={onDiscard}
133
+ />,
134
+ );
135
+ fireEvent.keyDown(dialog() as HTMLElement, { key: "Escape", code: "Escape" });
136
+ expect(onDiscard).not.toHaveBeenCalled();
137
+ });
138
+
139
+ it("marks the content so the save bar's outside-click guard can find it", () => {
140
+ renderWithProviders(
141
+ <UnsavedChangesDialog open fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
142
+ );
143
+ expect(dialog()?.hasAttribute("data-mp-savebar-guard")).toBe(true);
144
+ });
145
+
146
+ it("takes focus itself rather than leaving it behind the overlay", () => {
147
+ renderWithProviders(
148
+ <UnsavedChangesDialog open fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
149
+ );
150
+ expect(dialog()?.getAttribute("tabindex")).toBe("-1");
151
+ });
152
+
153
+ it("paints no focus outline on the sheet itself, so the ring stays on the buttons", () => {
154
+ renderWithProviders(
155
+ <UnsavedChangesDialog open fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
156
+ );
157
+ const outline = cssOf(dialog() as HTMLElement, "outline-width");
158
+ expect(outline === "" || outline === "0px").toBe(true);
159
+ });
160
+
161
+ it("caps its width so the sentence never runs the width of a desk monitor", () => {
162
+ renderWithProviders(
163
+ <UnsavedChangesDialog open fieldCount={2} onKeepEditing={noop} onDiscard={noop} />,
164
+ );
165
+ expect(cssOf(dialog() as HTMLElement, "max-width")).toBe("440px");
166
+ });
167
+ });
@@ -120,6 +120,14 @@ function barRadius(knobProps: KnobProps) {
120
120
  };
121
121
  }
122
122
 
123
+ function containerRadiusRest(knobProps: KnobProps) {
124
+ const fragment = knobProps.containerRadius as KnobProps["containerRadius"] & {
125
+ className?: string;
126
+ };
127
+ const { className, borderRadius: _topPair, ...rest } = fragment;
128
+ return { className, rest };
129
+ }
130
+
123
131
  export function ContextualSaveBar({
124
132
  forceVisible = false,
125
133
  discardDisabled = false,
@@ -211,10 +219,8 @@ export function ContextualSaveBar({
211
219
  const padX = knobProps.panelPadding.padding;
212
220
  const borderWidth = knobProps.borderRadius.borderWidth;
213
221
  const elevationProps = getElevationWrapperProps(knobProps, elevation);
214
- const { className: smoothClass, ...smoothRest } =
215
- knobProps.containerRadius as KnobProps["containerRadius"] & {
216
- className?: string;
217
- };
222
+ const { className: smoothClass, rest: smoothRest } = containerRadiusRest(knobProps);
223
+ const topRadius = knobProps.containerRadius.borderRadius;
218
224
  const transition = knobProps.transition;
219
225
 
220
226
  return (
@@ -225,6 +231,9 @@ export function ContextualSaveBar({
225
231
  key="contextual-savebar"
226
232
  data-mp-contextual-savebar=""
227
233
  data-mp-savebar-dock="bottom"
234
+ data-mp-savebar-radius-class="CONTAINER-CAP"
235
+ data-mp-savebar-top-radius={String(topRadius)}
236
+ data-mp-savebar-bottom-radius="0"
228
237
  role="region"
229
238
  aria-label={t("Unsaved changes")}
230
239
  position="sticky"
@@ -243,13 +252,13 @@ export function ContextualSaveBar({
243
252
  borderRightWidth={0}
244
253
  borderBottomWidth={0}
245
254
  {...smoothRest}
246
- {...barRadius(knobProps)}
247
255
  className={smoothClass}
248
256
  {...knobProps.gap}
249
257
  transition={transition}
250
258
  enterStyle={transition ? { y: 12, opacity: 0 } : undefined}
251
259
  exitStyle={transition ? { y: 12, opacity: 0 } : undefined}
252
260
  {...elevationProps}
261
+ {...barRadius(knobProps)}
253
262
  style={{
254
263
  ...(isWeb
255
264
  ? { paddingBottom: "calc(10px + env(safe-area-inset-bottom, 0px))" }
@@ -138,7 +138,9 @@ describe("DescriptionList", () => {
138
138
  });
139
139
  const root = list(result.container);
140
140
  expect(root?.getAttribute("data-stacked")).toBe("false");
141
- expect(root?.style.gridTemplateColumns).toContain("min(max-content, 24ch)");
141
+ expect(root?.getAttribute("data-label-column-width")).toBe("min(max-content, 24ch)");
142
+ expect(root?.style.gridTemplateColumns).toContain("fit-content(24ch)");
143
+ expect(root?.style.gridTemplateColumns).toContain("minmax(0, 1fr)");
142
144
  });
143
145
 
144
146
  it("the optional Change action is a keyboard-reachable button", () => {
@@ -251,4 +253,20 @@ describe("DescriptionList", () => {
251
253
  );
252
254
  expect(list(result.container)?.getAttribute("data-compact")).toBe("true");
253
255
  });
256
+
257
+ it("side rows share the list stacked flag (native host measures via onLayout)", () => {
258
+ stubContainerWidth(280);
259
+ let result!: ReturnType<typeof renderWithProviders>;
260
+ act(() => {
261
+ result = renderWithProviders(
262
+ <DescriptionList
263
+ placement="side"
264
+ items={[{ term: "Hostname", field: "input", value: "compose01" }]}
265
+ />,
266
+ );
267
+ });
268
+ const root = list(result.container);
269
+ expect(root?.getAttribute("data-stacked")).toBe("true");
270
+ expect(root?.querySelectorAll("[data-mpo-description-list-row]").length).toBe(1);
271
+ });
254
272
  });
@@ -7,7 +7,7 @@ import { DescriptionList, type DescriptionListItem } from "./index";
7
7
  const meta: Meta<typeof DescriptionList> = {
8
8
  title: "Forms/DescriptionList",
9
9
  component: DescriptionList,
10
- parameters: { status: { type: "beta" } },
10
+ parameters: { status: { type: "stable" } },
11
11
  argTypes: {
12
12
  placement: { control: "radio", options: ["side", "top"] },
13
13
  compact: { control: "boolean" },
@@ -67,6 +67,10 @@ const HOST: DescriptionListItem[] = [
67
67
  { term: "Decommissioned", field: "input", value: null },
68
68
  ];
69
69
 
70
+ export const Default: Story = {
71
+ render: (args) => <DescriptionList {...args} items={HOST} />,
72
+ };
73
+
70
74
  export const Anatomy: Story = {
71
75
  name: "Anatomy — term · value · Change",
72
76
  render: (args) => <DescriptionList {...args} items={HOST} />,
@@ -87,6 +87,15 @@ function purposeMaxCh(): number {
87
87
  return LABEL_COLUMN_MAX_CH;
88
88
  }
89
89
 
90
+ function labelColumnGridTrack(width: string): string {
91
+ const prefix = "min(max-content,";
92
+ if (width.startsWith(prefix) && width.endsWith(")")) {
93
+ const inner = width.slice(prefix.length, -1).trim();
94
+ if (inner.endsWith("ch")) return `fit-content(${inner})`;
95
+ }
96
+ return width;
97
+ }
98
+
90
99
  function listItemRhythm(density: string) {
91
100
  const compact = density === "compact";
92
101
  return {
@@ -320,18 +329,32 @@ function DescriptionListWeb({
320
329
  placement: DescriptionListPlacement;
321
330
  framed: boolean;
322
331
  }) {
332
+ // Write tracks after commit: React's style setter (and invalid `min()`
333
+ // track syntax) otherwise leave a one-column computed grid.
334
+ const columns = stacked
335
+ ? undefined
336
+ : hasAction
337
+ ? `${labelColumnGridTrack(labelColumnWidth)} minmax(0, 1fr) max-content`
338
+ : `${labelColumnGridTrack(labelColumnWidth)} minmax(0, 1fr)`;
339
+ const listRef = useRef<HTMLDivElement>(null);
340
+
341
+ useLayoutEffect(() => {
342
+ const el = listRef.current;
343
+ if (!el) return;
344
+ if (columns) {
345
+ el.style.setProperty("grid-template-columns", columns);
346
+ } else {
347
+ el.style.removeProperty("grid-template-columns");
348
+ }
349
+ }, [columns]);
350
+
323
351
  const style: CSSProperties = stacked
324
- ? { display: "block", width: "100%" }
325
- : {
326
- display: "grid",
327
- gridTemplateColumns: hasAction
328
- ? `${labelColumnWidth} minmax(0, 1fr) max-content`
329
- : `${labelColumnWidth} minmax(0, 1fr)`,
330
- width: "100%",
331
- };
352
+ ? { display: "block", width: "100%", minWidth: 0 }
353
+ : { display: "grid", width: "100%", minWidth: 0 };
332
354
 
333
355
  return (
334
- <YStack
356
+ <div
357
+ ref={listRef}
335
358
  data-mpo-description-list=""
336
359
  data-placement={placement}
337
360
  data-stacked={stacked ? "true" : "false"}
@@ -342,8 +365,6 @@ function DescriptionListWeb({
342
365
  data-label-column-width={labelColumnWidth}
343
366
  data-density={density}
344
367
  data-size={size}
345
- width="100%"
346
- minWidth={0}
347
368
  style={style}
348
369
  >
349
370
  {rows.map((row, index) => (
@@ -357,17 +378,26 @@ function DescriptionListWeb({
357
378
  quiet={quiet}
358
379
  />
359
380
  ))}
360
- </YStack>
381
+ </div>
361
382
  );
362
383
  }
363
384
 
364
- function useContainerWide(enabled: boolean): { ref: Ref<unknown>; wide: boolean } {
385
+ type HostLayoutEvent = { nativeEvent: { layout: { width: number } } };
386
+
387
+ function useContainerWide(enabled: boolean): {
388
+ ref: Ref<unknown>;
389
+ wide: boolean;
390
+ onLayout: ((event: HostLayoutEvent) => void) | undefined;
391
+ } {
365
392
  const ref = useRef<HTMLDivElement>(null);
366
- const [wide, setWide] = useState(true);
393
+ // Web assumes wide until measured (desktop stories). Native assumes stacked
394
+ // until onLayout — phones sit under the 480 collapse.
395
+ const [wide, setWide] = useState(isWeb);
367
396
 
368
397
  useLayoutEffect(() => {
398
+ if (!isWeb || !enabled) return;
369
399
  const el = ref.current;
370
- if (!el || !enabled) {
400
+ if (!el) {
371
401
  setWide(true);
372
402
  return;
373
403
  }
@@ -392,7 +422,14 @@ function useContainerWide(enabled: boolean): { ref: Ref<unknown>; wide: boolean
392
422
  return () => ro.disconnect();
393
423
  }, [enabled]);
394
424
 
395
- return { ref, wide };
425
+ const onLayout =
426
+ !isWeb && enabled
427
+ ? (event: HostLayoutEvent) => {
428
+ setWide(event.nativeEvent.layout.width >= FORM_GRID_COLLAPSE_WIDTH);
429
+ }
430
+ : undefined;
431
+
432
+ return { ref, wide, onLayout };
396
433
  }
397
434
 
398
435
  export function DescriptionList({
@@ -415,8 +452,8 @@ export function DescriptionList({
415
452
  return itemsFromChildren(children);
416
453
  }, [items, children]);
417
454
  const hasAction = rows.some(rowHasAction);
418
- const measureCollapse = placement === "side" && isWeb;
419
- const { ref, wide } = useContainerWide(measureCollapse);
455
+ const measureCollapse = placement === "side";
456
+ const { ref, wide, onLayout } = useContainerWide(measureCollapse);
420
457
  const stacked = placement === "top" || (placement === "side" && !wide);
421
458
 
422
459
  const list = (
@@ -453,7 +490,7 @@ export function DescriptionList({
453
490
  <DescriptionListRowView
454
491
  key={index}
455
492
  row={row}
456
- stacked={true}
493
+ stacked={stacked}
457
494
  hasActionColumn={hasAction}
458
495
  rhythm={rhythm}
459
496
  showRule={index > 0}
@@ -476,6 +513,7 @@ export function DescriptionList({
476
513
  ref={ref as never}
477
514
  data-mpo-description-list-host=""
478
515
  data-testid={testID}
516
+ onLayout={onLayout}
479
517
  minWidth={0}
480
518
  {...widthProps}
481
519
  {...(framed
@@ -1,4 +1,4 @@
1
- import { useResolvedKnobs } from "@multiplatform.one/theme";
1
+ import { FOCUS_RING_HALO_OFFSET, useResolvedKnobs } from "@multiplatform.one/theme";
2
2
  import { WarningCircleIcon } from "@phosphor-icons/react";
3
3
  import { type ReactNode, useEffect, useId, useRef } from "react";
4
4
  import { Anchor, H4, Paragraph, YStack, isWeb } from "tamagui";
@@ -152,7 +152,10 @@ export function ErrorSummary({
152
152
  outlineWidth: 2,
153
153
  outlineStyle: "solid",
154
154
  outlineColor: "$color8",
155
- outlineOffset: 2,
155
+ // LC-71 §4 halo: inline text link. The summary sits in a run of prose,
156
+ // so a band at offset 0 crosses the line box and collides with the
157
+ // ascenders/descenders around it.
158
+ outlineOffset: FOCUS_RING_HALO_OFFSET,
156
159
  }}
157
160
  data-testid="error-summary"
158
161
  >
@@ -24,8 +24,8 @@ const fieldsDir = resolve(dirname(fileURLToPath(import.meta.url)), "..", "fields
24
24
  /** Pickers whose trigger is a form FIELD: the panel may never be narrower. */
25
25
  const fieldShapedPickers = [
26
26
  "DatePicker/parts.tsx",
27
- "DatePicker/DatetimePicker.tsx",
28
- "TimePicker/index.tsx",
27
+ "DatePicker/DatetimePicker.catalog.tsx",
28
+ "TimePicker/catalog.tsx",
29
29
  "ColorPicker/parts.tsx",
30
30
  "Icon/index.tsx",
31
31
  ];