@multiplatform.one/backoffice 7.6.3 → 7.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. package/dist/cjs/chrome/BackofficeAwesomebar.native.js +1 -1
  2. package/dist/cjs/chrome/BackofficeAwesomebar.native.js.map +1 -1
  3. package/dist/cjs/chrome/CommandPalette.native.js +1 -1
  4. package/dist/cjs/chrome/CommandPalette.native.js.map +1 -1
  5. package/dist/cjs/chrome/HelpMenu.native.js +1 -1
  6. package/dist/cjs/chrome/HelpMenu.native.js.map +1 -1
  7. package/dist/cjs/chrome/NotificationsButton.native.js +1 -1
  8. package/dist/cjs/chrome/NotificationsButton.native.js.map +1 -1
  9. package/dist/cjs/chrome/UserMenu.native.js +1 -1
  10. package/dist/cjs/chrome/UserMenu.native.js.map +1 -1
  11. package/dist/cjs/chrome/awesomebar-data.native.js.map +1 -1
  12. package/dist/cjs/chrome/command-palette-model.native.js +1 -1
  13. package/dist/cjs/chrome/command-palette-model.native.js.map +1 -1
  14. package/dist/cjs/chrome/help-about-dialog.native.js +1 -1
  15. package/dist/cjs/chrome/help-about-dialog.native.js.map +1 -1
  16. package/dist/cjs/chrome/help-shortcuts-dialog.native.js +1 -1
  17. package/dist/cjs/chrome/help-shortcuts-dialog.native.js.map +1 -1
  18. package/dist/cjs/chrome/notifications-data.native.js.map +1 -1
  19. package/dist/cjs/chrome/notifications-panel.native.js +1 -1
  20. package/dist/cjs/chrome/notifications-panel.native.js.map +1 -1
  21. package/dist/cjs/chrome/notifications-utils.native.js.map +1 -1
  22. package/dist/cjs/chrome/shortcuts.native.js.map +1 -1
  23. package/dist/cjs/chrome/user-session.native.js.map +1 -1
  24. package/dist/cjs/config/BackofficeProvider.native.js +1 -1
  25. package/dist/cjs/config/BackofficeProvider.native.js.map +1 -1
  26. package/dist/cjs/config/capabilities.native.js.map +1 -1
  27. package/dist/cjs/config/events.native.js.map +1 -1
  28. package/dist/cjs/config/slots.native.js.map +1 -1
  29. package/dist/cjs/desk/Desk.native.js.map +1 -1
  30. package/dist/cjs/desk/DeskSurface.native.js.map +1 -1
  31. package/dist/cjs/desk/resolveDeskPath.native.js.map +1 -1
  32. package/dist/cjs/desk/scope.native.js.map +1 -1
  33. package/dist/cjs/desk/target.native.js.map +1 -1
  34. package/dist/cjs/form/DocFormScreen.native.js +1 -1
  35. package/dist/cjs/form/DocFormScreen.native.js.map +1 -1
  36. package/dist/cjs/form/FormConnections.native.js +1 -1
  37. package/dist/cjs/form/FormConnections.native.js.map +1 -1
  38. package/dist/cjs/form/FormDialogs.native.js +1 -1
  39. package/dist/cjs/form/FormDialogs.native.js.map +1 -1
  40. package/dist/cjs/form/FormErrorBoundary.native.js +1 -1
  41. package/dist/cjs/form/FormErrorBoundary.native.js.map +1 -1
  42. package/dist/cjs/form/FormHeaderCluster.native.js +1 -1
  43. package/dist/cjs/form/FormHeaderCluster.native.js.map +1 -1
  44. package/dist/cjs/form/FormSidebarPanel.native.js +1 -1
  45. package/dist/cjs/form/FormSidebarPanel.native.js.map +1 -1
  46. package/dist/cjs/form/FormTimeline.native.js +1 -1
  47. package/dist/cjs/form/FormTimeline.native.js.map +1 -1
  48. package/dist/cjs/form/FormToolbar.native.js +1 -1
  49. package/dist/cjs/form/FormToolbar.native.js.map +1 -1
  50. package/dist/cjs/form/connections-data.native.js.map +1 -1
  51. package/dist/cjs/form/createPrefill.cjs +3 -11
  52. package/dist/cjs/form/createPrefill.native.js +3 -11
  53. package/dist/cjs/form/createPrefill.native.js.map +1 -1
  54. package/dist/cjs/form/dependsOn.native.js.map +1 -1
  55. package/dist/cjs/form/dirtyTracking.cjs +4 -29
  56. package/dist/cjs/form/dirtyTracking.native.js +4 -48
  57. package/dist/cjs/form/dirtyTracking.native.js.map +1 -1
  58. package/dist/cjs/form/docinfo.native.js.map +1 -1
  59. package/dist/cjs/form/fetchFrom.cjs +4 -41
  60. package/dist/cjs/form/fetchFrom.native.js +4 -81
  61. package/dist/cjs/form/fetchFrom.native.js.map +1 -1
  62. package/dist/cjs/form/fieldPermissions.cjs +4 -29
  63. package/dist/cjs/form/fieldPermissions.native.js +4 -51
  64. package/dist/cjs/form/fieldPermissions.native.js.map +1 -1
  65. package/dist/cjs/form/formActions.cjs +2 -171
  66. package/dist/cjs/form/formActions.native.js +2 -178
  67. package/dist/cjs/form/formActions.native.js.map +1 -1
  68. package/dist/cjs/form/formLayout.cjs +5 -219
  69. package/dist/cjs/form/formLayout.native.js +5 -359
  70. package/dist/cjs/form/formLayout.native.js.map +1 -1
  71. package/dist/cjs/form/platformHooks.native.js.map +1 -1
  72. package/dist/cjs/form/sidebar-attachments.native.js +1 -1
  73. package/dist/cjs/form/sidebar-attachments.native.js.map +1 -1
  74. package/dist/cjs/form/sidebar-dialogs.native.js +1 -1
  75. package/dist/cjs/form/sidebar-dialogs.native.js.map +1 -1
  76. package/dist/cjs/form/sidebar-people.native.js +1 -1
  77. package/dist/cjs/form/sidebar-people.native.js.map +1 -1
  78. package/dist/cjs/form/sidebar-rpc.native.js.map +1 -1
  79. package/dist/cjs/form/sidebar-utils.native.js.map +1 -1
  80. package/dist/cjs/form/timeline-entries.native.js.map +1 -1
  81. package/dist/cjs/form/timeline-utils.native.js.map +1 -1
  82. package/dist/cjs/form/useFormEngine.cjs +2 -361
  83. package/dist/cjs/form/useFormEngine.native.js +2 -447
  84. package/dist/cjs/form/useFormEngine.native.js.map +1 -1
  85. package/dist/cjs/i18n/en.native.js.map +1 -1
  86. package/dist/cjs/i18n/index.native.js.map +1 -1
  87. package/dist/cjs/index.native.js +1 -1
  88. package/dist/cjs/index.native.js.map +1 -1
  89. package/dist/cjs/list/AddTagsDialog.native.js +1 -1
  90. package/dist/cjs/list/AddTagsDialog.native.js.map +1 -1
  91. package/dist/cjs/list/AssignToDialog.native.js +1 -1
  92. package/dist/cjs/list/AssignToDialog.native.js.map +1 -1
  93. package/dist/cjs/list/DoctypeListScreen.native.js +1 -1
  94. package/dist/cjs/list/DoctypeListScreen.native.js.map +1 -1
  95. package/dist/cjs/list/ListBulkActionsBar.native.js +1 -1
  96. package/dist/cjs/list/ListBulkActionsBar.native.js.map +1 -1
  97. package/dist/cjs/list/ListFilterBar.native.js +1 -1
  98. package/dist/cjs/list/ListFilterBar.native.js.map +1 -1
  99. package/dist/cjs/list/ListSidebar.native.js +1 -1
  100. package/dist/cjs/list/ListSidebar.native.js.map +1 -1
  101. package/dist/cjs/list/bulk-edit-dialog.native.js +1 -1
  102. package/dist/cjs/list/bulk-edit-dialog.native.js.map +1 -1
  103. package/dist/cjs/list/bulk-export.native.js.map +1 -1
  104. package/dist/cjs/list/bulk-submit-cancel.native.js.map +1 -1
  105. package/dist/cjs/list/bulkActions.native.js.map +1 -1
  106. package/dist/cjs/list/filter-chips.native.js +1 -1
  107. package/dist/cjs/list/filter-chips.native.js.map +1 -1
  108. package/dist/cjs/list/filter-editor.native.js +1 -1
  109. package/dist/cjs/list/filter-editor.native.js.map +1 -1
  110. package/dist/cjs/list/filter-fields.native.js.map +1 -1
  111. package/dist/cjs/list/filter-saved.native.js +1 -1
  112. package/dist/cjs/list/filter-saved.native.js.map +1 -1
  113. package/dist/cjs/list/filter-sort.native.js +1 -1
  114. package/dist/cjs/list/filter-sort.native.js.map +1 -1
  115. package/dist/cjs/list/filter-standard.native.js.map +1 -1
  116. package/dist/cjs/list/filterConversion.native.js.map +1 -1
  117. package/dist/cjs/list/list-tools-sheet.native.js +1 -1
  118. package/dist/cjs/list/list-tools-sheet.native.js.map +1 -1
  119. package/dist/cjs/list/listColumns.native.js.map +1 -1
  120. package/dist/cjs/list/listFields.native.js.map +1 -1
  121. package/dist/cjs/list/listFormat.native.js.map +1 -1
  122. package/dist/cjs/list/listUrlState.native.js.map +1 -1
  123. package/dist/cjs/list/sidebar-section.native.js +1 -1
  124. package/dist/cjs/list/sidebar-section.native.js.map +1 -1
  125. package/dist/cjs/list/sidebar-stats.native.js.map +1 -1
  126. package/dist/cjs/list/statusColors.native.js.map +1 -1
  127. package/dist/cjs/navigation/navigator.native.js.map +1 -1
  128. package/dist/cjs/navigation/paths.native.js.map +1 -1
  129. package/dist/cjs/oneAdapter/index.native.js.map +1 -1
  130. package/dist/cjs/quickEntry/QuickEntryDialog.native.js +1 -1
  131. package/dist/cjs/quickEntry/QuickEntryDialog.native.js.map +1 -1
  132. package/dist/cjs/quickEntry/quickEntryPlan.native.js.map +1 -1
  133. package/dist/cjs/report/DoctypeReportView.native.js +1 -1
  134. package/dist/cjs/report/DoctypeReportView.native.js.map +1 -1
  135. package/dist/cjs/report/QueryReportScreen.native.js +1 -1
  136. package/dist/cjs/report/QueryReportScreen.native.js.map +1 -1
  137. package/dist/cjs/report/queryReportColumns.native.js.map +1 -1
  138. package/dist/cjs/report/queryReportFilterBar.native.js +1 -1
  139. package/dist/cjs/report/queryReportFilterBar.native.js.map +1 -1
  140. package/dist/cjs/report/queryReportUrlState.native.js.map +1 -1
  141. package/dist/cjs/report/report-grid.native.js +1 -1
  142. package/dist/cjs/report/report-grid.native.js.map +1 -1
  143. package/dist/cjs/report/report-toolbar.native.js +1 -1
  144. package/dist/cjs/report/report-toolbar.native.js.map +1 -1
  145. package/dist/cjs/report/reportShapes.native.js.map +1 -1
  146. package/dist/cjs/report/reportViewModel.native.js.map +1 -1
  147. package/dist/cjs/report/savedReports.native.js.map +1 -1
  148. package/dist/cjs/report/useQueryReport.native.js.map +1 -1
  149. package/dist/cjs/shared/deskLinks.native.js.map +1 -1
  150. package/dist/cjs/shared/listNavContext.native.js.map +1 -1
  151. package/dist/cjs/shared/types.native.js.map +1 -1
  152. package/dist/cjs/shared/useDocinfo.native.js.map +1 -1
  153. package/dist/cjs/shared/useDoctypeMeta.native.js.map +1 -1
  154. package/dist/cjs/shared/useFrappeApp.native.js.map +1 -1
  155. package/dist/cjs/shared/useRecentVisit.native.js.map +1 -1
  156. package/dist/cjs/shared/useSessionUserId.native.js.map +1 -1
  157. package/dist/cjs/shared/useSlugTarget.native.js.map +1 -1
  158. package/dist/cjs/shared/useUserRoles.native.js.map +1 -1
  159. package/dist/cjs/shell/BackofficeShell.native.js +1 -1
  160. package/dist/cjs/shell/BackofficeShell.native.js.map +1 -1
  161. package/dist/cjs/shell/HomeRedirect.native.js +1 -1
  162. package/dist/cjs/shell/HomeRedirect.native.js.map +1 -1
  163. package/dist/cjs/shell/NotFoundScreen.native.js +1 -1
  164. package/dist/cjs/shell/NotFoundScreen.native.js.map +1 -1
  165. package/dist/cjs/shell/SlugScreen.native.js +1 -1
  166. package/dist/cjs/shell/SlugScreen.native.js.map +1 -1
  167. package/dist/cjs/shell/WorkspaceSidebar.native.js +1 -1
  168. package/dist/cjs/shell/WorkspaceSidebar.native.js.map +1 -1
  169. package/dist/cjs/shell/useWorkspaces.native.js.map +1 -1
  170. package/dist/cjs/shell/workspaceIcons.native.js.map +1 -1
  171. package/dist/cjs/views/CalendarView.native.js +1 -1
  172. package/dist/cjs/views/CalendarView.native.js.map +1 -1
  173. package/dist/cjs/views/DashboardView.native.js +1 -1
  174. package/dist/cjs/views/DashboardView.native.js.map +1 -1
  175. package/dist/cjs/views/DoctypeViewScreen.native.js.map +1 -1
  176. package/dist/cjs/views/ImageView.native.js +1 -1
  177. package/dist/cjs/views/ImageView.native.js.map +1 -1
  178. package/dist/cjs/views/KanbanView.native.js +1 -1
  179. package/dist/cjs/views/KanbanView.native.js.map +1 -1
  180. package/dist/cjs/views/ReportView.native.js +1 -1
  181. package/dist/cjs/views/ReportView.native.js.map +1 -1
  182. package/dist/cjs/views/TreeView.native.js +1 -1
  183. package/dist/cjs/views/TreeView.native.js.map +1 -1
  184. package/dist/cjs/views/ViewHeader.native.js +1 -1
  185. package/dist/cjs/views/ViewHeader.native.js.map +1 -1
  186. package/dist/cjs/views/ViewStates.native.js +1 -1
  187. package/dist/cjs/views/ViewStates.native.js.map +1 -1
  188. package/dist/cjs/views/ViewSwitcherMenu.native.js +1 -1
  189. package/dist/cjs/views/ViewSwitcherMenu.native.js.map +1 -1
  190. package/dist/cjs/views/calendar-field-selector.native.js +1 -1
  191. package/dist/cjs/views/calendar-field-selector.native.js.map +1 -1
  192. package/dist/cjs/views/connection.native.js.map +1 -1
  193. package/dist/cjs/views/dashboard-data.native.js.map +1 -1
  194. package/dist/cjs/views/deskViewConfigs.native.js.map +1 -1
  195. package/dist/cjs/views/kanban-board-controls.native.js +1 -1
  196. package/dist/cjs/views/kanban-board-controls.native.js.map +1 -1
  197. package/dist/cjs/views/kanban-field-picker.native.js +1 -1
  198. package/dist/cjs/views/kanban-field-picker.native.js.map +1 -1
  199. package/dist/cjs/views/kanbanBoardOps.native.js.map +1 -1
  200. package/dist/cjs/views/report-controls.native.js +1 -1
  201. package/dist/cjs/views/report-controls.native.js.map +1 -1
  202. package/dist/cjs/views/viewAvailability.native.js.map +1 -1
  203. package/dist/cjs/views/viewMeta.native.js.map +1 -1
  204. package/dist/cjs/workspace/WorkspaceChartBlock.native.js +1 -1
  205. package/dist/cjs/workspace/WorkspaceChartBlock.native.js.map +1 -1
  206. package/dist/cjs/workspace/WorkspaceGrid.native.js.map +1 -1
  207. package/dist/cjs/workspace/WorkspaceLinkCard.native.js +1 -1
  208. package/dist/cjs/workspace/WorkspaceLinkCard.native.js.map +1 -1
  209. package/dist/cjs/workspace/WorkspaceLinkDirectory.native.js +1 -1
  210. package/dist/cjs/workspace/WorkspaceLinkDirectory.native.js.map +1 -1
  211. package/dist/cjs/workspace/WorkspaceNumberCard.native.js +1 -1
  212. package/dist/cjs/workspace/WorkspaceNumberCard.native.js.map +1 -1
  213. package/dist/cjs/workspace/WorkspaceQuickList.cjs +1 -1
  214. package/dist/cjs/workspace/WorkspaceQuickList.native.js +4 -2
  215. package/dist/cjs/workspace/WorkspaceQuickList.native.js.map +1 -1
  216. package/dist/cjs/workspace/WorkspaceRecents.cjs +1 -3
  217. package/dist/cjs/workspace/WorkspaceRecents.native.js +4 -4
  218. package/dist/cjs/workspace/WorkspaceRecents.native.js.map +1 -1
  219. package/dist/cjs/workspace/WorkspaceScreen.native.js +1 -1
  220. package/dist/cjs/workspace/WorkspaceScreen.native.js.map +1 -1
  221. package/dist/cjs/workspace/WorkspaceShortcut.cjs +1 -3
  222. package/dist/cjs/workspace/WorkspaceShortcut.native.js +5 -4
  223. package/dist/cjs/workspace/WorkspaceShortcut.native.js.map +1 -1
  224. package/dist/cjs/workspace/parseContent.native.js.map +1 -1
  225. package/dist/cjs/workspace/types.native.js.map +1 -1
  226. package/dist/cjs/workspace/useDashboardChart.native.js.map +1 -1
  227. package/dist/cjs/workspace/useWorkspaceDoc.native.js.map +1 -1
  228. package/dist/esm/chrome/BackofficeAwesomebar.native.js.map +1 -1
  229. package/dist/esm/chrome/CommandPalette.native.js.map +1 -1
  230. package/dist/esm/chrome/HelpMenu.native.js.map +1 -1
  231. package/dist/esm/chrome/NotificationsButton.native.js.map +1 -1
  232. package/dist/esm/chrome/UserMenu.native.js.map +1 -1
  233. package/dist/esm/chrome/awesomebar-data.native.js.map +1 -1
  234. package/dist/esm/chrome/command-palette-model.native.js.map +1 -1
  235. package/dist/esm/chrome/help-about-dialog.native.js.map +1 -1
  236. package/dist/esm/chrome/help-shortcuts-dialog.native.js.map +1 -1
  237. package/dist/esm/chrome/notifications-data.native.js.map +1 -1
  238. package/dist/esm/chrome/notifications-panel.native.js.map +1 -1
  239. package/dist/esm/chrome/notifications-utils.native.js.map +1 -1
  240. package/dist/esm/chrome/shortcuts.native.js.map +1 -1
  241. package/dist/esm/chrome/user-session.native.js.map +1 -1
  242. package/dist/esm/config/BackofficeProvider.native.js.map +1 -1
  243. package/dist/esm/config/capabilities.native.js.map +1 -1
  244. package/dist/esm/config/events.native.js.map +1 -1
  245. package/dist/esm/config/slots.native.js.map +1 -1
  246. package/dist/esm/desk/Desk.native.js.map +1 -1
  247. package/dist/esm/desk/DeskSurface.mjs.map +1 -1
  248. package/dist/esm/desk/DeskSurface.native.js.map +1 -1
  249. package/dist/esm/desk/resolveDeskPath.native.js.map +1 -1
  250. package/dist/esm/desk/scope.native.js.map +1 -1
  251. package/dist/esm/desk/target.native.js.map +1 -1
  252. package/dist/esm/form/DocFormScreen.native.js.map +1 -1
  253. package/dist/esm/form/FormConnections.native.js.map +1 -1
  254. package/dist/esm/form/FormDialogs.native.js.map +1 -1
  255. package/dist/esm/form/FormErrorBoundary.native.js.map +1 -1
  256. package/dist/esm/form/FormHeaderCluster.native.js.map +1 -1
  257. package/dist/esm/form/FormSidebarPanel.native.js.map +1 -1
  258. package/dist/esm/form/FormTimeline.native.js.map +1 -1
  259. package/dist/esm/form/FormToolbar.native.js.map +1 -1
  260. package/dist/esm/form/connections-data.native.js.map +1 -1
  261. package/dist/esm/form/createPrefill.mjs +1 -9
  262. package/dist/esm/form/createPrefill.mjs.map +1 -1
  263. package/dist/esm/form/createPrefill.native.js +1 -9
  264. package/dist/esm/form/createPrefill.native.js.map +1 -1
  265. package/dist/esm/form/dependsOn.native.js.map +1 -1
  266. package/dist/esm/form/dirtyTracking.mjs +1 -26
  267. package/dist/esm/form/dirtyTracking.mjs.map +1 -1
  268. package/dist/esm/form/dirtyTracking.native.js +1 -45
  269. package/dist/esm/form/dirtyTracking.native.js.map +1 -1
  270. package/dist/esm/form/docinfo.native.js.map +1 -1
  271. package/dist/esm/form/fetchFrom.mjs +1 -38
  272. package/dist/esm/form/fetchFrom.mjs.map +1 -1
  273. package/dist/esm/form/fetchFrom.native.js +1 -78
  274. package/dist/esm/form/fetchFrom.native.js.map +1 -1
  275. package/dist/esm/form/fieldPermissions.mjs +1 -26
  276. package/dist/esm/form/fieldPermissions.mjs.map +1 -1
  277. package/dist/esm/form/fieldPermissions.native.js +1 -48
  278. package/dist/esm/form/fieldPermissions.native.js.map +1 -1
  279. package/dist/esm/form/formActions.mjs +1 -145
  280. package/dist/esm/form/formActions.mjs.map +1 -1
  281. package/dist/esm/form/formActions.native.js +1 -152
  282. package/dist/esm/form/formActions.native.js.map +1 -1
  283. package/dist/esm/form/formLayout.mjs +1 -215
  284. package/dist/esm/form/formLayout.mjs.map +1 -1
  285. package/dist/esm/form/formLayout.native.js +1 -355
  286. package/dist/esm/form/formLayout.native.js.map +1 -1
  287. package/dist/esm/form/platformHooks.native.js.map +1 -1
  288. package/dist/esm/form/sidebar-attachments.native.js.map +1 -1
  289. package/dist/esm/form/sidebar-dialogs.native.js.map +1 -1
  290. package/dist/esm/form/sidebar-people.native.js.map +1 -1
  291. package/dist/esm/form/sidebar-rpc.native.js.map +1 -1
  292. package/dist/esm/form/sidebar-utils.native.js.map +1 -1
  293. package/dist/esm/form/timeline-entries.native.js.map +1 -1
  294. package/dist/esm/form/timeline-utils.native.js.map +1 -1
  295. package/dist/esm/form/useFormEngine.mjs +1 -360
  296. package/dist/esm/form/useFormEngine.mjs.map +1 -1
  297. package/dist/esm/form/useFormEngine.native.js +1 -446
  298. package/dist/esm/form/useFormEngine.native.js.map +1 -1
  299. package/dist/esm/i18n/en.native.js.map +1 -1
  300. package/dist/esm/i18n/index.native.js.map +1 -1
  301. package/dist/esm/index.native.js.map +1 -1
  302. package/dist/esm/list/AddTagsDialog.native.js.map +1 -1
  303. package/dist/esm/list/AssignToDialog.native.js.map +1 -1
  304. package/dist/esm/list/DoctypeListScreen.native.js.map +1 -1
  305. package/dist/esm/list/ListBulkActionsBar.native.js.map +1 -1
  306. package/dist/esm/list/ListFilterBar.native.js.map +1 -1
  307. package/dist/esm/list/ListSidebar.native.js.map +1 -1
  308. package/dist/esm/list/bulk-edit-dialog.native.js.map +1 -1
  309. package/dist/esm/list/bulk-export.native.js.map +1 -1
  310. package/dist/esm/list/bulk-submit-cancel.native.js.map +1 -1
  311. package/dist/esm/list/bulkActions.native.js.map +1 -1
  312. package/dist/esm/list/filter-chips.native.js.map +1 -1
  313. package/dist/esm/list/filter-editor.native.js.map +1 -1
  314. package/dist/esm/list/filter-fields.native.js.map +1 -1
  315. package/dist/esm/list/filter-saved.native.js.map +1 -1
  316. package/dist/esm/list/filter-sort.native.js.map +1 -1
  317. package/dist/esm/list/filter-standard.native.js.map +1 -1
  318. package/dist/esm/list/filterConversion.native.js.map +1 -1
  319. package/dist/esm/list/list-tools-sheet.native.js.map +1 -1
  320. package/dist/esm/list/listColumns.native.js.map +1 -1
  321. package/dist/esm/list/listFields.native.js.map +1 -1
  322. package/dist/esm/list/listFormat.native.js.map +1 -1
  323. package/dist/esm/list/listUrlState.native.js.map +1 -1
  324. package/dist/esm/list/sidebar-section.native.js.map +1 -1
  325. package/dist/esm/list/sidebar-stats.native.js.map +1 -1
  326. package/dist/esm/list/statusColors.native.js.map +1 -1
  327. package/dist/esm/navigation/navigator.native.js.map +1 -1
  328. package/dist/esm/navigation/paths.native.js.map +1 -1
  329. package/dist/esm/oneAdapter/index.native.js.map +1 -1
  330. package/dist/esm/quickEntry/QuickEntryDialog.native.js.map +1 -1
  331. package/dist/esm/quickEntry/quickEntryPlan.native.js.map +1 -1
  332. package/dist/esm/report/DoctypeReportView.native.js.map +1 -1
  333. package/dist/esm/report/QueryReportScreen.native.js.map +1 -1
  334. package/dist/esm/report/queryReportColumns.native.js.map +1 -1
  335. package/dist/esm/report/queryReportFilterBar.native.js.map +1 -1
  336. package/dist/esm/report/queryReportUrlState.native.js.map +1 -1
  337. package/dist/esm/report/report-grid.native.js.map +1 -1
  338. package/dist/esm/report/report-toolbar.native.js.map +1 -1
  339. package/dist/esm/report/reportShapes.native.js.map +1 -1
  340. package/dist/esm/report/reportViewModel.native.js.map +1 -1
  341. package/dist/esm/report/savedReports.native.js.map +1 -1
  342. package/dist/esm/report/useQueryReport.native.js.map +1 -1
  343. package/dist/esm/shared/deskLinks.native.js.map +1 -1
  344. package/dist/esm/shared/listNavContext.native.js.map +1 -1
  345. package/dist/esm/shared/types.native.js.map +1 -1
  346. package/dist/esm/shared/useDocinfo.native.js.map +1 -1
  347. package/dist/esm/shared/useDoctypeMeta.mjs.map +1 -1
  348. package/dist/esm/shared/useDoctypeMeta.native.js.map +1 -1
  349. package/dist/esm/shared/useFrappeApp.native.js.map +1 -1
  350. package/dist/esm/shared/useRecentVisit.native.js.map +1 -1
  351. package/dist/esm/shared/useSessionUserId.native.js.map +1 -1
  352. package/dist/esm/shared/useSlugTarget.native.js.map +1 -1
  353. package/dist/esm/shared/useUserRoles.native.js.map +1 -1
  354. package/dist/esm/shell/BackofficeShell.native.js.map +1 -1
  355. package/dist/esm/shell/HomeRedirect.native.js.map +1 -1
  356. package/dist/esm/shell/NotFoundScreen.native.js.map +1 -1
  357. package/dist/esm/shell/SlugScreen.native.js.map +1 -1
  358. package/dist/esm/shell/WorkspaceSidebar.native.js.map +1 -1
  359. package/dist/esm/shell/useWorkspaces.native.js.map +1 -1
  360. package/dist/esm/shell/workspaceIcons.native.js.map +1 -1
  361. package/dist/esm/views/CalendarView.native.js.map +1 -1
  362. package/dist/esm/views/DashboardView.native.js.map +1 -1
  363. package/dist/esm/views/DoctypeViewScreen.native.js.map +1 -1
  364. package/dist/esm/views/ImageView.native.js.map +1 -1
  365. package/dist/esm/views/KanbanView.native.js.map +1 -1
  366. package/dist/esm/views/ReportView.native.js.map +1 -1
  367. package/dist/esm/views/TreeView.native.js.map +1 -1
  368. package/dist/esm/views/ViewHeader.native.js.map +1 -1
  369. package/dist/esm/views/ViewStates.native.js.map +1 -1
  370. package/dist/esm/views/ViewSwitcherMenu.native.js.map +1 -1
  371. package/dist/esm/views/calendar-field-selector.native.js.map +1 -1
  372. package/dist/esm/views/connection.native.js.map +1 -1
  373. package/dist/esm/views/dashboard-data.native.js.map +1 -1
  374. package/dist/esm/views/deskViewConfigs.native.js.map +1 -1
  375. package/dist/esm/views/kanban-board-controls.native.js.map +1 -1
  376. package/dist/esm/views/kanban-field-picker.native.js.map +1 -1
  377. package/dist/esm/views/kanbanBoardOps.native.js.map +1 -1
  378. package/dist/esm/views/report-controls.native.js.map +1 -1
  379. package/dist/esm/views/viewAvailability.native.js.map +1 -1
  380. package/dist/esm/views/viewMeta.native.js.map +1 -1
  381. package/dist/esm/workspace/WorkspaceChartBlock.native.js.map +1 -1
  382. package/dist/esm/workspace/WorkspaceGrid.native.js.map +1 -1
  383. package/dist/esm/workspace/WorkspaceLinkCard.native.js.map +1 -1
  384. package/dist/esm/workspace/WorkspaceLinkDirectory.native.js.map +1 -1
  385. package/dist/esm/workspace/WorkspaceNumberCard.native.js.map +1 -1
  386. package/dist/esm/workspace/WorkspaceQuickList.mjs +2 -2
  387. package/dist/esm/workspace/WorkspaceQuickList.mjs.map +1 -1
  388. package/dist/esm/workspace/WorkspaceQuickList.native.js +4 -2
  389. package/dist/esm/workspace/WorkspaceQuickList.native.js.map +1 -1
  390. package/dist/esm/workspace/WorkspaceRecents.mjs +1 -3
  391. package/dist/esm/workspace/WorkspaceRecents.mjs.map +1 -1
  392. package/dist/esm/workspace/WorkspaceRecents.native.js +3 -3
  393. package/dist/esm/workspace/WorkspaceRecents.native.js.map +1 -1
  394. package/dist/esm/workspace/WorkspaceScreen.native.js.map +1 -1
  395. package/dist/esm/workspace/WorkspaceShortcut.mjs +1 -3
  396. package/dist/esm/workspace/WorkspaceShortcut.mjs.map +1 -1
  397. package/dist/esm/workspace/WorkspaceShortcut.native.js +4 -3
  398. package/dist/esm/workspace/WorkspaceShortcut.native.js.map +1 -1
  399. package/dist/esm/workspace/parseContent.native.js.map +1 -1
  400. package/dist/esm/workspace/types.native.js.map +1 -1
  401. package/dist/esm/workspace/useDashboardChart.native.js.map +1 -1
  402. package/dist/esm/workspace/useWorkspaceDoc.native.js.map +1 -1
  403. package/dist/jsx/desk/DeskSurface.mjs.map +1 -1
  404. package/dist/jsx/desk/DeskSurface.native.js.map +1 -1
  405. package/dist/jsx/form/createPrefill.mjs +1 -9
  406. package/dist/jsx/form/createPrefill.mjs.map +1 -1
  407. package/dist/jsx/form/createPrefill.native.js +3 -11
  408. package/dist/jsx/form/createPrefill.native.js.map +1 -1
  409. package/dist/jsx/form/dirtyTracking.mjs +1 -26
  410. package/dist/jsx/form/dirtyTracking.mjs.map +1 -1
  411. package/dist/jsx/form/dirtyTracking.native.js +4 -48
  412. package/dist/jsx/form/dirtyTracking.native.js.map +1 -1
  413. package/dist/jsx/form/fetchFrom.mjs +1 -38
  414. package/dist/jsx/form/fetchFrom.mjs.map +1 -1
  415. package/dist/jsx/form/fetchFrom.native.js +4 -81
  416. package/dist/jsx/form/fetchFrom.native.js.map +1 -1
  417. package/dist/jsx/form/fieldPermissions.mjs +1 -26
  418. package/dist/jsx/form/fieldPermissions.mjs.map +1 -1
  419. package/dist/jsx/form/fieldPermissions.native.js +4 -51
  420. package/dist/jsx/form/fieldPermissions.native.js.map +1 -1
  421. package/dist/jsx/form/formActions.mjs +1 -145
  422. package/dist/jsx/form/formActions.mjs.map +1 -1
  423. package/dist/jsx/form/formActions.native.js +2 -178
  424. package/dist/jsx/form/formActions.native.js.map +1 -1
  425. package/dist/jsx/form/formLayout.mjs +1 -215
  426. package/dist/jsx/form/formLayout.mjs.map +1 -1
  427. package/dist/jsx/form/formLayout.native.js +5 -359
  428. package/dist/jsx/form/formLayout.native.js.map +1 -1
  429. package/dist/jsx/form/useFormEngine.mjs +1 -360
  430. package/dist/jsx/form/useFormEngine.mjs.map +1 -1
  431. package/dist/jsx/form/useFormEngine.native.js +2 -447
  432. package/dist/jsx/form/useFormEngine.native.js.map +1 -1
  433. package/dist/jsx/index.native.js.map +1 -1
  434. package/dist/jsx/shared/useDoctypeMeta.mjs.map +1 -1
  435. package/dist/jsx/shared/useDoctypeMeta.native.js.map +1 -1
  436. package/dist/jsx/workspace/WorkspaceQuickList.mjs +2 -2
  437. package/dist/jsx/workspace/WorkspaceQuickList.mjs.map +1 -1
  438. package/dist/jsx/workspace/WorkspaceQuickList.native.js +3 -1
  439. package/dist/jsx/workspace/WorkspaceQuickList.native.js.map +1 -1
  440. package/dist/jsx/workspace/WorkspaceRecents.mjs +1 -3
  441. package/dist/jsx/workspace/WorkspaceRecents.mjs.map +1 -1
  442. package/dist/jsx/workspace/WorkspaceRecents.native.js +3 -3
  443. package/dist/jsx/workspace/WorkspaceRecents.native.js.map +1 -1
  444. package/dist/jsx/workspace/WorkspaceShortcut.mjs +1 -3
  445. package/dist/jsx/workspace/WorkspaceShortcut.mjs.map +1 -1
  446. package/dist/jsx/workspace/WorkspaceShortcut.native.js +4 -3
  447. package/dist/jsx/workspace/WorkspaceShortcut.native.js.map +1 -1
  448. package/package.json +12 -13
  449. package/src/desk/DeskSurface.tsx +8 -4
  450. package/src/form/createPrefill.ts +5 -25
  451. package/src/form/dirtyTracking.ts +4 -61
  452. package/src/form/fetchFrom.ts +5 -108
  453. package/src/form/fieldPermissions.ts +7 -65
  454. package/src/form/formActions.ts +10 -281
  455. package/src/form/formEngineShim.spec.ts +122 -0
  456. package/src/form/formLayout.ts +15 -387
  457. package/src/form/useFormEngine.ts +5 -493
  458. package/src/shared/useDoctypeMeta.ts +12 -100
  459. package/src/workspace/WorkspaceQuickList.tsx +10 -2
  460. package/src/workspace/WorkspaceRecents.tsx +3 -1
  461. package/src/workspace/WorkspaceShortcut.tsx +4 -1
  462. package/types/desk/DeskSurface.d.ts.map +1 -1
  463. package/types/form/createPrefill.d.ts +5 -16
  464. package/types/form/createPrefill.d.ts.map +1 -1
  465. package/types/form/dirtyTracking.d.ts +4 -33
  466. package/types/form/dirtyTracking.d.ts.map +1 -1
  467. package/types/form/fetchFrom.d.ts +5 -40
  468. package/types/form/fetchFrom.d.ts.map +1 -1
  469. package/types/form/fieldPermissions.d.ts +7 -35
  470. package/types/form/fieldPermissions.d.ts.map +1 -1
  471. package/types/form/formActions.d.ts +6 -91
  472. package/types/form/formActions.d.ts.map +1 -1
  473. package/types/form/formLayout.d.ts +12 -89
  474. package/types/form/formLayout.d.ts.map +1 -1
  475. package/types/form/useFormEngine.d.ts +5 -58
  476. package/types/form/useFormEngine.d.ts.map +1 -1
  477. package/types/shared/useDoctypeMeta.d.ts +2 -100
  478. package/types/shared/useDoctypeMeta.d.ts.map +1 -1
  479. package/types/workspace/WorkspaceQuickList.d.ts.map +1 -1
  480. package/types/workspace/WorkspaceRecents.d.ts.map +1 -1
  481. package/types/workspace/WorkspaceShortcut.d.ts.map +1 -1
  482. package/src/form/dirtyTracking.spec.ts +0 -91
  483. package/src/form/fetchFrom.spec.ts +0 -92
  484. package/src/form/fieldPermissions.spec.ts +0 -61
  485. package/src/form/formLayout.spec.ts +0 -373
@@ -1,496 +1,8 @@
1
1
  /**
2
- * The desk form state engine.
3
- *
4
- * - Edit mode: the doc lives in a name-filtered live collection
5
- * (useFrappeCollection + useLiveQuery) so realtime updates flow in; saves
6
- * write only dirty fields through the collection's optimistic update path
7
- * (live update_doc enforces If-Match OCC — a version conflict surfaces as
8
- * a save error and flips `conflict` so the UI can offer a reload).
9
- * - Create mode: seeds meta defaults (+ optional Duplicate/Amend prefill)
10
- * and inserts via direct REST so the server-issued name is returned for
11
- * router.replace(formPath(...)).
12
- * - Dirty tracking against the last server baseline; external updates land
13
- * on clean fields in place, dirty fields are preserved.
14
- * - Submit / Cancel lifecycle for is_submittable doctypes via
15
- * frappe.client.submit / frappe.client.cancel (probed) — realtime then
16
- * refreshes the live doc; Amend is a create-mode copy with amended_from.
2
+ * Desk form state engine — moved to
3
+ * `@multiplatform.one/frappe-ui/src/formEngine/useFormEngine` (MPO-15).
4
+ * Re-exported here so existing imports keep resolving.
17
5
  */
18
6
 
19
- import { eq, useFrappeCollection, useLiveQuery } from "@multiplatform.one/frappe";
20
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
21
- import type { DoctypeMeta } from "../shared/useDoctypeMeta";
22
- import type { FrappeConnection } from "./formActions";
23
- import {
24
- cancelDoc,
25
- createHttpClient,
26
- getLoggedUser,
27
- insertDoc,
28
- submitDoc,
29
- validateLink,
30
- } from "./formActions";
31
- import { buildCreateDefaults, isPromptNamed } from "./formLayout";
32
- import { takeCreatePrefill } from "./createPrefill";
33
- import { evaluateDependsOn } from "./dependsOn";
34
- import { computeDirtyFields, isEmptyValue, isSameValue } from "./dirtyTracking";
35
- import { applyFetchedValues, buildFetchMap } from "./fetchFrom";
36
-
37
- type DocRecord = Record<string, unknown> & { name: string; doctype: string };
38
-
39
- export interface FormEngine {
40
- /** Current (locally edited) doc values. */
41
- doc: Record<string, unknown>;
42
- /** Last authoritative server snapshot (undefined in create mode). */
43
- baseline: Record<string, unknown> | undefined;
44
- isLoading: boolean;
45
- /** Edit-mode doc missing after load settles (bad name / no permission). */
46
- notFound: boolean;
47
- /** The open doc was deleted on the server while open. */
48
- wasDeleted: boolean;
49
- isCreate: boolean;
50
- isDirty: boolean;
51
- dirtyFields: string[];
52
- isSaving: boolean;
53
- /** Per-field + `general` error messages. */
54
- errors: Record<string, string>;
55
- /** True after a save failed with a version conflict (OCC 409). */
56
- conflict: boolean;
57
- /** Logged-in user (for comments / likes / assignments). */
58
- currentUser: string;
59
- docstatus: number;
60
- setValue: (field: string, value: unknown) => void;
61
- /**
62
- * Save. Create mode resolves with the server-issued doc name;
63
- * edit mode resolves with the current name. Undefined = validation failed.
64
- */
65
- save: () => Promise<string | undefined>;
66
- /** Submit lifecycle (is_submittable): docstatus 0 → 1. */
67
- submit: () => Promise<boolean>;
68
- /** Cancel lifecycle: docstatus 1 → 2. */
69
- cancel: () => Promise<boolean>;
70
- /** Delete the doc through the live collection. */
71
- remove: () => Promise<boolean>;
72
- /** Discard local edits / clear conflict, back to the server baseline. */
73
- reload: () => void;
74
- /** Client-side required validation (fires on save too). */
75
- validate: () => Record<string, string>;
76
- }
77
-
78
- const LAYOUT_TYPES = new Set(["Section Break", "Column Break", "Tab Break", "Fold"]);
79
-
80
- function isConflictError(err: unknown): boolean {
81
- const e = err as { status?: number; exc_type?: string; message?: string } | undefined;
82
- if (!e) return false;
83
- if (e.status === 409) return true;
84
- if (e.exc_type === "TimestampMismatchError") return true;
85
- return /TimestampMismatch|has been modified/i.test(e.message ?? "");
86
- }
87
-
88
- function extractServerError(err: unknown, fallback: string): string {
89
- const e = err as { _server_messages?: string; message?: string; exc_type?: string } | undefined;
90
- if (e?._server_messages) {
91
- try {
92
- const messages = JSON.parse(e._server_messages) as string[];
93
- const parsed = messages
94
- .map((msg) => {
95
- try {
96
- return (JSON.parse(msg) as { message?: string }).message ?? "";
97
- } catch {
98
- return msg;
99
- }
100
- })
101
- .filter(Boolean);
102
- if (parsed.length > 0) return parsed.join("\n");
103
- } catch {
104
- // fall through
105
- }
106
- }
107
- return e?.message || fallback;
108
- }
109
-
110
- export function useFormEngine(
111
- connection: FrappeConnection | undefined,
112
- doctype: string,
113
- /** Document name, or undefined for create mode. */
114
- name: string | undefined,
115
- meta: DoctypeMeta | undefined,
116
- translate: (key: string, options?: Record<string, unknown>) => string,
117
- ): FormEngine {
118
- const isCreate = !name;
119
- const [localDoc, setLocalDoc] = useState<Record<string, unknown>>({});
120
- const [baseline, setBaseline] = useState<Record<string, unknown> | undefined>(undefined);
121
- const [isSaving, setIsSaving] = useState(false);
122
- const [errors, setErrors] = useState<Record<string, string>>({});
123
- const [conflict, setConflict] = useState(false);
124
- const [wasDeleted, setWasDeleted] = useState(false);
125
- const [currentUser, setCurrentUser] = useState("");
126
- const everLoadedRef = useRef(false);
127
- const seededRef = useRef(false);
128
- const localDocRef = useRef(localDoc);
129
- localDocRef.current = localDoc;
130
- const baselineRef = useRef(baseline);
131
- baselineRef.current = baseline;
132
-
133
- // ---------------------------------------------------------------------
134
- // Live doc subscription (edit mode)
135
- // ---------------------------------------------------------------------
136
- const docCollection = useFrappeCollection<DocRecord>(name ? connection : undefined, doctype, {
137
- filters: name ? { name } : undefined,
138
- });
139
- const { data: rawDocData, isLoading: isDocLoading } = useLiveQuery(
140
- (q) => {
141
- if (!docCollection || !name) return null;
142
- return q.from({ _doc: docCollection }).where(({ _doc }) => eq(_doc.name, name));
143
- },
144
- [docCollection, name],
145
- );
146
- const liveDoc = useMemo(() => {
147
- const arr = Array.isArray(rawDocData) ? rawDocData : rawDocData ? [rawDocData] : [];
148
- return (arr[0] ?? null) as DocRecord | null;
149
- }, [rawDocData]);
150
-
151
- // ---------------------------------------------------------------------
152
- // Session user
153
- // ---------------------------------------------------------------------
154
- useEffect(() => {
155
- if (!connection) return;
156
- let cancelled = false;
157
- getLoggedUser(createHttpClient(connection))
158
- .then((user) => {
159
- if (!cancelled) setCurrentUser(user);
160
- })
161
- .catch(() => {
162
- // Anonymous fallback — comment composer degrades gracefully.
163
- });
164
- return () => {
165
- cancelled = true;
166
- };
167
- }, [connection?.baseURL]);
168
-
169
- // ---------------------------------------------------------------------
170
- // Reset per-document
171
- // ---------------------------------------------------------------------
172
- useEffect(() => {
173
- everLoadedRef.current = false;
174
- seededRef.current = false;
175
- setWasDeleted(false);
176
- setConflict(false);
177
- setErrors({});
178
- setBaseline(undefined);
179
- setLocalDoc({});
180
- }, [doctype, name]);
181
-
182
- // ---------------------------------------------------------------------
183
- // Create-mode seeding (meta defaults + Duplicate/Amend prefill)
184
- // ---------------------------------------------------------------------
185
- useEffect(() => {
186
- if (!isCreate || !meta || seededRef.current) return;
187
- seededRef.current = true;
188
- const defaults = buildCreateDefaults(meta.fields, currentUser || undefined);
189
- const prefill = takeCreatePrefill(doctype);
190
- setLocalDoc({ ...defaults, ...prefill, doctype });
191
- // currentUser intentionally not a dep: seeding happens once per mount;
192
- // a late-resolving user only matters for brand-new blank forms where
193
- // the meta usually arrives later anyway.
194
- }, [isCreate, meta, doctype]);
195
-
196
- // ---------------------------------------------------------------------
197
- // Field-level in-place sync (edit mode): server updates land on clean
198
- // fields; dirty fields keep the user's edits.
199
- // ---------------------------------------------------------------------
200
- useEffect(() => {
201
- if (!name) return;
202
- if (liveDoc) {
203
- everLoadedRef.current = true;
204
- setWasDeleted(false);
205
- const incoming = liveDoc as Record<string, unknown>;
206
- const prevBaseline = baselineRef.current;
207
- if (!prevBaseline) {
208
- setBaseline(incoming);
209
- setLocalDoc(incoming);
210
- return;
211
- }
212
- const local = localDocRef.current;
213
- const merged: Record<string, unknown> = { ...incoming };
214
- for (const key of Object.keys(local)) {
215
- // Same predicate as dirty tracking: a normalization-identical local
216
- // value is not an edit, so the incoming server value wins.
217
- if (!isSameValue(local[key], prevBaseline[key])) merged[key] = local[key];
218
- }
219
- setBaseline(incoming);
220
- setLocalDoc(merged);
221
- } else if (everLoadedRef.current && !isDocLoading) {
222
- setWasDeleted(true);
223
- }
224
- }, [liveDoc, isDocLoading, name]);
225
-
226
- // ---------------------------------------------------------------------
227
- // Dirty tracking
228
- // ---------------------------------------------------------------------
229
- const dirtyFields = useMemo(() => computeDirtyFields(localDoc, baseline), [localDoc, baseline]);
230
- const isDirty = dirtyFields.length > 0;
231
-
232
- // ---------------------------------------------------------------------
233
- // fetch_from preview: when a Link with dependent fetch_from targets
234
- // changes, pull the source columns via frappe.client.validate_link and
235
- // patch the targets (desk validate_link_and_fetch). Server stays
236
- // authoritative on save.
237
- // ---------------------------------------------------------------------
238
- const fetchMap = useMemo(() => (meta ? buildFetchMap(meta.fields) : undefined), [meta]);
239
- const fetchStateRef = useRef<{
240
- meta: DoctypeMeta | undefined;
241
- connection: FrappeConnection | undefined;
242
- }>({ meta: undefined, connection: undefined });
243
- fetchStateRef.current = { meta, connection };
244
- const fetchMapRef = useRef(fetchMap);
245
- fetchMapRef.current = fetchMap;
246
-
247
- const runFetchFrom = useCallback((field: string, value: unknown) => {
248
- const rules = fetchMapRef.current?.get(field);
249
- if (!rules || rules.length === 0) return;
250
- const { meta: currentMeta, connection: currentConnection } = fetchStateRef.current;
251
- const linkField = currentMeta?.fields.find((f) => f.fieldname === field);
252
- const targetDoctype = typeof linkField?.options === "string" ? linkField.options : "";
253
- const applyPatch = (fetched: Record<string, unknown>) => {
254
- setLocalDoc((prev) => {
255
- // The link changed again while the fetch was in flight — drop it.
256
- if (prev[field] !== value) return prev;
257
- const patch = applyFetchedValues(rules, fetched, prev);
258
- return Object.keys(patch).length > 0 ? { ...prev, ...patch } : prev;
259
- });
260
- };
261
- if (value === undefined || value === null || value === "") {
262
- // Cleared link → desk blanks the dependent targets.
263
- applyPatch({});
264
- return;
265
- }
266
- if (!currentConnection || !targetDoctype || currentConnection.fixtures) return;
267
- const sources = Array.from(new Set(rules.map((rule) => rule.source)));
268
- validateLink(createHttpClient(currentConnection), targetDoctype, String(value), sources)
269
- .then(applyPatch)
270
- .catch(() => {
271
- // Invalid link / no read perm on source — leave targets as-is;
272
- // the server re-validates on save.
273
- });
274
- }, []);
275
-
276
- const setValue = useCallback(
277
- (field: string, value: unknown) => {
278
- setLocalDoc((prev) => ({ ...prev, [field]: value }));
279
- setErrors((prev) => {
280
- if (!(field in prev)) return prev;
281
- const next = { ...prev };
282
- delete next[field];
283
- return next;
284
- });
285
- runFetchFrom(field, value);
286
- },
287
- [runFetchFrom],
288
- );
289
-
290
- // ---------------------------------------------------------------------
291
- // Validation
292
- // ---------------------------------------------------------------------
293
- const validate = useCallback((): Record<string, string> => {
294
- if (!meta) return {};
295
- // Same evaluation context desk gives depends_on: `__islocal` marks an
296
- // unsaved doc, `__session_user` backs `frappe.session.user` references.
297
- const doc: Record<string, unknown> = {
298
- ...localDocRef.current,
299
- __islocal: isCreate ? 1 : 0,
300
- ...(currentUser ? { __session_user: currentUser } : {}),
301
- };
302
- const validationErrors: Record<string, string> = {};
303
- // Prompt-named doctypes need a user-entered name before insert
304
- // (probed: REST insert without one fails with "Please set the document name").
305
- if (isCreate && isPromptNamed(meta.autoname, meta.naming_rule) && isEmptyValue(doc.name)) {
306
- validationErrors.name = translate("nameRequired", {
307
- defaultValue: "Name is required",
308
- });
309
- }
310
- for (const field of meta.fields) {
311
- if (field.hidden || LAYOUT_TYPES.has(field.fieldtype)) continue;
312
- // Desk parity: a field hidden by depends_on is not enforced client-side.
313
- if (!evaluateDependsOn(field.depends_on, doc, true)) continue;
314
- const required =
315
- !!field.reqd ||
316
- (!!field.mandatory_depends_on && evaluateDependsOn(field.mandatory_depends_on, doc, false));
317
- if (!required) continue;
318
- if (isEmptyValue(doc[field.fieldname])) {
319
- validationErrors[field.fieldname] = translate("fieldRequired", {
320
- defaultValue: "{{label}} is required",
321
- label: field.label || field.fieldname,
322
- });
323
- }
324
- }
325
- return validationErrors;
326
- }, [meta, isCreate, currentUser, translate]);
327
-
328
- // ---------------------------------------------------------------------
329
- // Save
330
- // ---------------------------------------------------------------------
331
- const save = useCallback(async (): Promise<string | undefined> => {
332
- if (wasDeleted || !connection) return undefined;
333
- const requiredErrors = validate();
334
- if (Object.keys(requiredErrors).length > 0) {
335
- setErrors(requiredErrors);
336
- return undefined;
337
- }
338
- setIsSaving(true);
339
- setErrors({});
340
- try {
341
- if (name) {
342
- if (!docCollection) return undefined;
343
- const local = localDocRef.current;
344
- const base = baselineRef.current ?? {};
345
- // Same predicate as dirty tracking: normalization-identical values
346
- // must not be written back to the server as phantom edits.
347
- const changed = Object.keys(local).filter(
348
- (key) => key !== "doctype" && key !== "name" && !isSameValue(local[key], base[key]),
349
- );
350
- if (changed.length > 0) {
351
- const tx = docCollection.update(name, (draft) => {
352
- for (const key of changed) {
353
- (draft as Record<string, unknown>)[key] = local[key];
354
- }
355
- });
356
- await tx.isPersisted.promise;
357
- }
358
- setConflict(false);
359
- return name;
360
- }
361
- // Create mode: direct REST insert to obtain the server-issued name.
362
- // A user-entered `name` is kept for prompt-named doctypes; empty names
363
- // are stripped so hash/series autonaming applies.
364
- const { doctype: _dt, name: newName, ...values } = localDocRef.current;
365
- if (typeof newName === "string" && newName.trim()) {
366
- values.name = newName.trim();
367
- }
368
- const created = await insertDoc(createHttpClient(connection), doctype, values);
369
- return String(created.name ?? "");
370
- } catch (err) {
371
- if (isConflictError(err)) {
372
- setConflict(true);
373
- setErrors({
374
- general: translate("conflictError", {
375
- defaultValue:
376
- "This document was modified on the server after you opened it. Reload to get the latest version — your unsaved edits will be discarded.",
377
- }),
378
- });
379
- } else {
380
- setErrors({
381
- general: extractServerError(
382
- err,
383
- translate("saveFailed", { defaultValue: "Failed to save" }),
384
- ),
385
- });
386
- }
387
- return undefined;
388
- } finally {
389
- setIsSaving(false);
390
- }
391
- }, [wasDeleted, connection, validate, name, docCollection, doctype, translate]);
392
-
393
- // ---------------------------------------------------------------------
394
- // Submit / Cancel lifecycle
395
- // ---------------------------------------------------------------------
396
- const submit = useCallback(async (): Promise<boolean> => {
397
- if (!connection || !name) return false;
398
- setIsSaving(true);
399
- setErrors({});
400
- try {
401
- // The full current server doc (incl. `modified`) is required for OCC.
402
- const base = baselineRef.current;
403
- if (!base) return false;
404
- await submitDoc(createHttpClient(connection), { ...base, doctype });
405
- return true;
406
- } catch (err) {
407
- if (isConflictError(err)) setConflict(true);
408
- setErrors({
409
- general: extractServerError(
410
- err,
411
- translate("submitFailed", { defaultValue: "Failed to submit" }),
412
- ),
413
- });
414
- return false;
415
- } finally {
416
- setIsSaving(false);
417
- }
418
- }, [connection, name, doctype, translate]);
419
-
420
- const cancel = useCallback(async (): Promise<boolean> => {
421
- if (!connection || !name) return false;
422
- setIsSaving(true);
423
- setErrors({});
424
- try {
425
- await cancelDoc(createHttpClient(connection), doctype, name);
426
- return true;
427
- } catch (err) {
428
- setErrors({
429
- general: extractServerError(
430
- err,
431
- translate("cancelFailed", { defaultValue: "Failed to cancel" }),
432
- ),
433
- });
434
- return false;
435
- } finally {
436
- setIsSaving(false);
437
- }
438
- }, [connection, name, doctype, translate]);
439
-
440
- const remove = useCallback(async (): Promise<boolean> => {
441
- if (!docCollection || !name || wasDeleted) return false;
442
- setIsSaving(true);
443
- setErrors({});
444
- try {
445
- const tx = docCollection.delete(name);
446
- await tx.isPersisted.promise;
447
- return true;
448
- } catch (err) {
449
- setErrors({
450
- general: extractServerError(
451
- err,
452
- translate("deleteFailed", { defaultValue: "Failed to delete" }),
453
- ),
454
- });
455
- return false;
456
- } finally {
457
- setIsSaving(false);
458
- }
459
- }, [docCollection, name, wasDeleted, translate]);
460
-
461
- const reload = useCallback(() => {
462
- setConflict(false);
463
- setErrors({});
464
- if (baselineRef.current) {
465
- setLocalDoc(baselineRef.current);
466
- } else if (!name) {
467
- seededRef.current = false;
468
- setLocalDoc({ doctype });
469
- }
470
- }, [doctype, name]);
471
-
472
- const docstatus = Number((baseline as { docstatus?: unknown } | undefined)?.docstatus ?? 0);
473
-
474
- return {
475
- doc: localDoc,
476
- baseline,
477
- isLoading: !!name && isDocLoading && !everLoadedRef.current,
478
- notFound: !!name && !isDocLoading && !liveDoc && !everLoadedRef.current,
479
- wasDeleted,
480
- isCreate,
481
- isDirty,
482
- dirtyFields,
483
- isSaving,
484
- errors,
485
- conflict,
486
- currentUser,
487
- docstatus,
488
- setValue,
489
- save,
490
- submit,
491
- cancel,
492
- remove,
493
- reload,
494
- validate,
495
- };
496
- }
7
+ export { useFormEngine } from "@multiplatform.one/frappe-ui";
8
+ export type { FormEngine } from "@multiplatform.one/frappe-ui";
@@ -6,109 +6,21 @@
6
6
  // module-wide cache either way.
7
7
  import type { FixtureProvider } from "@multiplatform.one/frappe";
8
8
  import { useFrappeConfig } from "@multiplatform.one/frappe-ui";
9
+ import type { DocFieldMeta, DoctypeMeta } from "@multiplatform.one/frappe-ui";
9
10
  import { useCallback, useEffect, useMemo, useState } from "react";
10
11
  import { useFrappeApp } from "./useFrappeApp";
11
12
 
12
- /** A single DocField row from a DocType meta (loose server is source of truth). */
13
- export interface DocFieldMeta {
14
- fieldname: string;
15
- label?: string;
16
- fieldtype: string;
17
- options?: string;
18
- reqd?: 0 | 1;
19
- hidden?: 0 | 1;
20
- read_only?: 0 | 1;
21
- bold?: 0 | 1;
22
- in_list_view?: 0 | 1;
23
- in_standard_filter?: 0 | 1;
24
- in_global_search?: 0 | 1;
25
- allow_in_quick_entry?: 0 | 1;
26
- allow_on_submit?: 0 | 1;
27
- no_copy?: 0 | 1;
28
- collapsible?: 0 | 1;
29
- collapsible_depends_on?: string;
30
- depends_on?: string;
31
- mandatory_depends_on?: string;
32
- read_only_depends_on?: string;
33
- fetch_from?: string;
34
- permlevel?: number;
35
- length?: number;
36
- default?: string;
37
- description?: string;
38
- precision?: string | number;
39
- idx?: number;
40
- [key: string]: unknown;
41
- }
42
-
43
- /** DocType Link child row (Connections tab). Probed: `group` arrives null when unset. */
44
- export interface DocLinkMeta {
45
- name?: string;
46
- link_doctype: string;
47
- link_fieldname: string;
48
- group?: string | null;
49
- hidden?: 0 | 1;
50
- is_child_table?: 0 | 1;
51
- parent_doctype?: string;
52
- table_fieldname?: string;
53
- [key: string]: unknown;
54
- }
55
-
56
- /** Role permission row from the DocType meta. */
57
- export interface DocPermissionRule {
58
- role?: string;
59
- permlevel?: number;
60
- read?: 0 | 1;
61
- write?: 0 | 1;
62
- create?: 0 | 1;
63
- delete?: 0 | 1;
64
- submit?: 0 | 1;
65
- cancel?: 0 | 1;
66
- amend?: 0 | 1;
67
- print?: 0 | 1;
68
- email?: 0 | 1;
69
- share?: 0 | 1;
70
- if_owner?: 0 | 1;
71
- [key: string]: unknown;
72
- }
73
-
74
- /** DocType meta as returned by frappe.desk.form.load.getdoctype (loose). */
75
- export interface DoctypeMeta {
76
- doctype?: string;
77
- name: string;
78
- module?: string;
79
- issingle?: 0 | 1;
80
- istable?: 0 | 1;
81
- is_submittable?: 0 | 1;
82
- is_tree?: 0 | 1;
83
- /** Desk treeview_settings asset (`{doctype}_tree.js`) — gates Tree. */
84
- __tree_js?: string;
85
- /** Desk calendar_settings asset (`{doctype}_calendar.js`) — gates Calendar. */
86
- __calendar_js?: string;
87
- is_virtual?: 0 | 1;
88
- editable_grid?: 0 | 1;
89
- track_changes?: 0 | 1;
90
- quick_entry?: 0 | 1;
91
- autoname?: string;
92
- naming_rule?: string;
93
- allow_rename?: 0 | 1;
94
- allow_copy?: 0 | 1;
95
- read_only?: 0 | 1;
96
- in_create?: 0 | 1;
97
- hide_toolbar?: 0 | 1;
98
- max_attachments?: number;
99
- title_field?: string;
100
- image_field?: string;
101
- search_fields?: string;
102
- sort_field?: string;
103
- sort_order?: string;
104
- icon?: string;
105
- document_type?: string;
106
- fields: DocFieldMeta[];
107
- permissions?: DocPermissionRule[];
108
- links?: DocLinkMeta[];
109
- states?: Array<{ title?: string; color?: string } & Record<string, unknown>>;
110
- [key: string]: unknown;
111
- }
13
+ // The meta SHAPES live one tier down, in
14
+ // `@multiplatform.one/frappe-ui/src/formEngine/doctypeMeta` the desk form
15
+ // engine consumes them and the engine moved there (MPO-15). This module keeps
16
+ // the LOADER (it needs the backoffice app context) and re-exports the shapes
17
+ // so every existing `@multiplatform.one/backoffice` import still resolves.
18
+ export type {
19
+ DocFieldMeta,
20
+ DocLinkMeta,
21
+ DocPermissionRule,
22
+ DoctypeMeta,
23
+ } from "@multiplatform.one/frappe-ui";
112
24
 
113
25
  export interface DoctypeMetaBundle {
114
26
  /** Parent doctype meta (docs[0]) */
@@ -7,7 +7,11 @@
7
7
  */
8
8
  import { Card, Separator, Text, XStack, YStack } from "@multiplatform.one/components";
9
9
  import { FrappeList } from "@multiplatform.one/frappe-ui";
10
- import { ensureFocusVisibleRing, useResolvedKnobs } from "@multiplatform.one/theme";
10
+ import {
11
+ ensureFocusVisibleRing,
12
+ FOCUS_RING_HALO_OFFSET,
13
+ useResolvedKnobs,
14
+ } from "@multiplatform.one/theme";
11
15
  import { useMemo } from "react";
12
16
  import { useTranslation } from "react-i18next";
13
17
  import { useBackofficeNavigator, useBackofficePaths } from "../config/BackofficeProvider";
@@ -62,7 +66,11 @@ export function WorkspaceQuickList({ row }: WorkspaceQuickListProps) {
62
66
  tabIndex={0}
63
67
  outlineWidth={0}
64
68
  focusStyle={{ outlineWidth: 0 }}
65
- focusVisibleStyle={ensureFocusVisibleRing({ outlineOffset: 2 })}
69
+ // LC-71 §4 halo: inline text link ("View All" sits on the header
70
+ // row beside the section title, not on its own ground).
71
+ focusVisibleStyle={ensureFocusVisibleRing({
72
+ outlineOffset: FOCUS_RING_HALO_OFFSET,
73
+ })}
66
74
  hoverStyle={{ color: "$color12" }}
67
75
  onPress={() => navigator.navigate(paths.list(row.document_type))}
68
76
  >
@@ -86,7 +86,9 @@ export function WorkspaceRecents() {
86
86
  tabIndex={0}
87
87
  outlineWidth={0}
88
88
  focusStyle={{ outlineWidth: 0 }}
89
- focusVisibleStyle={ensureFocusVisibleRing({ outlineOffset: 2 })}
89
+ // Default ring (offset 0): a recents card is a standalone
90
+ // rectangle on the page ground, so no LC-71 §4 carve-out (MPO-92).
91
+ focusVisibleStyle={ensureFocusVisibleRing()}
90
92
  >
91
93
  <XStack paddingHorizontal="$3" minHeight={44} alignItems="center" {...knobProps.gap}>
92
94
  <ClockCounterClockwiseIcon size={iconSize} color={iconColor} aria-hidden />
@@ -210,7 +210,10 @@ export function WorkspaceShortcut({ row, onPress }: WorkspaceShortcutProps) {
210
210
  tabIndex={target.disabled && !onPress ? undefined : 0}
211
211
  outlineWidth={0}
212
212
  focusStyle={{ outlineWidth: 0 }}
213
- focusVisibleStyle={ensureFocusVisibleRing({ outlineOffset: 2 })}
213
+ // Default ring (offset 0): a shortcut tile is a standalone rectangle on
214
+ // the page ground, not a thumb or an inline link, so it takes no LC-71 §4
215
+ // carve-out (MPO-92).
216
+ focusVisibleStyle={ensureFocusVisibleRing()}
214
217
  >
215
218
  {/* Compact chip anatomy: icon + label + count, ≥44px press target
216
219
  (DG-LAY-04), self-sized so the band wraps instead of stretching. */}
@@ -1 +1 @@
1
- {"version":3,"file":"DeskSurface.d.ts","sourceRoot":"","sources":["../../src/desk/DeskSurface.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAC3B,aAAa,CAAC,gBAAgB,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAEpD,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAoCzF,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,gEAAgE;IAChE,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACnC;AAED,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,SAAS,EACT,QAAQ,EACR,cAAc,EACd,KAAK,GACN,EAAE,oBAAoB,2CAoCtB;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,4CAMjC"}
1
+ {"version":3,"file":"DeskSurface.d.ts","sourceRoot":"","sources":["../../src/desk/DeskSurface.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAC3B,aAAa,CAAC,gBAAgB,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAEpD,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAoCzF,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,gEAAgE;IAChE,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACnC;AAED,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,SAAS,EACT,QAAQ,EACR,cAAc,EACd,KAAK,GACN,EAAE,oBAAoB,2CAwCtB;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,4CAMjC"}