@multiplatform.one/frappe-ui 7.66.0 → 7.68.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 (470) hide show
  1. package/dist/cjs/FileBrowser/index.cjs +15 -25
  2. package/dist/cjs/FileBrowser/index.native.js +15 -25
  3. package/dist/cjs/FileBrowser/index.native.js.map +1 -1
  4. package/dist/cjs/FormSidebar.cjs +107 -194
  5. package/dist/cjs/FormSidebar.native.js +120 -216
  6. package/dist/cjs/FormSidebar.native.js.map +1 -1
  7. package/dist/cjs/FrappeAssignment.cjs +0 -3
  8. package/dist/cjs/FrappeAssignment.native.js +0 -3
  9. package/dist/cjs/FrappeAssignment.native.js.map +1 -1
  10. package/dist/cjs/FrappeConnectionIndicator.cjs +5 -24
  11. package/dist/cjs/FrappeConnectionIndicator.native.js +5 -24
  12. package/dist/cjs/FrappeConnectionIndicator.native.js.map +1 -1
  13. package/dist/cjs/FrappeDashboard.cjs +0 -2
  14. package/dist/cjs/FrappeDashboard.native.js +0 -2
  15. package/dist/cjs/FrappeDashboard.native.js.map +1 -1
  16. package/dist/cjs/FrappeForm.cjs +6 -5
  17. package/dist/cjs/FrappeForm.native.js +6 -5
  18. package/dist/cjs/FrappeForm.native.js.map +1 -1
  19. package/dist/cjs/FrappeFormActions.cjs +20 -30
  20. package/dist/cjs/FrappeFormActions.native.js +23 -31
  21. package/dist/cjs/FrappeFormActions.native.js.map +1 -1
  22. package/dist/cjs/FrappeImageView.cjs +46 -65
  23. package/dist/cjs/FrappeImageView.native.js +46 -68
  24. package/dist/cjs/FrappeImageView.native.js.map +1 -1
  25. package/dist/cjs/FrappeKanban.cjs +0 -1
  26. package/dist/cjs/FrappeKanban.native.js +0 -1
  27. package/dist/cjs/FrappeKanban.native.js.map +1 -1
  28. package/dist/cjs/FrappeLikedBy.cjs +1 -1
  29. package/dist/cjs/FrappeLikedBy.native.js +1 -1
  30. package/dist/cjs/FrappeLikedBy.native.js.map +1 -1
  31. package/dist/cjs/FrappeListView.cjs +24 -68
  32. package/dist/cjs/FrappeListView.native.js +25 -72
  33. package/dist/cjs/FrappeListView.native.js.map +1 -1
  34. package/dist/cjs/FrappeRecordView.cjs +4 -0
  35. package/dist/cjs/FrappeRecordView.native.js +4 -0
  36. package/dist/cjs/FrappeRecordView.native.js.map +1 -1
  37. package/dist/cjs/FrappeReportBuilder.cjs +21 -18
  38. package/dist/cjs/FrappeReportBuilder.native.js +21 -18
  39. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  40. package/dist/cjs/FrappeReportView.cjs +2 -4
  41. package/dist/cjs/FrappeReportView.native.js +2 -4
  42. package/dist/cjs/FrappeReportView.native.js.map +1 -1
  43. package/dist/cjs/SyncErrorNotice.cjs +8 -36
  44. package/dist/cjs/SyncErrorNotice.native.js +8 -36
  45. package/dist/cjs/SyncErrorNotice.native.js.map +1 -1
  46. package/dist/cjs/desk/DeskFormSidebar.cjs +1 -6
  47. package/dist/cjs/desk/DeskFormSidebar.native.js +1 -6
  48. package/dist/cjs/desk/DeskFormSidebar.native.js.map +1 -1
  49. package/dist/cjs/desk/DeskShell.cjs +0 -1
  50. package/dist/cjs/desk/DeskShell.native.js +0 -1
  51. package/dist/cjs/desk/DeskShell.native.js.map +1 -1
  52. package/dist/cjs/fields/Date/catalog.native.js +0 -1
  53. package/dist/cjs/fields/Date/catalog.native.js.map +1 -1
  54. package/dist/cjs/fields/Date/index.native.js +4 -363
  55. package/dist/cjs/fields/Date/index.native.js.map +1 -1
  56. package/dist/cjs/fields/FileUpload.cjs +50 -58
  57. package/dist/cjs/fields/FileUpload.native.js +50 -56
  58. package/dist/cjs/fields/FileUpload.native.js.map +1 -1
  59. package/dist/cjs/insights/InsightsFacetTags.cjs +16 -92
  60. package/dist/cjs/insights/InsightsFacetTags.native.js +15 -97
  61. package/dist/cjs/insights/InsightsFacetTags.native.js.map +1 -1
  62. package/dist/cjs/list/FacetBadge.cjs +4 -28
  63. package/dist/cjs/list/FacetBadge.native.js +4 -28
  64. package/dist/cjs/list/FacetBadge.native.js.map +1 -1
  65. package/dist/cjs/list/FacetRail.cjs +37 -128
  66. package/dist/cjs/list/FacetRail.native.js +32 -130
  67. package/dist/cjs/list/FacetRail.native.js.map +1 -1
  68. package/dist/cjs/list/ListControls.cjs +1 -3
  69. package/dist/cjs/list/ListControls.native.js +1 -3
  70. package/dist/cjs/list/ListControls.native.js.map +1 -1
  71. package/dist/cjs/list/ListControlsSheet.cjs +5 -15
  72. package/dist/cjs/list/ListControlsSheet.native.js +7 -17
  73. package/dist/cjs/list/ListControlsSheet.native.js.map +1 -1
  74. package/dist/cjs/list/ListSidebarToolbar.cjs +5 -20
  75. package/dist/cjs/list/ListSidebarToolbar.native.js +7 -22
  76. package/dist/cjs/list/ListSidebarToolbar.native.js.map +1 -1
  77. package/dist/cjs/list/RecordCard.cjs +95 -127
  78. package/dist/cjs/list/RecordCard.native.js +78 -96
  79. package/dist/cjs/list/RecordCard.native.js.map +1 -1
  80. package/dist/cjs/list/ShufflePanel.cjs +55 -36
  81. package/dist/cjs/list/ShufflePanel.native.js +62 -39
  82. package/dist/cjs/list/ShufflePanel.native.js.map +1 -1
  83. package/dist/cjs/list/listColumns.cjs +1 -1
  84. package/dist/cjs/list/listColumns.native.js +1 -1
  85. package/dist/cjs/list/listColumns.native.js.map +1 -1
  86. package/dist/cjs/record/RecordHero.cjs +7 -85
  87. package/dist/cjs/record/RecordHero.native.js +7 -85
  88. package/dist/cjs/record/RecordHero.native.js.map +1 -1
  89. package/dist/cjs/record/RecordPage.cjs +5 -10
  90. package/dist/cjs/record/RecordPage.native.js +5 -10
  91. package/dist/cjs/record/RecordPage.native.js.map +1 -1
  92. package/dist/cjs/report/ReportViewToolbar.cjs +76 -47
  93. package/dist/cjs/report/ReportViewToolbar.native.js +79 -48
  94. package/dist/cjs/report/ReportViewToolbar.native.js.map +1 -1
  95. package/dist/esm/FileBrowser/index.mjs +16 -26
  96. package/dist/esm/FileBrowser/index.mjs.map +1 -1
  97. package/dist/esm/FileBrowser/index.native.js +16 -26
  98. package/dist/esm/FileBrowser/index.native.js.map +1 -1
  99. package/dist/esm/FormSidebar.mjs +110 -197
  100. package/dist/esm/FormSidebar.mjs.map +1 -1
  101. package/dist/esm/FormSidebar.native.js +123 -219
  102. package/dist/esm/FormSidebar.native.js.map +1 -1
  103. package/dist/esm/FrappeAssignment.mjs +0 -3
  104. package/dist/esm/FrappeAssignment.mjs.map +1 -1
  105. package/dist/esm/FrappeAssignment.native.js +0 -3
  106. package/dist/esm/FrappeAssignment.native.js.map +1 -1
  107. package/dist/esm/FrappeConnectionIndicator.mjs +7 -26
  108. package/dist/esm/FrappeConnectionIndicator.mjs.map +1 -1
  109. package/dist/esm/FrappeConnectionIndicator.native.js +7 -26
  110. package/dist/esm/FrappeConnectionIndicator.native.js.map +1 -1
  111. package/dist/esm/FrappeDashboard.mjs +0 -2
  112. package/dist/esm/FrappeDashboard.mjs.map +1 -1
  113. package/dist/esm/FrappeDashboard.native.js +0 -2
  114. package/dist/esm/FrappeDashboard.native.js.map +1 -1
  115. package/dist/esm/FrappeForm.mjs +7 -6
  116. package/dist/esm/FrappeForm.mjs.map +1 -1
  117. package/dist/esm/FrappeForm.native.js +7 -6
  118. package/dist/esm/FrappeForm.native.js.map +1 -1
  119. package/dist/esm/FrappeFormActions.mjs +22 -32
  120. package/dist/esm/FrappeFormActions.mjs.map +1 -1
  121. package/dist/esm/FrappeFormActions.native.js +25 -33
  122. package/dist/esm/FrappeFormActions.native.js.map +1 -1
  123. package/dist/esm/FrappeImageView.mjs +48 -67
  124. package/dist/esm/FrappeImageView.mjs.map +1 -1
  125. package/dist/esm/FrappeImageView.native.js +48 -70
  126. package/dist/esm/FrappeImageView.native.js.map +1 -1
  127. package/dist/esm/FrappeKanban.mjs +0 -1
  128. package/dist/esm/FrappeKanban.mjs.map +1 -1
  129. package/dist/esm/FrappeKanban.native.js +0 -1
  130. package/dist/esm/FrappeKanban.native.js.map +1 -1
  131. package/dist/esm/FrappeLikedBy.mjs +1 -1
  132. package/dist/esm/FrappeLikedBy.mjs.map +1 -1
  133. package/dist/esm/FrappeLikedBy.native.js +1 -1
  134. package/dist/esm/FrappeLikedBy.native.js.map +1 -1
  135. package/dist/esm/FrappeListView.mjs +25 -69
  136. package/dist/esm/FrappeListView.mjs.map +1 -1
  137. package/dist/esm/FrappeListView.native.js +26 -73
  138. package/dist/esm/FrappeListView.native.js.map +1 -1
  139. package/dist/esm/FrappeRecordView.mjs +4 -0
  140. package/dist/esm/FrappeRecordView.mjs.map +1 -1
  141. package/dist/esm/FrappeRecordView.native.js +4 -0
  142. package/dist/esm/FrappeRecordView.native.js.map +1 -1
  143. package/dist/esm/FrappeReportBuilder.mjs +21 -18
  144. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  145. package/dist/esm/FrappeReportBuilder.native.js +21 -18
  146. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  147. package/dist/esm/FrappeReportView.mjs +3 -5
  148. package/dist/esm/FrappeReportView.mjs.map +1 -1
  149. package/dist/esm/FrappeReportView.native.js +3 -5
  150. package/dist/esm/FrappeReportView.native.js.map +1 -1
  151. package/dist/esm/SyncErrorNotice.mjs +10 -38
  152. package/dist/esm/SyncErrorNotice.mjs.map +1 -1
  153. package/dist/esm/SyncErrorNotice.native.js +10 -38
  154. package/dist/esm/SyncErrorNotice.native.js.map +1 -1
  155. package/dist/esm/desk/DeskFormSidebar.mjs +1 -6
  156. package/dist/esm/desk/DeskFormSidebar.mjs.map +1 -1
  157. package/dist/esm/desk/DeskFormSidebar.native.js +1 -6
  158. package/dist/esm/desk/DeskFormSidebar.native.js.map +1 -1
  159. package/dist/esm/desk/DeskShell.mjs +0 -1
  160. package/dist/esm/desk/DeskShell.mjs.map +1 -1
  161. package/dist/esm/desk/DeskShell.native.js +0 -1
  162. package/dist/esm/desk/DeskShell.native.js.map +1 -1
  163. package/dist/esm/fields/Date/catalog.mjs.map +1 -1
  164. package/dist/esm/fields/Date/catalog.native.js +0 -1
  165. package/dist/esm/fields/Date/catalog.native.js.map +1 -1
  166. package/dist/esm/fields/Date/index.native.js +2 -361
  167. package/dist/esm/fields/Date/index.native.js.map +1 -1
  168. package/dist/esm/fields/FileUpload.mjs +53 -61
  169. package/dist/esm/fields/FileUpload.mjs.map +1 -1
  170. package/dist/esm/fields/FileUpload.native.js +53 -59
  171. package/dist/esm/fields/FileUpload.native.js.map +1 -1
  172. package/dist/esm/insights/InsightsFacetTags.mjs +18 -94
  173. package/dist/esm/insights/InsightsFacetTags.mjs.map +1 -1
  174. package/dist/esm/insights/InsightsFacetTags.native.js +17 -99
  175. package/dist/esm/insights/InsightsFacetTags.native.js.map +1 -1
  176. package/dist/esm/list/FacetBadge.mjs +5 -29
  177. package/dist/esm/list/FacetBadge.mjs.map +1 -1
  178. package/dist/esm/list/FacetBadge.native.js +5 -29
  179. package/dist/esm/list/FacetBadge.native.js.map +1 -1
  180. package/dist/esm/list/FacetRail.mjs +40 -131
  181. package/dist/esm/list/FacetRail.mjs.map +1 -1
  182. package/dist/esm/list/FacetRail.native.js +35 -133
  183. package/dist/esm/list/FacetRail.native.js.map +1 -1
  184. package/dist/esm/list/ListControls.mjs +1 -3
  185. package/dist/esm/list/ListControls.mjs.map +1 -1
  186. package/dist/esm/list/ListControls.native.js +1 -3
  187. package/dist/esm/list/ListControls.native.js.map +1 -1
  188. package/dist/esm/list/ListControlsSheet.mjs +6 -16
  189. package/dist/esm/list/ListControlsSheet.mjs.map +1 -1
  190. package/dist/esm/list/ListControlsSheet.native.js +8 -18
  191. package/dist/esm/list/ListControlsSheet.native.js.map +1 -1
  192. package/dist/esm/list/ListSidebarToolbar.mjs +6 -21
  193. package/dist/esm/list/ListSidebarToolbar.mjs.map +1 -1
  194. package/dist/esm/list/ListSidebarToolbar.native.js +8 -23
  195. package/dist/esm/list/ListSidebarToolbar.native.js.map +1 -1
  196. package/dist/esm/list/RecordCard.mjs +95 -127
  197. package/dist/esm/list/RecordCard.mjs.map +1 -1
  198. package/dist/esm/list/RecordCard.native.js +78 -96
  199. package/dist/esm/list/RecordCard.native.js.map +1 -1
  200. package/dist/esm/list/ShufflePanel.mjs +57 -38
  201. package/dist/esm/list/ShufflePanel.mjs.map +1 -1
  202. package/dist/esm/list/ShufflePanel.native.js +64 -41
  203. package/dist/esm/list/ShufflePanel.native.js.map +1 -1
  204. package/dist/esm/list/listColumns.mjs +1 -1
  205. package/dist/esm/list/listColumns.mjs.map +1 -1
  206. package/dist/esm/list/listColumns.native.js +1 -1
  207. package/dist/esm/list/listColumns.native.js.map +1 -1
  208. package/dist/esm/record/RecordHero.mjs +8 -86
  209. package/dist/esm/record/RecordHero.mjs.map +1 -1
  210. package/dist/esm/record/RecordHero.native.js +8 -86
  211. package/dist/esm/record/RecordHero.native.js.map +1 -1
  212. package/dist/esm/record/RecordPage.mjs +6 -11
  213. package/dist/esm/record/RecordPage.mjs.map +1 -1
  214. package/dist/esm/record/RecordPage.native.js +6 -11
  215. package/dist/esm/record/RecordPage.native.js.map +1 -1
  216. package/dist/esm/report/ReportViewToolbar.mjs +78 -49
  217. package/dist/esm/report/ReportViewToolbar.mjs.map +1 -1
  218. package/dist/esm/report/ReportViewToolbar.native.js +81 -50
  219. package/dist/esm/report/ReportViewToolbar.native.js.map +1 -1
  220. package/dist/jsx/FileBrowser/index.mjs +16 -26
  221. package/dist/jsx/FileBrowser/index.mjs.map +1 -1
  222. package/dist/jsx/FileBrowser/index.native.js +15 -25
  223. package/dist/jsx/FileBrowser/index.native.js.map +1 -1
  224. package/dist/jsx/FormSidebar.mjs +110 -197
  225. package/dist/jsx/FormSidebar.mjs.map +1 -1
  226. package/dist/jsx/FormSidebar.native.js +120 -216
  227. package/dist/jsx/FormSidebar.native.js.map +1 -1
  228. package/dist/jsx/FrappeAssignment.mjs +0 -3
  229. package/dist/jsx/FrappeAssignment.mjs.map +1 -1
  230. package/dist/jsx/FrappeAssignment.native.js +0 -3
  231. package/dist/jsx/FrappeAssignment.native.js.map +1 -1
  232. package/dist/jsx/FrappeConnectionIndicator.mjs +7 -26
  233. package/dist/jsx/FrappeConnectionIndicator.mjs.map +1 -1
  234. package/dist/jsx/FrappeConnectionIndicator.native.js +5 -24
  235. package/dist/jsx/FrappeConnectionIndicator.native.js.map +1 -1
  236. package/dist/jsx/FrappeDashboard.mjs +0 -2
  237. package/dist/jsx/FrappeDashboard.mjs.map +1 -1
  238. package/dist/jsx/FrappeDashboard.native.js +0 -2
  239. package/dist/jsx/FrappeDashboard.native.js.map +1 -1
  240. package/dist/jsx/FrappeForm.mjs +7 -6
  241. package/dist/jsx/FrappeForm.mjs.map +1 -1
  242. package/dist/jsx/FrappeForm.native.js +6 -5
  243. package/dist/jsx/FrappeForm.native.js.map +1 -1
  244. package/dist/jsx/FrappeFormActions.mjs +22 -32
  245. package/dist/jsx/FrappeFormActions.mjs.map +1 -1
  246. package/dist/jsx/FrappeFormActions.native.js +23 -31
  247. package/dist/jsx/FrappeFormActions.native.js.map +1 -1
  248. package/dist/jsx/FrappeImageView.mjs +48 -67
  249. package/dist/jsx/FrappeImageView.mjs.map +1 -1
  250. package/dist/jsx/FrappeImageView.native.js +46 -68
  251. package/dist/jsx/FrappeImageView.native.js.map +1 -1
  252. package/dist/jsx/FrappeKanban.mjs +0 -1
  253. package/dist/jsx/FrappeKanban.mjs.map +1 -1
  254. package/dist/jsx/FrappeKanban.native.js +0 -1
  255. package/dist/jsx/FrappeKanban.native.js.map +1 -1
  256. package/dist/jsx/FrappeLikedBy.mjs +1 -1
  257. package/dist/jsx/FrappeLikedBy.mjs.map +1 -1
  258. package/dist/jsx/FrappeLikedBy.native.js +1 -1
  259. package/dist/jsx/FrappeLikedBy.native.js.map +1 -1
  260. package/dist/jsx/FrappeListView.mjs +25 -69
  261. package/dist/jsx/FrappeListView.mjs.map +1 -1
  262. package/dist/jsx/FrappeListView.native.js +25 -72
  263. package/dist/jsx/FrappeListView.native.js.map +1 -1
  264. package/dist/jsx/FrappeRecordView.mjs +4 -0
  265. package/dist/jsx/FrappeRecordView.mjs.map +1 -1
  266. package/dist/jsx/FrappeRecordView.native.js +4 -0
  267. package/dist/jsx/FrappeRecordView.native.js.map +1 -1
  268. package/dist/jsx/FrappeReportBuilder.mjs +21 -18
  269. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  270. package/dist/jsx/FrappeReportBuilder.native.js +21 -18
  271. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  272. package/dist/jsx/FrappeReportView.mjs +3 -5
  273. package/dist/jsx/FrappeReportView.mjs.map +1 -1
  274. package/dist/jsx/FrappeReportView.native.js +2 -4
  275. package/dist/jsx/FrappeReportView.native.js.map +1 -1
  276. package/dist/jsx/SyncErrorNotice.mjs +10 -38
  277. package/dist/jsx/SyncErrorNotice.mjs.map +1 -1
  278. package/dist/jsx/SyncErrorNotice.native.js +8 -36
  279. package/dist/jsx/SyncErrorNotice.native.js.map +1 -1
  280. package/dist/jsx/desk/DeskFormSidebar.mjs +1 -6
  281. package/dist/jsx/desk/DeskFormSidebar.mjs.map +1 -1
  282. package/dist/jsx/desk/DeskFormSidebar.native.js +1 -6
  283. package/dist/jsx/desk/DeskFormSidebar.native.js.map +1 -1
  284. package/dist/jsx/desk/DeskShell.mjs +0 -1
  285. package/dist/jsx/desk/DeskShell.mjs.map +1 -1
  286. package/dist/jsx/desk/DeskShell.native.js +0 -1
  287. package/dist/jsx/desk/DeskShell.native.js.map +1 -1
  288. package/dist/jsx/fields/Date/catalog.mjs.map +1 -1
  289. package/dist/jsx/fields/Date/catalog.native.js +0 -1
  290. package/dist/jsx/fields/Date/catalog.native.js.map +1 -1
  291. package/dist/jsx/fields/Date/index.native.js +4 -363
  292. package/dist/jsx/fields/Date/index.native.js.map +1 -1
  293. package/dist/jsx/fields/FileUpload.mjs +53 -61
  294. package/dist/jsx/fields/FileUpload.mjs.map +1 -1
  295. package/dist/jsx/fields/FileUpload.native.js +50 -56
  296. package/dist/jsx/fields/FileUpload.native.js.map +1 -1
  297. package/dist/jsx/insights/InsightsFacetTags.mjs +18 -94
  298. package/dist/jsx/insights/InsightsFacetTags.mjs.map +1 -1
  299. package/dist/jsx/insights/InsightsFacetTags.native.js +15 -97
  300. package/dist/jsx/insights/InsightsFacetTags.native.js.map +1 -1
  301. package/dist/jsx/list/FacetBadge.mjs +5 -29
  302. package/dist/jsx/list/FacetBadge.mjs.map +1 -1
  303. package/dist/jsx/list/FacetBadge.native.js +4 -28
  304. package/dist/jsx/list/FacetBadge.native.js.map +1 -1
  305. package/dist/jsx/list/FacetRail.mjs +40 -131
  306. package/dist/jsx/list/FacetRail.mjs.map +1 -1
  307. package/dist/jsx/list/FacetRail.native.js +32 -130
  308. package/dist/jsx/list/FacetRail.native.js.map +1 -1
  309. package/dist/jsx/list/ListControls.mjs +1 -3
  310. package/dist/jsx/list/ListControls.mjs.map +1 -1
  311. package/dist/jsx/list/ListControls.native.js +1 -3
  312. package/dist/jsx/list/ListControls.native.js.map +1 -1
  313. package/dist/jsx/list/ListControlsSheet.mjs +6 -16
  314. package/dist/jsx/list/ListControlsSheet.mjs.map +1 -1
  315. package/dist/jsx/list/ListControlsSheet.native.js +7 -17
  316. package/dist/jsx/list/ListControlsSheet.native.js.map +1 -1
  317. package/dist/jsx/list/ListSidebarToolbar.mjs +6 -21
  318. package/dist/jsx/list/ListSidebarToolbar.mjs.map +1 -1
  319. package/dist/jsx/list/ListSidebarToolbar.native.js +7 -22
  320. package/dist/jsx/list/ListSidebarToolbar.native.js.map +1 -1
  321. package/dist/jsx/list/RecordCard.mjs +95 -127
  322. package/dist/jsx/list/RecordCard.mjs.map +1 -1
  323. package/dist/jsx/list/RecordCard.native.js +78 -96
  324. package/dist/jsx/list/RecordCard.native.js.map +1 -1
  325. package/dist/jsx/list/ShufflePanel.mjs +57 -38
  326. package/dist/jsx/list/ShufflePanel.mjs.map +1 -1
  327. package/dist/jsx/list/ShufflePanel.native.js +62 -39
  328. package/dist/jsx/list/ShufflePanel.native.js.map +1 -1
  329. package/dist/jsx/list/listColumns.mjs +1 -1
  330. package/dist/jsx/list/listColumns.mjs.map +1 -1
  331. package/dist/jsx/list/listColumns.native.js +1 -1
  332. package/dist/jsx/list/listColumns.native.js.map +1 -1
  333. package/dist/jsx/record/RecordHero.mjs +8 -86
  334. package/dist/jsx/record/RecordHero.mjs.map +1 -1
  335. package/dist/jsx/record/RecordHero.native.js +7 -85
  336. package/dist/jsx/record/RecordHero.native.js.map +1 -1
  337. package/dist/jsx/record/RecordPage.mjs +6 -11
  338. package/dist/jsx/record/RecordPage.mjs.map +1 -1
  339. package/dist/jsx/record/RecordPage.native.js +5 -10
  340. package/dist/jsx/record/RecordPage.native.js.map +1 -1
  341. package/dist/jsx/report/ReportViewToolbar.mjs +78 -49
  342. package/dist/jsx/report/ReportViewToolbar.mjs.map +1 -1
  343. package/dist/jsx/report/ReportViewToolbar.native.js +79 -48
  344. package/dist/jsx/report/ReportViewToolbar.native.js.map +1 -1
  345. package/package.json +16 -16
  346. package/src/FileBrowser/index.tsx +11 -15
  347. package/src/FormSidebar.stories.tsx +1 -1
  348. package/src/FormSidebar.tsx +146 -251
  349. package/src/FrappeAssignment.tsx +0 -3
  350. package/src/FrappeConnectionIndicator.tsx +6 -28
  351. package/src/FrappeDashboard.spec.tsx +7 -3
  352. package/src/FrappeDashboard.tsx +0 -2
  353. package/src/FrappeForm.connections.spec.tsx +2 -2
  354. package/src/FrappeForm.deskSemantics.spec.tsx +2 -2
  355. package/src/FrappeForm.lifecycle.spec.tsx +27 -27
  356. package/src/FrappeForm.tsx +11 -7
  357. package/src/FrappeFormActions.tsx +24 -38
  358. package/src/FrappeImageView.stories.tsx +1 -6
  359. package/src/FrappeImageView.tsx +52 -66
  360. package/src/FrappeKanban.tsx +0 -1
  361. package/src/FrappeLikedBy.tsx +1 -1
  362. package/src/FrappeListView.controls.spec.tsx +3 -2
  363. package/src/FrappeListView.spec.tsx +7 -3
  364. package/src/FrappeListView.tsx +23 -56
  365. package/src/FrappeRecordView.tsx +16 -3
  366. package/src/FrappeReportBuilder.tsx +21 -19
  367. package/src/FrappeReportView.tsx +3 -6
  368. package/src/SyncErrorNotice.spec.tsx +7 -12
  369. package/src/SyncErrorNotice.stories.tsx +2 -4
  370. package/src/SyncErrorNotice.tsx +13 -41
  371. package/src/desk/DeskFormSidebar.tsx +1 -2
  372. package/src/desk/DeskShell.tsx +1 -1
  373. package/src/desk/deskDocumentRoutes.spec.tsx +7 -4
  374. package/src/fields/Date/catalog.tsx +6 -7
  375. package/src/fields/Date/nativeIsCatalog.spec.tsx +26 -0
  376. package/src/fields/Date/typeParity.spec.tsx +26 -102
  377. package/src/fields/FileUpload.spec.tsx +18 -3
  378. package/src/fields/FileUpload.tsx +64 -68
  379. package/src/frappeRemainder.designLaw.spec.ts +8 -7
  380. package/src/insights/InsightsFacetTags.tsx +21 -102
  381. package/src/list/FacetBadge.tsx +7 -29
  382. package/src/list/FacetRail.spec.tsx +11 -10
  383. package/src/list/FacetRail.tsx +49 -161
  384. package/src/list/ListControls.tsx +1 -3
  385. package/src/list/ListControlsSheet.tsx +10 -12
  386. package/src/list/ListSidebarToolbar.tsx +7 -18
  387. package/src/list/RecordCard.native.tsx +65 -71
  388. package/src/list/RecordCard.spec.tsx +8 -5
  389. package/src/list/RecordCard.tsx +110 -129
  390. package/src/list/ShufflePanel.tsx +63 -38
  391. package/src/list/listColumns.tsx +1 -1
  392. package/src/record/RecordHero.tsx +11 -51
  393. package/src/record/RecordPage.tsx +8 -11
  394. package/src/report/ReportViewToolbar.spec.tsx +45 -3
  395. package/src/report/ReportViewToolbar.tsx +113 -62
  396. package/src/useFrappeForm.spec.tsx +1 -1
  397. package/types/FileBrowser/index.d.ts.map +1 -1
  398. package/types/FormSidebar.d.ts +13 -3
  399. package/types/FormSidebar.d.ts.map +1 -1
  400. package/types/FrappeAssignment.d.ts.map +1 -1
  401. package/types/FrappeConnectionIndicator.d.ts +2 -1
  402. package/types/FrappeConnectionIndicator.d.ts.map +1 -1
  403. package/types/FrappeDashboard.d.ts.map +1 -1
  404. package/types/FrappeFormActions.d.ts.map +1 -1
  405. package/types/FrappeImageView.d.ts.map +1 -1
  406. package/types/FrappeKanban.d.ts.map +1 -1
  407. package/types/FrappeListView.d.ts.map +1 -1
  408. package/types/FrappeRecordView.d.ts.map +1 -1
  409. package/types/FrappeReportBuilder.d.ts.map +1 -1
  410. package/types/FrappeReportView.d.ts.map +1 -1
  411. package/types/SyncErrorNotice.d.ts +4 -6
  412. package/types/SyncErrorNotice.d.ts.map +1 -1
  413. package/types/desk/DeskFormSidebar.d.ts.map +1 -1
  414. package/types/desk/DeskShell.d.ts.map +1 -1
  415. package/types/fields/Date/catalog.d.ts +5 -4
  416. package/types/fields/Date/catalog.d.ts.map +1 -1
  417. package/types/fields/FileUpload.d.ts.map +1 -1
  418. package/types/insights/InsightsFacetTags.d.ts +4 -1
  419. package/types/insights/InsightsFacetTags.d.ts.map +1 -1
  420. package/types/list/FacetBadge.d.ts +3 -3
  421. package/types/list/FacetBadge.d.ts.map +1 -1
  422. package/types/list/FacetRail.d.ts +7 -5
  423. package/types/list/FacetRail.d.ts.map +1 -1
  424. package/types/list/ListControls.d.ts.map +1 -1
  425. package/types/list/ListControlsSheet.d.ts.map +1 -1
  426. package/types/list/ListSidebarToolbar.d.ts.map +1 -1
  427. package/types/list/RecordCard.d.ts +6 -6
  428. package/types/list/RecordCard.d.ts.map +1 -1
  429. package/types/list/RecordCard.native.d.ts +4 -3
  430. package/types/list/RecordCard.native.d.ts.map +1 -1
  431. package/types/list/ShufflePanel.d.ts +8 -3
  432. package/types/list/ShufflePanel.d.ts.map +1 -1
  433. package/types/record/RecordHero.d.ts +5 -1
  434. package/types/record/RecordHero.d.ts.map +1 -1
  435. package/types/record/RecordPage.d.ts.map +1 -1
  436. package/types/report/ReportViewToolbar.d.ts.map +1 -1
  437. package/dist/cjs/fields/Date/dateTimePickerLoader.cjs +0 -38
  438. package/dist/cjs/fields/Date/dateTimePickerLoader.native.js +0 -42
  439. package/dist/cjs/fields/Date/dateTimePickerLoader.native.js.map +0 -1
  440. package/dist/cjs/fields/Date/sheetKeyboard.cjs +0 -54
  441. package/dist/cjs/fields/Date/sheetKeyboard.native.js +0 -57
  442. package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +0 -1
  443. package/dist/esm/fields/Date/dateTimePickerLoader.mjs +0 -13
  444. package/dist/esm/fields/Date/dateTimePickerLoader.mjs.map +0 -1
  445. package/dist/esm/fields/Date/dateTimePickerLoader.native.js +0 -14
  446. package/dist/esm/fields/Date/dateTimePickerLoader.native.js.map +0 -1
  447. package/dist/esm/fields/Date/sheetKeyboard.mjs +0 -21
  448. package/dist/esm/fields/Date/sheetKeyboard.mjs.map +0 -1
  449. package/dist/esm/fields/Date/sheetKeyboard.native.js +0 -21
  450. package/dist/esm/fields/Date/sheetKeyboard.native.js.map +0 -1
  451. package/dist/jsx/fields/Date/dateTimePickerLoader.mjs +0 -13
  452. package/dist/jsx/fields/Date/dateTimePickerLoader.mjs.map +0 -1
  453. package/dist/jsx/fields/Date/dateTimePickerLoader.native.js +0 -42
  454. package/dist/jsx/fields/Date/dateTimePickerLoader.native.js.map +0 -1
  455. package/dist/jsx/fields/Date/sheetKeyboard.mjs +0 -21
  456. package/dist/jsx/fields/Date/sheetKeyboard.mjs.map +0 -1
  457. package/dist/jsx/fields/Date/sheetKeyboard.native.js +0 -57
  458. package/dist/jsx/fields/Date/sheetKeyboard.native.js.map +0 -1
  459. package/src/fields/Date/dateTimePickerLoader.ts +0 -25
  460. package/src/fields/Date/index.native.tsx +0 -445
  461. package/src/fields/Date/nativeFallback.spec.tsx +0 -21
  462. package/src/fields/Date/nativePresentation.spec.tsx +0 -278
  463. package/src/fields/Date/sheetKeyboard.spec.ts +0 -60
  464. package/src/fields/Date/sheetKeyboard.ts +0 -45
  465. package/types/fields/Date/dateTimePickerLoader.d.ts +0 -11
  466. package/types/fields/Date/dateTimePickerLoader.d.ts.map +0 -1
  467. package/types/fields/Date/index.native.d.ts +0 -14
  468. package/types/fields/Date/index.native.d.ts.map +0 -1
  469. package/types/fields/Date/sheetKeyboard.d.ts +0 -20
  470. package/types/fields/Date/sheetKeyboard.d.ts.map +0 -1
@@ -5,16 +5,12 @@
5
5
  * The web field used to render ONE date-only calendar whatever the type
6
6
  * (SB-M-617): a `Datetime` dropped its time component from the picker, and a
7
7
  * `Time` rendered EMPTY, because the calendar adopts its value through
8
- * `coerceToDate` and `new Date("09:00")` is an Invalid Date. Native, meanwhile,
9
- * had just been activated with all three implemented. These cases pin the
10
- * three web controls — display, edit, and the exact wire string — and then
11
- * drive the SAME pick through both platform halves and assert the emitted
12
- * strings are byte-identical, which is the only reason one `wire.ts` body is
13
- * worth sharing.
14
- *
15
- * The suite runs on web, so the native half's two native-only edges are mocked
16
- * exactly as `nativePresentation.spec.tsx` mocks them: the OS picker (recorded
17
- * rather than rendered) and the platform flags. The web half imports neither.
8
+ * `coerceToDate` and `new Date("09:00")` is an Invalid Date. These cases pin
9
+ * the three web controls — display, edit, and the exact wire string — and
10
+ * then assert the moment an OS sheet commits on native serializes to the same
11
+ * bytes. Native has no fork of this field (FZ-8000): the same catalog field
12
+ * runs there, forms' pickers commit a `Date` from `OsDateTimeSheet`, and the
13
+ * catalog writes it through the one `wire.ts` body.
18
14
  */
19
15
 
20
16
  import { describe, it, expect, vi, beforeAll, beforeEach } from "vitest";
@@ -23,38 +19,6 @@ import { describe, it, expect, vi, beforeAll, beforeEach } from "vitest";
23
19
  // import transforms the whole fields graph.
24
20
  vi.setConfig({ testTimeout: 240_000 });
25
21
 
26
- const mockState = vi.hoisted(() => ({
27
- isIos: true,
28
- isAndroid: false,
29
- /** Props of every mounted OS picker, newest last. */
30
- picks: [] as Record<string, unknown>[],
31
- }));
32
-
33
- vi.mock("./dateTimePickerLoader", () => ({
34
- loadDateTimePicker: () => (props: Record<string, unknown>) => {
35
- mockState.picks.push(props);
36
- return null;
37
- },
38
- }));
39
-
40
- vi.mock("@multiplatform.one/platform", async (importOriginal) => {
41
- const actual = (await importOriginal()) as Record<string, unknown>;
42
- const real = actual.platform as Record<string, unknown>;
43
- return {
44
- ...actual,
45
- platform: new Proxy(
46
- {},
47
- {
48
- get(_target, prop) {
49
- if (prop === "isIos") return mockState.isIos;
50
- if (prop === "isAndroid") return mockState.isAndroid;
51
- return real[prop as string];
52
- },
53
- },
54
- ),
55
- };
56
- });
57
-
58
22
  // Mock react-native-reanimated to prevent ESM module resolution failures
59
23
  // (same shim as tests/fieldRenderers.spec.tsx).
60
24
  vi.mock("react-native-reanimated", () => ({
@@ -95,9 +59,9 @@ vi.mock("react-native-reanimated", () => ({
95
59
  import { renderWithProviders } from "@multiplatform.one/test-utils";
96
60
  import { act, cleanup, fireEvent, waitFor } from "@testing-library/react";
97
61
  import React from "react";
62
+ import { toFrappeDateValue } from "./wire";
98
63
 
99
64
  const loadWebDateField = async () => (await import(".")).Date;
100
- const loadNativeDateField = async () => (await import("./index.native")).Date;
101
65
 
102
66
  /** Intl puts a narrow no-break space before the meridiem; no test should care. */
103
67
  const norm = (value: string) => value.replace(/\s+/gu, " ").trim();
@@ -155,10 +119,12 @@ async function pressText(root: ParentNode, text: string) {
155
119
  let target: Element | null = null;
156
120
  await waitFor(
157
121
  () => {
158
- const node = Array.from(root.querySelectorAll("*")).find(
159
- (el) => el.children.length === 0 && norm(el.textContent ?? "") === norm(text),
160
- );
161
- if (!node) throw new Error(`no element with text "${text}"`);
122
+ // LC-260: Next and Done are icon buttons, named by their label.
123
+ const node =
124
+ Array.from(root.querySelectorAll("*")).find(
125
+ (el) => el.children.length === 0 && norm(el.textContent ?? "") === norm(text),
126
+ ) ?? root.querySelector(`[aria-label="${text}"]`);
127
+ if (!node) throw new Error(`no element with text or label "${text}"`);
162
128
  target = node;
163
129
  },
164
130
  { timeout: 30_000 },
@@ -180,16 +146,13 @@ async function selectPeriod(period: "AM" | "PM") {
180
146
  // (110-155s quiet, past 240s under load), and charging it to an assertion made
181
147
  // whichever case ran first time out.
182
148
  beforeAll(async () => {
183
- await Promise.all([loadWebDateField(), loadNativeDateField()]);
149
+ await loadWebDateField();
184
150
  }, 900_000);
185
151
 
186
152
  beforeEach(() => {
187
153
  // Both halves portal their surfaces, so a previous case's chrome would
188
154
  // otherwise still be in the document when the next one queries it.
189
155
  cleanup();
190
- mockState.picks.length = 0;
191
- mockState.isIos = true;
192
- mockState.isAndroid = false;
193
156
  });
194
157
 
195
158
  // ---------------------------------------------------------------------------
@@ -356,41 +319,14 @@ describe("web Date field — type=datetime renders date AND time", () => {
356
319
  // Cross-half parity — the reason one `wire.ts` body is shared
357
320
  // ---------------------------------------------------------------------------
358
321
 
359
- /** Drive the native half through a pick and return the single emitted string. */
360
- async function nativePick(
361
- type: "date" | "datetime" | "time",
362
- value: string,
363
- triggerText: string,
364
- steps: Date[],
365
- ): Promise<string> {
366
- const DateField = await loadNativeDateField();
367
- const onChange = vi.fn();
368
- const result = renderWithProviders(
369
- <DateField label="Field" value={value} onChange={onChange} type={type} />,
370
- );
371
- await pressText(result.container, triggerText);
372
- await waitFor(() => expect(mockState.picks.length).toBeGreaterThan(0), { timeout: 30_000 });
373
-
374
- for (const [index, step] of steps.entries()) {
375
- const onPickerChange = mockState.picks[mockState.picks.length - 1].onChange as (
376
- event: unknown,
377
- date?: Date,
378
- ) => void;
379
- await act(async () => {
380
- onPickerChange({ type: "set" }, step);
381
- });
382
- // A datetime runs calendar → Next → wheel; the sheet's Next is the seam.
383
- if (index === 0 && steps.length > 1) {
384
- await pressText(document.body, "Next");
385
- await waitFor(() => expect(mockState.picks[mockState.picks.length - 1].mode).toBe("time"), {
386
- timeout: 30_000,
387
- });
388
- }
389
- }
390
- await pressText(document.body, "Done");
391
-
392
- expect(onChange).toHaveBeenCalledTimes(1);
393
- return onChange.mock.calls[0][0] as string;
322
+ /**
323
+ * What the catalog writes for the moment an OS sheet commits on native: forms'
324
+ * native `DatePicker` and `DatetimePicker` hand the field a `Date`, and its
325
+ * `TimePicker` an `HH:mm:ss` string, through the same `onChange` the web
326
+ * pickers use.
327
+ */
328
+ function nativeWrite(type: "date" | "datetime" | "time", committed: Date): string {
329
+ return toFrappeDateValue(committed, type);
394
330
  }
395
331
 
396
332
  /** Drive the web half through the equivalent pick and return the last string. */
@@ -419,9 +355,7 @@ describe("web and native persist byte-identical wire strings", () => {
419
355
  fireEvent.click(dayCell(15)!);
420
356
  });
421
357
  });
422
- cleanup();
423
- mockState.picks.length = 0;
424
- const native = await nativePick("date", "2026-03-05", "Mar 5, 2026", [new Date(2026, 2, 15)]);
358
+ const native = nativeWrite("date", new Date(2026, 2, 15));
425
359
 
426
360
  expect({ web, native }).toEqual({ web: "2026-03-15", native: "2026-03-15" });
427
361
  expect(web).toBe(native);
@@ -431,11 +365,7 @@ describe("web and native persist byte-identical wire strings", () => {
431
365
  const web = await webPick("time", "09:00:00", async () => {
432
366
  await selectPeriod("PM");
433
367
  });
434
- cleanup();
435
- mockState.picks.length = 0;
436
- const native = await nativePick("time", "09:00:00", "9:00 AM", [
437
- new Date(2026, 2, 5, 21, 0, 0),
438
- ]);
368
+ const native = nativeWrite("time", new Date(2026, 2, 5, 21, 0, 0));
439
369
 
440
370
  expect({ web, native }).toEqual({ web: "21:00:00", native: "21:00:00" });
441
371
  expect(web).toBe(native);
@@ -448,14 +378,8 @@ describe("web and native persist byte-identical wire strings", () => {
448
378
  fireEvent.click(dayCell(20)!);
449
379
  });
450
380
  });
451
- cleanup();
452
- mockState.picks.length = 0;
453
- // The native two-step: the calendar commits the day (dropping the clock,
454
- // which is why the wheel step re-supplies it), then the wheel commits it.
455
- const native = await nativePick("datetime", "2026-03-05 14:30:00", "Mar 5, 2026, 2:30 PM", [
456
- new Date(2026, 2, 20),
457
- new Date(2026, 0, 1, 14, 30),
458
- ]);
381
+ // The OS sheet's calendar-then-wheel commits one moment from both halves.
382
+ const native = nativeWrite("datetime", new Date(2026, 2, 20, 14, 30));
459
383
 
460
384
  expect({ web, native }).toEqual({
461
385
  web: "2026-03-20 14:30:00",
@@ -123,7 +123,7 @@ describe("FileUpload size gate", () => {
123
123
  * `aria-label` still fails. Recorded on MPO-123.
124
124
  */
125
125
  const buttonLabelled = (container: HTMLElement, prefix: string) =>
126
- Array.from(container.querySelectorAll("button")).find((b) =>
126
+ Array.from(container.querySelectorAll('button, [role="button"]')).find((b) =>
127
127
  (b.getAttribute("aria-label") ?? "").startsWith(prefix),
128
128
  );
129
129
 
@@ -226,8 +226,9 @@ describe("FileUpload transfer", () => {
226
226
  /^Retry \S/,
227
227
  );
228
228
  expect(remove?.getAttribute("aria-label")).toMatch(/^Remove \S/);
229
- // The visible text stays the short verb; the file name lives on the label.
230
- expect(buttonLabelled(result.container, "Retry ")?.textContent).toContain("Retry");
229
+ // LC-260: the button shows only its glyph; the name lives on the label.
230
+ expect(buttonLabelled(result.container, "Retry ")?.textContent).toBe("");
231
+ expect(buttonLabelled(result.container, "Retry ")?.querySelector("svg")).toBeTruthy();
231
232
 
232
233
  await act(async () => {
233
234
  fireEvent.click(buttonLabelled(result.container, "Retry ") as Element);
@@ -292,6 +293,20 @@ describe("FileUpload with a value", () => {
292
293
  expect(onChange).toHaveBeenCalledWith("");
293
294
  });
294
295
 
296
+ it("an image's Replace and Remove are glyphs on the media plate over it (LC-260, LC-176)", () => {
297
+ const result = renderWithProviders(
298
+ <FileUpload label="Photo" value="/files/sprite.png" isImage onChange={() => {}} />,
299
+ );
300
+ const actions = result.container.querySelector('[data-file-upload="preview-actions"]');
301
+ expect(actions).toBeTruthy();
302
+ const buttons = Array.from(actions!.querySelectorAll("[data-mp-action]"));
303
+ expect(buttons.map((b) => b.getAttribute("aria-label"))).toEqual(["Replace", "Remove"]);
304
+ for (const button of buttons) {
305
+ expect(button.getAttribute("data-mp-icon-button")).toBe("media");
306
+ expect(button.textContent).toBe("");
307
+ }
308
+ });
309
+
295
310
  it("readOnly hides Replace and Remove — the value is visible, not editable", () => {
296
311
  const result = renderWithProviders(
297
312
  <FileUpload label="Attachment" value="/files/report.pdf" readOnly onChange={() => {}} />,
@@ -1,13 +1,13 @@
1
1
  import { useFrappeCollection } from "@multiplatform.one/frappe";
2
2
  import { Skeleton } from "@multiplatform.one/forms";
3
- import { FileIcon, UploadIcon, XIcon } from "@phosphor-icons/react";
3
+ import { FileIcon, UploadIcon } from "@phosphor-icons/react";
4
4
  import { sizeRecipeForToken, useResolvedKnobs, sizeTokenStep } from "@multiplatform.one/theme";
5
5
  import type React from "react";
6
6
  import { useCallback, useEffect, useRef, useState } from "react";
7
7
  import { useTranslation } from "react-i18next";
8
8
  import { Button, Image, Label, Text as TamaguiText, XStack, YStack } from "tamagui";
9
9
  import { useFrappeConfig } from "../FrappeProvider";
10
- import { Text } from "@multiplatform.one/components";
10
+ import { Text, ActionButton } from "@multiplatform.one/components";
11
11
 
12
12
  export type FrappeFileUploadHandler = (
13
13
  file: File,
@@ -291,6 +291,28 @@ export function FileUpload({
291
291
  );
292
292
  }
293
293
 
294
+ // LC-260 ICONS-OVER-WORDS: Replace and Remove are their symbols, floating
295
+ // over an image on the LC-176 media plate.
296
+ const fileActions =
297
+ !readOnly && !transfer
298
+ ? (overMedia: boolean) => (
299
+ <>
300
+ <ActionButton
301
+ kind="replace"
302
+ overMedia={overMedia}
303
+ disabled={isLocked}
304
+ onPress={handleClick}
305
+ />
306
+ <ActionButton
307
+ kind="remove"
308
+ overMedia={overMedia}
309
+ disabled={isLocked}
310
+ onPress={handleRemove}
311
+ />
312
+ </>
313
+ )
314
+ : undefined;
315
+
294
316
  return (
295
317
  <YStack {...knobProps.gap}>
296
318
  {label && (
@@ -325,17 +347,12 @@ export function FileUpload({
325
347
  </Text>
326
348
  </YStack>
327
349
  {transfer.status === "uploading" ? (
328
- <Button
329
- size="$2"
330
- variant="outlined"
331
- icon={XIcon}
332
- aria-label={t("Cancel {{name}}", { name: transfer.file.name })}
350
+ <ActionButton
351
+ kind="cancel"
352
+ label={t("Cancel {{name}}", { name: transfer.file.name })}
333
353
  disabled={isLocked}
334
354
  onPress={handleCancel}
335
- {...knobProps.borderRadius}
336
- >
337
- {t("Cancel")}
338
- </Button>
355
+ />
339
356
  ) : null}
340
357
  </XStack>
341
358
  {transfer.status === "uploading" ? (
@@ -364,27 +381,18 @@ export function FileUpload({
364
381
  {transfer.action}
365
382
  </Text>
366
383
  <XStack {...knobProps.gap}>
367
- <Button
368
- size="$2"
369
- variant="outlined"
370
- aria-label={t("Retry {{name}}", { name: transfer.file.name })}
384
+ <ActionButton
385
+ kind="retry"
386
+ label={t("Retry {{name}}", { name: transfer.file.name })}
371
387
  disabled={isLocked}
372
388
  onPress={handleRetry}
373
- {...knobProps.borderRadius}
374
- >
375
- {t("Retry")}
376
- </Button>
377
- <Button
378
- size="$2"
379
- variant="outlined"
380
- icon={XIcon}
381
- aria-label={t("Remove {{name}}", { name: transfer.file.name })}
389
+ />
390
+ <ActionButton
391
+ kind="remove"
392
+ label={t("Remove {{name}}", { name: transfer.file.name })}
382
393
  disabled={isLocked}
383
394
  onPress={handleRemoveFailed}
384
- {...knobProps.borderRadius}
385
- >
386
- {t("Remove")}
387
- </Button>
395
+ />
388
396
  </XStack>
389
397
  </YStack>
390
398
  ) : null}
@@ -404,8 +412,8 @@ export function FileUpload({
404
412
  ) : null}
405
413
 
406
414
  {value ? (
407
- <YStack {...knobProps.gap}>
408
- {isImage ? (
415
+ isImage ? (
416
+ <YStack position="relative" alignSelf="flex-start">
409
417
  <Image
410
418
  // src (string), not source: the RN source object leaks onto the
411
419
  // DOM <img> as source="[object Object]" on web
@@ -416,45 +424,33 @@ export function FileUpload({
416
424
  {...knobProps.borderRadius}
417
425
  objectFit="cover"
418
426
  />
419
- ) : (
420
- <XStack
421
- gap="$2"
422
- alignItems="center"
423
- {...knobProps.panelPadding}
424
- {...{ backgroundColor: "$color2" }}
425
- >
426
- <FileIcon size={20} />
427
- <Text flex={1} numberOfLines={1}>
428
- {value.split("/").pop() || value}
429
- </Text>
430
- </XStack>
431
- )}
432
-
433
- {!readOnly && !transfer ? (
434
- <XStack {...knobProps.gap}>
435
- <Button
436
- size="$2"
437
- variant="outlined"
438
- icon={UploadIcon}
439
- disabled={isLocked}
440
- onPress={handleClick}
441
- {...knobProps.borderRadius}
427
+ {fileActions ? (
428
+ <XStack
429
+ data-file-upload="preview-actions"
430
+ position="absolute"
431
+ top="$2"
432
+ right="$2"
433
+ zIndex={1}
434
+ {...knobProps.gap}
442
435
  >
443
- {t("Replace")}
444
- </Button>
445
- <Button
446
- size="$2"
447
- variant="outlined"
448
- icon={XIcon}
449
- disabled={isLocked}
450
- onPress={handleRemove}
451
- {...knobProps.borderRadius}
452
- >
453
- {t("Remove")}
454
- </Button>
455
- </XStack>
456
- ) : null}
457
- </YStack>
436
+ {fileActions(true)}
437
+ </XStack>
438
+ ) : null}
439
+ </YStack>
440
+ ) : (
441
+ <XStack
442
+ gap="$2"
443
+ alignItems="center"
444
+ {...knobProps.panelPadding}
445
+ {...{ backgroundColor: "$color2" }}
446
+ >
447
+ <FileIcon size={20} />
448
+ <Text flex={1} numberOfLines={1}>
449
+ {value.split("/").pop() || value}
450
+ </Text>
451
+ {fileActions?.(false)}
452
+ </XStack>
453
+ )
458
454
  ) : null}
459
455
 
460
456
  {helperText && !error && !transfer ? (
@@ -84,13 +84,14 @@ describe("Frappe remainder wrappers — design-law 100%", () => {
84
84
  expect(stories).toMatch(/from ["']\.\/ChartCard["']/);
85
85
  });
86
86
 
87
- it("FrappeImageView uses catalog Card, controlIcon icons, and no media pip (R11/R12)", () => {
87
+ it("FrappeImageView is the MPO ImageGrid photos grid, controlIcon icons, and no media pip (R11/R12, LC-264)", () => {
88
88
  const source = read("FrappeImageView.tsx");
89
- expect(source).toContain("Card");
89
+ expect(source).toMatch(/ImageGrid[\s\S]*from "@multiplatform.one\/components"/);
90
+ expect(source).toContain('variant="photos"');
90
91
  expect(source).toContain("controlIcon");
91
92
  expect(source).not.toMatch(/size=\{48\}/);
92
93
  expect(source).not.toContain("<Tint");
93
- expect(source).toContain("No status pip");
94
+ expect(source).toMatch(/no pip/i);
94
95
  });
95
96
 
96
97
  it("FrappeTreeView uses label fragment and controlIcon, not 12/14px", () => {
@@ -156,10 +157,10 @@ describe("Frappe remainder wrappers — design-law 100%", () => {
156
157
  expect(list).toContain("formCommonColors.muted");
157
158
  });
158
159
 
159
- it("native Date trigger/actions are house Button", () => {
160
- const source = read("fields/Date/index.native.tsx");
161
- expect(source).toMatch(/Button[\s\S]*from "@multiplatform.one\/forms"/);
162
- expect(source).not.toMatch(/Button.*from "tamagui"/);
160
+ it("native Date is the catalog field on the forms pickers, not a fork (LC-175)", () => {
161
+ const source = read("fields/Date/catalog.tsx");
162
+ expect(source).toMatch(/DatePicker[\s\S]*from "@multiplatform.one\/forms"/);
163
+ expect(read("fields/Date/index.tsx")).toContain('export { Date } from "./catalog"');
163
164
  });
164
165
 
165
166
  it("fieldRegistry TextEditor fallback is Skeleton; SmallText/LongText use textAreaProps", () => {
@@ -1,97 +1,7 @@
1
- import { Tags, Text, XStack, isWeb } from "@multiplatform.one/components";
2
- import {
3
- ensureFocusVisibleRing,
4
- ensureKeyboardModalityTracking,
5
- keyboardFocusRingProps,
6
- useResolvedKnobs,
7
- wasKeyboardFocus,
8
- } from "@multiplatform.one/theme";
9
- import { useState } from "react";
1
+ import { Chip, Tags } from "@multiplatform.one/components";
10
2
  import { useTranslation } from "react-i18next";
11
3
  import type { InsightsCount } from "./insightsData";
12
4
 
13
- const chipFocusRing = ensureFocusVisibleRing(keyboardFocusRingProps);
14
-
15
- interface FacetTagChipProps {
16
- value: string;
17
- count: number;
18
- label: string;
19
- tint?: string;
20
- onPress: () => void;
21
- testID?: string;
22
- }
23
-
24
- /**
25
- * A pressable facet value painted from its tint's ramp (DF-04), at the
26
- * compact nestedControl height with the press target restored by hitSlop
27
- * (LC-54, LC-73); the keyboard ring rides the whole chip (LC-71).
28
- */
29
- function FacetTagChip({ value, count, label, tint = "gray", onPress, testID }: FacetTagChipProps) {
30
- const { t } = useTranslation();
31
- const { knobProps } = useResolvedKnobs();
32
- const nested = knobProps.nestedControl;
33
- const [kbFocus, setKbFocus] = useState(false);
34
- if (isWeb) ensureKeyboardModalityTracking();
35
- return (
36
- <XStack
37
- {...knobProps.borderRadius}
38
- role="button"
39
- tabIndex={0}
40
- aria-label={t("{{value}}, {{count}} records", { value: label, count })}
41
- cursor="pointer"
42
- alignItems="center"
43
- gap="$1.5"
44
- paddingHorizontal="$2"
45
- minHeight={nested.px}
46
- height={nested.px}
47
- hitSlop={nested.hitSlop}
48
- data-nested-px={nested.px}
49
- backgroundColor={`$${tint}3` as never}
50
- hoverStyle={{ backgroundColor: `$${tint}4` as never }}
51
- pressStyle={{ backgroundColor: `$${tint}5` as never }}
52
- outlineWidth={0}
53
- focusStyle={{ outlineWidth: 0 }}
54
- focusVisibleStyle={chipFocusRing}
55
- {...(isWeb
56
- ? {
57
- onFocus: () => {
58
- if (wasKeyboardFocus()) setKbFocus(true);
59
- },
60
- onBlur: () => setKbFocus(false),
61
- onKeyDown: (event: { key?: string; preventDefault?: () => void }) => {
62
- if (event.key === "Enter" || event.key === " ") {
63
- event.preventDefault?.();
64
- onPress();
65
- }
66
- },
67
- }
68
- : undefined)}
69
- {...(kbFocus ? keyboardFocusRingProps : undefined)}
70
- onPress={onPress}
71
- testID={testID ? `${testID}-${value}` : undefined}
72
- >
73
- <XStack
74
- width="$1"
75
- height="$1"
76
- borderRadius={1000}
77
- backgroundColor={`$${tint}9` as never}
78
- flexShrink={0}
79
- />
80
- <Text
81
- {...knobProps.label}
82
- color={`$${tint}11` as never}
83
- textTransform="capitalize"
84
- userSelect="none"
85
- >
86
- {label}
87
- </Text>
88
- <Text {...knobProps.label} color={`$${tint}11` as never} opacity={0.7} userSelect="none">
89
- {count}
90
- </Text>
91
- </XStack>
92
- );
93
- }
94
-
95
5
  export interface InsightsFacetTagsProps {
96
6
  distribution: readonly InsightsCount[];
97
7
  label: (value: string) => string;
@@ -100,7 +10,10 @@ export interface InsightsFacetTagsProps {
100
10
  testID?: string;
101
11
  }
102
12
 
103
- /** A facet's values with their record counts, each opening the list narrowed to it. */
13
+ /**
14
+ * A facet's values with their record counts as MPO `Chip`s painted from each
15
+ * value's ramp (DF-04, LC-175), each opening the list narrowed to it.
16
+ */
104
17
  export function InsightsFacetTags({
105
18
  distribution,
106
19
  label,
@@ -115,16 +28,22 @@ export function InsightsFacetTags({
115
28
  enableAdd={false}
116
29
  enableRemove={false}
117
30
  labels={{ noTags: t("No values yet") }}
118
- renderTag={(tag) => (
119
- <FacetTagChip
120
- value={tag.id}
121
- count={distribution.find((entry) => entry.value === tag.id)?.count ?? 0}
122
- label={tag.label}
123
- tint={tint?.(tag.id)}
124
- onPress={() => onSelect(tag.id)}
125
- testID={testID}
126
- />
127
- )}
31
+ renderTag={(tag) => {
32
+ const count = distribution.find((entry) => entry.value === tag.id)?.count ?? 0;
33
+ const hue = tint?.(tag.id) ?? "gray";
34
+ return (
35
+ <Chip
36
+ color={hue}
37
+ swatch={`$${hue}9` as never}
38
+ count={count}
39
+ aria-label={t("{{value}}, {{count}} records", { value: tag.label, count })}
40
+ onPress={() => onSelect(tag.id)}
41
+ testID={testID ? `${testID}-${tag.id}` : undefined}
42
+ >
43
+ {tag.label}
44
+ </Chip>
45
+ );
46
+ }}
128
47
  />
129
48
  );
130
49
  }
@@ -1,44 +1,22 @@
1
- import { Text, XStack } from "@multiplatform.one/components";
2
- import { hairlineWidth, sizeTokenStep, useResolvedKnobs } from "@multiplatform.one/theme";
1
+ import { Chip, type ChipSize } from "@multiplatform.one/components";
3
2
  import type { SizeTokens } from "tamagui";
4
- import { facetBadgeSteps } from "./facetBadgeSteps";
5
3
 
6
4
  export interface FacetBadgeProps {
7
5
  label: string;
8
6
  /** Theme ramp (`"green"`) painting the badge (LC-147). */
9
7
  tint?: string;
10
- /** Size token (Tamagui's own `size`); below `$true` the badge draws a step smaller. */
8
+ /** Size token (Tamagui's own `size`); omitted, the chip takes the ambient size. */
11
9
  size?: SizeTokens;
12
10
  }
13
11
 
14
12
  /**
15
- * One facet value as a static badge at the ambient size token, the tint's
16
- * step-4 fill, step-7 border and step-12 text (DF-04, AA in both schemes).
13
+ * One facet value as a static MPO `Chip` tinted from its ramp: the ramp's
14
+ * step-4 fill and step-12 ink, AA in both schemes (DF-04, LC-175).
17
15
  */
18
16
  export function FacetBadge({ label, tint = "gray", size }: FacetBadgeProps) {
19
- const { knobProps } = useResolvedKnobs({ size });
20
- const small = sizeTokenStep(knobProps.sizeToken) < 0;
21
17
  return (
22
- <XStack
23
- {...knobProps.borderRadius}
24
- paddingHorizontal={small ? "$1.5" : "$2"}
25
- paddingVertical={small ? "$0.5" : "$1"}
26
- backgroundColor={`$${tint}${facetBadgeSteps.fill}` as never}
27
- borderColor={`$${tint}${facetBadgeSteps.border}` as never}
28
- borderWidth={hairlineWidth}
29
- alignItems="center"
30
- >
31
- <Text
32
- {...knobProps.label}
33
- {...knobProps.body}
34
- textTransform="capitalize"
35
- fontWeight="700"
36
- color={`$${tint}${facetBadgeSteps.ink}` as never}
37
- {...(small ? { fontSize: "$1" as const } : null)}
38
- letterSpacing={0.3}
39
- >
40
- {label}
41
- </Text>
42
- </XStack>
18
+ <Chip color={tint} size={size as ChipSize | undefined}>
19
+ {label}
20
+ </Chip>
43
21
  );
44
22
  }