@multiplatform.one/frappe-ui 7.28.1 → 7.29.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 (325) hide show
  1. package/dist/cjs/FrappeCalendar.cjs +3 -2
  2. package/dist/cjs/FrappeCalendar.native.js +3 -2
  3. package/dist/cjs/FrappeCalendar.native.js.map +1 -1
  4. package/dist/cjs/FrappeForm.cjs +148 -464
  5. package/dist/cjs/FrappeForm.native.js +152 -633
  6. package/dist/cjs/FrappeForm.native.js.map +1 -1
  7. package/dist/cjs/FrappeListView.cjs +5 -27
  8. package/dist/cjs/FrappeListView.native.js +11 -32
  9. package/dist/cjs/FrappeListView.native.js.map +1 -1
  10. package/dist/cjs/FrappeReportBuilder.cjs +523 -309
  11. package/dist/cjs/FrappeReportBuilder.native.js +658 -353
  12. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  13. package/dist/cjs/FrappeReportView.cjs +35 -234
  14. package/dist/cjs/FrappeReportView.native.js +39 -283
  15. package/dist/cjs/FrappeReportView.native.js.map +1 -1
  16. package/dist/cjs/dependsOn.cjs +2 -2
  17. package/dist/cjs/dependsOn.native.js +1 -2
  18. package/dist/cjs/dependsOn.native.js.map +1 -1
  19. package/dist/cjs/fields/shared/EditorPreviewPanes.cjs +2 -2
  20. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js +2 -2
  21. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  22. package/dist/cjs/formEngine/docPermissions.cjs +20 -0
  23. package/dist/cjs/formEngine/docPermissions.native.js +69 -0
  24. package/dist/cjs/formEngine/docPermissions.native.js.map +1 -1
  25. package/dist/cjs/formEngine/index.cjs +2 -0
  26. package/dist/cjs/formEngine/index.native.js +2 -0
  27. package/dist/cjs/formEngine/index.native.js.map +1 -1
  28. package/dist/cjs/index.cjs +67 -7
  29. package/dist/cjs/index.native.js +67 -7
  30. package/dist/cjs/index.native.js.map +1 -1
  31. package/dist/cjs/liveErrors.cjs +8 -2
  32. package/dist/cjs/liveErrors.native.js +8 -2
  33. package/dist/cjs/liveErrors.native.js.map +1 -1
  34. package/dist/cjs/measures.cjs +31 -0
  35. package/dist/cjs/measures.native.js +34 -0
  36. package/dist/cjs/measures.native.js.map +1 -0
  37. package/dist/cjs/recordShape.cjs +103 -0
  38. package/dist/cjs/recordShape.native.js +115 -0
  39. package/dist/cjs/recordShape.native.js.map +1 -0
  40. package/dist/cjs/report/ReportGrid.cjs +453 -0
  41. package/dist/cjs/report/ReportGrid.native.js +510 -0
  42. package/dist/cjs/report/ReportGrid.native.js.map +1 -0
  43. package/dist/cjs/report/ReportViewToolbar.cjs +253 -0
  44. package/dist/cjs/report/ReportViewToolbar.native.js +303 -0
  45. package/dist/cjs/report/ReportViewToolbar.native.js.map +1 -0
  46. package/dist/cjs/report/queryReport.cjs +444 -0
  47. package/dist/cjs/report/queryReport.native.js +588 -0
  48. package/dist/cjs/report/queryReport.native.js.map +1 -0
  49. package/dist/cjs/report/queryReportColumns.cjs +131 -0
  50. package/dist/cjs/report/queryReportColumns.native.js +159 -0
  51. package/dist/cjs/report/queryReportColumns.native.js.map +1 -0
  52. package/dist/cjs/report/reportViewModel.cjs +386 -0
  53. package/dist/cjs/report/reportViewModel.native.js +657 -0
  54. package/dist/cjs/report/reportViewModel.native.js.map +1 -0
  55. package/dist/cjs/report/savedReports.cjs +137 -0
  56. package/dist/cjs/report/savedReports.native.js +169 -0
  57. package/dist/cjs/report/savedReports.native.js.map +1 -0
  58. package/dist/cjs/report/useFrappeReport.cjs +184 -0
  59. package/dist/cjs/report/useFrappeReport.native.js +214 -0
  60. package/dist/cjs/report/useFrappeReport.native.js.map +1 -0
  61. package/dist/cjs/report/useQueryReport.cjs +201 -0
  62. package/dist/cjs/report/useQueryReport.native.js +233 -0
  63. package/dist/cjs/report/useQueryReport.native.js.map +1 -0
  64. package/dist/cjs/useFrappeForm.cjs +558 -0
  65. package/dist/cjs/useFrappeForm.native.js +714 -0
  66. package/dist/cjs/useFrappeForm.native.js.map +1 -0
  67. package/dist/esm/FrappeCalendar.mjs +4 -3
  68. package/dist/esm/FrappeCalendar.mjs.map +1 -1
  69. package/dist/esm/FrappeCalendar.native.js +4 -3
  70. package/dist/esm/FrappeCalendar.native.js.map +1 -1
  71. package/dist/esm/FrappeForm.mjs +151 -467
  72. package/dist/esm/FrappeForm.mjs.map +1 -1
  73. package/dist/esm/FrappeForm.native.js +155 -636
  74. package/dist/esm/FrappeForm.native.js.map +1 -1
  75. package/dist/esm/FrappeListView.mjs +6 -28
  76. package/dist/esm/FrappeListView.mjs.map +1 -1
  77. package/dist/esm/FrappeListView.native.js +12 -33
  78. package/dist/esm/FrappeListView.native.js.map +1 -1
  79. package/dist/esm/FrappeReportBuilder.mjs +526 -312
  80. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  81. package/dist/esm/FrappeReportBuilder.native.js +661 -356
  82. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  83. package/dist/esm/FrappeReportView.mjs +30 -229
  84. package/dist/esm/FrappeReportView.mjs.map +1 -1
  85. package/dist/esm/FrappeReportView.native.js +34 -278
  86. package/dist/esm/FrappeReportView.native.js.map +1 -1
  87. package/dist/esm/dependsOn.mjs +2 -2
  88. package/dist/esm/dependsOn.mjs.map +1 -1
  89. package/dist/esm/dependsOn.native.js +1 -2
  90. package/dist/esm/dependsOn.native.js.map +1 -1
  91. package/dist/esm/fields/shared/EditorPreviewPanes.mjs +2 -2
  92. package/dist/esm/fields/shared/EditorPreviewPanes.mjs.map +1 -1
  93. package/dist/esm/fields/shared/EditorPreviewPanes.native.js +2 -2
  94. package/dist/esm/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  95. package/dist/esm/formEngine/docPermissions.mjs +19 -1
  96. package/dist/esm/formEngine/docPermissions.mjs.map +1 -1
  97. package/dist/esm/formEngine/docPermissions.native.js +68 -1
  98. package/dist/esm/formEngine/docPermissions.native.js.map +1 -1
  99. package/dist/esm/formEngine/index.mjs +2 -2
  100. package/dist/esm/formEngine/index.mjs.map +1 -1
  101. package/dist/esm/formEngine/index.native.js +2 -2
  102. package/dist/esm/formEngine/index.native.js.map +1 -1
  103. package/dist/esm/index.mjs +16 -4
  104. package/dist/esm/index.mjs.map +1 -1
  105. package/dist/esm/index.native.js +16 -4
  106. package/dist/esm/index.native.js.map +1 -1
  107. package/dist/esm/liveErrors.mjs +8 -3
  108. package/dist/esm/liveErrors.mjs.map +1 -1
  109. package/dist/esm/liveErrors.native.js +8 -3
  110. package/dist/esm/liveErrors.native.js.map +1 -1
  111. package/dist/esm/measures.mjs +5 -0
  112. package/dist/esm/measures.mjs.map +1 -0
  113. package/dist/esm/measures.native.js +5 -0
  114. package/dist/esm/measures.native.js.map +1 -0
  115. package/dist/esm/recordShape.mjs +74 -0
  116. package/dist/esm/recordShape.mjs.map +1 -0
  117. package/dist/esm/recordShape.native.js +83 -0
  118. package/dist/esm/recordShape.native.js.map +1 -0
  119. package/dist/esm/report/ReportGrid.mjs +428 -0
  120. package/dist/esm/report/ReportGrid.mjs.map +1 -0
  121. package/dist/esm/report/ReportGrid.native.js +471 -0
  122. package/dist/esm/report/ReportGrid.native.js.map +1 -0
  123. package/dist/esm/report/ReportViewToolbar.mjs +228 -0
  124. package/dist/esm/report/ReportViewToolbar.mjs.map +1 -0
  125. package/dist/esm/report/ReportViewToolbar.native.js +264 -0
  126. package/dist/esm/report/ReportViewToolbar.native.js.map +1 -0
  127. package/dist/esm/report/queryReport.mjs +404 -0
  128. package/dist/esm/report/queryReport.mjs.map +1 -0
  129. package/dist/esm/report/queryReport.native.js +545 -0
  130. package/dist/esm/report/queryReport.native.js.map +1 -0
  131. package/dist/esm/report/queryReportColumns.mjs +105 -0
  132. package/dist/esm/report/queryReportColumns.mjs.map +1 -0
  133. package/dist/esm/report/queryReportColumns.native.js +119 -0
  134. package/dist/esm/report/queryReportColumns.native.js.map +1 -0
  135. package/dist/esm/report/reportViewModel.mjs +343 -0
  136. package/dist/esm/report/reportViewModel.mjs.map +1 -0
  137. package/dist/esm/report/reportViewModel.native.js +611 -0
  138. package/dist/esm/report/reportViewModel.native.js.map +1 -0
  139. package/dist/esm/report/savedReports.mjs +112 -0
  140. package/dist/esm/report/savedReports.mjs.map +1 -0
  141. package/dist/esm/report/savedReports.native.js +141 -0
  142. package/dist/esm/report/savedReports.native.js.map +1 -0
  143. package/dist/esm/report/useFrappeReport.mjs +158 -0
  144. package/dist/esm/report/useFrappeReport.mjs.map +1 -0
  145. package/dist/esm/report/useFrappeReport.native.js +185 -0
  146. package/dist/esm/report/useFrappeReport.native.js.map +1 -0
  147. package/dist/esm/report/useQueryReport.mjs +176 -0
  148. package/dist/esm/report/useQueryReport.mjs.map +1 -0
  149. package/dist/esm/report/useQueryReport.native.js +205 -0
  150. package/dist/esm/report/useQueryReport.native.js.map +1 -0
  151. package/dist/esm/useFrappeForm.mjs +533 -0
  152. package/dist/esm/useFrappeForm.mjs.map +1 -0
  153. package/dist/esm/useFrappeForm.native.js +686 -0
  154. package/dist/esm/useFrappeForm.native.js.map +1 -0
  155. package/dist/jsx/FrappeCalendar.mjs +4 -3
  156. package/dist/jsx/FrappeCalendar.mjs.map +1 -1
  157. package/dist/jsx/FrappeCalendar.native.js +3 -2
  158. package/dist/jsx/FrappeCalendar.native.js.map +1 -1
  159. package/dist/jsx/FrappeForm.mjs +151 -467
  160. package/dist/jsx/FrappeForm.mjs.map +1 -1
  161. package/dist/jsx/FrappeForm.native.js +152 -633
  162. package/dist/jsx/FrappeForm.native.js.map +1 -1
  163. package/dist/jsx/FrappeListView.mjs +6 -28
  164. package/dist/jsx/FrappeListView.mjs.map +1 -1
  165. package/dist/jsx/FrappeListView.native.js +11 -32
  166. package/dist/jsx/FrappeListView.native.js.map +1 -1
  167. package/dist/jsx/FrappeReportBuilder.mjs +526 -312
  168. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  169. package/dist/jsx/FrappeReportBuilder.native.js +658 -353
  170. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  171. package/dist/jsx/FrappeReportView.mjs +30 -229
  172. package/dist/jsx/FrappeReportView.mjs.map +1 -1
  173. package/dist/jsx/FrappeReportView.native.js +39 -283
  174. package/dist/jsx/FrappeReportView.native.js.map +1 -1
  175. package/dist/jsx/dependsOn.mjs +2 -2
  176. package/dist/jsx/dependsOn.mjs.map +1 -1
  177. package/dist/jsx/dependsOn.native.js +1 -2
  178. package/dist/jsx/dependsOn.native.js.map +1 -1
  179. package/dist/jsx/fields/shared/EditorPreviewPanes.mjs +2 -2
  180. package/dist/jsx/fields/shared/EditorPreviewPanes.mjs.map +1 -1
  181. package/dist/jsx/fields/shared/EditorPreviewPanes.native.js +2 -2
  182. package/dist/jsx/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  183. package/dist/jsx/formEngine/docPermissions.mjs +19 -1
  184. package/dist/jsx/formEngine/docPermissions.mjs.map +1 -1
  185. package/dist/jsx/formEngine/docPermissions.native.js +69 -0
  186. package/dist/jsx/formEngine/docPermissions.native.js.map +1 -1
  187. package/dist/jsx/formEngine/index.mjs +2 -2
  188. package/dist/jsx/formEngine/index.mjs.map +1 -1
  189. package/dist/jsx/formEngine/index.native.js +2 -0
  190. package/dist/jsx/formEngine/index.native.js.map +1 -1
  191. package/dist/jsx/index.js +16 -4
  192. package/dist/jsx/index.js.map +1 -1
  193. package/dist/jsx/index.mjs +16 -4
  194. package/dist/jsx/index.mjs.map +1 -1
  195. package/dist/jsx/index.native.js +67 -7
  196. package/dist/jsx/index.native.js.map +1 -1
  197. package/dist/jsx/liveErrors.mjs +8 -3
  198. package/dist/jsx/liveErrors.mjs.map +1 -1
  199. package/dist/jsx/liveErrors.native.js +8 -2
  200. package/dist/jsx/liveErrors.native.js.map +1 -1
  201. package/dist/jsx/measures.mjs +5 -0
  202. package/dist/jsx/measures.mjs.map +1 -0
  203. package/dist/jsx/measures.native.js +34 -0
  204. package/dist/jsx/measures.native.js.map +1 -0
  205. package/dist/jsx/recordShape.mjs +74 -0
  206. package/dist/jsx/recordShape.mjs.map +1 -0
  207. package/dist/jsx/recordShape.native.js +115 -0
  208. package/dist/jsx/recordShape.native.js.map +1 -0
  209. package/dist/jsx/report/ReportGrid.mjs +428 -0
  210. package/dist/jsx/report/ReportGrid.mjs.map +1 -0
  211. package/dist/jsx/report/ReportGrid.native.js +510 -0
  212. package/dist/jsx/report/ReportGrid.native.js.map +1 -0
  213. package/dist/jsx/report/ReportViewToolbar.mjs +228 -0
  214. package/dist/jsx/report/ReportViewToolbar.mjs.map +1 -0
  215. package/dist/jsx/report/ReportViewToolbar.native.js +303 -0
  216. package/dist/jsx/report/ReportViewToolbar.native.js.map +1 -0
  217. package/dist/jsx/report/queryReport.mjs +404 -0
  218. package/dist/jsx/report/queryReport.mjs.map +1 -0
  219. package/dist/jsx/report/queryReport.native.js +588 -0
  220. package/dist/jsx/report/queryReport.native.js.map +1 -0
  221. package/dist/jsx/report/queryReportColumns.mjs +105 -0
  222. package/dist/jsx/report/queryReportColumns.mjs.map +1 -0
  223. package/dist/jsx/report/queryReportColumns.native.js +159 -0
  224. package/dist/jsx/report/queryReportColumns.native.js.map +1 -0
  225. package/dist/jsx/report/reportViewModel.mjs +343 -0
  226. package/dist/jsx/report/reportViewModel.mjs.map +1 -0
  227. package/dist/jsx/report/reportViewModel.native.js +657 -0
  228. package/dist/jsx/report/reportViewModel.native.js.map +1 -0
  229. package/dist/jsx/report/savedReports.mjs +112 -0
  230. package/dist/jsx/report/savedReports.mjs.map +1 -0
  231. package/dist/jsx/report/savedReports.native.js +169 -0
  232. package/dist/jsx/report/savedReports.native.js.map +1 -0
  233. package/dist/jsx/report/useFrappeReport.mjs +158 -0
  234. package/dist/jsx/report/useFrappeReport.mjs.map +1 -0
  235. package/dist/jsx/report/useFrappeReport.native.js +214 -0
  236. package/dist/jsx/report/useFrappeReport.native.js.map +1 -0
  237. package/dist/jsx/report/useQueryReport.mjs +176 -0
  238. package/dist/jsx/report/useQueryReport.mjs.map +1 -0
  239. package/dist/jsx/report/useQueryReport.native.js +233 -0
  240. package/dist/jsx/report/useQueryReport.native.js.map +1 -0
  241. package/dist/jsx/useFrappeForm.mjs +533 -0
  242. package/dist/jsx/useFrappeForm.mjs.map +1 -0
  243. package/dist/jsx/useFrappeForm.native.js +714 -0
  244. package/dist/jsx/useFrappeForm.native.js.map +1 -0
  245. package/package.json +16 -16
  246. package/src/FrappeCalendar.tsx +8 -2
  247. package/src/FrappeForm.stories.tsx +52 -0
  248. package/src/FrappeForm.tsx +176 -565
  249. package/src/FrappeListView.cards.stories.tsx +3 -6
  250. package/src/FrappeListView.tsx +15 -55
  251. package/src/FrappeReportBuilder.stories.tsx +34 -7
  252. package/src/FrappeReportBuilder.tsx +790 -380
  253. package/src/FrappeReportView.spec.tsx +10 -6
  254. package/src/FrappeReportView.stories.tsx +20 -1
  255. package/src/FrappeReportView.tsx +89 -415
  256. package/src/dependsOn.ts +4 -1
  257. package/src/fields/shared/EditorPreviewPanes.tsx +2 -2
  258. package/src/formEngine/docPermissions.spec.ts +36 -1
  259. package/src/formEngine/docPermissions.ts +34 -0
  260. package/src/formEngine/index.ts +8 -1
  261. package/src/frappeRemainder.designLaw.spec.ts +9 -1
  262. package/src/frappeRoutes.spec.tsx +9 -0
  263. package/src/frappeViews.designLaw.spec.ts +15 -2
  264. package/src/guestFallback.spec.tsx +236 -0
  265. package/src/index.ts +117 -16
  266. package/src/liveErrors.spec.ts +10 -0
  267. package/src/liveErrors.ts +16 -3
  268. package/src/measures.ts +11 -0
  269. package/src/recordShape.spec.ts +100 -0
  270. package/src/recordShape.ts +133 -0
  271. package/src/report/ReportGrid.spec.tsx +175 -0
  272. package/src/report/ReportGrid.tsx +530 -0
  273. package/src/report/ReportViewToolbar.spec.tsx +90 -0
  274. package/src/report/ReportViewToolbar.tsx +314 -0
  275. package/src/report/queryReport.spec.ts +483 -0
  276. package/src/report/queryReport.ts +722 -0
  277. package/src/report/queryReportColumns.tsx +123 -0
  278. package/src/report/reportViewModel.spec.ts +393 -0
  279. package/src/report/reportViewModel.ts +617 -0
  280. package/src/report/savedReports.ts +172 -0
  281. package/src/report/seam.spec.ts +216 -0
  282. package/src/report/useFrappeReport.ts +241 -0
  283. package/src/report/useQueryReport.spec.tsx +131 -0
  284. package/src/report/useQueryReport.ts +309 -0
  285. package/src/useFrappeForm.spec.tsx +209 -0
  286. package/src/useFrappeForm.ts +778 -0
  287. package/types/FrappeCalendar.d.ts.map +1 -1
  288. package/types/FrappeForm.d.ts +21 -1
  289. package/types/FrappeForm.d.ts.map +1 -1
  290. package/types/FrappeListView.d.ts.map +1 -1
  291. package/types/FrappeReportBuilder.d.ts +66 -16
  292. package/types/FrappeReportBuilder.d.ts.map +1 -1
  293. package/types/FrappeReportView.d.ts +9 -127
  294. package/types/FrappeReportView.d.ts.map +1 -1
  295. package/types/dependsOn.d.ts.map +1 -1
  296. package/types/formEngine/docPermissions.d.ts +14 -0
  297. package/types/formEngine/docPermissions.d.ts.map +1 -1
  298. package/types/formEngine/index.d.ts +1 -1
  299. package/types/formEngine/index.d.ts.map +1 -1
  300. package/types/index.d.ts +15 -3
  301. package/types/index.d.ts.map +1 -1
  302. package/types/liveErrors.d.ts +9 -1
  303. package/types/liveErrors.d.ts.map +1 -1
  304. package/types/measures.d.ts +3 -0
  305. package/types/measures.d.ts.map +1 -0
  306. package/types/recordShape.d.ts +45 -0
  307. package/types/recordShape.d.ts.map +1 -0
  308. package/types/report/ReportGrid.d.ts +20 -0
  309. package/types/report/ReportGrid.d.ts.map +1 -0
  310. package/types/report/ReportViewToolbar.d.ts +31 -0
  311. package/types/report/ReportViewToolbar.d.ts.map +1 -0
  312. package/types/report/queryReport.d.ts +181 -0
  313. package/types/report/queryReport.d.ts.map +1 -0
  314. package/types/report/queryReportColumns.d.ts +12 -0
  315. package/types/report/queryReportColumns.d.ts.map +1 -0
  316. package/types/report/reportViewModel.d.ts +146 -0
  317. package/types/report/reportViewModel.d.ts.map +1 -0
  318. package/types/report/savedReports.d.ts +27 -0
  319. package/types/report/savedReports.d.ts.map +1 -0
  320. package/types/report/useFrappeReport.d.ts +60 -0
  321. package/types/report/useFrappeReport.d.ts.map +1 -0
  322. package/types/report/useQueryReport.d.ts +37 -0
  323. package/types/report/useQueryReport.d.ts.map +1 -0
  324. package/types/useFrappeForm.d.ts +142 -0
  325. package/types/useFrappeForm.d.ts.map +1 -0
@@ -32,7 +32,6 @@ var import_frappe = require("@multiplatform.one/frappe");
32
32
  var import_components = require("@multiplatform.one/components");
33
33
  var import_schemaForm = require("./schemaForm/index.cjs");
34
34
  var import_FormSidebar = require("./FormSidebar.cjs");
35
- var import_db = require("@tanstack/db");
36
35
  var import_react = require("@phosphor-icons/react");
37
36
  var import_react2 = require("react");
38
37
  var import_react_i18next = require("react-i18next");
@@ -43,56 +42,23 @@ var import_FrappeProvider = require("./FrappeProvider.cjs");
43
42
  var import_FrappeReconnectIndicator = require("./FrappeReconnectIndicator.cjs");
44
43
  var import_timeline = require("./components/timeline.cjs");
45
44
  var import_desktop = require("@multiplatform.one/desktop");
46
- var import_fetchFrom = require("./formEngine/fetchFrom.cjs");
47
- var import_fieldPermissions = require("./formEngine/fieldPermissions.cjs");
48
- var import_formActions = require("./formEngine/formActions.cjs");
49
- var import_formLayout = require("./formEngine/formLayout.cjs");
50
- var import_createPrefill = require("./formEngine/createPrefill.cjs");
51
45
  var import_docLifecycle = require("./formEngine/docLifecycle.cjs");
52
- var import_useAmendedAs = require("./formEngine/useAmendedAs.cjs");
53
- var import_useDocRights = require("./formEngine/useDocRights.cjs");
54
- var import_useFormEngine = require("./formEngine/useFormEngine.cjs");
55
46
  var import_FrappeFormActions = require("./FrappeFormActions.cjs");
56
47
  var import_frappeConnections = require("./frappeConnections.cjs");
57
48
  var import_FrappeFormConnections = require("./FrappeFormConnections.cjs");
58
49
  var import_FrappeNotConfigured = require("./FrappeNotConfigured.cjs");
59
50
  var import_FrappeRowsReader = require("./FrappeRowsReader.cjs");
51
+ var import_liveErrors = require("./liveErrors.cjs");
52
+ var import_recordShape = require("./recordShape.cjs");
60
53
  var import_frappeNavigation = require("./frappeNavigation.cjs");
54
+ var import_useFrappeForm = require("./useFrappeForm.cjs");
61
55
  var import_jsx_runtime = require("react/jsx-runtime");
62
56
  var import_react3 = require("react");
63
- function isEmptyFieldValue(value) {
64
- if (value === void 0 || value === null) return true;
65
- if (typeof value === "string" && value.trim() === "") return true;
66
- if (Array.isArray(value) && value.length === 0) return true;
67
- return false;
68
- }
69
- function sectionsToLayoutFields(sections) {
70
- const fields = [];
71
- sections.forEach((section, sectionIndex) => {
72
- fields.push({
73
- fieldname: `__section_${sectionIndex}`,
74
- fieldtype: section.tab ? "Tab Break" : "Section Break",
75
- label: section.label,
76
- collapsible: section.collapsible ? 1 : 0
77
- });
78
- section.columns.forEach((column, columnIndex) => {
79
- if (columnIndex > 0) {
80
- fields.push({
81
- fieldname: `__column_${sectionIndex}_${columnIndex}`,
82
- fieldtype: "Column Break"
83
- });
84
- }
85
- fields.push(...column.fields);
86
- });
87
- });
88
- return fields;
89
- }
90
- const documentBookkeeping = /* @__PURE__ */new Set(["name", "owner", "creation", "modified", "modified_by", "docstatus", "idx", "doctype", "_user_tags", "_comments", "_assign", "_liked_by", "_seen"]);
91
- function fieldsFromDocument(doc) {
92
- return Object.entries(doc).filter(([key, value]) => !key.startsWith("$") && !documentBookkeeping.has(key) && (value === null || typeof value === "string" || typeof value === "number")).map(([key, value]) => ({
93
- name: key,
94
- label: key.replace(/_/g, " ").replace(/(^|\s)\S/g, c => c.toUpperCase()),
95
- type: typeof value === "number" ? Number.isInteger(value) ? "Int" : "Float" : "Data",
57
+ function schemaFieldsFromRecord(doc) {
58
+ return (0, import_recordShape.fieldsFromRecord)(doc).map(field => ({
59
+ name: field.fieldname,
60
+ label: field.label,
61
+ type: field.fieldtype,
96
62
  readOnly: true
97
63
  }));
98
64
  }
@@ -236,20 +202,48 @@ function FrappeFormRoute({
236
202
  }))
237
203
  });
238
204
  }
239
- function FrappeFormBody({
240
- baseURL,
241
- auth,
242
- syncOptions,
205
+ function FrappeFormBody(props) {
206
+ if (props.form) return /* @__PURE__ */(0, import_jsx_runtime.jsx)(FrappeFormView, {
207
+ ...props,
208
+ form: props.form
209
+ });
210
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(FrappeFormOwned, {
211
+ ...props
212
+ });
213
+ }
214
+ function FrappeFormOwned(props) {
215
+ const config = (0, import_FrappeProvider.useFrappeConfig)();
216
+ if (!(props.baseURL ?? config?.baseURL)) {
217
+ throw new Error("FrappeForm requires baseURL prop or FrappeProvider with baseURL");
218
+ }
219
+ const form = (0, import_useFrappeForm.useFrappeForm)({
220
+ doctype: props.doctype,
221
+ name: props.name,
222
+ baseURL: props.baseURL,
223
+ auth: props.auth,
224
+ syncOptions: props.syncOptions,
225
+ fields: props.fields,
226
+ sections: props.sections,
227
+ hideFields: props.hideFields,
228
+ hideSections: props.hideSections,
229
+ roles: props.roles,
230
+ readShares: props.showSidebar ?? true,
231
+ disabled: props.disabled,
232
+ initialDoc: props.initialDoc
233
+ });
234
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(FrappeFormView, {
235
+ ...props,
236
+ form
237
+ });
238
+ }
239
+ function FrappeFormView({
240
+ form,
243
241
  doctype,
244
242
  name,
245
- fields,
246
243
  children,
247
244
  overrides,
248
- hideFields,
249
245
  readOnlyFields,
250
- sections,
251
246
  order,
252
- roles,
253
247
  onSave,
254
248
  onCancel,
255
249
  onDelete,
@@ -258,73 +252,55 @@ function FrappeFormBody({
258
252
  showToolbar = true,
259
253
  showSidebar = true,
260
254
  showTimeline = true,
255
+ showBanners = true,
261
256
  disabled = false,
262
257
  sectionHeadingLevel,
263
258
  connections,
264
259
  showConnections = true,
265
- initialDoc,
260
+ extraTabs,
261
+ renderFieldWrapper,
262
+ renderTab,
266
263
  loadingFallback,
267
264
  notFoundFallback,
268
265
  errorFallback,
269
266
  routePage
270
267
  }) {
271
- const config = (0, import_FrappeProvider.useFrappeConfig)();
272
268
  const {
273
269
  knobProps
274
270
  } = (0, import_theme.useResolvedKnobs)();
275
271
  const {
276
272
  t
277
273
  } = (0, import_react_i18next.useTranslation)();
278
- const seedDoc = name && initialDoc && initialDoc.name === name ? initialDoc : void 0;
279
- const seedRef = (0, import_react2.useRef)(seedDoc);
280
- seedRef.current = seedDoc;
281
- const [localDoc, setLocalDoc] = (0, import_react2.useState)(() => seedDoc ?? {});
282
- const [baselineDoc, setBaselineDoc] = (0, import_react2.useState)(() => seedDoc);
283
- const [docError, setDocError] = (0, import_react2.useState)(null);
284
- const [conflictFields, setConflictFields] = (0, import_react2.useState)([]);
285
- const [wasDeleted, setWasDeleted] = (0, import_react2.useState)(false);
286
- const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
287
- const [errors, setErrors] = (0, import_react2.useState)({});
288
- const [activeTab, setActiveTab] = (0, import_react2.useState)(void 0);
289
- const everLoadedRef = (0, import_react2.useRef)(false);
290
- const localDocRef = (0, import_react2.useRef)(localDoc);
291
- localDocRef.current = localDoc;
292
- const baselineRef = (0, import_react2.useRef)(baselineDoc);
293
- baselineRef.current = baselineDoc;
294
- const createDraftRef = (0, import_react2.useRef)(void 0);
295
- const finalBaseURL = baseURL ?? config?.baseURL;
296
- const finalAuth = auth ?? config?.auth;
297
- const finalSyncOptions = syncOptions ?? config?.syncOptions;
298
- if (!finalBaseURL) {
299
- throw new Error("FrappeForm requires baseURL prop or FrappeProvider with baseURL");
300
- }
301
- const frappeConfig = (0, import_react2.useMemo)(() => ({
302
- baseURL: finalBaseURL,
303
- socketPort: config?.socketPort,
304
- siteName: config?.siteName,
305
- socketBaseURL: config?.socketBaseURL,
306
- auth: finalAuth,
307
- syncOptions: finalSyncOptions,
308
- realtime: config?.realtime,
309
- fixtures: config?.fixtures
310
- }), [finalBaseURL, config?.socketPort, config?.siteName, config?.socketBaseURL, config?.realtime, finalAuth, finalSyncOptions, config?.fixtures]);
311
274
  const {
312
275
  meta,
313
- isLoading: isMetaLoading,
314
- error: metaError
315
- } = (0, import_frappe.useDocTypeMeta)(frappeConfig, doctype);
316
- const isSubmittable = !!meta?.is_submittable;
276
+ metaLoading: isMetaLoading,
277
+ metaError,
278
+ doc: localDoc,
279
+ baseline: baselineDoc,
280
+ setValue,
281
+ errors,
282
+ isSubmitting,
283
+ docstatus,
284
+ isSubmittable,
285
+ rights,
286
+ rightsPending,
287
+ canWrite: canWriteRecord,
288
+ wasDeleted,
289
+ conflictFields,
290
+ docError,
291
+ tabs: formTabs,
292
+ promptNamed,
293
+ activeTab,
294
+ setActiveTab,
295
+ amendedAs
296
+ } = form;
297
+ const frappeConfig = form.connection;
317
298
  const isCreate = !name;
318
- const docstatus = Number(baselineDoc?.docstatus ?? 0);
319
- const layoutFields = (0, import_react2.useMemo)(() => {
320
- if (!meta) return void 0;
321
- return sections ? sectionsToLayoutFields(sections) : meta.fields;
322
- }, [meta, sections]);
323
- const amendedAs = (0, import_useAmendedAs.useAmendedAs)(isSubmittable && docstatus === 2 ? frappeConfig : void 0, doctype, name);
299
+ const hasUnsavedChanges = form.isDirty;
324
300
  const readsWithoutMeta = !children && !meta && Boolean(metaError) && Boolean(name);
325
301
  const recordTabs = (0, import_react2.useMemo)(() => {
326
302
  if (!readsWithoutMeta || !baselineDoc) return void 0;
327
- const recordFields = fieldsFromDocument(baselineDoc);
303
+ const recordFields = schemaFieldsFromRecord(baselineDoc);
328
304
  return [{
329
305
  key: "__details",
330
306
  label: t("Details"),
@@ -338,87 +314,7 @@ function FrappeFormBody({
338
314
  }
339
315
  }];
340
316
  }, [readsWithoutMeta, baselineDoc, t]);
341
- const promptNamed = isCreate && !!meta && (0, import_formLayout.isPromptNamed)(meta.autoname, meta.naming_rule);
342
- const fetchMap = (0, import_react2.useMemo)(() => meta ? (0, import_fetchFrom.buildFetchMap)(meta.fields) : void 0, [meta]);
343
- const handleDocSyncError = (0, import_react2.useCallback)(err => {
344
- setDocError(err instanceof Error ? err : new Error(String(err)));
345
- }, []);
346
- const docCollection = (0, import_frappe.useFrappeCollection)(name ? frappeConfig : void 0, doctype, {
347
- fields,
348
- filters: name ? {
349
- name
350
- } : void 0,
351
- onSyncError: handleDocSyncError
352
- });
353
- const {
354
- data: rawDocData,
355
- isLoading: isDocLoading
356
- } = (0, import_frappe.useLiveQuery)(q => {
357
- if (!docCollection || !name) return null;
358
- return q.from({
359
- _doc: docCollection
360
- }).where(({
361
- _doc
362
- }) => {
363
- if (!_doc) return (0, import_db.eq)(name, name);
364
- return (0, import_db.eq)(_doc.name, name);
365
- });
366
- }, [docCollection, name]);
367
- const liveDoc = (0, import_react2.useMemo)(() => {
368
- const arr = Array.isArray(rawDocData) ? rawDocData : rawDocData ? [rawDocData] : [];
369
- const doc = arr[0] ?? null;
370
- return doc ? {
371
- data: doc,
372
- isLoading: isDocLoading
373
- } : name ? {
374
- data: null,
375
- isLoading: isDocLoading
376
- } : null;
377
- }, [rawDocData, isDocLoading, name]);
378
- const collection = (0, import_frappe.useFrappeCollection)(name ? void 0 : frappeConfig, doctype, {
379
- fields
380
- });
381
- const shareCollection = (0, import_frappe.useFrappeCollection)(showSidebar && name ? frappeConfig : void 0, "DocShare", {
382
- fields: ["name", "user", "everyone", "read", "write", "share"],
383
- filters: {
384
- share_doctype: doctype,
385
- share_name: name
386
- }
387
- });
388
- const {
389
- data: rawShareRows
390
- } = (0, import_frappe.useLiveQuery)(q => shareCollection ? q.from({
391
- _share: shareCollection
392
- }) : null, [shareCollection]);
393
- const shareRows = (0, import_react2.useMemo)(() => shareCollection ? rawShareRows ?? [] : void 0, [shareCollection, rawShareRows]);
394
- const owner = baselineDoc?.owner;
395
- const {
396
- rights,
397
- pending: rightsPending,
398
- roles: effectiveRoles
399
- } = (0, import_useDocRights.useDocRights)(frappeConfig, meta, {
400
- roles,
401
- owner: typeof owner === "string" ? owner : void 0,
402
- shares: shareRows
403
- });
404
- const permLevels = (0, import_react2.useMemo)(() => (0, import_fieldPermissions.buildPermLevelMatrix)(meta?.permissions, effectiveRoles), [meta?.permissions, effectiveRoles]);
405
- const formTabs = (0, import_react2.useMemo)(() => {
406
- if (!layoutFields) return void 0;
407
- return (0, import_formLayout.buildFormTabs)({
408
- fields: layoutFields,
409
- doc: {
410
- ...localDoc,
411
- __islocal: isCreate ? 1 : 0
412
- },
413
- docstatus,
414
- formReadOnly: !!meta?.read_only,
415
- isCreate,
416
- detailsLabel: t("Details"),
417
- permLevels,
418
- hiddenFields: hideFields
419
- });
420
- }, [layoutFields, localDoc, docstatus, meta?.read_only, isCreate, permLevels, hideFields, t]);
421
- const assignmentCollection = (0, import_frappe.useFrappeCollection)(showSidebar && name && !frappeConfig.fixtures ? frappeConfig : void 0, "ToDo", {
317
+ const assignmentCollection = (0, import_frappe.useFrappeCollection)(showSidebar && name && frappeConfig && !frappeConfig.fixtures ? frappeConfig : void 0, "ToDo", {
422
318
  fields: ["name", "allocated_to", "status", "reference_type", "reference_name"],
423
319
  filters: {
424
320
  reference_type: doctype,
@@ -432,16 +328,6 @@ function FrappeFormBody({
432
328
  _assignment: assignmentCollection
433
329
  }) : null, [assignmentCollection]);
434
330
  const assignmentRows = (0, import_react2.useMemo)(() => assignmentCollection ? rawAssignmentRows ?? [] : void 0, [assignmentCollection, rawAssignmentRows]);
435
- (0, import_react2.useEffect)(() => {
436
- everLoadedRef.current = false;
437
- if (name) createDraftRef.current = void 0;
438
- setWasDeleted(false);
439
- setConflictFields([]);
440
- setDocError(null);
441
- const seed = seedRef.current;
442
- setBaselineDoc(seed);
443
- if (seed) setLocalDoc(seed);
444
- }, [doctype, name]);
445
331
  const effectiveConnections = (0, import_react2.useMemo)(() => connections ?? (0, import_frappeConnections.connectionsFromMeta)(meta), [connections, meta]);
446
332
  const readsConnections = Boolean(children) && Boolean(name) && effectiveConnections.length > 0;
447
333
  const [connectionSnapshots, setConnectionSnapshots] = (0, import_react2.useState)({});
@@ -472,262 +358,48 @@ function FrappeFormBody({
472
358
  const connectionsLoading = connectionReads.some(({
473
359
  link
474
360
  }) => connectionSnapshots[link.doctype]?.isLoading ?? true);
475
- (0, import_frappe.useFrappeDoctypeEvents)(name ? frappeConfig : void 0, doctype, event => {
476
- if (event.type !== "doc_deleted") return;
477
- const payload = event.payload;
478
- if (payload?.name === name) setWasDeleted(true);
479
- }, Boolean(name));
480
- (0, import_react2.useEffect)(() => {
481
- const incoming = liveDoc?.data;
482
- if (incoming) {
483
- everLoadedRef.current = true;
484
- setWasDeleted(false);
485
- const baseline = baselineRef.current;
486
- if (!baseline) {
487
- setBaselineDoc(incoming);
488
- setLocalDoc(incoming);
489
- return;
490
- }
491
- const local = localDocRef.current;
492
- const merged = {
493
- ...incoming
494
- };
495
- const newConflicts = [];
496
- for (const key of Object.keys(local)) {
497
- const localValue = local[key];
498
- if (localValue === baseline[key]) continue;
499
- merged[key] = localValue;
500
- const remote = incoming[key];
501
- if (remote !== baseline[key] && remote !== localValue) newConflicts.push(key);
502
- }
503
- setBaselineDoc(incoming);
504
- setLocalDoc(merged);
505
- if (newConflicts.length > 0) {
506
- setConflictFields(prev => Array.from(/* @__PURE__ */new Set([...prev, ...newConflicts])));
507
- }
508
- } else if (name && everLoadedRef.current && !liveDoc?.isLoading) {
509
- setWasDeleted(true);
510
- } else if (!name) {
511
- if (createDraftRef.current?.doctype !== doctype) {
512
- createDraftRef.current = {
513
- doctype,
514
- values: (0, import_createPrefill.takeCreatePrefill)(doctype)
515
- };
516
- }
517
- setLocalDoc({
518
- ...createDraftRef.current.values,
519
- doctype
520
- });
521
- }
522
- }, [liveDoc?.data, liveDoc?.isLoading, doctype, name]);
523
- const dirtyFieldNames = (0, import_react2.useMemo)(() => {
524
- const local = localDoc;
525
- const base = baselineDoc;
526
- const dirty = [];
527
- for (const key of Object.keys(local)) {
528
- if (key === "doctype" || key === "name") continue;
529
- if (base ? local[key] !== base[key] : local[key] !== void 0) dirty.push(key);
530
- }
531
- return dirty;
532
- }, [localDoc, baselineDoc]);
533
- const hasUnsavedChanges = dirtyFieldNames.length > 0;
534
- const runFetchFrom = (field, value) => {
535
- const rules = fetchMap?.get(field);
536
- if (!rules || rules.length === 0) return;
537
- const applyPatch = fetched2 => {
538
- setLocalDoc(prev => {
539
- const current = prev;
540
- if (current[field] !== value) return prev;
541
- const patch = (0, import_fetchFrom.applyFetchedValues)(rules, fetched2, current);
542
- return Object.keys(patch).length > 0 ? {
543
- ...current,
544
- ...patch
545
- } : prev;
546
- });
547
- };
548
- if (isEmptyFieldValue(value)) {
549
- applyPatch({});
550
- return;
551
- }
552
- const linkField = meta?.fields.find(metaField => metaField.fieldname === field);
553
- const targetDoctype = typeof linkField?.options === "string" ? linkField.options : "";
554
- if (!targetDoctype) return;
555
- const sources = Array.from(new Set(rules.map(rule => rule.source)));
556
- const fixtures = frappeConfig.fixtures;
557
- const fetched = fixtures ? fixtures.getDoc(targetDoctype, String(value), sources).then(doc => doc ?? {}) : (0, import_formActions.validateLink)((0, import_formActions.createHttpClient)(frappeConfig), targetDoctype, String(value), sources);
558
- fetched.then(applyPatch).catch(() => void 0);
559
- };
560
- const setValue = (field, value) => {
561
- setLocalDoc(prev => ({
562
- ...prev,
563
- [field]: value
564
- }));
565
- setErrors(prev => {
566
- const newErrors = {
567
- ...prev
568
- };
569
- delete newErrors[String(field)];
570
- return newErrors;
571
- });
572
- runFetchFrom(String(field), value);
573
- };
574
- const validateRequiredFields = () => {
575
- if (!formTabs) return {};
576
- const validationErrors = {};
577
- const doc = localDoc;
578
- if (promptNamed && isEmptyFieldValue(doc.name)) {
579
- validationErrors.name = t("Name is required");
580
- }
581
- for (const tab of formTabs) {
582
- for (const field of tab.schema.fields) {
583
- if (!field.required) continue;
584
- if (isEmptyFieldValue(doc[field.name])) {
585
- validationErrors[field.name] = t("{{label}} is required", {
586
- label: field.label || field.name
587
- });
588
- }
589
- }
590
- }
591
- return validationErrors;
592
- };
593
- const canWriteRecord = isCreate ? rights.create : rights.write;
594
361
  const handleSave = async () => {
595
- if (wasDeleted || !canWriteRecord) return;
596
- const requiredErrors = validateRequiredFields();
597
- if (Object.keys(requiredErrors).length > 0) {
598
- setErrors(requiredErrors);
599
- return;
600
- }
601
- setIsSubmitting(true);
602
- setErrors({});
603
- try {
604
- if (name) {
605
- if (!docCollection) return;
606
- const changedFields = dirtyFieldNames;
607
- if (changedFields.length > 0) {
608
- const local = localDoc;
609
- const tx = docCollection.update(name, draft => {
610
- for (const key of changedFields) {
611
- draft[key] = local[key];
612
- }
613
- });
614
- await tx.isPersisted.promise;
615
- }
616
- setConflictFields([]);
617
- } else {
618
- if (!collection) return;
619
- const temporaryName = localDoc.name ?? `new-${Date.now()}`;
620
- const docToInsert = {
621
- ...localDoc,
622
- doctype,
623
- name: temporaryName
624
- };
625
- const tx = collection.insert(docToInsert);
626
- await tx.isPersisted.promise;
627
- const createdName = (0, import_frappe.getFrappeSyncModule)(frappeConfig)?.createdName(temporaryName) ?? temporaryName;
628
- onSave?.({
629
- ...localDoc,
630
- name: createdName
631
- });
632
- return;
633
- }
634
- onSave?.(localDoc);
635
- } catch (err) {
636
- const e = err;
637
- if (e?.exc_type === "ValidationError") {
638
- const validationErrors = {};
639
- if (e._server_messages) {
640
- try {
641
- const messages = JSON.parse(e._server_messages);
642
- for (const msg of messages) {
643
- const parsed = typeof msg === "string" ? JSON.parse(msg) : msg;
644
- if (parsed.message) {
645
- validationErrors.general = parsed.message;
646
- }
647
- }
648
- } catch {
649
- validationErrors.general = t("Validation error occurred");
650
- }
651
- }
652
- setErrors(validationErrors);
653
- } else {
654
- setErrors({
655
- general: e?.message || t("Failed to save document")
656
- });
657
- }
658
- } finally {
659
- setIsSubmitting(false);
660
- }
362
+ const saved = await form.save();
363
+ if (!saved) return;
364
+ onSave?.(isCreate ? {
365
+ ...localDoc,
366
+ name: saved
367
+ } : localDoc);
661
368
  };
662
369
  const handleCancel = () => {
663
- if (baselineDoc) {
664
- setLocalDoc(baselineDoc);
665
- } else if (liveDoc?.data) {
666
- setLocalDoc(liveDoc.data);
667
- } else {
668
- setLocalDoc({
669
- doctype
670
- });
671
- }
672
- setConflictFields([]);
673
- setErrors({});
370
+ form.reset();
674
371
  onCancel?.();
675
372
  };
676
373
  const handleDelete = async () => {
677
- if (!docCollection || !name || wasDeleted || !rights.delete) return;
374
+ if (!name || wasDeleted || !rights.delete) return;
678
375
  if (!(await import_desktop.dialog.confirm(t("Delete this {{doctype}}?", {
679
376
  doctype
680
377
  })))) return;
681
- setIsSubmitting(true);
682
- setErrors({});
683
- try {
684
- const tx = docCollection.delete(name);
685
- await tx.isPersisted.promise;
686
- onDelete?.(localDoc);
687
- } catch (err) {
688
- setErrors({
689
- general: err?.message || t("Failed to delete")
690
- });
691
- } finally {
692
- setIsSubmitting(false);
693
- }
378
+ if (await form.remove()) onDelete?.(localDoc);
694
379
  };
695
- const transitionDocstatus = async (to, question, failure) => {
696
- if (!docCollection || !name || wasDeleted || !rights[to === 1 ? "submit" : "cancel"]) return;
697
- if (to === 1) {
698
- const requiredErrors = validateRequiredFields();
699
- if (Object.keys(requiredErrors).length > 0) {
700
- setErrors(requiredErrors);
701
- return;
702
- }
703
- }
704
- if (!(await import_desktop.dialog.confirm(question))) return;
705
- setIsSubmitting(true);
706
- setErrors({});
707
- try {
708
- const tx = docCollection.update(name, draft => {
709
- draft.docstatus = to;
710
- });
711
- await tx.isPersisted.promise;
712
- } catch (err) {
713
- setErrors({
714
- general: (0, import_useFormEngine.extractServerError)(err, failure)
715
- });
716
- } finally {
717
- setIsSubmitting(false);
380
+ const handleSubmitDocument = async () => {
381
+ if (!name || wasDeleted || !rights.submit) return;
382
+ const requiredErrors = form.validate();
383
+ if (Object.keys(requiredErrors).length > 0) {
384
+ form.setErrors(requiredErrors);
385
+ return;
718
386
  }
387
+ if (!(await import_desktop.dialog.confirm(t("Permanently Submit {{name}}?", {
388
+ name
389
+ })))) return;
390
+ await form.submitDocument();
391
+ };
392
+ const handleCancelDocument = async () => {
393
+ if (!name || wasDeleted || !rights.cancel) return;
394
+ if (!(await import_desktop.dialog.confirm(t("Permanently Cancel {{name}}?", {
395
+ name
396
+ })))) return;
397
+ await form.cancelDocument();
719
398
  };
720
- const handleSubmitDocument = () => transitionDocstatus(1, t("Permanently Submit {{name}}?", {
721
- name
722
- }), t("Failed to submit"));
723
- const handleCancelDocument = () => transitionDocstatus(2, t("Permanently Cancel {{name}}?", {
724
- name
725
- }), t("Failed to cancel"));
726
399
  const handleAmend = () => {
727
- if (!meta || !name || !onAmend || !rights.amend) return;
728
- const draft = (0, import_docLifecycle.buildAmendValues)(meta.fields, localDoc, name);
729
- (0, import_createPrefill.setCreatePrefill)(doctype, draft);
730
- onAmend(draft);
400
+ if (!onAmend) return;
401
+ const draft = form.amend();
402
+ if (draft) onAmend(draft);
731
403
  };
732
404
  const titleField = meta?.title_field;
733
405
  const titleValue = titleField ? localDoc[titleField] : void 0;
@@ -787,27 +459,34 @@ function FrappeFormBody({
787
459
  }));
788
460
  }
789
461
  if (!children && metaError && !meta && !name) {
790
- return frame(/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
462
+ return frame((0, import_liveErrors.isPermissionError)(metaError) ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.EmptyState, {
463
+ testID: "frappe-form-not-permitted",
464
+ title: t("You can't create {{doctype}}", {
465
+ doctype
466
+ }),
467
+ description: metaError.message
468
+ }) : /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.AsyncBoundary, {
791
469
  ...knobProps.panelPadding,
792
- alignItems: "center",
793
- ...knobProps.gap,
794
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
795
- color: import_forms.formCommonColors.error,
796
- ...knobProps.body,
797
- children: t("Failed to load {{doctype}} form", {
798
- doctype
799
- })
800
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
801
- color: import_forms.formCommonColors.muted,
802
- ...knobProps.body,
803
- children: metaError.message
804
- })]
470
+ error: metaError,
471
+ errorTitle: t("Failed to load {{doctype}} form", {
472
+ doctype
473
+ })
805
474
  }));
806
475
  }
807
- const isDocReading = Boolean(name) && (!docCollection || Boolean(liveDoc?.isLoading));
808
- const showsSeed = Boolean(seedDoc) && isDocReading;
809
- if (name && docError && !liveDoc?.data && !wasDeleted) {
476
+ if (name && form.status === "error" && docError) {
810
477
  if (errorFallback !== void 0) return frame(errorFallback);
478
+ if ((0, import_liveErrors.isPermissionError)(docError)) {
479
+ return frame(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.EmptyState, {
480
+ testID: "frappe-form-not-permitted",
481
+ title: t("You can't open {{doctype}} {{name}}", {
482
+ doctype,
483
+ name
484
+ }),
485
+ description: t("Your session can't read this {{doctype}}.", {
486
+ doctype
487
+ })
488
+ }));
489
+ }
811
490
  return frame(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.AsyncBoundary, {
812
491
  ...knobProps.panelPadding,
813
492
  error: docError,
@@ -816,7 +495,7 @@ function FrappeFormBody({
816
495
  })
817
496
  }));
818
497
  }
819
- if (name && isDocReading && !showsSeed && !wasDeleted) {
498
+ if (name && form.status === "loading") {
820
499
  if (loadingFallback !== void 0) return frame(loadingFallback);
821
500
  return frame(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.YStack, {
822
501
  ...knobProps.panelPadding,
@@ -826,7 +505,7 @@ function FrappeFormBody({
826
505
  })
827
506
  }));
828
507
  }
829
- if (name && !isDocReading && !liveDoc?.data && !wasDeleted) {
508
+ if (name && form.status === "notFound") {
830
509
  if (notFoundFallback !== void 0) return frame(notFoundFallback);
831
510
  return frame(/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
832
511
  ...knobProps.panelPadding,
@@ -876,15 +555,13 @@ function FrappeFormBody({
876
555
  const toolbarShown = showToolbar && !readsWithoutMeta && Boolean(indicator || docAction || showDelete || showEdit || showClose);
877
556
  const shownTabs = formTabs ?? recordTabs;
878
557
  const imageFieldName = meta?.image_field;
879
- const sidebarImageUrl = imageFieldName ? resolveFileUrl(localDoc[imageFieldName], finalBaseURL) : void 0;
558
+ const sidebarImageUrl = imageFieldName ? resolveFileUrl(localDoc[imageFieldName], frappeConfig?.baseURL) : void 0;
880
559
  const conflictLabels = conflictFields.map(fieldname => {
881
560
  const field = meta?.fields.find(metaField => metaField.fieldname === fieldname);
882
561
  return field?.label || fieldname;
883
562
  }).join(", ");
884
- const formTabItems = (shownTabs ?? []).map(tab => ({
885
- value: tab.key,
886
- label: tab.label,
887
- content: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_schemaForm.SchemaForm, {
563
+ const formTabItems = (shownTabs ?? []).map(tab => {
564
+ const content = /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_schemaForm.SchemaForm, {
888
565
  schema: tab.schema,
889
566
  doc: localDoc,
890
567
  setValue: (field, value) => setValue(field, value),
@@ -893,10 +570,16 @@ function FrappeFormBody({
893
570
  overrides,
894
571
  readOnlyFields,
895
572
  sectionHeadingLevel,
896
- order
897
- })
898
- }));
899
- const tabItems = showConnections && name && effectiveConnections.length > 0 ? [...formTabItems, {
573
+ order,
574
+ renderFieldWrapper
575
+ });
576
+ return {
577
+ value: tab.key,
578
+ label: tab.label,
579
+ content: renderTab ? renderTab(tab, content) : content
580
+ };
581
+ });
582
+ const tabItems = [...formTabItems, ...(showConnections && name && frappeConfig && effectiveConnections.length > 0 ? [{
900
583
  value: "__connections",
901
584
  label: t("Connections"),
902
585
  content: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeFormConnections.FrappeFormConnections, {
@@ -904,12 +587,12 @@ function FrappeFormBody({
904
587
  connections: effectiveConnections,
905
588
  name
906
589
  })
907
- }] : formTabItems;
590
+ }] : []), ...(extraTabs ?? [])];
908
591
  const effectiveTab = activeTab && tabItems.some(tab => tab.value === activeTab) ? activeTab : tabItems[0]?.value;
909
592
  const localName = localDoc.name;
910
593
  const sidebar = showSidebar && name && meta ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FormSidebar.FormSidebar, {
911
594
  imageUrl: sidebarImageUrl,
912
- sections: buildSidebarSections(localDoc, shareRows, t, assignmentRows),
595
+ sections: buildSidebarSections(localDoc, form.shareRows, t, assignmentRows),
913
596
  metadata: mapDocToSidebarMetadata(localDoc, t)
914
597
  }) : void 0;
915
598
  return frame(
@@ -923,14 +606,14 @@ function FrappeFormBody({
923
606
  flexGrow: 1,
924
607
  flexShrink: 1,
925
608
  flexBasis: "auto",
926
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeReconnectIndicator.FrappeReconnectIndicator, {
609
+ children: [frappeConfig ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeReconnectIndicator.FrappeReconnectIndicator, {
927
610
  config: frappeConfig
928
- }), connectionReads.map(read => /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeRowsReader.FrappeRowsReader, {
611
+ }) : null, frappeConfig ? connectionReads.map(read => /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeRowsReader.FrappeRowsReader, {
929
612
  connection: frappeConfig,
930
613
  doctype: read.link.doctype,
931
614
  options: read.options,
932
615
  onChange: read.onChange
933
- }, read.link.doctype)), wasDeleted && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.XStack, {
616
+ }, read.link.doctype)) : null, showBanners && wasDeleted && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.XStack, {
934
617
  role: "alert",
935
618
  alignItems: "center",
936
619
  ...knobProps.containerRadius,
@@ -946,7 +629,7 @@ function FrappeFormBody({
946
629
  doctype
947
630
  })
948
631
  })
949
- }), !wasDeleted && conflictFields.length > 0 && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.XStack, {
632
+ }), showBanners && !wasDeleted && conflictFields.length > 0 && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.XStack, {
950
633
  role: "status",
951
634
  alignItems: "center",
952
635
  ...knobProps.containerRadius,
@@ -1008,6 +691,7 @@ function FrappeFormBody({
1008
691
  }), errors.general && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
1009
692
  color: import_forms.formCommonColors.error,
1010
693
  ...knobProps.body,
694
+ role: "alert",
1011
695
  children: errors.general
1012
696
  }), toolbarShown && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeFormActions.FrappeFormActions, {
1013
697
  indicator,