@multiplatform.one/backoffice 7.22.0 → 7.23.1

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 (383) hide show
  1. package/dist/cjs/list/DoctypeListScreen.cjs +4 -42
  2. package/dist/cjs/list/DoctypeListScreen.native.js +5 -43
  3. package/dist/cjs/list/DoctypeListScreen.native.js.map +1 -1
  4. package/dist/cjs/list/filter-chips.cjs +3 -3
  5. package/dist/cjs/list/filter-chips.native.js +3 -3
  6. package/dist/cjs/list/filter-chips.native.js.map +1 -1
  7. package/dist/cjs/list/filter-editor.cjs +10 -11
  8. package/dist/cjs/list/filter-editor.native.js +10 -11
  9. package/dist/cjs/list/filter-editor.native.js.map +1 -1
  10. package/dist/cjs/list/filter-fields.cjs +15 -267
  11. package/dist/cjs/list/filter-fields.native.js +15 -337
  12. package/dist/cjs/list/filter-fields.native.js.map +1 -1
  13. package/dist/cjs/list/filter-standard.cjs +5 -6
  14. package/dist/cjs/list/filter-standard.native.js +5 -6
  15. package/dist/cjs/list/filter-standard.native.js.map +1 -1
  16. package/dist/cjs/list/list-tools-sheet.cjs +2 -2
  17. package/dist/cjs/list/list-tools-sheet.native.js +2 -2
  18. package/dist/cjs/list/list-tools-sheet.native.js.map +1 -1
  19. package/dist/cjs/list/listColumns.cjs +2 -371
  20. package/dist/cjs/list/listColumns.native.js +2 -418
  21. package/dist/cjs/list/listColumns.native.js.map +1 -1
  22. package/dist/cjs/list/listFields.cjs +4 -24
  23. package/dist/cjs/list/listFields.native.js +4 -50
  24. package/dist/cjs/list/listFields.native.js.map +1 -1
  25. package/dist/cjs/list/listFormat.cjs +7 -42
  26. package/dist/cjs/list/listFormat.native.js +7 -45
  27. package/dist/cjs/list/listFormat.native.js.map +1 -1
  28. package/dist/cjs/list/statusColors.cjs +2 -76
  29. package/dist/cjs/list/statusColors.native.js +2 -80
  30. package/dist/cjs/list/statusColors.native.js.map +1 -1
  31. package/dist/cjs/report/queryReportColumns.cjs +2 -2
  32. package/dist/cjs/report/queryReportColumns.native.js +2 -2
  33. package/dist/cjs/report/queryReportColumns.native.js.map +1 -1
  34. package/dist/cjs/report/queryReportFilterBar.cjs +5 -6
  35. package/dist/cjs/report/queryReportFilterBar.native.js +5 -6
  36. package/dist/cjs/report/queryReportFilterBar.native.js.map +1 -1
  37. package/dist/cjs/report/report-grid.cjs +2 -2
  38. package/dist/cjs/report/report-grid.native.js +2 -2
  39. package/dist/cjs/report/report-grid.native.js.map +1 -1
  40. package/dist/cjs/report/report-toolbar.cjs +2 -2
  41. package/dist/cjs/report/report-toolbar.native.js +2 -2
  42. package/dist/cjs/report/report-toolbar.native.js.map +1 -1
  43. package/dist/cjs/report/reportViewModel.cjs +3 -3
  44. package/dist/cjs/report/reportViewModel.native.js +3 -3
  45. package/dist/cjs/report/reportViewModel.native.js.map +1 -1
  46. package/dist/esm/list/DoctypeListScreen.mjs +3 -41
  47. package/dist/esm/list/DoctypeListScreen.mjs.map +1 -1
  48. package/dist/esm/list/DoctypeListScreen.native.js +4 -42
  49. package/dist/esm/list/DoctypeListScreen.native.js.map +1 -1
  50. package/dist/esm/list/filter-chips.mjs +1 -1
  51. package/dist/esm/list/filter-chips.native.js +1 -1
  52. package/dist/esm/list/filter-chips.native.js.map +1 -1
  53. package/dist/esm/list/filter-editor.mjs +1 -2
  54. package/dist/esm/list/filter-editor.mjs.map +1 -1
  55. package/dist/esm/list/filter-editor.native.js +1 -2
  56. package/dist/esm/list/filter-editor.native.js.map +1 -1
  57. package/dist/esm/list/filter-fields.mjs +1 -253
  58. package/dist/esm/list/filter-fields.mjs.map +1 -1
  59. package/dist/esm/list/filter-fields.native.js +1 -323
  60. package/dist/esm/list/filter-fields.native.js.map +1 -1
  61. package/dist/esm/list/filter-standard.mjs +1 -2
  62. package/dist/esm/list/filter-standard.mjs.map +1 -1
  63. package/dist/esm/list/filter-standard.native.js +1 -2
  64. package/dist/esm/list/filter-standard.native.js.map +1 -1
  65. package/dist/esm/list/list-tools-sheet.mjs +1 -1
  66. package/dist/esm/list/list-tools-sheet.native.js +1 -1
  67. package/dist/esm/list/list-tools-sheet.native.js.map +1 -1
  68. package/dist/esm/list/listColumns.mjs +1 -370
  69. package/dist/esm/list/listColumns.mjs.map +1 -1
  70. package/dist/esm/list/listColumns.native.js +1 -417
  71. package/dist/esm/list/listColumns.native.js.map +1 -1
  72. package/dist/esm/list/listFields.mjs +1 -21
  73. package/dist/esm/list/listFields.mjs.map +1 -1
  74. package/dist/esm/list/listFields.native.js +1 -47
  75. package/dist/esm/list/listFields.native.js.map +1 -1
  76. package/dist/esm/list/listFormat.mjs +1 -36
  77. package/dist/esm/list/listFormat.mjs.map +1 -1
  78. package/dist/esm/list/listFormat.native.js +1 -39
  79. package/dist/esm/list/listFormat.native.js.map +1 -1
  80. package/dist/esm/list/statusColors.mjs +1 -75
  81. package/dist/esm/list/statusColors.mjs.map +1 -1
  82. package/dist/esm/list/statusColors.native.js +1 -79
  83. package/dist/esm/list/statusColors.native.js.map +1 -1
  84. package/dist/esm/report/queryReportColumns.mjs +1 -1
  85. package/dist/esm/report/queryReportColumns.native.js +1 -1
  86. package/dist/esm/report/queryReportColumns.native.js.map +1 -1
  87. package/dist/esm/report/queryReportFilterBar.mjs +1 -2
  88. package/dist/esm/report/queryReportFilterBar.mjs.map +1 -1
  89. package/dist/esm/report/queryReportFilterBar.native.js +1 -2
  90. package/dist/esm/report/queryReportFilterBar.native.js.map +1 -1
  91. package/dist/esm/report/report-grid.mjs +1 -1
  92. package/dist/esm/report/report-grid.native.js +1 -1
  93. package/dist/esm/report/report-grid.native.js.map +1 -1
  94. package/dist/esm/report/report-toolbar.mjs +1 -1
  95. package/dist/esm/report/report-toolbar.native.js +1 -1
  96. package/dist/esm/report/report-toolbar.native.js.map +1 -1
  97. package/dist/esm/report/reportViewModel.mjs +1 -1
  98. package/dist/esm/report/reportViewModel.mjs.map +1 -1
  99. package/dist/esm/report/reportViewModel.native.js +1 -1
  100. package/dist/esm/report/reportViewModel.native.js.map +1 -1
  101. package/dist/jsx/chrome/BackofficeAwesomebar.native.js +1 -1
  102. package/dist/jsx/chrome/BackofficeAwesomebar.native.js.map +1 -1
  103. package/dist/jsx/chrome/CommandPalette.native.js +1 -1
  104. package/dist/jsx/chrome/CommandPalette.native.js.map +1 -1
  105. package/dist/jsx/chrome/HelpMenu.native.js +1 -1
  106. package/dist/jsx/chrome/HelpMenu.native.js.map +1 -1
  107. package/dist/jsx/chrome/NotificationsButton.native.js +1 -1
  108. package/dist/jsx/chrome/NotificationsButton.native.js.map +1 -1
  109. package/dist/jsx/chrome/UserMenu.native.js +1 -1
  110. package/dist/jsx/chrome/UserMenu.native.js.map +1 -1
  111. package/dist/jsx/chrome/awesomebar-data.native.js.map +1 -1
  112. package/dist/jsx/chrome/command-palette-model.native.js +1 -1
  113. package/dist/jsx/chrome/command-palette-model.native.js.map +1 -1
  114. package/dist/jsx/chrome/help-about-dialog.native.js +1 -1
  115. package/dist/jsx/chrome/help-about-dialog.native.js.map +1 -1
  116. package/dist/jsx/chrome/help-shortcuts-dialog.native.js +1 -1
  117. package/dist/jsx/chrome/help-shortcuts-dialog.native.js.map +1 -1
  118. package/dist/jsx/chrome/notifications-data.native.js.map +1 -1
  119. package/dist/jsx/chrome/notifications-panel.native.js +1 -1
  120. package/dist/jsx/chrome/notifications-panel.native.js.map +1 -1
  121. package/dist/jsx/chrome/notifications-utils.native.js.map +1 -1
  122. package/dist/jsx/chrome/shortcuts.native.js.map +1 -1
  123. package/dist/jsx/chrome/user-session.native.js.map +1 -1
  124. package/dist/jsx/config/BackofficeProvider.native.js +1 -1
  125. package/dist/jsx/config/BackofficeProvider.native.js.map +1 -1
  126. package/dist/jsx/config/capabilities.native.js.map +1 -1
  127. package/dist/jsx/config/events.native.js.map +1 -1
  128. package/dist/jsx/config/slots.native.js.map +1 -1
  129. package/dist/jsx/desk/Desk.native.js.map +1 -1
  130. package/dist/jsx/desk/DeskSurface.native.js.map +1 -1
  131. package/dist/jsx/desk/resolveDeskPath.native.js.map +1 -1
  132. package/dist/jsx/desk/scope.native.js.map +1 -1
  133. package/dist/jsx/desk/target.native.js.map +1 -1
  134. package/dist/jsx/form/DocFormScreen.native.js +1 -1
  135. package/dist/jsx/form/DocFormScreen.native.js.map +1 -1
  136. package/dist/jsx/form/FormConnections.native.js +1 -1
  137. package/dist/jsx/form/FormConnections.native.js.map +1 -1
  138. package/dist/jsx/form/FormDialogs.native.js +1 -1
  139. package/dist/jsx/form/FormDialogs.native.js.map +1 -1
  140. package/dist/jsx/form/FormErrorBoundary.native.js +1 -1
  141. package/dist/jsx/form/FormErrorBoundary.native.js.map +1 -1
  142. package/dist/jsx/form/FormHeaderCluster.native.js +1 -1
  143. package/dist/jsx/form/FormHeaderCluster.native.js.map +1 -1
  144. package/dist/jsx/form/FormSidebarPanel.native.js +1 -1
  145. package/dist/jsx/form/FormSidebarPanel.native.js.map +1 -1
  146. package/dist/jsx/form/FormTimeline.native.js +1 -1
  147. package/dist/jsx/form/FormTimeline.native.js.map +1 -1
  148. package/dist/jsx/form/FormToolbar.native.js +1 -1
  149. package/dist/jsx/form/FormToolbar.native.js.map +1 -1
  150. package/dist/jsx/form/connections-data.native.js.map +1 -1
  151. package/dist/jsx/form/createPrefill.native.js.map +1 -1
  152. package/dist/jsx/form/dependsOn.native.js.map +1 -1
  153. package/dist/jsx/form/dirtyTracking.native.js.map +1 -1
  154. package/dist/jsx/form/docinfo.native.js.map +1 -1
  155. package/dist/jsx/form/fetchFrom.native.js.map +1 -1
  156. package/dist/jsx/form/fieldPermissions.native.js.map +1 -1
  157. package/dist/jsx/form/formActions.native.js.map +1 -1
  158. package/dist/jsx/form/formLayout.native.js.map +1 -1
  159. package/dist/jsx/form/platformHooks.native.js.map +1 -1
  160. package/dist/jsx/form/sidebar-attachments.native.js +1 -1
  161. package/dist/jsx/form/sidebar-attachments.native.js.map +1 -1
  162. package/dist/jsx/form/sidebar-dialogs.native.js +1 -1
  163. package/dist/jsx/form/sidebar-dialogs.native.js.map +1 -1
  164. package/dist/jsx/form/sidebar-people.native.js +1 -1
  165. package/dist/jsx/form/sidebar-people.native.js.map +1 -1
  166. package/dist/jsx/form/sidebar-rpc.native.js.map +1 -1
  167. package/dist/jsx/form/sidebar-utils.native.js.map +1 -1
  168. package/dist/jsx/form/timeline-entries.native.js.map +1 -1
  169. package/dist/jsx/form/timeline-utils.native.js.map +1 -1
  170. package/dist/jsx/form/useFormEngine.native.js.map +1 -1
  171. package/dist/jsx/i18n/en.native.js.map +1 -1
  172. package/dist/jsx/i18n/index.native.js.map +1 -1
  173. package/dist/jsx/index.native.js +1 -1
  174. package/dist/jsx/index.native.js.map +1 -1
  175. package/dist/jsx/list/AddTagsDialog.native.js +1 -1
  176. package/dist/jsx/list/AddTagsDialog.native.js.map +1 -1
  177. package/dist/jsx/list/AssignToDialog.native.js +1 -1
  178. package/dist/jsx/list/AssignToDialog.native.js.map +1 -1
  179. package/dist/jsx/list/DoctypeListScreen.mjs +3 -41
  180. package/dist/jsx/list/DoctypeListScreen.mjs.map +1 -1
  181. package/dist/jsx/list/DoctypeListScreen.native.js +6 -44
  182. package/dist/jsx/list/DoctypeListScreen.native.js.map +1 -1
  183. package/dist/jsx/list/ListBulkActionsBar.native.js +1 -1
  184. package/dist/jsx/list/ListBulkActionsBar.native.js.map +1 -1
  185. package/dist/jsx/list/ListFilterBar.native.js +1 -1
  186. package/dist/jsx/list/ListFilterBar.native.js.map +1 -1
  187. package/dist/jsx/list/ListSidebar.native.js +1 -1
  188. package/dist/jsx/list/ListSidebar.native.js.map +1 -1
  189. package/dist/jsx/list/bulk-edit-dialog.native.js +1 -1
  190. package/dist/jsx/list/bulk-edit-dialog.native.js.map +1 -1
  191. package/dist/jsx/list/bulk-export.native.js.map +1 -1
  192. package/dist/jsx/list/bulk-submit-cancel.native.js.map +1 -1
  193. package/dist/jsx/list/bulkActions.native.js.map +1 -1
  194. package/dist/jsx/list/filter-chips.mjs +1 -1
  195. package/dist/jsx/list/filter-chips.native.js +4 -4
  196. package/dist/jsx/list/filter-chips.native.js.map +1 -1
  197. package/dist/jsx/list/filter-editor.mjs +1 -2
  198. package/dist/jsx/list/filter-editor.mjs.map +1 -1
  199. package/dist/jsx/list/filter-editor.native.js +11 -12
  200. package/dist/jsx/list/filter-editor.native.js.map +1 -1
  201. package/dist/jsx/list/filter-fields.mjs +1 -253
  202. package/dist/jsx/list/filter-fields.mjs.map +1 -1
  203. package/dist/jsx/list/filter-fields.native.js +15 -337
  204. package/dist/jsx/list/filter-fields.native.js.map +1 -1
  205. package/dist/jsx/list/filter-saved.native.js +1 -1
  206. package/dist/jsx/list/filter-saved.native.js.map +1 -1
  207. package/dist/jsx/list/filter-sort.native.js +1 -1
  208. package/dist/jsx/list/filter-sort.native.js.map +1 -1
  209. package/dist/jsx/list/filter-standard.mjs +1 -2
  210. package/dist/jsx/list/filter-standard.mjs.map +1 -1
  211. package/dist/jsx/list/filter-standard.native.js +5 -6
  212. package/dist/jsx/list/filter-standard.native.js.map +1 -1
  213. package/dist/jsx/list/filterConversion.native.js.map +1 -1
  214. package/dist/jsx/list/list-tools-sheet.mjs +1 -1
  215. package/dist/jsx/list/list-tools-sheet.native.js +3 -3
  216. package/dist/jsx/list/list-tools-sheet.native.js.map +1 -1
  217. package/dist/jsx/list/listColumns.mjs +1 -370
  218. package/dist/jsx/list/listColumns.mjs.map +1 -1
  219. package/dist/jsx/list/listColumns.native.js +2 -418
  220. package/dist/jsx/list/listColumns.native.js.map +1 -1
  221. package/dist/jsx/list/listFields.mjs +1 -21
  222. package/dist/jsx/list/listFields.mjs.map +1 -1
  223. package/dist/jsx/list/listFields.native.js +4 -50
  224. package/dist/jsx/list/listFields.native.js.map +1 -1
  225. package/dist/jsx/list/listFormat.mjs +1 -36
  226. package/dist/jsx/list/listFormat.mjs.map +1 -1
  227. package/dist/jsx/list/listFormat.native.js +7 -45
  228. package/dist/jsx/list/listFormat.native.js.map +1 -1
  229. package/dist/jsx/list/listUrlState.native.js.map +1 -1
  230. package/dist/jsx/list/sidebar-section.native.js +1 -1
  231. package/dist/jsx/list/sidebar-section.native.js.map +1 -1
  232. package/dist/jsx/list/sidebar-stats.native.js.map +1 -1
  233. package/dist/jsx/list/statusColors.mjs +1 -75
  234. package/dist/jsx/list/statusColors.mjs.map +1 -1
  235. package/dist/jsx/list/statusColors.native.js +2 -80
  236. package/dist/jsx/list/statusColors.native.js.map +1 -1
  237. package/dist/jsx/navigation/navigator.native.js.map +1 -1
  238. package/dist/jsx/navigation/paths.native.js.map +1 -1
  239. package/dist/jsx/oneAdapter/index.native.js.map +1 -1
  240. package/dist/jsx/quickEntry/QuickEntryDialog.native.js +1 -1
  241. package/dist/jsx/quickEntry/QuickEntryDialog.native.js.map +1 -1
  242. package/dist/jsx/quickEntry/quickEntryPlan.native.js.map +1 -1
  243. package/dist/jsx/report/DoctypeReportView.native.js +1 -1
  244. package/dist/jsx/report/DoctypeReportView.native.js.map +1 -1
  245. package/dist/jsx/report/QueryReportScreen.native.js +1 -1
  246. package/dist/jsx/report/QueryReportScreen.native.js.map +1 -1
  247. package/dist/jsx/report/queryReportColumns.mjs +1 -1
  248. package/dist/jsx/report/queryReportColumns.native.js +2 -2
  249. package/dist/jsx/report/queryReportColumns.native.js.map +1 -1
  250. package/dist/jsx/report/queryReportFilterBar.mjs +1 -2
  251. package/dist/jsx/report/queryReportFilterBar.mjs.map +1 -1
  252. package/dist/jsx/report/queryReportFilterBar.native.js +6 -7
  253. package/dist/jsx/report/queryReportFilterBar.native.js.map +1 -1
  254. package/dist/jsx/report/queryReportUrlState.native.js.map +1 -1
  255. package/dist/jsx/report/report-grid.mjs +1 -1
  256. package/dist/jsx/report/report-grid.native.js +3 -3
  257. package/dist/jsx/report/report-grid.native.js.map +1 -1
  258. package/dist/jsx/report/report-toolbar.mjs +1 -1
  259. package/dist/jsx/report/report-toolbar.native.js +3 -3
  260. package/dist/jsx/report/report-toolbar.native.js.map +1 -1
  261. package/dist/jsx/report/reportShapes.native.js.map +1 -1
  262. package/dist/jsx/report/reportViewModel.mjs +1 -1
  263. package/dist/jsx/report/reportViewModel.mjs.map +1 -1
  264. package/dist/jsx/report/reportViewModel.native.js +3 -3
  265. package/dist/jsx/report/reportViewModel.native.js.map +1 -1
  266. package/dist/jsx/report/savedReports.native.js.map +1 -1
  267. package/dist/jsx/report/useQueryReport.native.js.map +1 -1
  268. package/dist/jsx/shared/deskLinks.native.js.map +1 -1
  269. package/dist/jsx/shared/listNavContext.native.js.map +1 -1
  270. package/dist/jsx/shared/types.native.js.map +1 -1
  271. package/dist/jsx/shared/useDocinfo.native.js.map +1 -1
  272. package/dist/jsx/shared/useDoctypeMeta.native.js.map +1 -1
  273. package/dist/jsx/shared/useFrappeApp.native.js.map +1 -1
  274. package/dist/jsx/shared/useRecentVisit.native.js.map +1 -1
  275. package/dist/jsx/shared/useSessionUserId.native.js.map +1 -1
  276. package/dist/jsx/shared/useSlugTarget.native.js.map +1 -1
  277. package/dist/jsx/shared/useUserRoles.native.js.map +1 -1
  278. package/dist/jsx/shell/BackofficeShell.native.js +1 -1
  279. package/dist/jsx/shell/BackofficeShell.native.js.map +1 -1
  280. package/dist/jsx/shell/HomeRedirect.native.js +1 -1
  281. package/dist/jsx/shell/HomeRedirect.native.js.map +1 -1
  282. package/dist/jsx/shell/NotFoundScreen.native.js +1 -1
  283. package/dist/jsx/shell/NotFoundScreen.native.js.map +1 -1
  284. package/dist/jsx/shell/SlugScreen.native.js +1 -1
  285. package/dist/jsx/shell/SlugScreen.native.js.map +1 -1
  286. package/dist/jsx/shell/WorkspaceSidebar.native.js +1 -1
  287. package/dist/jsx/shell/WorkspaceSidebar.native.js.map +1 -1
  288. package/dist/jsx/shell/useWorkspaces.native.js.map +1 -1
  289. package/dist/jsx/shell/workspaceIcons.native.js.map +1 -1
  290. package/dist/jsx/views/CalendarView.native.js +1 -1
  291. package/dist/jsx/views/CalendarView.native.js.map +1 -1
  292. package/dist/jsx/views/DashboardView.native.js +1 -1
  293. package/dist/jsx/views/DashboardView.native.js.map +1 -1
  294. package/dist/jsx/views/DoctypeViewScreen.native.js.map +1 -1
  295. package/dist/jsx/views/ImageView.native.js +1 -1
  296. package/dist/jsx/views/ImageView.native.js.map +1 -1
  297. package/dist/jsx/views/KanbanView.native.js +1 -1
  298. package/dist/jsx/views/KanbanView.native.js.map +1 -1
  299. package/dist/jsx/views/ReportView.native.js +1 -1
  300. package/dist/jsx/views/ReportView.native.js.map +1 -1
  301. package/dist/jsx/views/TreeView.native.js +1 -1
  302. package/dist/jsx/views/TreeView.native.js.map +1 -1
  303. package/dist/jsx/views/ViewHeader.native.js +1 -1
  304. package/dist/jsx/views/ViewHeader.native.js.map +1 -1
  305. package/dist/jsx/views/ViewStates.native.js +1 -1
  306. package/dist/jsx/views/ViewStates.native.js.map +1 -1
  307. package/dist/jsx/views/ViewSwitcherMenu.native.js +1 -1
  308. package/dist/jsx/views/ViewSwitcherMenu.native.js.map +1 -1
  309. package/dist/jsx/views/calendar-field-selector.native.js +1 -1
  310. package/dist/jsx/views/calendar-field-selector.native.js.map +1 -1
  311. package/dist/jsx/views/connection.native.js.map +1 -1
  312. package/dist/jsx/views/dashboard-data.native.js.map +1 -1
  313. package/dist/jsx/views/deskViewConfigs.native.js.map +1 -1
  314. package/dist/jsx/views/kanban-board-controls.native.js +1 -1
  315. package/dist/jsx/views/kanban-board-controls.native.js.map +1 -1
  316. package/dist/jsx/views/kanban-field-picker.native.js +1 -1
  317. package/dist/jsx/views/kanban-field-picker.native.js.map +1 -1
  318. package/dist/jsx/views/kanbanBoardOps.native.js.map +1 -1
  319. package/dist/jsx/views/report-controls.native.js +1 -1
  320. package/dist/jsx/views/report-controls.native.js.map +1 -1
  321. package/dist/jsx/views/viewAvailability.native.js.map +1 -1
  322. package/dist/jsx/views/viewMeta.native.js.map +1 -1
  323. package/dist/jsx/workspace/WorkspaceChartBlock.native.js +1 -1
  324. package/dist/jsx/workspace/WorkspaceChartBlock.native.js.map +1 -1
  325. package/dist/jsx/workspace/WorkspaceGrid.native.js.map +1 -1
  326. package/dist/jsx/workspace/WorkspaceLinkCard.native.js +1 -1
  327. package/dist/jsx/workspace/WorkspaceLinkCard.native.js.map +1 -1
  328. package/dist/jsx/workspace/WorkspaceLinkDirectory.native.js +1 -1
  329. package/dist/jsx/workspace/WorkspaceLinkDirectory.native.js.map +1 -1
  330. package/dist/jsx/workspace/WorkspaceNumberCard.native.js +1 -1
  331. package/dist/jsx/workspace/WorkspaceNumberCard.native.js.map +1 -1
  332. package/dist/jsx/workspace/WorkspaceQuickList.native.js +1 -1
  333. package/dist/jsx/workspace/WorkspaceQuickList.native.js.map +1 -1
  334. package/dist/jsx/workspace/WorkspaceRecents.native.js +1 -1
  335. package/dist/jsx/workspace/WorkspaceRecents.native.js.map +1 -1
  336. package/dist/jsx/workspace/WorkspaceScreen.native.js +1 -1
  337. package/dist/jsx/workspace/WorkspaceScreen.native.js.map +1 -1
  338. package/dist/jsx/workspace/WorkspaceShortcut.native.js +1 -1
  339. package/dist/jsx/workspace/WorkspaceShortcut.native.js.map +1 -1
  340. package/dist/jsx/workspace/parseContent.native.js.map +1 -1
  341. package/dist/jsx/workspace/types.native.js.map +1 -1
  342. package/dist/jsx/workspace/useDashboardChart.native.js.map +1 -1
  343. package/dist/jsx/workspace/useWorkspaceDoc.native.js.map +1 -1
  344. package/package.json +12 -12
  345. package/src/backofficeScreens.designLaw.spec.ts +1 -3
  346. package/src/list/DoctypeListScreen.auth.spec.tsx +84 -0
  347. package/src/list/DoctypeListScreen.tsx +18 -51
  348. package/src/list/filter-chips.tsx +1 -1
  349. package/src/list/filter-editor.tsx +2 -2
  350. package/src/list/filter-fields.tsx +29 -356
  351. package/src/list/filter-standard.tsx +2 -2
  352. package/src/list/list-tools-sheet.tsx +1 -1
  353. package/src/list/listColumns.tsx +11 -488
  354. package/src/list/listFields.ts +9 -66
  355. package/src/list/listFormat.ts +12 -77
  356. package/src/list/listShim.spec.ts +101 -0
  357. package/src/list/statusColors.ts +7 -92
  358. package/src/report/queryReportColumns.tsx +1 -1
  359. package/src/report/queryReportFilterBar.tsx +7 -2
  360. package/src/report/report-grid.tsx +1 -1
  361. package/src/report/report-toolbar.tsx +1 -1
  362. package/src/report/reportViewModel.ts +5 -1
  363. package/types/list/DoctypeListScreen.d.ts +1 -1
  364. package/types/list/DoctypeListScreen.d.ts.map +1 -1
  365. package/types/list/filter-editor.d.ts.map +1 -1
  366. package/types/list/filter-fields.d.ts +10 -78
  367. package/types/list/filter-fields.d.ts.map +1 -1
  368. package/types/list/filter-standard.d.ts.map +1 -1
  369. package/types/list/listColumns.d.ts +10 -40
  370. package/types/list/listColumns.d.ts.map +1 -1
  371. package/types/list/listFields.d.ts +5 -13
  372. package/types/list/listFields.d.ts.map +1 -1
  373. package/types/list/listFormat.d.ts +5 -27
  374. package/types/list/listFormat.d.ts.map +1 -1
  375. package/types/list/statusColors.d.ts +6 -11
  376. package/types/list/statusColors.d.ts.map +1 -1
  377. package/types/report/queryReportFilterBar.d.ts.map +1 -1
  378. package/types/report/reportViewModel.d.ts +1 -1
  379. package/types/report/reportViewModel.d.ts.map +1 -1
  380. package/src/list/filter-fields.spec.ts +0 -29
  381. package/src/list/listFields.spec.ts +0 -148
  382. package/src/list/listFormat.spec.ts +0 -151
  383. package/src/list/statusColors.spec.ts +0 -100
@@ -0,0 +1,84 @@
1
+ // A Keycloak-signed-in reader hands the provider its token as a getter
2
+ // (MPO-399). Every request the list makes must carry that bearer: the bench
3
+ // answers a tokenless call as Guest (403), which is how the header count
4
+ // read "0 results" beside a full page of rows.
5
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
6
+ import { screen, waitFor } from "@testing-library/react";
7
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
8
+ import { BackofficeProvider } from "../config/BackofficeProvider";
9
+ import { createMemoryNavigator } from "../navigation/navigator";
10
+ import { DoctypeListScreen } from "./DoctypeListScreen";
11
+
12
+ const doctype = "Pokemon";
13
+ const bearer = "Bearer kc-access-token";
14
+
15
+ const meta = {
16
+ name: doctype,
17
+ doctype: "DocType",
18
+ title_field: "pokemon_name",
19
+ fields: [
20
+ { fieldname: "pokemon_name", fieldtype: "Data", label: "Pokemon Name", in_list_view: 1 },
21
+ ],
22
+ permissions: [{ role: "Pokemon Reader", read: 1 }],
23
+ };
24
+
25
+ let run = 0;
26
+ let calls: { path: string; authorization: string | null }[] = [];
27
+
28
+ function json(body: unknown, status = 200) {
29
+ return new Response(JSON.stringify(body), {
30
+ status,
31
+ headers: { "content-type": "application/json" },
32
+ });
33
+ }
34
+
35
+ beforeEach(() => {
36
+ run += 1;
37
+ calls = [];
38
+ vi.stubGlobal("fetch", async (input: string | URL | Request, init?: RequestInit) => {
39
+ const url = new URL(String(input instanceof Request ? input.url : input));
40
+ const headers = new Headers(input instanceof Request ? input.headers : init?.headers);
41
+ const authorization = headers.get("Authorization");
42
+ calls.push({ path: `${url.pathname}${url.search}`, authorization });
43
+ if (authorization !== bearer) {
44
+ return json({ exc_type: "PermissionError" }, 403);
45
+ }
46
+ const method = url.pathname.replace(/^\/api\/method\//, "");
47
+ if (method === "frappe.auth.get_logged_user") return json({ message: "ash@pokemon.test" });
48
+ if (method === "frappe.core.doctype.user.user.get_roles") {
49
+ return json({ message: ["Pokemon Reader"] });
50
+ }
51
+ if (method === "frappe.desk.form.load.getdoctype") return json({ docs: [meta] });
52
+ if (method === "frappe.client.get_count") return json({ message: 21 });
53
+ if (url.pathname === `/api/resource/${doctype}`) {
54
+ return json({ data: [{ name: "bulbasaur", doctype, pokemon_name: "Bulbasaur" }] });
55
+ }
56
+ return json({ data: [], message: [] });
57
+ });
58
+ });
59
+
60
+ afterEach(() => {
61
+ vi.restoreAllMocks();
62
+ vi.unstubAllGlobals();
63
+ });
64
+
65
+ describe("DoctypeListScreen auth", () => {
66
+ it("sends the provider's token getter on every call, the header count included", async () => {
67
+ renderWithProviders(
68
+ <BackofficeProvider
69
+ frappe={{
70
+ baseURL: `https://list-auth-${run}.spec.test`,
71
+ auth: { useToken: true, type: "Bearer", token: async () => "kc-access-token" },
72
+ }}
73
+ navigation={createMemoryNavigator("/backoffice")}
74
+ >
75
+ <DoctypeListScreen doctype={doctype} />
76
+ </BackofficeProvider>,
77
+ );
78
+
79
+ await waitFor(() => expect(screen.getByText("21 results")).toBeTruthy(), { timeout: 5000 });
80
+ const counts = calls.filter((call) => call.path.includes("frappe.client.get_count"));
81
+ expect(counts.length).toBeGreaterThan(0);
82
+ expect(calls.filter((call) => call.authorization !== bearer)).toEqual([]);
83
+ });
84
+ });
@@ -32,10 +32,14 @@ import {
32
32
  } from "@phosphor-icons/react";
33
33
  import {
34
34
  FrappeTable,
35
+ buildListColumns,
35
36
  docFieldsToFilterFields,
37
+ listFieldsToFetch,
36
38
  sessionDocRights,
37
39
  useFrappeAggregate,
38
40
  useFrappeConfig,
41
+ type ListDoc,
42
+ type ListRow,
39
43
  } from "@multiplatform.one/frappe-ui";
40
44
  import type {
41
45
  BulkAction,
@@ -86,8 +90,6 @@ import {
86
90
  import { toggleFacetFilter } from "./sidebar-stats";
87
91
  import { ListFilterBar } from "./ListFilterBar";
88
92
  import { ListSidebar } from "./ListSidebar";
89
- import { type ListDoc, type ListRow, buildListColumns } from "./listColumns";
90
- import { listFieldsToFetch } from "./listFields";
91
93
  import {
92
94
  parseFiltersParam,
93
95
  parseSortParam,
@@ -359,38 +361,11 @@ export function DoctypeListScreen({
359
361
  effectiveSortRef.current = { field: sortField, order: sortOrder };
360
362
  const currentFilters = effectiveFilters ?? withFixed(baseFilters);
361
363
 
362
- const connection = useMemo(
363
- () =>
364
- config
365
- ? {
366
- baseURL: config.baseURL,
367
- socketPort: config.socketPort,
368
- siteName: config.siteName,
369
- socketBaseURL: config.socketBaseURL,
370
- auth: config.auth
371
- ? {
372
- useToken: config.auth.useToken,
373
- token: typeof config.auth.token === "string" ? config.auth.token : undefined,
374
- type: config.auth.type,
375
- }
376
- : undefined,
377
- // Forward the provider's engine options: the SyncModule is
378
- // shared per baseURL and the FIRST consumer's config wins — a
379
- // connection built without syncOptions here would silently
380
- // strip persistKey/cdcInterval for every other screen when the
381
- // list's aggregate watcher happens to construct the engine
382
- // first (observed on GNOME, where this screen is the first
383
- // engine touch).
384
- syncOptions: config.syncOptions,
385
- socketOptions: config.socketOptions,
386
- fixtures: config.fixtures,
387
- }
388
- : undefined,
389
- [config],
390
- );
391
-
392
- // Live result count — realtime refetch on doctype events.
393
- const count = useFrappeAggregate(connection, {
364
+ // Live result count — realtime refetch on doctype events. It takes the
365
+ // provider config itself, never a copy: the SyncModule is shared per socket
366
+ // target and the first consumer's config wins, so a field a copy drops
367
+ // (syncOptions, a token getter) is gone for every screen.
368
+ const count = useFrappeAggregate(config, {
394
369
  doctype,
395
370
  filters: currentFilters.length > 0 ? currentFilters : undefined,
396
371
  });
@@ -453,23 +428,15 @@ export function DoctypeListScreen({
453
428
 
454
429
  const fields = useMemo(() => listFieldsToFetch(meta, permMatrix), [meta, permMatrix]);
455
430
 
456
- // Filterable-field declarations (meta fields + the desk `_` facet
457
- // columns). With the table's filter chrome suppressed these render no
458
- // toolbar surface — they resolve filter TYPES for the injected tuples and
459
- // keep FrappeTable from refetching meta to derive its own list.
460
- const filterableFields = useMemo<FilterableField[] | undefined>(() => {
461
- if (!meta?.fields) return undefined;
462
- return [
463
- ...docFieldsToFilterFields(meta.fields),
464
- {
465
- id: "_assign",
466
- label: t("list.assignedTo", "Assigned To"),
467
- type: "text",
468
- },
469
- { id: "_user_tags", label: t("list.tags", "Tags"), type: "text" },
470
- { id: "_liked_by", label: t("list.likedBy", "Liked By"), type: "text" },
471
- ];
472
- }, [meta, t]);
431
+ // Filterable-field declarations from the one vocabulary (meta fields, the
432
+ // standard doc fields and the desk `_` facet columns). With the table's
433
+ // filter chrome suppressed these render no toolbar surface — they resolve
434
+ // filter TYPES for the injected tuples and keep FrappeTable from
435
+ // refetching meta to derive its own list.
436
+ const filterableFields = useMemo<FilterableField[] | undefined>(
437
+ () => (meta?.fields ? docFieldsToFilterFields(meta.fields) : undefined),
438
+ [meta],
439
+ );
473
440
 
474
441
  const initialTableFilters = useMemo<TableFilter[]>(
475
442
  () => frappeFiltersToTableFilters(withFixed(baseFilters)),
@@ -10,7 +10,7 @@ import { useTranslation } from "react-i18next";
10
10
  import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
11
11
  import type { FrappeFilters } from "../shared/types";
12
12
  import type { DoctypeMeta } from "../shared/useDoctypeMeta";
13
- import { filterTupleLabel, filterableFieldsFromMeta } from "./filter-fields";
13
+ import { filterTupleLabel, filterableFieldsFromMeta } from "@multiplatform.one/frappe-ui";
14
14
 
15
15
  export interface FilterChipsProps {
16
16
  meta?: DoctypeMeta;
@@ -16,7 +16,6 @@ import {
16
16
  // House Button: the raw tamagui Button (components re-export) never gets the
17
17
  // house 44px press floor (LC-54) — filter chrome takes the forms Button.
18
18
  import { Button, Input, Select } from "@multiplatform.one/forms";
19
- import { Link as LinkField } from "@multiplatform.one/frappe-ui";
20
19
  import { FunnelIcon, PlusIcon, XIcon } from "@phosphor-icons/react";
21
20
  import { useMemo, useRef, useState } from "react";
22
21
  import { useTranslation } from "react-i18next";
@@ -28,13 +27,14 @@ import {
28
27
  defaultOperatorForKind,
29
28
  draftToTuple,
30
29
  filterableFieldsFromMeta,
30
+ Link as LinkField,
31
31
  operatorsForKind,
32
32
  selectOptionsFromField,
33
33
  tupleToDraft,
34
34
  type DeskOperator,
35
35
  type FilterFieldDescriptor,
36
36
  type FilterRowDraft,
37
- } from "./filter-fields";
37
+ } from "@multiplatform.one/frappe-ui";
38
38
 
39
39
  export interface FilterEditorButtonProps {
40
40
  meta?: DoctypeMeta;
@@ -1,359 +1,32 @@
1
1
  /**
2
- * Field + operator model for the list filter chrome (desk parity).
3
- *
4
- * Maps DoctypeMeta DocFields to kind-aware filter descriptors
5
- * (select/link/check/date/number/text) and defines desk's operator
6
- * vocabulary (=, !=, like, not like, in, not in, comparisons, between,
7
- * is set / is not set) with two-way tuple conversion. This model speaks
8
- * frappe tuples natively — the table package's FilterValue vocabulary is
9
- * bridged separately (filterConversion.ts) for the DataTable surface;
10
- * desk's own operator list is the parity target here.
2
+ * The filterable-field vocabulary — moved to
3
+ * `@multiplatform.one/frappe-ui/src/filterFields` (MPO-15), where it is the
4
+ * one vocabulary both list stacks read: this desk chrome and FrappeTable's
5
+ * toolbar (`docFieldsToFilterFields`). Re-exported here so the barrel and
6
+ * the `@multiplatform.one/backoffice/src/list/filter-fields` deep import
7
+ * keep resolving (the GNOME shim deep-imports this path). New code imports
8
+ * from `@multiplatform.one/frappe-ui`.
11
9
  */
12
- import type { FrappeFilter, FrappeFilters } from "../shared/types";
13
- import type { DocFieldMeta, DoctypeMeta } from "../shared/useDoctypeMeta";
14
10
 
15
- // ── Field descriptors ─────────────────────────────────────────
16
-
17
- export type FilterFieldKind = "select" | "link" | "check" | "date" | "number" | "text";
18
-
19
- export interface FilterFieldDescriptor {
20
- fieldname: string;
21
- label: string;
22
- fieldtype: string;
23
- kind: FilterFieldKind;
24
- /** Link target doctype, or the raw Select options string. */
25
- options?: string;
26
- }
27
-
28
- /** Layout / non-data fieldtypes that cannot meaningfully filter. */
29
- const NON_FILTERABLE_FIELDTYPES = new Set([
30
- "Section Break",
31
- "Column Break",
32
- "Tab Break",
33
- "Fold",
34
- "Heading",
35
- "HTML",
36
- "Button",
37
- "Image",
38
- "Attach",
39
- "Attach Image",
40
- "Signature",
41
- "Geolocation",
42
- "Password",
43
- ]);
44
-
45
- const NUMBER_FIELDTYPES = new Set(["Int", "Float", "Currency", "Percent", "Duration", "Rating"]);
46
- const DATE_FIELDTYPES = new Set(["Date", "Datetime", "Time"]);
47
-
48
- /** Editor kind for a frappe fieldtype (Dynamic Link has no static target → text). */
49
- export function fieldKind(fieldtype: string): FilterFieldKind {
50
- if (fieldtype === "Select") return "select";
51
- if (fieldtype === "Link") return "link";
52
- if (fieldtype === "Check") return "check";
53
- if (DATE_FIELDTYPES.has(fieldtype)) return "date";
54
- if (NUMBER_FIELDTYPES.has(fieldtype)) return "number";
55
- return "text";
56
- }
57
-
58
- function toDescriptor(field: DocFieldMeta): FilterFieldDescriptor {
59
- return {
60
- fieldname: field.fieldname,
61
- label: field.label || field.fieldname,
62
- fieldtype: field.fieldtype,
63
- kind: fieldKind(field.fieldtype),
64
- options: field.options,
65
- };
66
- }
67
-
68
- /** Standard doc fields present on every doctype but absent from meta.fields. */
69
- export function standardDocFilterFields(): FilterFieldDescriptor[] {
70
- return [
71
- { fieldname: "name", label: "ID", fieldtype: "Data", kind: "text" },
72
- { fieldname: "owner", label: "Created By", fieldtype: "Link", kind: "link", options: "User" },
73
- { fieldname: "creation", label: "Created On", fieldtype: "Datetime", kind: "date" },
74
- { fieldname: "modified", label: "Last Updated On", fieldtype: "Datetime", kind: "date" },
75
- {
76
- fieldname: "modified_by",
77
- label: "Last Updated By",
78
- fieldtype: "Link",
79
- kind: "link",
80
- options: "User",
81
- },
82
- // Desk `_` facet columns — the sidebar facets and heart column write
83
- // tuples on these, so chips and the editor must label them (desk offers
84
- // them in its filter field picker too). Never surface the raw
85
- // underscore fieldname (no-raw-fieldname rule candidate).
86
- { fieldname: "_assign", label: "Assigned To", fieldtype: "Data", kind: "text" },
87
- { fieldname: "_user_tags", label: "Tags", fieldtype: "Data", kind: "text" },
88
- { fieldname: "_liked_by", label: "Liked By", fieldtype: "Data", kind: "text" },
89
- { fieldname: "_comments", label: "Comments", fieldtype: "Data", kind: "text" },
90
- ];
91
- }
92
-
93
- /**
94
- * All fields offered by the filter editor's field picker — data fields from
95
- * meta (hidden ones included, desk parity) plus the standard doc fields.
96
- */
97
- export function filterableFieldsFromMeta(meta?: DoctypeMeta): FilterFieldDescriptor[] {
98
- const out: FilterFieldDescriptor[] = [];
99
- const seen = new Set<string>();
100
- for (const field of meta?.fields ?? []) {
101
- if (!field.fieldname || seen.has(field.fieldname)) continue;
102
- const fieldtype = String(field.fieldtype);
103
- if (NON_FILTERABLE_FIELDTYPES.has(fieldtype) || fieldtype.startsWith("Table")) continue;
104
- seen.add(field.fieldname);
105
- out.push(toDescriptor(field));
106
- }
107
- for (const standard of standardDocFilterFields()) {
108
- if (!seen.has(standard.fieldname)) out.push(standard);
109
- }
110
- return out;
111
- }
112
-
113
- /** Fields flagged `in_standard_filter`, in meta order (the quick-filter row).
114
- * Desk always offers ID plus the title field as live header inputs even when
115
- * those flags are off — typing a fragment of ID/subject is the fastest
116
- * narrowing habit list users have (audit E1). */
117
- export function standardFiltersFromMeta(meta?: DoctypeMeta): FilterFieldDescriptor[] {
118
- const fromMeta = (meta?.fields ?? [])
119
- .filter((field) => field.in_standard_filter === 1 && field.hidden !== 1 && field.fieldname)
120
- .map(toDescriptor);
121
- const seen = new Set(fromMeta.map((field) => field.fieldname));
122
- const extras: FilterFieldDescriptor[] = [];
123
- if (!seen.has("name")) {
124
- extras.push({ fieldname: "name", label: "ID", fieldtype: "Data", kind: "text" });
125
- seen.add("name");
126
- }
127
- const titleField = meta?.title_field;
128
- if (titleField && !seen.has(titleField)) {
129
- const titleMeta = meta?.fields?.find((field) => field.fieldname === titleField);
130
- extras.push({
131
- fieldname: titleField,
132
- label: titleMeta?.label || "Title",
133
- fieldtype: titleMeta?.fieldtype || "Data",
134
- kind: fieldKind(titleMeta?.fieldtype || "Data"),
135
- });
136
- }
137
- return extras.length > 0 ? [...extras, ...fromMeta] : fromMeta;
138
- }
139
-
140
- /** Select fieldtype options string → dropdown options (blank lines dropped). */
141
- export function selectOptionsFromField(options?: string): Array<{ label: string; value: string }> {
142
- return (options ?? "")
143
- .split("\n")
144
- .map((line) => line.trim())
145
- .filter(Boolean)
146
- .map((line) => ({ label: line, value: line }));
147
- }
148
-
149
- /**
150
- * Human label for a fieldname — descriptor label when known, else a
151
- * title-cased form. The raw identifier (underscores) never reaches chips or
152
- * editor rows (no-raw-fieldname rule candidate, parity audit pair 04/16).
153
- */
154
- export function fieldLabelFor(fields: FilterFieldDescriptor[], fieldname: string): string {
155
- const known = fields.find((field) => field.fieldname === fieldname)?.label;
156
- if (known) return known;
157
- const pretty = fieldname
158
- .replace(/^_+/, "")
159
- .split("_")
160
- .filter(Boolean)
161
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
162
- .join(" ");
163
- return pretty || fieldname;
164
- }
165
-
166
- // ── Desk operator vocabulary ──────────────────────────────────
167
-
168
- export type DeskOperator =
169
- | "="
170
- | "!="
171
- | "like"
172
- | "not like"
173
- | "in"
174
- | "not in"
175
- | ">"
176
- | "<"
177
- | ">="
178
- | "<="
179
- | "between"
180
- | "is set"
181
- | "is not set";
182
-
183
- /** English operator labels — translate at render time via t(). */
184
- export const DESK_OPERATOR_LABELS: Record<DeskOperator, string> = {
185
- "=": "Equals",
186
- "!=": "Not Equals",
187
- like: "Like",
188
- "not like": "Not Like",
189
- in: "In",
190
- "not in": "Not In",
191
- ">": "Greater Than",
192
- "<": "Less Than",
193
- ">=": "Greater Than or Equal",
194
- "<=": "Less Than or Equal",
195
- between: "Between",
196
- "is set": "Is Set",
197
- "is not set": "Is Not Set",
198
- };
199
-
200
- const BASE_OPERATORS: DeskOperator[] = [
201
- "=",
202
- "!=",
203
- "like",
204
- "not like",
205
- "in",
206
- "not in",
207
- "is set",
208
- "is not set",
209
- ];
210
-
211
- /** Operators offered for an editor kind (desk's list, comparisons gated). */
212
- export function operatorsForKind(kind: FilterFieldKind): DeskOperator[] {
213
- switch (kind) {
214
- case "check":
215
- return ["=", "!="];
216
- case "number":
217
- case "date":
218
- return ["=", "!=", ">", "<", ">=", "<=", "between", "in", "not in", "is set", "is not set"];
219
- default:
220
- return BASE_OPERATORS;
221
- }
222
- }
223
-
224
- /** Initial operator when a field is picked (desk: text searches, others match). */
225
- export function defaultOperatorForKind(kind: FilterFieldKind): DeskOperator {
226
- return kind === "text" ? "like" : "=";
227
- }
228
-
229
- // ── Editor row model + tuple conversion ───────────────────────
230
-
231
- export interface FilterRowDraft {
232
- fieldname: string;
233
- operator: DeskOperator;
234
- /** Scalar editor value (single input / select / link / comma list). */
235
- value: string;
236
- /** Multi values: in / not in multi-select, or [from, to] for between. */
237
- values: string[];
238
- }
239
-
240
- /**
241
- * Draft → frappe tuple; null while the draft is incomplete.
242
- * `like` wraps `%value%` unless the user typed their own wildcard;
243
- * `is set` / `is not set` become ["field", "is", "set" | "not set"].
244
- */
245
- export function draftToTuple(draft: FilterRowDraft, kind: FilterFieldKind): FrappeFilter | null {
246
- const { fieldname, operator } = draft;
247
- if (!fieldname) return null;
248
- switch (operator) {
249
- case "is set":
250
- return [fieldname, "is", "set"];
251
- case "is not set":
252
- return [fieldname, "is", "not set"];
253
- case "in":
254
- case "not in": {
255
- const values =
256
- kind === "select"
257
- ? draft.values.map((value) => value.trim()).filter(Boolean)
258
- : draft.value
259
- .split(",")
260
- .map((value) => value.trim())
261
- .filter(Boolean);
262
- return values.length ? [fieldname, operator, values] : null;
263
- }
264
- case "between": {
265
- const from = (draft.values[0] ?? "").trim();
266
- const to = (draft.values[1] ?? "").trim();
267
- return from && to ? [fieldname, "between", [from, to]] : null;
268
- }
269
- case "like":
270
- case "not like": {
271
- const text = draft.value.trim();
272
- if (!text) return null;
273
- return [fieldname, operator, text.includes("%") ? text : `%${text}%`];
274
- }
275
- default: {
276
- const text = draft.value.trim();
277
- return text ? [fieldname, operator, text] : null;
278
- }
279
- }
280
- }
281
-
282
- const SCALAR_OPERATORS: readonly string[] = ["=", "!=", "like", "not like", ">", "<", ">=", "<="];
283
-
284
- /** Frappe tuple → editable draft (inverse of draftToTuple). */
285
- export function tupleToDraft(tuple: FrappeFilter): FilterRowDraft {
286
- const [fieldname, operator, raw] = tuple;
287
- if (operator === "is") {
288
- return {
289
- fieldname,
290
- operator: raw === "set" ? "is set" : "is not set",
291
- value: "",
292
- values: [],
293
- };
294
- }
295
- if (operator === "in" || operator === "not in") {
296
- const values = Array.isArray(raw)
297
- ? raw.map(String)
298
- : String(raw ?? "")
299
- .split(",")
300
- .map((value) => value.trim())
301
- .filter(Boolean);
302
- return { fieldname, operator, value: values.join(", "), values };
303
- }
304
- if (operator === "between") {
305
- const values = Array.isArray(raw) ? raw.map(String) : [];
306
- return {
307
- fieldname,
308
- operator: "between",
309
- value: "",
310
- values: [values[0] ?? "", values[1] ?? ""],
311
- };
312
- }
313
- const known = SCALAR_OPERATORS.includes(operator) ? (operator as DeskOperator) : "=";
314
- return {
315
- fieldname,
316
- operator: known,
317
- value: raw === null || raw === undefined ? "" : String(raw),
318
- values: [],
319
- };
320
- }
321
-
322
- // ── Filter list helpers ───────────────────────────────────────
323
-
324
- /**
325
- * Quick-filter semantics: a standard filter control owns every tuple for its
326
- * fieldname — replace them with `tuple`, or clear when `tuple` is undefined.
327
- */
328
- export function setFieldFilter(
329
- filters: FrappeFilters,
330
- fieldname: string,
331
- tuple?: FrappeFilter,
332
- ): FrappeFilters {
333
- const rest = filters.filter(([name]) => name !== fieldname);
334
- return tuple ? [...rest, tuple] : rest;
335
- }
336
-
337
- /** The active quick-filter display value for a fieldname ("" when none). */
338
- export function quickFilterValue(filters: FrappeFilters, fieldname: string): string {
339
- const tuple = filters.find(([name]) => name === fieldname);
340
- if (!tuple) return "";
341
- const [, operator, raw] = tuple;
342
- if (operator === "like") {
343
- const text = String(raw ?? "");
344
- return text.startsWith("%") && text.endsWith("%") && text.length >= 2
345
- ? text.slice(1, -1)
346
- : text;
347
- }
348
- if (operator === "=") return raw === null || raw === undefined ? "" : String(raw);
349
- return "";
350
- }
351
-
352
- /** Chip label: "Status = Open", "Due Date between a, b", "Owner is set". */
353
- export function filterTupleLabel(fields: FilterFieldDescriptor[], tuple: FrappeFilter): string {
354
- const [fieldname, operator, raw] = tuple;
355
- const label = fieldLabelFor(fields, fieldname);
356
- if (operator === "is") return `${label} ${raw === "set" ? "is set" : "is not set"}`;
357
- const value = Array.isArray(raw) ? raw.map(String).join(", ") : String(raw ?? "");
358
- return `${label} ${operator} ${value}`;
359
- }
11
+ export {
12
+ defaultOperatorForKind,
13
+ DESK_OPERATOR_LABELS,
14
+ draftToTuple,
15
+ fieldKind,
16
+ fieldLabelFor,
17
+ filterableFieldsFromMeta,
18
+ filterTupleLabel,
19
+ operatorsForKind,
20
+ quickFilterValue,
21
+ selectOptionsFromField,
22
+ setFieldFilter,
23
+ standardDocFilterFields,
24
+ standardFiltersFromMeta,
25
+ tupleToDraft,
26
+ } from "@multiplatform.one/frappe-ui";
27
+ export type {
28
+ DeskOperator,
29
+ FilterFieldDescriptor,
30
+ FilterFieldKind,
31
+ FilterRowDraft,
32
+ } from "@multiplatform.one/frappe-ui";
@@ -9,17 +9,17 @@
9
9
  */
10
10
  import { XStack, YStack } from "@multiplatform.one/components";
11
11
  import { Checkbox, Input, Select } from "@multiplatform.one/forms";
12
- import { Link as LinkField } from "@multiplatform.one/frappe-ui";
13
12
  import { useEffect, useRef, useState } from "react";
14
13
  import type { FrappeFilter, FrappeFilters } from "../shared/types";
15
14
  import type { DoctypeMeta } from "../shared/useDoctypeMeta";
16
15
  import {
16
+ Link as LinkField,
17
17
  quickFilterValue,
18
18
  selectOptionsFromField,
19
19
  setFieldFilter,
20
20
  standardFiltersFromMeta,
21
21
  type FilterFieldDescriptor,
22
- } from "./filter-fields";
22
+ } from "@multiplatform.one/frappe-ui";
23
23
 
24
24
  export interface StandardFiltersProps {
25
25
  meta?: DoctypeMeta;
@@ -19,7 +19,7 @@ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
19
19
  import type { FrappeFilters } from "../shared/types";
20
20
  import type { DoctypeMeta } from "../shared/useDoctypeMeta";
21
21
  import { FilterEditorPanel } from "./filter-editor";
22
- import { standardFiltersFromMeta } from "./filter-fields";
22
+ import { standardFiltersFromMeta } from "@multiplatform.one/frappe-ui";
23
23
  import { SavedFiltersControl } from "./filter-saved";
24
24
  import { SortControl } from "./filter-sort";
25
25
  import { StandardFilters } from "./filter-standard";