@multiplatform.one/frappe-ui 7.10.0 → 7.15.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 (342) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/FrappeDashboard.cjs +8 -10
  3. package/dist/cjs/FrappeDashboard.native.js +8 -14
  4. package/dist/cjs/FrappeDashboard.native.js.map +1 -1
  5. package/dist/cjs/FrappeForm.cjs +465 -175
  6. package/dist/cjs/FrappeForm.native.js +611 -207
  7. package/dist/cjs/FrappeForm.native.js.map +1 -1
  8. package/dist/cjs/FrappeFormConnections.cjs +125 -0
  9. package/dist/cjs/FrappeFormConnections.native.js +149 -0
  10. package/dist/cjs/FrappeFormConnections.native.js.map +1 -0
  11. package/dist/cjs/FrappeImageView.cjs +7 -9
  12. package/dist/cjs/FrappeImageView.native.js +7 -13
  13. package/dist/cjs/FrappeImageView.native.js.map +1 -1
  14. package/dist/cjs/FrappeList.cjs +29 -4
  15. package/dist/cjs/FrappeList.native.js +37 -5
  16. package/dist/cjs/FrappeList.native.js.map +1 -1
  17. package/dist/cjs/FrappeListView.cjs +102 -29
  18. package/dist/cjs/FrappeListView.native.js +109 -29
  19. package/dist/cjs/FrappeListView.native.js.map +1 -1
  20. package/dist/cjs/FrappeProvider.cjs +7 -2
  21. package/dist/cjs/FrappeProvider.native.js +7 -2
  22. package/dist/cjs/FrappeProvider.native.js.map +1 -1
  23. package/dist/cjs/FrappeReportBuilder.cjs +10 -11
  24. package/dist/cjs/FrappeReportBuilder.native.js +10 -16
  25. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  26. package/dist/cjs/FrappeRowsReader.cjs +49 -0
  27. package/dist/cjs/FrappeRowsReader.native.js +53 -0
  28. package/dist/cjs/FrappeRowsReader.native.js.map +1 -0
  29. package/dist/cjs/FrappeTable.cjs +18 -6
  30. package/dist/cjs/FrappeTable.native.js +24 -6
  31. package/dist/cjs/FrappeTable.native.js.map +1 -1
  32. package/dist/cjs/fieldRegistry.cjs +36 -11
  33. package/dist/cjs/fieldRegistry.native.js +59 -11
  34. package/dist/cjs/fieldRegistry.native.js.map +1 -1
  35. package/dist/cjs/fields/Date/index.native.js +5 -2
  36. package/dist/cjs/fields/Date/index.native.js.map +1 -1
  37. package/dist/cjs/fields/Date/sheetKeyboard.cjs +2 -2
  38. package/dist/cjs/fields/Date/sheetKeyboard.native.js +2 -2
  39. package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
  40. package/dist/cjs/fields/DateRange/index.cjs +2 -1
  41. package/dist/cjs/fields/DateRange/index.native.js +4 -1
  42. package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
  43. package/dist/cjs/formEngine/index.cjs +4 -2
  44. package/dist/cjs/formEngine/index.native.js +3 -1
  45. package/dist/cjs/formEngine/index.native.js.map +1 -1
  46. package/dist/cjs/formEngine/useSessionRoles.cjs +77 -0
  47. package/dist/cjs/formEngine/useSessionRoles.native.js +84 -0
  48. package/dist/cjs/formEngine/useSessionRoles.native.js.map +1 -0
  49. package/dist/cjs/frappeConnections.cjs +41 -0
  50. package/dist/cjs/frappeConnections.native.js +50 -0
  51. package/dist/cjs/frappeConnections.native.js.map +1 -0
  52. package/dist/cjs/frappeNavigation.cjs +107 -0
  53. package/dist/cjs/frappeNavigation.native.js +112 -0
  54. package/dist/cjs/frappeNavigation.native.js.map +1 -0
  55. package/dist/cjs/index.cjs +18 -1
  56. package/dist/cjs/index.native.js +18 -1
  57. package/dist/cjs/index.native.js.map +1 -1
  58. package/dist/cjs/schemaForm/index.cjs +4 -1
  59. package/dist/cjs/schemaForm/index.native.js +4 -1
  60. package/dist/cjs/schemaForm/index.native.js.map +1 -1
  61. package/dist/cjs/useConnectionFilters.cjs +146 -0
  62. package/dist/cjs/useConnectionFilters.native.js +213 -0
  63. package/dist/cjs/useConnectionFilters.native.js.map +1 -0
  64. package/dist/cjs/useFrappePagination.cjs +37 -18
  65. package/dist/cjs/useFrappePagination.native.js +59 -23
  66. package/dist/cjs/useFrappePagination.native.js.map +1 -1
  67. package/dist/cjs/useFrappeRows.native.js.map +1 -1
  68. package/dist/esm/FrappeDashboard.mjs +9 -11
  69. package/dist/esm/FrappeDashboard.mjs.map +1 -1
  70. package/dist/esm/FrappeDashboard.native.js +9 -15
  71. package/dist/esm/FrappeDashboard.native.js.map +1 -1
  72. package/dist/esm/FrappeForm.mjs +471 -181
  73. package/dist/esm/FrappeForm.mjs.map +1 -1
  74. package/dist/esm/FrappeForm.native.js +599 -195
  75. package/dist/esm/FrappeForm.native.js.map +1 -1
  76. package/dist/esm/FrappeFormConnections.mjs +99 -0
  77. package/dist/esm/FrappeFormConnections.mjs.map +1 -0
  78. package/dist/esm/FrappeFormConnections.native.js +120 -0
  79. package/dist/esm/FrappeFormConnections.native.js.map +1 -0
  80. package/dist/esm/FrappeImageView.mjs +8 -10
  81. package/dist/esm/FrappeImageView.mjs.map +1 -1
  82. package/dist/esm/FrappeImageView.native.js +8 -14
  83. package/dist/esm/FrappeImageView.native.js.map +1 -1
  84. package/dist/esm/FrappeList.mjs +31 -6
  85. package/dist/esm/FrappeList.mjs.map +1 -1
  86. package/dist/esm/FrappeList.native.js +39 -7
  87. package/dist/esm/FrappeList.native.js.map +1 -1
  88. package/dist/esm/FrappeListView.mjs +103 -30
  89. package/dist/esm/FrappeListView.mjs.map +1 -1
  90. package/dist/esm/FrappeListView.native.js +110 -30
  91. package/dist/esm/FrappeListView.native.js.map +1 -1
  92. package/dist/esm/FrappeProvider.mjs +7 -2
  93. package/dist/esm/FrappeProvider.mjs.map +1 -1
  94. package/dist/esm/FrappeProvider.native.js +7 -2
  95. package/dist/esm/FrappeProvider.native.js.map +1 -1
  96. package/dist/esm/FrappeReportBuilder.mjs +11 -12
  97. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  98. package/dist/esm/FrappeReportBuilder.native.js +11 -17
  99. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  100. package/dist/esm/FrappeRowsReader.mjs +24 -0
  101. package/dist/esm/FrappeRowsReader.mjs.map +1 -0
  102. package/dist/esm/FrappeRowsReader.native.js +25 -0
  103. package/dist/esm/FrappeRowsReader.native.js.map +1 -0
  104. package/dist/esm/FrappeTable.mjs +18 -6
  105. package/dist/esm/FrappeTable.mjs.map +1 -1
  106. package/dist/esm/FrappeTable.native.js +24 -6
  107. package/dist/esm/FrappeTable.native.js.map +1 -1
  108. package/dist/esm/fieldRegistry.mjs +35 -12
  109. package/dist/esm/fieldRegistry.mjs.map +1 -1
  110. package/dist/esm/fieldRegistry.native.js +58 -12
  111. package/dist/esm/fieldRegistry.native.js.map +1 -1
  112. package/dist/esm/fields/Date/index.native.js +6 -3
  113. package/dist/esm/fields/Date/index.native.js.map +1 -1
  114. package/dist/esm/fields/Date/sheetKeyboard.mjs +2 -2
  115. package/dist/esm/fields/Date/sheetKeyboard.mjs.map +1 -1
  116. package/dist/esm/fields/Date/sheetKeyboard.native.js +2 -2
  117. package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
  118. package/dist/esm/fields/DateRange/index.mjs +2 -1
  119. package/dist/esm/fields/DateRange/index.mjs.map +1 -1
  120. package/dist/esm/fields/DateRange/index.native.js +4 -1
  121. package/dist/esm/fields/DateRange/index.native.js.map +1 -1
  122. package/dist/esm/formEngine/index.mjs +2 -1
  123. package/dist/esm/formEngine/index.mjs.map +1 -1
  124. package/dist/esm/formEngine/index.native.js +2 -1
  125. package/dist/esm/formEngine/index.native.js.map +1 -1
  126. package/dist/esm/formEngine/useSessionRoles.mjs +52 -0
  127. package/dist/esm/formEngine/useSessionRoles.mjs.map +1 -0
  128. package/dist/esm/formEngine/useSessionRoles.native.js +56 -0
  129. package/dist/esm/formEngine/useSessionRoles.native.js.map +1 -0
  130. package/dist/esm/frappeConnections.mjs +15 -0
  131. package/dist/esm/frappeConnections.mjs.map +1 -0
  132. package/dist/esm/frappeConnections.native.js +21 -0
  133. package/dist/esm/frappeConnections.native.js.map +1 -0
  134. package/dist/esm/frappeNavigation.mjs +78 -0
  135. package/dist/esm/frappeNavigation.mjs.map +1 -0
  136. package/dist/esm/frappeNavigation.native.js +80 -0
  137. package/dist/esm/frappeNavigation.native.js.map +1 -0
  138. package/dist/esm/index.mjs +7 -3
  139. package/dist/esm/index.mjs.map +1 -1
  140. package/dist/esm/index.native.js +7 -3
  141. package/dist/esm/index.native.js.map +1 -1
  142. package/dist/esm/schemaForm/index.mjs +4 -1
  143. package/dist/esm/schemaForm/index.mjs.map +1 -1
  144. package/dist/esm/schemaForm/index.native.js +4 -1
  145. package/dist/esm/schemaForm/index.native.js.map +1 -1
  146. package/dist/esm/useConnectionFilters.mjs +121 -0
  147. package/dist/esm/useConnectionFilters.mjs.map +1 -0
  148. package/dist/esm/useConnectionFilters.native.js +185 -0
  149. package/dist/esm/useConnectionFilters.native.js.map +1 -0
  150. package/dist/esm/useFrappePagination.mjs +38 -19
  151. package/dist/esm/useFrappePagination.mjs.map +1 -1
  152. package/dist/esm/useFrappePagination.native.js +60 -24
  153. package/dist/esm/useFrappePagination.native.js.map +1 -1
  154. package/dist/esm/useFrappeRows.mjs.map +1 -1
  155. package/dist/esm/useFrappeRows.native.js.map +1 -1
  156. package/dist/jsx/FrappeDashboard.mjs +9 -11
  157. package/dist/jsx/FrappeDashboard.mjs.map +1 -1
  158. package/dist/jsx/FrappeDashboard.native.js +8 -14
  159. package/dist/jsx/FrappeDashboard.native.js.map +1 -1
  160. package/dist/jsx/FrappeForm.mjs +471 -181
  161. package/dist/jsx/FrappeForm.mjs.map +1 -1
  162. package/dist/jsx/FrappeForm.native.js +611 -207
  163. package/dist/jsx/FrappeForm.native.js.map +1 -1
  164. package/dist/jsx/FrappeFormConnections.mjs +99 -0
  165. package/dist/jsx/FrappeFormConnections.mjs.map +1 -0
  166. package/dist/jsx/FrappeFormConnections.native.js +149 -0
  167. package/dist/jsx/FrappeFormConnections.native.js.map +1 -0
  168. package/dist/jsx/FrappeImageView.mjs +8 -10
  169. package/dist/jsx/FrappeImageView.mjs.map +1 -1
  170. package/dist/jsx/FrappeImageView.native.js +7 -13
  171. package/dist/jsx/FrappeImageView.native.js.map +1 -1
  172. package/dist/jsx/FrappeList.mjs +31 -6
  173. package/dist/jsx/FrappeList.mjs.map +1 -1
  174. package/dist/jsx/FrappeList.native.js +37 -5
  175. package/dist/jsx/FrappeList.native.js.map +1 -1
  176. package/dist/jsx/FrappeListView.mjs +103 -30
  177. package/dist/jsx/FrappeListView.mjs.map +1 -1
  178. package/dist/jsx/FrappeListView.native.js +109 -29
  179. package/dist/jsx/FrappeListView.native.js.map +1 -1
  180. package/dist/jsx/FrappeProvider.mjs +7 -2
  181. package/dist/jsx/FrappeProvider.mjs.map +1 -1
  182. package/dist/jsx/FrappeProvider.native.js +7 -2
  183. package/dist/jsx/FrappeProvider.native.js.map +1 -1
  184. package/dist/jsx/FrappeReportBuilder.mjs +11 -12
  185. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  186. package/dist/jsx/FrappeReportBuilder.native.js +10 -16
  187. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  188. package/dist/jsx/FrappeRowsReader.mjs +24 -0
  189. package/dist/jsx/FrappeRowsReader.mjs.map +1 -0
  190. package/dist/jsx/FrappeRowsReader.native.js +53 -0
  191. package/dist/jsx/FrappeRowsReader.native.js.map +1 -0
  192. package/dist/jsx/FrappeTable.mjs +18 -6
  193. package/dist/jsx/FrappeTable.mjs.map +1 -1
  194. package/dist/jsx/FrappeTable.native.js +24 -6
  195. package/dist/jsx/FrappeTable.native.js.map +1 -1
  196. package/dist/jsx/fieldRegistry.mjs +35 -12
  197. package/dist/jsx/fieldRegistry.mjs.map +1 -1
  198. package/dist/jsx/fieldRegistry.native.js +59 -11
  199. package/dist/jsx/fieldRegistry.native.js.map +1 -1
  200. package/dist/jsx/fields/Date/index.native.js +5 -2
  201. package/dist/jsx/fields/Date/index.native.js.map +1 -1
  202. package/dist/jsx/fields/Date/sheetKeyboard.mjs +2 -2
  203. package/dist/jsx/fields/Date/sheetKeyboard.mjs.map +1 -1
  204. package/dist/jsx/fields/Date/sheetKeyboard.native.js +2 -2
  205. package/dist/jsx/fields/Date/sheetKeyboard.native.js.map +1 -1
  206. package/dist/jsx/fields/DateRange/index.mjs +2 -1
  207. package/dist/jsx/fields/DateRange/index.mjs.map +1 -1
  208. package/dist/jsx/fields/DateRange/index.native.js +4 -1
  209. package/dist/jsx/fields/DateRange/index.native.js.map +1 -1
  210. package/dist/jsx/formEngine/index.mjs +2 -1
  211. package/dist/jsx/formEngine/index.mjs.map +1 -1
  212. package/dist/jsx/formEngine/index.native.js +3 -1
  213. package/dist/jsx/formEngine/index.native.js.map +1 -1
  214. package/dist/jsx/formEngine/useSessionRoles.mjs +52 -0
  215. package/dist/jsx/formEngine/useSessionRoles.mjs.map +1 -0
  216. package/dist/jsx/formEngine/useSessionRoles.native.js +84 -0
  217. package/dist/jsx/formEngine/useSessionRoles.native.js.map +1 -0
  218. package/dist/jsx/frappeConnections.mjs +15 -0
  219. package/dist/jsx/frappeConnections.mjs.map +1 -0
  220. package/dist/jsx/frappeConnections.native.js +50 -0
  221. package/dist/jsx/frappeConnections.native.js.map +1 -0
  222. package/dist/jsx/frappeNavigation.mjs +78 -0
  223. package/dist/jsx/frappeNavigation.mjs.map +1 -0
  224. package/dist/jsx/frappeNavigation.native.js +112 -0
  225. package/dist/jsx/frappeNavigation.native.js.map +1 -0
  226. package/dist/jsx/index.js +7 -3
  227. package/dist/jsx/index.js.map +1 -1
  228. package/dist/jsx/index.mjs +7 -3
  229. package/dist/jsx/index.mjs.map +1 -1
  230. package/dist/jsx/index.native.js +18 -1
  231. package/dist/jsx/index.native.js.map +1 -1
  232. package/dist/jsx/schemaForm/index.mjs +4 -1
  233. package/dist/jsx/schemaForm/index.mjs.map +1 -1
  234. package/dist/jsx/schemaForm/index.native.js +4 -1
  235. package/dist/jsx/schemaForm/index.native.js.map +1 -1
  236. package/dist/jsx/useConnectionFilters.mjs +121 -0
  237. package/dist/jsx/useConnectionFilters.mjs.map +1 -0
  238. package/dist/jsx/useConnectionFilters.native.js +213 -0
  239. package/dist/jsx/useConnectionFilters.native.js.map +1 -0
  240. package/dist/jsx/useFrappePagination.mjs +38 -19
  241. package/dist/jsx/useFrappePagination.mjs.map +1 -1
  242. package/dist/jsx/useFrappePagination.native.js +59 -23
  243. package/dist/jsx/useFrappePagination.native.js.map +1 -1
  244. package/dist/jsx/useFrappeRows.mjs.map +1 -1
  245. package/dist/jsx/useFrappeRows.native.js.map +1 -1
  246. package/package.json +26 -22
  247. package/src/FileBrowser/AttachLibrary.stories.tsx +23 -0
  248. package/src/FrappeDashboard.tsx +11 -16
  249. package/src/FrappeForm.connections.spec.tsx +280 -0
  250. package/src/FrappeForm.connections.stories.tsx +93 -0
  251. package/src/FrappeForm.deskSemantics.spec.tsx +284 -0
  252. package/src/FrappeForm.tsx +560 -145
  253. package/src/FrappeFormConnections.tsx +148 -0
  254. package/src/FrappeGuestMeta.spec.tsx +143 -0
  255. package/src/FrappeImageView.tsx +8 -12
  256. package/src/FrappeList.tsx +71 -15
  257. package/src/FrappeListView.cards.spec.tsx +175 -0
  258. package/src/FrappeListView.cards.stories.tsx +131 -0
  259. package/src/FrappeListView.connections.spec.tsx +192 -0
  260. package/src/FrappeListView.connections.stories.tsx +99 -0
  261. package/src/FrappeListView.seed.spec.tsx +228 -0
  262. package/src/FrappeListView.tsx +177 -31
  263. package/src/FrappeProvider.catchUp.spec.tsx +502 -0
  264. package/src/FrappeProvider.tsx +15 -3
  265. package/src/FrappeReportBuilder.tsx +11 -19
  266. package/src/FrappeRowsReader.tsx +38 -0
  267. package/src/FrappeTable.optionalProps.spec.tsx +249 -0
  268. package/src/FrappeTable.spec.tsx +32 -42
  269. package/src/FrappeTable.stories.spec.tsx +55 -0
  270. package/src/FrappeTable.stories.tsx +28 -37
  271. package/src/FrappeTable.tsx +108 -45
  272. package/src/childTableDependsOn.spec.tsx +85 -0
  273. package/src/desk/DeskFormSidebar.spec.tsx +20 -0
  274. package/src/desk/DeskFormSidebar.stories.tsx +42 -0
  275. package/src/fieldRegistry.spec.tsx +27 -64
  276. package/src/fieldRegistry.ts +71 -14
  277. package/src/fields/Date/index.native.tsx +4 -2
  278. package/src/fields/Date/sheetKeyboard.spec.ts +14 -5
  279. package/src/fields/Date/sheetKeyboard.ts +12 -4
  280. package/src/fields/DateRange/DateRange.spec.tsx +67 -0
  281. package/src/fields/DateRange/index.tsx +5 -1
  282. package/src/fields/LinkTree.spec.tsx +8 -0
  283. package/src/fields/LinkTree.stories.tsx +28 -5
  284. package/src/fields/Select/Select.hydration.spec.tsx +177 -0
  285. package/src/formEngine/doctypeMeta.ts +15 -114
  286. package/src/formEngine/index.ts +2 -0
  287. package/src/formEngine/seam.spec.ts +23 -4
  288. package/src/formEngine/useSessionRoles.ts +73 -0
  289. package/src/frappeConnections.ts +50 -0
  290. package/src/frappeNavigation.tsx +112 -0
  291. package/src/frappeRoutes.spec.tsx +335 -0
  292. package/src/index.ts +28 -1
  293. package/src/schemaForm/index.tsx +1 -0
  294. package/src/useConnectionFilters.tsx +157 -0
  295. package/src/useFrappePagination.ts +70 -26
  296. package/src/useFrappeRows.sharedPath.spec.tsx +206 -0
  297. package/src/useFrappeRows.ts +5 -4
  298. package/types/FrappeDashboard.d.ts +3 -4
  299. package/types/FrappeDashboard.d.ts.map +1 -1
  300. package/types/FrappeForm.d.ts +57 -5
  301. package/types/FrappeForm.d.ts.map +1 -1
  302. package/types/FrappeFormConnections.d.ts +18 -0
  303. package/types/FrappeFormConnections.d.ts.map +1 -0
  304. package/types/FrappeImageView.d.ts +2 -3
  305. package/types/FrappeImageView.d.ts.map +1 -1
  306. package/types/FrappeList.d.ts +20 -2
  307. package/types/FrappeList.d.ts.map +1 -1
  308. package/types/FrappeListView.d.ts +53 -3
  309. package/types/FrappeListView.d.ts.map +1 -1
  310. package/types/FrappeProvider.d.ts +10 -3
  311. package/types/FrappeProvider.d.ts.map +1 -1
  312. package/types/FrappeReportBuilder.d.ts.map +1 -1
  313. package/types/FrappeRowsReader.d.ts +26 -0
  314. package/types/FrappeRowsReader.d.ts.map +1 -0
  315. package/types/FrappeTable.d.ts +39 -8
  316. package/types/FrappeTable.d.ts.map +1 -1
  317. package/types/fieldRegistry.d.ts +17 -3
  318. package/types/fieldRegistry.d.ts.map +1 -1
  319. package/types/fields/Date/index.native.d.ts.map +1 -1
  320. package/types/fields/Date/sheetKeyboard.d.ts +4 -3
  321. package/types/fields/Date/sheetKeyboard.d.ts.map +1 -1
  322. package/types/fields/DateRange/index.d.ts.map +1 -1
  323. package/types/formEngine/doctypeMeta.d.ts +10 -114
  324. package/types/formEngine/doctypeMeta.d.ts.map +1 -1
  325. package/types/formEngine/index.d.ts +1 -0
  326. package/types/formEngine/index.d.ts.map +1 -1
  327. package/types/formEngine/useSessionRoles.d.ts +19 -0
  328. package/types/formEngine/useSessionRoles.d.ts.map +1 -0
  329. package/types/frappeConnections.d.ts +33 -0
  330. package/types/frappeConnections.d.ts.map +1 -0
  331. package/types/frappeNavigation.d.ts +49 -0
  332. package/types/frappeNavigation.d.ts.map +1 -0
  333. package/types/index.d.ts +7 -3
  334. package/types/index.d.ts.map +1 -1
  335. package/types/schemaForm/index.d.ts.map +1 -1
  336. package/types/useConnectionFilters.d.ts +34 -0
  337. package/types/useConnectionFilters.d.ts.map +1 -0
  338. package/types/useFrappePagination.d.ts +18 -5
  339. package/types/useFrappePagination.d.ts.map +1 -1
  340. package/types/useFrappeRows.d.ts +5 -4
  341. package/types/useFrappeRows.d.ts.map +1 -1
  342. package/src/FileBrowser/AttachLibrary.spec.tsx +0 -74
@@ -43,46 +43,55 @@ var import_FrappeProvider = require("./FrappeProvider.cjs");
43
43
  var import_FrappeReconnectIndicator = require("./FrappeReconnectIndicator.cjs");
44
44
  var import_timeline = require("./components/timeline.cjs");
45
45
  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_useSessionRoles = require("./formEngine/useSessionRoles.cjs");
51
+ var import_frappeConnections = require("./frappeConnections.cjs");
52
+ var import_FrappeFormConnections = require("./FrappeFormConnections.cjs");
53
+ var import_FrappeRowsReader = require("./FrappeRowsReader.cjs");
54
+ var import_frappeNavigation = require("./frappeNavigation.cjs");
46
55
  var import_jsx_runtime = require("react/jsx-runtime");
47
- const LAYOUT_FIELDTYPES = /* @__PURE__ */new Set(["Section Break", "Column Break", "Tab Break"]);
56
+ var import_react3 = require("react");
48
57
  function isEmptyFieldValue(value) {
49
58
  if (value === void 0 || value === null) return true;
50
59
  if (typeof value === "string" && value.trim() === "") return true;
51
60
  if (Array.isArray(value) && value.length === 0) return true;
52
61
  return false;
53
62
  }
54
- function mapFieldToGenericSchema(field) {
55
- return {
56
- type: field.fieldtype,
57
- name: field.fieldname,
58
- label: field.label,
59
- options: field.options,
60
- required: !!field.reqd,
61
- hidden: !!field.hidden,
62
- readOnly: !!field.read_only,
63
- precision: field.precision,
64
- depends_on: field.depends_on,
65
- // Pass through additional Frappe-specific metadata
66
- fieldtype: field.fieldtype,
67
- fieldname: field.fieldname,
68
- in_list_view: field.in_list_view,
69
- in_standard_filter: field.in_standard_filter
70
- };
63
+ function sectionsToLayoutFields(sections) {
64
+ const fields = [];
65
+ sections.forEach((section, sectionIndex) => {
66
+ fields.push({
67
+ fieldname: `__section_${sectionIndex}`,
68
+ fieldtype: section.tab ? "Tab Break" : "Section Break",
69
+ label: section.label,
70
+ collapsible: section.collapsible ? 1 : 0
71
+ });
72
+ section.columns.forEach((column, columnIndex) => {
73
+ if (columnIndex > 0) {
74
+ fields.push({
75
+ fieldname: `__column_${sectionIndex}_${columnIndex}`,
76
+ fieldtype: "Column Break"
77
+ });
78
+ }
79
+ fields.push(...column.fields);
80
+ });
81
+ });
82
+ return fields;
71
83
  }
72
- function mapMetaToFormSchema(meta, sectionOverrides) {
73
- const sections = sectionOverrides ?? meta.sections;
74
- const genericSections = sections.map(section => ({
75
- label: section.label,
76
- collapsible: section.collapsible,
77
- columns: section.columns.map(col => ({
78
- fields: col.fields.map(mapFieldToGenericSchema)
79
- }))
84
+ const documentBookkeeping = /* @__PURE__ */new Set(["name", "owner", "creation", "modified", "modified_by", "docstatus", "idx", "doctype", "_user_tags", "_comments", "_assign", "_liked_by", "_seen"]);
85
+ function fieldsFromDocument(doc) {
86
+ return Object.entries(doc).filter(([key, value]) => !key.startsWith("$") && !documentBookkeeping.has(key) && (value === null || typeof value === "string" || typeof value === "number")).map(([key, value]) => ({
87
+ name: key,
88
+ label: key.replace(/_/g, " ").replace(/(^|\s)\S/g, c => c.toUpperCase()),
89
+ type: typeof value === "number" ? Number.isInteger(value) ? "Int" : "Float" : "Data",
90
+ readOnly: true
80
91
  }));
81
- const allFields = meta.fields.map(mapFieldToGenericSchema);
82
- return {
83
- sections: genericSections,
84
- fields: allFields
85
- };
92
+ }
93
+ function hasRestrictedPermLevel(meta) {
94
+ return !!meta?.fields.some(field => Number(field.permlevel ?? 0) > 0);
86
95
  }
87
96
  function resolveFileUrl(value, baseURL) {
88
97
  if (!value || typeof value !== "string") return void 0;
@@ -148,7 +157,72 @@ function mapDocToSidebarMetadata(doc, t) {
148
157
  }
149
158
  return metadata;
150
159
  }
151
- function FrappeForm({
160
+ function FrappeForm(props) {
161
+ const {
162
+ route,
163
+ ...formProps
164
+ } = props;
165
+ if (route === void 0) return /* @__PURE__ */(0, import_jsx_runtime.jsx)(FrappeFormBody, {
166
+ ...formProps
167
+ });
168
+ return /* @__PURE__ */(0, import_jsx_runtime.jsx)(FrappeFormRoute, {
169
+ ...formProps,
170
+ route
171
+ });
172
+ }
173
+ function FrappeFormRoute({
174
+ route,
175
+ name: nameProp,
176
+ onSave,
177
+ onCancel,
178
+ onDelete,
179
+ onEdit,
180
+ ...props
181
+ }) {
182
+ const router = (0, import_frappeNavigation.useFrappeRouter)();
183
+ const fromPath = router ? (0, import_frappeNavigation.frappeRouteTarget)(route, router.pathname) : void 0;
184
+ const target = nameProp ? {
185
+ mode: fromPath?.mode === "view" ? "view" : "edit",
186
+ name: nameProp
187
+ } : fromPath?.mode === "view" || fromPath?.mode === "edit" ? fromPath : {
188
+ mode: "create"
189
+ };
190
+ const go = next => router?.navigate((0, import_frappeNavigation.frappeRouteHref)(route, next));
191
+ const name = target.mode === "view" || target.mode === "edit" ? target.name : void 0;
192
+ return /* @__PURE__ */(0, import_react3.createElement)(FrappeFormBody, {
193
+ ...props,
194
+ key: `${target.mode}:${name ?? ""}`,
195
+ name,
196
+ routePage: {
197
+ onBack: () => go({
198
+ mode: "list"
199
+ })
200
+ },
201
+ onEdit: target.mode === "view" ? onEdit ?? (() => go({
202
+ mode: "edit",
203
+ name: target.name
204
+ })) : void 0,
205
+ onSave: onSave ?? (doc => {
206
+ const saved = doc.name ?? name;
207
+ go(saved ? {
208
+ mode: "view",
209
+ name: saved
210
+ } : {
211
+ mode: "list"
212
+ });
213
+ }),
214
+ onCancel: onCancel ?? (() => go(name ? {
215
+ mode: "view",
216
+ name
217
+ } : {
218
+ mode: "list"
219
+ })),
220
+ onDelete: onDelete ?? (() => go({
221
+ mode: "list"
222
+ }))
223
+ });
224
+ }
225
+ function FrappeFormBody({
152
226
  baseURL,
153
227
  auth,
154
228
  syncOptions,
@@ -161,14 +235,23 @@ function FrappeForm({
161
235
  readOnlyFields,
162
236
  sections,
163
237
  order,
238
+ roles,
164
239
  onSave,
165
240
  onCancel,
166
241
  onDelete,
242
+ onEdit,
167
243
  showToolbar = true,
168
244
  showSidebar = true,
169
245
  showTimeline = true,
170
246
  disabled = false,
171
- sectionHeadingLevel
247
+ sectionHeadingLevel,
248
+ connections,
249
+ showConnections = true,
250
+ initialDoc,
251
+ loadingFallback,
252
+ notFoundFallback,
253
+ errorFallback,
254
+ routePage
172
255
  }) {
173
256
  const config = (0, import_FrappeProvider.useFrappeConfig)();
174
257
  const {
@@ -177,12 +260,17 @@ function FrappeForm({
177
260
  const {
178
261
  t
179
262
  } = (0, import_react_i18next.useTranslation)();
180
- const [localDoc, setLocalDoc] = (0, import_react2.useState)({});
181
- const [baselineDoc, setBaselineDoc] = (0, import_react2.useState)(void 0);
263
+ const seedDoc = name && initialDoc && initialDoc.name === name ? initialDoc : void 0;
264
+ const seedRef = (0, import_react2.useRef)(seedDoc);
265
+ seedRef.current = seedDoc;
266
+ const [localDoc, setLocalDoc] = (0, import_react2.useState)(() => seedDoc ?? {});
267
+ const [baselineDoc, setBaselineDoc] = (0, import_react2.useState)(() => seedDoc);
268
+ const [docError, setDocError] = (0, import_react2.useState)(null);
182
269
  const [conflictFields, setConflictFields] = (0, import_react2.useState)([]);
183
270
  const [wasDeleted, setWasDeleted] = (0, import_react2.useState)(false);
184
271
  const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
185
272
  const [errors, setErrors] = (0, import_react2.useState)({});
273
+ const [activeTab, setActiveTab] = (0, import_react2.useState)(void 0);
186
274
  const everLoadedRef = (0, import_react2.useRef)(false);
187
275
  const localDocRef = (0, import_react2.useRef)(localDoc);
188
276
  localDocRef.current = localDoc;
@@ -209,16 +297,59 @@ function FrappeForm({
209
297
  isLoading: isMetaLoading,
210
298
  error: metaError
211
299
  } = (0, import_frappe.useDocTypeMeta)(frappeConfig, doctype);
212
- const formSchema = (0, import_react2.useMemo)(() => {
300
+ const sessionRoles = (0, import_useSessionRoles.useSessionRoles)(!roles && hasRestrictedPermLevel(meta) ? frappeConfig : void 0);
301
+ const effectiveRoles = roles ?? sessionRoles;
302
+ const permLevels = (0, import_react2.useMemo)(() => (0, import_fieldPermissions.buildPermLevelMatrix)(meta?.permissions, effectiveRoles), [meta?.permissions, effectiveRoles]);
303
+ const isCreate = !name;
304
+ const docstatus = Number(baselineDoc?.docstatus ?? 0);
305
+ const layoutFields = (0, import_react2.useMemo)(() => {
213
306
  if (!meta) return void 0;
214
- return mapMetaToFormSchema(meta, sections);
307
+ return sections ? sectionsToLayoutFields(sections) : meta.fields;
215
308
  }, [meta, sections]);
216
- const hideFieldSet = (0, import_react2.useMemo)(() => new Set(hideFields ?? []), [hideFields]);
309
+ const formTabs = (0, import_react2.useMemo)(() => {
310
+ if (!layoutFields) return void 0;
311
+ return (0, import_formLayout.buildFormTabs)({
312
+ fields: layoutFields,
313
+ doc: {
314
+ ...localDoc,
315
+ __islocal: isCreate ? 1 : 0
316
+ },
317
+ docstatus,
318
+ formReadOnly: !!meta?.read_only,
319
+ isCreate,
320
+ detailsLabel: t("Details"),
321
+ permLevels,
322
+ hiddenFields: hideFields
323
+ });
324
+ }, [layoutFields, localDoc, docstatus, meta?.read_only, isCreate, permLevels, hideFields, t]);
325
+ const readsWithoutMeta = !children && !meta && Boolean(metaError) && Boolean(name);
326
+ const recordTabs = (0, import_react2.useMemo)(() => {
327
+ if (!readsWithoutMeta || !baselineDoc) return void 0;
328
+ const recordFields = fieldsFromDocument(baselineDoc);
329
+ return [{
330
+ key: "__details",
331
+ label: t("Details"),
332
+ schema: {
333
+ sections: [{
334
+ columns: [{
335
+ fields: recordFields
336
+ }]
337
+ }],
338
+ fields: recordFields
339
+ }
340
+ }];
341
+ }, [readsWithoutMeta, baselineDoc, t]);
342
+ const promptNamed = isCreate && !!meta && (0, import_formLayout.isPromptNamed)(meta.autoname, meta.naming_rule);
343
+ const fetchMap = (0, import_react2.useMemo)(() => meta ? (0, import_fetchFrom.buildFetchMap)(meta.fields) : void 0, [meta]);
344
+ const handleDocSyncError = (0, import_react2.useCallback)(err => {
345
+ setDocError(err instanceof Error ? err : new Error(String(err)));
346
+ }, []);
217
347
  const docCollection = (0, import_frappe.useFrappeCollection)(name ? frappeConfig : void 0, doctype, {
218
348
  fields,
219
349
  filters: name ? {
220
350
  name
221
- } : void 0
351
+ } : void 0,
352
+ onSyncError: handleDocSyncError
222
353
  });
223
354
  const {
224
355
  data: rawDocData,
@@ -279,8 +410,41 @@ function FrappeForm({
279
410
  everLoadedRef.current = false;
280
411
  setWasDeleted(false);
281
412
  setConflictFields([]);
282
- setBaselineDoc(void 0);
413
+ setDocError(null);
414
+ const seed = seedRef.current;
415
+ setBaselineDoc(seed);
416
+ if (seed) setLocalDoc(seed);
283
417
  }, [doctype, name]);
418
+ const effectiveConnections = (0, import_react2.useMemo)(() => connections ?? (0, import_frappeConnections.connectionsFromMeta)(meta), [connections, meta]);
419
+ const readsConnections = Boolean(children) && Boolean(name) && effectiveConnections.length > 0;
420
+ const [connectionSnapshots, setConnectionSnapshots] = (0, import_react2.useState)({});
421
+ (0, import_react2.useEffect)(() => {
422
+ setConnectionSnapshots({});
423
+ }, [doctype, name]);
424
+ const connectionReads = (0, import_react2.useMemo)(() => readsConnections && name ? effectiveConnections.map(link => ({
425
+ link,
426
+ options: {
427
+ fields: (0, import_frappeConnections.connectionFields)(link),
428
+ filters: [[link.fieldname, "=", name]],
429
+ limit: link.limit ?? 0
430
+ },
431
+ onChange: snapshot => setConnectionSnapshots(prev => ({
432
+ ...prev,
433
+ [link.doctype]: snapshot
434
+ }))
435
+ })) : [], [readsConnections, effectiveConnections, name]);
436
+ const connectionRows = (0, import_react2.useMemo)(() => {
437
+ const rows = {};
438
+ for (const {
439
+ link
440
+ } of connectionReads) {
441
+ rows[link.doctype] = connectionSnapshots[link.doctype]?.rows ?? [];
442
+ }
443
+ return rows;
444
+ }, [connectionReads, connectionSnapshots]);
445
+ const connectionsLoading = connectionReads.some(({
446
+ link
447
+ }) => connectionSnapshots[link.doctype]?.isLoading ?? true);
284
448
  (0, import_frappe.useFrappeDoctypeEvents)(name ? frappeConfig : void 0, doctype, event => {
285
449
  if (event.type !== "doc_deleted") return;
286
450
  const payload = event.payload;
@@ -333,6 +497,32 @@ function FrappeForm({
333
497
  return dirty;
334
498
  }, [localDoc, baselineDoc]);
335
499
  const hasUnsavedChanges = dirtyFieldNames.length > 0;
500
+ const runFetchFrom = (field, value) => {
501
+ const rules = fetchMap?.get(field);
502
+ if (!rules || rules.length === 0) return;
503
+ const applyPatch = fetched2 => {
504
+ setLocalDoc(prev => {
505
+ const current = prev;
506
+ if (current[field] !== value) return prev;
507
+ const patch = (0, import_fetchFrom.applyFetchedValues)(rules, fetched2, current);
508
+ return Object.keys(patch).length > 0 ? {
509
+ ...current,
510
+ ...patch
511
+ } : prev;
512
+ });
513
+ };
514
+ if (isEmptyFieldValue(value)) {
515
+ applyPatch({});
516
+ return;
517
+ }
518
+ const linkField = meta?.fields.find(metaField => metaField.fieldname === field);
519
+ const targetDoctype = typeof linkField?.options === "string" ? linkField.options : "";
520
+ if (!targetDoctype) return;
521
+ const sources = Array.from(new Set(rules.map(rule => rule.source)));
522
+ const fixtures = frappeConfig.fixtures;
523
+ 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);
524
+ fetched.then(applyPatch).catch(() => void 0);
525
+ };
336
526
  const setValue = (field, value) => {
337
527
  setLocalDoc(prev => ({
338
528
  ...prev,
@@ -345,19 +535,23 @@ function FrappeForm({
345
535
  delete newErrors[String(field)];
346
536
  return newErrors;
347
537
  });
538
+ runFetchFrom(String(field), value);
348
539
  };
349
540
  const validateRequiredFields = () => {
350
- if (!meta) return {};
541
+ if (!formTabs) return {};
351
542
  const validationErrors = {};
352
543
  const doc = localDoc;
353
- for (const field of meta.fields) {
354
- if (!field.reqd) continue;
355
- if (field.hidden || LAYOUT_FIELDTYPES.has(field.fieldtype)) continue;
356
- if (hideFieldSet.has(field.fieldname)) continue;
357
- if (isEmptyFieldValue(doc[field.fieldname])) {
358
- validationErrors[field.fieldname] = t("{{label}} is required", {
359
- label: field.label || field.fieldname
360
- });
544
+ if (promptNamed && isEmptyFieldValue(doc.name)) {
545
+ validationErrors.name = t("Name is required");
546
+ }
547
+ for (const tab of formTabs) {
548
+ for (const field of tab.schema.fields) {
549
+ if (!field.required) continue;
550
+ if (isEmptyFieldValue(doc[field.name])) {
551
+ validationErrors[field.name] = t("{{label}} is required", {
552
+ label: field.label || field.name
553
+ });
554
+ }
361
555
  }
362
556
  }
363
557
  return validationErrors;
@@ -387,13 +581,20 @@ function FrappeForm({
387
581
  setConflictFields([]);
388
582
  } else {
389
583
  if (!collection) return;
584
+ const temporaryName = localDoc.name ?? `new-${Date.now()}`;
390
585
  const docToInsert = {
391
586
  ...localDoc,
392
587
  doctype,
393
- name: localDoc.name ?? `new-${Date.now()}`
588
+ name: temporaryName
394
589
  };
395
590
  const tx = collection.insert(docToInsert);
396
591
  await tx.isPersisted.promise;
592
+ const createdName = (0, import_frappe.getFrappeSyncModule)(frappeConfig)?.createdName(temporaryName) ?? temporaryName;
593
+ onSave?.({
594
+ ...localDoc,
595
+ name: createdName
596
+ });
597
+ return;
397
598
  }
398
599
  onSave?.(localDoc);
399
600
  } catch (err) {
@@ -456,17 +657,45 @@ function FrappeForm({
456
657
  setIsSubmitting(false);
457
658
  }
458
659
  };
660
+ const titleField = meta?.title_field;
661
+ const titleValue = titleField ? localDoc[titleField] : void 0;
662
+ const pageTitle = isCreate ? t("New {{doctype}}", {
663
+ doctype
664
+ }) : String(titleValue || name);
665
+ const frame = (content, aside) => routePage ?
666
+ // flexBasis auto: see DeskFormPage (react-native-web's min-height:0
667
+ // reset would cap the scroll page at viewport height).
668
+ /* @__PURE__ */
669
+ (0, import_jsx_runtime.jsx)(import_components.DetailPageLayout, {
670
+ flexBasis: "auto",
671
+ toolbarLeading: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_forms.Button, {
672
+ size: "$3",
673
+ chromeless: true,
674
+ icon: import_react.ArrowLeftIcon,
675
+ onPress: routePage.onBack,
676
+ "aria-label": t("Back to {{doctype}} list", {
677
+ doctype
678
+ }),
679
+ children: doctype
680
+ }),
681
+ header: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.PageHeader, {
682
+ title: pageTitle,
683
+ divider: false
684
+ }),
685
+ aside,
686
+ children: content
687
+ }) : content;
459
688
  if (!children && isMetaLoading && !meta) {
460
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.YStack, {
689
+ return frame(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.YStack, {
461
690
  ...knobProps.panelPadding,
462
691
  testID: "frappe-form-skeleton",
463
692
  children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.AsyncSkeleton, {
464
693
  layout: "generic"
465
694
  })
466
- });
695
+ }));
467
696
  }
468
- if (!children && metaError && !meta) {
469
- return /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
697
+ if (!children && metaError && !meta && !name) {
698
+ return frame(/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
470
699
  ...knobProps.panelPadding,
471
700
  alignItems: "center",
472
701
  ...knobProps.gap,
@@ -481,19 +710,33 @@ function FrappeForm({
481
710
  ...knobProps.body,
482
711
  children: metaError.message
483
712
  })]
484
- });
713
+ }));
485
714
  }
486
- if (name && liveDoc?.isLoading && !wasDeleted) {
487
- return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.YStack, {
715
+ const isDocReading = Boolean(name) && (!docCollection || Boolean(liveDoc?.isLoading));
716
+ const showsSeed = Boolean(seedDoc) && isDocReading;
717
+ if (name && docError && !liveDoc?.data && !wasDeleted) {
718
+ if (errorFallback !== void 0) return frame(errorFallback);
719
+ return frame(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.AsyncBoundary, {
720
+ ...knobProps.panelPadding,
721
+ error: docError,
722
+ errorTitle: t("Failed to load {{doctype}}", {
723
+ doctype
724
+ })
725
+ }));
726
+ }
727
+ if (name && isDocReading && !showsSeed && !wasDeleted) {
728
+ if (loadingFallback !== void 0) return frame(loadingFallback);
729
+ return frame(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.YStack, {
488
730
  ...knobProps.panelPadding,
489
731
  testID: "frappe-form-skeleton",
490
732
  children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.AsyncSkeleton, {
491
733
  layout: "generic"
492
734
  })
493
- });
735
+ }));
494
736
  }
495
- if (name && !liveDoc?.isLoading && !liveDoc?.data && !wasDeleted) {
496
- return /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
737
+ if (name && !isDocReading && !liveDoc?.data && !wasDeleted) {
738
+ if (notFoundFallback !== void 0) return frame(notFoundFallback);
739
+ return frame(/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
497
740
  ...knobProps.panelPadding,
498
741
  alignItems: "center",
499
742
  ...knobProps.gap,
@@ -510,132 +753,179 @@ function FrappeForm({
510
753
  name
511
754
  })
512
755
  })]
513
- });
756
+ }));
514
757
  }
515
758
  const effectiveDisabled = disabled || wasDeleted;
759
+ const readOnlyView = Boolean(onEdit) || readsWithoutMeta;
760
+ const fieldsDisabled = effectiveDisabled || readOnlyView;
761
+ const shownTabs = formTabs ?? recordTabs;
516
762
  const imageFieldName = meta?.image_field;
517
763
  const sidebarImageUrl = imageFieldName ? resolveFileUrl(localDoc[imageFieldName], finalBaseURL) : void 0;
518
764
  const conflictLabels = conflictFields.map(fieldname => {
519
765
  const field = meta?.fields.find(metaField => metaField.fieldname === fieldname);
520
766
  return field?.label || fieldname;
521
767
  }).join(", ");
522
- return (
523
- // flexBasis auto (not the flex:1 shorthand's 0%): inside scroll-flow page
524
- // scaffolds (LC-29 templates) the parent is auto-height, and a 0% basis
525
- // collapses this stack to zero height on web — content then paints over
526
- // whatever follows. Bounded parents still fill (grow 1) exactly as before.
527
- /* @__PURE__ */
528
- (0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
529
- ...knobProps.gapLg,
768
+ const formTabItems = (shownTabs ?? []).map(tab => ({
769
+ value: tab.key,
770
+ label: tab.label,
771
+ content: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_schemaForm.SchemaForm, {
772
+ schema: tab.schema,
773
+ doc: localDoc,
774
+ setValue: (field, value) => setValue(field, value),
775
+ errors,
776
+ disabled: fieldsDisabled,
777
+ overrides,
778
+ readOnlyFields,
779
+ sectionHeadingLevel,
780
+ order
781
+ })
782
+ }));
783
+ const tabItems = showConnections && name && effectiveConnections.length > 0 ? [...formTabItems, {
784
+ value: "__connections",
785
+ label: t("Connections"),
786
+ content: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeFormConnections.FrappeFormConnections, {
787
+ connection: frappeConfig,
788
+ connections: effectiveConnections,
789
+ name
790
+ })
791
+ }] : formTabItems;
792
+ const effectiveTab = activeTab && tabItems.some(tab => tab.value === activeTab) ? activeTab : tabItems[0]?.value;
793
+ const localName = localDoc.name;
794
+ const sidebar = showSidebar && name && meta ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FormSidebar.FormSidebar, {
795
+ imageUrl: sidebarImageUrl,
796
+ sections: buildSidebarSections(localDoc, shareRows, t, assignmentRows),
797
+ metadata: mapDocToSidebarMetadata(localDoc, t)
798
+ }) : void 0;
799
+ return frame(
800
+ // flexBasis auto (not the flex:1 shorthand's 0%): inside scroll-flow page
801
+ // scaffolds (LC-29 templates) the parent is auto-height, and a 0% basis
802
+ // collapses this stack to zero height on web — content then paints over
803
+ // whatever follows. Bounded parents still fill (grow 1) exactly as before.
804
+ /* @__PURE__ */
805
+ (0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
806
+ ...knobProps.gapLg,
807
+ flexGrow: 1,
808
+ flexShrink: 1,
809
+ flexBasis: "auto",
810
+ children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeReconnectIndicator.FrappeReconnectIndicator, {
811
+ config: frappeConfig
812
+ }), connectionReads.map(read => /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeRowsReader.FrappeRowsReader, {
813
+ connection: frappeConfig,
814
+ doctype: read.link.doctype,
815
+ options: read.options,
816
+ onChange: read.onChange
817
+ }, read.link.doctype)), wasDeleted && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.XStack, {
818
+ role: "alert",
819
+ alignItems: "center",
820
+ ...knobProps.containerRadius,
821
+ ...knobProps.panelPadding,
822
+ backgroundColor: "$red3",
823
+ testID: "frappe-form-deleted-banner",
824
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
825
+ color: import_forms.formCommonColors.error,
826
+ ...knobProps.body,
827
+ children: hasUnsavedChanges ? t("This {{doctype}} was deleted on the server. Fields are read-only and your unsaved edits can no longer be saved.", {
828
+ doctype
829
+ }) : t("This {{doctype}} was deleted on the server. Fields are read-only.", {
830
+ doctype
831
+ })
832
+ })
833
+ }), !wasDeleted && conflictFields.length > 0 && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.XStack, {
834
+ role: "status",
835
+ alignItems: "center",
836
+ ...knobProps.containerRadius,
837
+ ...knobProps.panelPadding,
838
+ backgroundColor: "$orange3",
839
+ testID: "frappe-form-conflict-banner",
840
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
841
+ color: "$orange11",
842
+ ...knobProps.body,
843
+ children: t("Changed elsewhere while you were editing: {{fields}}. Your edits are kept \u2014 saving will overwrite the newer server values.", {
844
+ fields: conflictLabels
845
+ })
846
+ })
847
+ }), /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.XStack, {
530
848
  flexGrow: 1,
531
849
  flexShrink: 1,
532
850
  flexBasis: "auto",
533
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FrappeReconnectIndicator.FrappeReconnectIndicator, {
534
- config: frappeConfig
535
- }), wasDeleted && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.XStack, {
536
- role: "alert",
537
- alignItems: "center",
538
- ...knobProps.containerRadius,
539
- ...knobProps.panelPadding,
540
- backgroundColor: "$red3",
541
- testID: "frappe-form-deleted-banner",
542
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
543
- color: import_forms.formCommonColors.error,
544
- ...knobProps.body,
545
- children: hasUnsavedChanges ? t("This {{doctype}} was deleted on the server. Fields are read-only and your unsaved edits can no longer be saved.", {
546
- doctype
547
- }) : t("This {{doctype}} was deleted on the server. Fields are read-only.", {
548
- doctype
549
- })
550
- })
551
- }), !wasDeleted && conflictFields.length > 0 && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.XStack, {
552
- role: "status",
553
- alignItems: "center",
554
- ...knobProps.containerRadius,
555
- ...knobProps.panelPadding,
556
- backgroundColor: "$orange3",
557
- testID: "frappe-form-conflict-banner",
558
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
559
- color: "$orange11",
560
- ...knobProps.body,
561
- children: t("Changed elsewhere while you were editing: {{fields}}. Your edits are kept \u2014 saving will overwrite the newer server values.", {
562
- fields: conflictLabels
563
- })
564
- })
565
- }), /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.XStack, {
566
- flexGrow: 1,
567
- flexShrink: 1,
568
- flexBasis: "auto",
851
+ ...knobProps.gapLg,
852
+ children: [routePage ? null : sidebar, /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
853
+ flex: 1,
569
854
  ...knobProps.gapLg,
570
- children: [showSidebar && name && meta && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_FormSidebar.FormSidebar, {
571
- imageUrl: sidebarImageUrl,
572
- sections: buildSidebarSections(localDoc, shareRows, t, assignmentRows),
573
- metadata: mapDocToSidebarMetadata(localDoc, t)
574
- }), /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
575
- flex: 1,
855
+ children: [children ?
856
+ // Render-prop mode
857
+ children({
858
+ doc: localDoc,
859
+ setValue,
860
+ isSubmitting,
861
+ errors,
862
+ meta,
863
+ disabled: fieldsDisabled,
864
+ connections: connectionRows,
865
+ connectionsLoading
866
+ }) : shownTabs ? /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.YStack, {
576
867
  ...knobProps.gapLg,
577
- children: [children ?
578
- // Render-prop mode
579
- children({
580
- doc: localDoc,
581
- setValue,
582
- isSubmitting,
583
- errors,
584
- meta,
868
+ children: [promptNamed && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_forms.Input, {
869
+ label: t("Name"),
870
+ value: typeof localName === "string" ? localName : "",
871
+ onChangeText: value => setValue("name", value),
872
+ placeholder: t("New document name"),
873
+ error: errors.name,
585
874
  disabled: effectiveDisabled
586
- }) : formSchema ?
587
- // Schema-driven mode using generic SchemaForm from @multiplatform.one/forms
588
- /* @__PURE__ */
589
- (0, import_jsx_runtime.jsx)(import_schemaForm.SchemaForm, {
590
- schema: formSchema,
591
- doc: localDoc,
592
- setValue: (field, value) => setValue(field, value),
593
- errors,
594
- disabled: effectiveDisabled,
595
- overrides,
596
- hideFields,
597
- readOnlyFields,
598
- sectionHeadingLevel,
599
- order
600
- }) :
601
- // Metadata unavailable (should be covered by metaError branch above)
602
- /* @__PURE__ */
603
- (0, import_jsx_runtime.jsx)(import_tamagui.YStack, {
604
- ...knobProps.panelPadding,
605
- alignItems: "center",
606
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
607
- color: import_forms.formCommonColors.muted,
608
- ...knobProps.body,
609
- children: t("Form schema unavailable")
610
- })
611
- }), errors.general && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
612
- color: import_forms.formCommonColors.error,
875
+ }), tabItems.length > 1 ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_components.Tabs, {
876
+ items: tabItems,
877
+ value: effectiveTab,
878
+ onChange: setActiveTab,
879
+ lazyMount: true
880
+ }) : tabItems[0]?.content ?? null]
881
+ }) :
882
+ // Metadata unavailable (should be covered by metaError branch above)
883
+ /* @__PURE__ */
884
+ (0, import_jsx_runtime.jsx)(import_tamagui.YStack, {
885
+ ...knobProps.panelPadding,
886
+ alignItems: "center",
887
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
888
+ color: import_forms.formCommonColors.muted,
613
889
  ...knobProps.body,
614
- children: errors.general
615
- }), showToolbar && /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.XStack, {
616
- ...knobProps.gap,
617
- justifyContent: "flex-end",
618
- alignItems: "center",
619
- paddingTop: "$3",
620
- children: [hasUnsavedChanges && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
621
- color: "$orange11",
622
- marginInlineEnd: "auto",
623
- ...knobProps.body,
624
- children: t("Not Saved")
625
- }), name && onDelete && !wasDeleted && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_forms.Button, {
626
- outlined: true,
627
- error: true,
628
- icon: import_react.TrashIcon,
629
- loading: isSubmitting,
630
- disabled: effectiveDisabled,
631
- disabledReason: t("Form is read-only"),
632
- disabledReasonPlacement: "inline",
633
- onPress: handleDelete,
634
- children: t("Delete")
635
- }), onCancel && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_forms.Button, {
890
+ children: t("Form schema unavailable")
891
+ })
892
+ }), errors.general && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
893
+ color: import_forms.formCommonColors.error,
894
+ ...knobProps.body,
895
+ children: errors.general
896
+ }), showToolbar && !readsWithoutMeta && /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_tamagui.XStack, {
897
+ ...knobProps.gap,
898
+ justifyContent: "flex-end",
899
+ alignItems: "center",
900
+ paddingTop: "$3",
901
+ children: [hasUnsavedChanges && !onEdit && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_tamagui.Text, {
902
+ color: "$orange11",
903
+ marginInlineEnd: "auto",
904
+ ...knobProps.body,
905
+ children: t("Not Saved")
906
+ }), name && onDelete && !wasDeleted && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_forms.Button, {
907
+ outlined: true,
908
+ error: true,
909
+ icon: import_react.TrashIcon,
910
+ loading: isSubmitting,
911
+ disabled: effectiveDisabled,
912
+ disabledReason: t("Form is read-only"),
913
+ disabledReasonPlacement: "inline",
914
+ onPress: handleDelete,
915
+ children: t("Delete")
916
+ }), onEdit ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_forms.Button, {
917
+ accent: true,
918
+ icon: import_react.PencilSimpleIcon,
919
+ disabled: effectiveDisabled,
920
+ disabledReason: t("Form is read-only"),
921
+ disabledReasonPlacement: "inline",
922
+ onPress: onEdit,
923
+ children: t("Edit")
924
+ }) : /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
925
+ children: [onCancel && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_forms.Button, {
636
926
  outlined: true,
637
927
  icon: import_react.XIcon,
638
- disabled: isSubmitting || disabled,
928
+ disabled,
639
929
  disabledReason: t("Form is read-only"),
640
930
  disabledReasonPlacement: "inline",
641
931
  onPress: handleCancel,
@@ -652,11 +942,11 @@ function FrappeForm({
652
942
  })]
653
943
  })]
654
944
  })]
655
- }), showTimeline && name && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_timeline.Timeline, {
656
- doctype,
657
- docname: name,
658
- label: t("Activity")
659
945
  })]
660
- })
661
- );
946
+ }), showTimeline && name && !readsWithoutMeta && /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_timeline.Timeline, {
947
+ doctype,
948
+ docname: name,
949
+ label: t("Activity")
950
+ })]
951
+ }), routePage ? sidebar : void 0);
662
952
  }