@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
@@ -65,12 +65,12 @@ function isModifiedPress(event?: PressLikeEvent): boolean {
65
65
  }
66
66
 
67
67
  /**
68
- * A record as a tile: the image well is the card (tinted by the record's
69
- * facet, its values stickered on it, its code stamped in the corner) with
70
- * the title and a muted subtitle under it. A routed card is a stretched
71
- * link with the heart as its sibling button (LC-74), so a first-paint click
72
- * on the heart never follows the link; modified clicks keep the browser's
73
- * new-tab semantics.
68
+ * A record as an MPO media `Card` (LC-175): the image well, tinted by the
69
+ * record's facet, is the card's full-bleed media, with the title, code,
70
+ * muted subtitle and facet chips in the body under it. A routed card is a
71
+ * stretched link in the card's overlay with the heart as its sibling button
72
+ * above it (LC-74), so a first-paint click on the heart never follows the
73
+ * link; modified clicks keep the browser's new-tab semantics.
74
74
  */
75
75
  export function RecordCard({
76
76
  title,
@@ -109,21 +109,80 @@ export function RecordCard({
109
109
  favorite?.toggle();
110
110
  };
111
111
 
112
- const passThrough = href ? "box-none" : undefined;
113
- const inert = href ? "none" : undefined;
112
+ const heart = favorite ? (
113
+ <XStack
114
+ position="absolute"
115
+ top="$1"
116
+ right="$1"
117
+ zIndex={2}
118
+ {...(isWeb
119
+ ? {
120
+ onClickCapture: (event: { preventDefault: () => void }) => {
121
+ event.preventDefault();
122
+ },
123
+ }
124
+ : undefined)}
125
+ >
126
+ <Button
127
+ plate="media"
128
+ selected={false}
129
+ onPress={handleToggleFavorite}
130
+ render="button"
131
+ type="button"
132
+ col={(favorite.active ? "$red9" : "$color11") as never}
133
+ icon={<HeartIcon size={20} weight={favorite.active ? "fill" : "regular"} />}
134
+ aria-label={
135
+ favorite.active
136
+ ? t("Remove {{name}} from favorites", { name: title })
137
+ : t("Add {{name}} to favorites", { name: title })
138
+ }
139
+ aria-pressed={favorite.active}
140
+ testID={favoriteTestID}
141
+ />
142
+ </XStack>
143
+ ) : null;
114
144
 
115
145
  return (
116
146
  <Card
117
147
  testID={testID}
118
- position="relative"
119
- {...knobProps.cardSurface}
120
- // Full-bleed media: the card has no inset of its own and its radius
121
- // clips the image well; the body below carries the inset.
122
- padding={0}
123
- gap={0}
124
- overflow="hidden"
125
- data-record-card-bleed=""
126
- elevation={knobProps.elevation}
148
+ media={
149
+ <YStack position="relative">
150
+ <ImageWell
151
+ sources={images}
152
+ alt={title}
153
+ tint={tint}
154
+ inset={0.04}
155
+ borderRadius={0}
156
+ lazy={lazy}
157
+ {...({ "data-record-card-media": "" } as Record<string, unknown>)}
158
+ />
159
+ {heart}
160
+ </YStack>
161
+ }
162
+ overlay={
163
+ href ? (
164
+ <Anchor
165
+ href={href as never}
166
+ position="absolute"
167
+ top={0}
168
+ left={0}
169
+ right={0}
170
+ bottom={0}
171
+ textDecorationLine="none"
172
+ outlineWidth={0}
173
+ aria-label={title}
174
+ onPress={handlePress}
175
+ {...(isWeb
176
+ ? {
177
+ onFocus: () => {
178
+ if (wasKeyboardFocus()) setAnchorKeyboardFocus(true);
179
+ },
180
+ onBlur: () => setAnchorKeyboardFocus(false),
181
+ }
182
+ : undefined)}
183
+ />
184
+ ) : undefined
185
+ }
127
186
  cursor="pointer"
128
187
  {...transitionProps(knobProps.motion.control, [
129
188
  "boxShadow",
@@ -146,119 +205,41 @@ export function RecordCard({
146
205
  focusVisibleStyle: focusRing,
147
206
  })}
148
207
  >
149
- {href ? (
150
- <Anchor
151
- href={href as never}
152
- position="absolute"
153
- top={0}
154
- left={0}
155
- right={0}
156
- bottom={0}
157
- zIndex={0}
158
- textDecorationLine="none"
159
- outlineWidth={0}
160
- aria-label={title}
161
- onPress={handlePress}
162
- {...(isWeb
163
- ? {
164
- onFocus: () => {
165
- if (wasKeyboardFocus()) setAnchorKeyboardFocus(true);
166
- },
167
- onBlur: () => setAnchorKeyboardFocus(false),
168
- }
169
- : undefined)}
170
- />
208
+ <XStack gap="$2" alignItems="baseline">
209
+ <Text
210
+ {...knobProps.heading}
211
+ fontWeight="700"
212
+ fontSize="$4"
213
+ numberOfLines={1}
214
+ color="$color12"
215
+ flexShrink={1}
216
+ >
217
+ {title}
218
+ </Text>
219
+ {code ? (
220
+ <Text
221
+ fontSize="$2"
222
+ fontWeight="700"
223
+ color="$color10"
224
+ flexShrink={0}
225
+ {...({ "data-record-card-code": "" } as Record<string, unknown>)}
226
+ >
227
+ {code}
228
+ </Text>
229
+ ) : null}
230
+ </XStack>
231
+ {subtitle ? (
232
+ <Text {...knobProps.body} fontSize="$2" color="$color10" numberOfLines={1}>
233
+ {subtitle}
234
+ </Text>
235
+ ) : null}
236
+ {badges.length > 0 ? (
237
+ <XStack gap="$1.5" flexWrap="wrap">
238
+ {badges.map((badge) => (
239
+ <FacetBadge key={badge.value} label={badge.label} tint={badge.tint} size="$3" />
240
+ ))}
241
+ </XStack>
171
242
  ) : null}
172
- <YStack gap={0} zIndex={1} pointerEvents={passThrough}>
173
- <YStack position="relative" pointerEvents={passThrough}>
174
- <ImageWell
175
- sources={images}
176
- alt={title}
177
- tint={tint}
178
- inset={0.04}
179
- borderRadius={0}
180
- lazy={lazy}
181
- pointerEvents={inert}
182
- {...({ "data-record-card-media": "" } as Record<string, unknown>)}
183
- />
184
- {favorite ? (
185
- <XStack
186
- position="absolute"
187
- top="$1"
188
- right="$1"
189
- zIndex={2}
190
- pointerEvents="auto"
191
- {...(isWeb
192
- ? {
193
- onClickCapture: (event: { preventDefault: () => void }) => {
194
- event.preventDefault();
195
- },
196
- }
197
- : undefined)}
198
- >
199
- <Button
200
- circular
201
- chromeless
202
- minWidth={knobProps.sizeToken}
203
- minHeight={knobProps.sizeToken}
204
- {...transitionProps(knobProps.motion.control)}
205
- backgroundColor="$background08"
206
- hoverStyle={{ backgroundColor: "$background", scale: 1.08 }}
207
- pressStyle={{ backgroundColor: "$background", scale: 0.92 }}
208
- onPress={handleToggleFavorite}
209
- render="button"
210
- type="button"
211
- col={(favorite.active ? "$red9" : "$color11") as never}
212
- icon={<HeartIcon size={20} weight={favorite.active ? "fill" : "regular"} />}
213
- aria-label={
214
- favorite.active
215
- ? t("Remove {{name}} from favorites", { name: title })
216
- : t("Add {{name}} to favorites", { name: title })
217
- }
218
- aria-pressed={favorite.active}
219
- testID={favoriteTestID}
220
- />
221
- </XStack>
222
- ) : null}
223
- </YStack>
224
- <YStack {...knobProps.panelPadding} gap="$1.5" pointerEvents={inert}>
225
- <XStack gap="$2" alignItems="baseline">
226
- <Text
227
- {...knobProps.heading}
228
- fontWeight="700"
229
- fontSize="$4"
230
- numberOfLines={1}
231
- color="$color12"
232
- flexShrink={1}
233
- >
234
- {title}
235
- </Text>
236
- {code ? (
237
- <Text
238
- fontSize="$2"
239
- fontWeight="700"
240
- color="$color10"
241
- flexShrink={0}
242
- {...({ "data-record-card-code": "" } as Record<string, unknown>)}
243
- >
244
- {code}
245
- </Text>
246
- ) : null}
247
- </XStack>
248
- {subtitle ? (
249
- <Text {...knobProps.body} fontSize="$2" color="$color10" numberOfLines={1}>
250
- {subtitle}
251
- </Text>
252
- ) : null}
253
- {badges.length > 0 ? (
254
- <XStack gap="$1.5" flexWrap="wrap">
255
- {badges.map((badge) => (
256
- <FacetBadge key={badge.value} label={badge.label} tint={badge.tint} size="$3" />
257
- ))}
258
- </XStack>
259
- ) : null}
260
- </YStack>
261
- </YStack>
262
243
  </Card>
263
244
  );
264
245
  }
@@ -1,6 +1,14 @@
1
- import { Button, Wheel, XStack, YStack } from "@multiplatform.one/components";
1
+ import {
2
+ Button,
3
+ Tooltip,
4
+ Wheel,
5
+ XStack,
6
+ YStack,
7
+ useImageGridGeometry,
8
+ type ImageGridProps,
9
+ } from "@multiplatform.one/components";
2
10
  import { useResolvedKnobs } from "@multiplatform.one/theme";
3
- import { ArrowCounterClockwiseIcon, ArrowRightIcon } from "@phosphor-icons/react";
11
+ import { ArrowRightIcon, ShuffleIcon } from "@phosphor-icons/react";
4
12
  import type React from "react";
5
13
  import { useMemo, useState } from "react";
6
14
  import { useTranslation } from "react-i18next";
@@ -16,11 +24,11 @@ export interface ShufflePanelProps<TDoc extends { name?: string }> {
16
24
  /** Draws the current pick beside the wheel. */
17
25
  renderPick: (doc: TDoc) => React.ReactNode;
18
26
  onGo: (doc: TDoc) => void;
27
+ /** The card grid below, so the pick takes exactly one of its tracks. */
28
+ grid?: Pick<ImageGridProps<unknown>, "columns" | "tileSize">;
19
29
  testID?: string;
20
30
  }
21
31
 
22
- const pickWidth = "$12";
23
-
24
32
  function randomOtherIndex(current: number, length: number): number {
25
33
  if (length < 2) return Math.max(0, current);
26
34
  const offset = 1 + Math.floor(Math.random() * (length - 1));
@@ -28,8 +36,10 @@ function randomOtherIndex(current: number, length: number): number {
28
36
  }
29
37
 
30
38
  /**
31
- * Pick a random record: a wheel of record labels beside the current pick.
32
- * Drag or flick the wheel, or Spin for a random jump, then Go opens it.
39
+ * Pick a random record: a wheel of record labels with Shuffle and Open as
40
+ * icon buttons (LC-260), beside the current pick drawn at the card grid's
41
+ * own tile width. The panel paints no card of its own, so the pick card never
42
+ * sits inside another (LC-169).
33
43
  */
34
44
  export function ShufflePanel<TDoc extends { name?: string }>({
35
45
  id,
@@ -38,10 +48,12 @@ export function ShufflePanel<TDoc extends { name?: string }>({
38
48
  itemLabel,
39
49
  renderPick,
40
50
  onGo,
51
+ grid,
41
52
  testID,
42
53
  }: ShufflePanelProps<TDoc>) {
43
54
  const { t } = useTranslation();
44
55
  const { knobProps } = useResolvedKnobs();
56
+ const { columns, gutter } = useImageGridGeometry(grid);
45
57
  const named = useMemo(() => rows.filter((row) => row.name), [rows]);
46
58
  const items = useMemo(
47
59
  () => named.map((row) => ({ value: row.name as string, label: itemLabel(row) })),
@@ -59,49 +71,62 @@ export function ShufflePanel<TDoc extends { name?: string }>({
59
71
  const current = named.findIndex((row) => row.name === pick.name);
60
72
  setSelected(named[randomOtherIndex(current, named.length)]?.name ?? "");
61
73
  };
74
+ const pickLabel = itemLabel(pick);
75
+ const tracks = Math.max(2, columns);
62
76
 
63
77
  return (
64
78
  <XStack
65
79
  id={id}
66
80
  role="region"
67
81
  aria-label={label}
68
- {...knobProps.surface}
69
- {...knobProps.borderRadius}
70
- {...knobProps.panelPadding}
71
- {...knobProps.gap}
82
+ gap={gutter}
72
83
  alignItems="center"
73
- flexWrap="wrap"
74
84
  testID={testID}
75
85
  >
76
- <Wheel
77
- items={items}
78
- value={pick.name as string}
79
- onChange={(next) => setSelected(String(next))}
80
- visibleItems={3}
81
- loop
82
- aria-label={label}
83
- />
84
- <YStack width={pickWidth} flexShrink={0}>
86
+ {/* The controls span every track but the pick's, with the gutters
87
+ between them, so the pick lands on one tile's exact width. */}
88
+ <YStack
89
+ flexGrow={tracks - 1}
90
+ flexShrink={1}
91
+ flexBasis={gutter * (tracks - 2)}
92
+ minWidth={0}
93
+ alignItems="center"
94
+ {...knobProps.gap}
95
+ >
96
+ <Wheel
97
+ items={items}
98
+ value={pick.name as string}
99
+ onChange={(next) => setSelected(String(next))}
100
+ visibleItems={3}
101
+ loop
102
+ aria-label={label}
103
+ />
104
+ <XStack alignItems="center" gap="$2">
105
+ <Tooltip content={t("Shuffle")}>
106
+ <Button
107
+ chromeless
108
+ accentInk
109
+ icon={ShuffleIcon}
110
+ aria-label={t("Shuffle")}
111
+ onPress={spin}
112
+ testID={testID ? `${testID}-spin` : undefined}
113
+ />
114
+ </Tooltip>
115
+ <Tooltip content={t("Open {{name}}", { name: pickLabel })}>
116
+ <Button
117
+ chromeless
118
+ accentInk
119
+ icon={ArrowRightIcon}
120
+ aria-label={t("Open {{name}}", { name: pickLabel })}
121
+ onPress={() => onGo(pick)}
122
+ testID={testID ? `${testID}-go` : undefined}
123
+ />
124
+ </Tooltip>
125
+ </XStack>
126
+ </YStack>
127
+ <YStack flexGrow={1} flexShrink={1} flexBasis={0} minWidth={0}>
85
128
  {renderPick(pick)}
86
129
  </YStack>
87
- <XStack {...knobProps.gap} alignItems="center" flexShrink={0}>
88
- <Button
89
- outlined
90
- onPress={spin}
91
- icon={<ArrowCounterClockwiseIcon size={16} />}
92
- testID={testID ? `${testID}-spin` : undefined}
93
- >
94
- {t("Spin")}
95
- </Button>
96
- <Button
97
- theme="accent"
98
- onPress={() => onGo(pick)}
99
- iconAfter={<ArrowRightIcon size={16} />}
100
- testID={testID ? `${testID}-go` : undefined}
101
- >
102
- {t("Go")}
103
- </Button>
104
- </XStack>
105
130
  </XStack>
106
131
  );
107
132
  }
@@ -259,13 +259,13 @@ function LikeControl({
259
259
  }
260
260
  return (
261
261
  <Button
262
- circular
263
262
  chromeless
264
263
  size="$2"
265
264
  col={(liked ? "$red10" : "$color8") as never}
266
265
  icon={<HeartIcon size={16} weight={liked ? "fill" : "regular"} />}
267
266
  aria-label={likeLabel}
268
267
  aria-pressed={liked}
268
+ selected={false}
269
269
  onPress={(event) => {
270
270
  stopRowPress(event);
271
271
  onToggleLike(name, !liked);
@@ -1,5 +1,5 @@
1
1
  import {
2
- Skeleton,
2
+ AsyncSkeleton,
3
3
  TamaguiSizableText,
4
4
  Text,
5
5
  XStack,
@@ -8,7 +8,6 @@ import {
8
8
  } from "@multiplatform.one/components";
9
9
  import { sizeRecipeEscape, useResolvedKnobs } from "@multiplatform.one/theme";
10
10
  import type { ReactNode } from "react";
11
- import { useTranslation } from "react-i18next";
12
11
 
13
12
  /**
14
13
  * The record hero's geometry, shared by the loaded hero and its skeleton so
@@ -92,56 +91,17 @@ export function RecordVitals({ tiles }: { tiles: readonly RecordVitalTile[] }) {
92
91
  );
93
92
  }
94
93
 
95
- const bone = (px: number) =>
96
- sizeRecipeEscape(px, "loading bones sized to the record page they stand in for");
97
-
98
- /** The hero and tab strip's loading twin, on the same geometry. */
94
+ /**
95
+ * The hero and tab strip's loading twin: the MPO detail skeleton on the
96
+ * record hero's own geometry, so the page does not jump when the record
97
+ * lands (LC-20, LC-175).
98
+ */
99
99
  export function RecordSkeleton({ testID }: { testID?: string }) {
100
- const { t } = useTranslation();
101
- const { knobProps } = useResolvedKnobs();
102
100
  return (
103
- <YStack testID={testID} data-async-skeleton="record" aria-busy aria-label={t("Loading")}>
104
- <RecordHeroFrame {...{ "data-skeleton-part": "art" }}>
105
- <YStack alignItems="center">
106
- <Skeleton
107
- variant="rounded"
108
- width={bone(recordHeroArtHeight)}
109
- height={bone(recordHeroArtHeight)}
110
- />
111
- </YStack>
112
- </RecordHeroFrame>
113
- <RecordHeroIdentityColumn {...{ "data-skeleton-part": "identity" }}>
114
- <XStack gap="$2">
115
- <Skeleton width={bone(40)} height={bone(20)} />
116
- <Skeleton variant="rounded" width={bone(56)} height={bone(22)} />
117
- <Skeleton variant="rounded" width={bone(56)} height={bone(22)} />
118
- </XStack>
119
- <Skeleton width={bone(220)} height={bone(40)} />
120
- <Skeleton width={bone(140)} height={bone(18)} />
121
- <XStack columnGap={knobProps.gapLg.gap} paddingTop={knobProps.gap.gap}>
122
- {[0, 1, 2].map((tile) => (
123
- <YStack key={tile} gap="$1">
124
- <Skeleton width={bone(56)} height={bone(14)} />
125
- <Skeleton width={bone(48)} height={bone(22)} />
126
- </YStack>
127
- ))}
128
- </XStack>
129
- </RecordHeroIdentityColumn>
130
- <YStack {...knobProps.gapLg} paddingTop={knobProps.panelPadding.padding}>
131
- <XStack
132
- {...knobProps.gapLg}
133
- {...knobProps.panelPadding}
134
- paddingVertical={0}
135
- {...{ "data-skeleton-part": "tabs" }}
136
- >
137
- {[96, 64, 88].map((width, tab) => (
138
- <Skeleton key={tab} width={bone(width)} height={bone(40)} />
139
- ))}
140
- </XStack>
141
- <YStack {...knobProps.panelPadding} paddingVertical={0}>
142
- <Skeleton.Text lines={4} />
143
- </YStack>
144
- </YStack>
145
- </YStack>
101
+ <AsyncSkeleton
102
+ layout="detail"
103
+ hero={{ height: recordHeroStageHeight, art: recordHeroArtHeight }}
104
+ testID={testID}
105
+ />
146
106
  );
147
107
  }
@@ -15,7 +15,11 @@ import {
15
15
  type DropdownMenuEntry,
16
16
  } from "@multiplatform.one/components";
17
17
  import { Button } from "@multiplatform.one/forms";
18
- import { formatAbsoluteDateTime, useResolvedKnobs } from "@multiplatform.one/theme";
18
+ import {
19
+ DETAIL_READABLE_WIDTH,
20
+ formatAbsoluteDateTime,
21
+ useResolvedKnobs,
22
+ } from "@multiplatform.one/theme";
19
23
  import { DotsThreeOutlineIcon, HeartIcon, PencilSimpleIcon } from "@phosphor-icons/react";
20
24
  import type { ComponentType, ReactNode } from "react";
21
25
  import { useTranslation } from "react-i18next";
@@ -297,12 +301,9 @@ export function RecordPage<TDoc extends { name: string; doctype: string }>({
297
301
  <>
298
302
  {favorites ? (
299
303
  <Button
300
- circular
301
- chromeless
302
- minWidth={knobProps.sizeToken}
303
- minHeight={knobProps.sizeToken}
304
+ selected={false}
304
305
  onPress={() => toggle(name)}
305
- col={(favorite ? "$red9" : "$color11") as never}
306
+ {...(favorite ? { col: "$red9" as never } : undefined)}
306
307
  icon={<HeartIcon size={24} weight={favorite ? "fill" : "regular"} />}
307
308
  aria-label={favoriteLabel}
308
309
  aria-pressed={favorite}
@@ -314,11 +315,6 @@ export function RecordPage<TDoc extends { name: string; doctype: string }>({
314
315
  {menu.length > 0 ? (
315
316
  <DropdownMenu items={menu} placement="bottom-end">
316
317
  <Button
317
- circular
318
- chromeless
319
- minWidth={knobProps.sizeToken}
320
- minHeight={knobProps.sizeToken}
321
- col={"$color" as never}
322
318
  icon={<DotsThreeOutlineIcon size={22} weight="fill" />}
323
319
  aria-label={t("More actions")}
324
320
  testID={`${slug}-detail-more`}
@@ -332,6 +328,7 @@ export function RecordPage<TDoc extends { name: string; doctype: string }>({
332
328
  <Screen
333
329
  noPadding
334
330
  gap={0}
331
+ maxWidth={DETAIL_READABLE_WIDTH}
335
332
  topBar={
336
333
  <RecordTopBar
337
334
  listName={listName}
@@ -11,8 +11,10 @@
11
11
  */
12
12
  import { renderWithProviders } from "@multiplatform.one/test-utils";
13
13
  import { fireEvent, waitFor } from "@testing-library/react";
14
+ import i18next from "i18next";
14
15
  import React from "react";
15
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
16
+ import { initReactI18next } from "react-i18next";
17
+ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
16
18
  import type { ReportColumnDef } from "./reportViewModel";
17
19
  import { ReportViewToolbar as ReportToolbar } from "./ReportViewToolbar";
18
20
 
@@ -32,7 +34,7 @@ const columns: ReportColumnDef[] = [
32
34
  },
33
35
  ];
34
36
 
35
- function renderToolbar() {
37
+ function renderToolbar(overrides: Partial<React.ComponentProps<typeof ReportToolbar>> = {}) {
36
38
  return renderWithProviders(
37
39
  <ReportToolbar
38
40
  columns={columns}
@@ -50,10 +52,19 @@ function renderToolbar() {
50
52
  onSaveReport={vi.fn()}
51
53
  onDeleteReport={vi.fn()}
52
54
  onExport={vi.fn()}
55
+ {...overrides}
53
56
  />,
54
57
  );
55
58
  }
56
59
 
60
+ beforeAll(async () => {
61
+ await i18next.use(initReactI18next).init({
62
+ lng: "en",
63
+ interpolation: { escapeValue: false },
64
+ resources: { en: { translation: {} } },
65
+ });
66
+ });
67
+
57
68
  let errorSpy: ReturnType<typeof vi.spyOn> | null = null;
58
69
  beforeEach(() => {
59
70
  // Strict local spy: the shared test setup filters known leak warnings
@@ -75,7 +86,7 @@ describe("ReportToolbar Save As popover (LC-46 DOM prop hygiene)", () => {
75
86
  it("opens the Save As popover without leaking non-DOM props", async () => {
76
87
  const result = renderToolbar();
77
88
 
78
- const saveAs = result.findTextElement("Save As…");
89
+ const saveAs = result.getButton("Save report");
79
90
  expect(saveAs).toBeDefined();
80
91
  fireEvent.click(saveAs as Element);
81
92
 
@@ -88,3 +99,34 @@ describe("ReportToolbar Save As popover (LC-46 DOM prop hygiene)", () => {
88
99
  expect(document.querySelector("[elevate]")).toBeNull();
89
100
  });
90
101
  });
102
+
103
+ describe("ReportToolbar actions are icons, delete is direct (LC-260, LC-261, LC-262)", () => {
104
+ it("names icon-only actions in their labels and counts columns without a dot join", () => {
105
+ const result = renderToolbar({ onClearColumnFilters: vi.fn(), columnFilterCount: 2 });
106
+ expect(result.getButton("Export CSV")?.textContent?.trim()).toBe("");
107
+ expect(result.getButton("Save report")?.textContent?.trim()).toBe("");
108
+ const columnsTrigger = result.getButton("Columns, 2 of 2");
109
+ expect(columnsTrigger?.textContent).toContain("2/2");
110
+ expect(document.body.textContent).not.toContain("·");
111
+ });
112
+
113
+ it("deletes the selected saved report from a trash button, after a confirm", async () => {
114
+ const onDeleteReport = vi.fn();
115
+ const result = renderToolbar({
116
+ savedReports: [{ name: "RPT-1", reportName: "Open moves" }],
117
+ currentReport: "RPT-1",
118
+ onDeleteReport,
119
+ });
120
+ fireEvent.click(result.getButton("Delete “Open moves”") as Element);
121
+ expect(onDeleteReport).not.toHaveBeenCalled();
122
+ const confirm = await waitFor(() => {
123
+ const button = Array.from(document.querySelectorAll('button, [role="button"]')).find(
124
+ (node) => node.textContent?.trim() === "Delete",
125
+ );
126
+ if (!button) throw new Error("no confirm");
127
+ return button;
128
+ });
129
+ fireEvent.click(confirm);
130
+ expect(onDeleteReport).toHaveBeenCalledWith("RPT-1");
131
+ });
132
+ });