@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
@@ -0,0 +1,157 @@
1
+ import type React from "react";
2
+ import { useCallback, useMemo, useRef, useState } from "react";
3
+ import type { FrappeConnection } from "./frappeConnections";
4
+ import { FrappeRowsReader, type FrappeRowsSnapshot } from "./FrappeRowsReader";
5
+ import type { FrappeRowsConnection } from "./useFrappeRows";
6
+
7
+ /** `[field, operator, value]` on the doctype itself. */
8
+ export type FrappeFieldFilter = [string, string, unknown];
9
+ /** `[doctype, field, operator, value]`: Frappe's filter on another doctype's rows. */
10
+ export type FrappeDoctypeFilter = [string, string, string, unknown];
11
+ export type FrappeFilters =
12
+ | Record<string, unknown>
13
+ | Array<FrappeFieldFilter | FrappeDoctypeFilter>;
14
+
15
+ export interface ConnectionFiltersResult {
16
+ /**
17
+ * The filters to send: the doctype's own, plus one `["name", "in", names]`
18
+ * per connection filtered on. A `[doctype, …]` filter on a doctype that is
19
+ * no declared connection passes through untouched (a child table, which
20
+ * the bench joins itself).
21
+ */
22
+ filters: Record<string, unknown> | Array<FrappeFieldFilter | FrappeDoctypeFilter> | undefined;
23
+ /** A connection's rows are still being read; the result is not known yet. */
24
+ pending: boolean;
25
+ error: Error | null;
26
+ /** Mount these: one reader per connection filtered on. */
27
+ readers: React.ReactNode;
28
+ }
29
+
30
+ interface LinkedFilter {
31
+ connection: FrappeConnection;
32
+ conditions: FrappeFieldFilter[];
33
+ }
34
+
35
+ type Snapshot = FrappeRowsSnapshot<Record<string, unknown> & { name: string; doctype: string }>;
36
+
37
+ /**
38
+ * Resolves filters on a connection (Pokemon by `Pokemon Poke Type.poke_type`)
39
+ * into a filter on the doctype itself. Frappe's four-part filter joins child
40
+ * tables on the server; a standalone doctype linking back through a Link field
41
+ * is no child table, so the linked rows are read live here and their link
42
+ * values become `name in (...)`. Several conditions on one connection hold on
43
+ * the same linked row, as they do for a child table.
44
+ */
45
+ export function useConnectionFilters(
46
+ connection: FrappeRowsConnection | undefined,
47
+ doctype: string,
48
+ filters: FrappeFilters | undefined,
49
+ /** `undefined` while the declaration is still loading (meta.links). */
50
+ connections: readonly FrappeConnection[] | undefined,
51
+ ): ConnectionFiltersResult {
52
+ const filtersKey = JSON.stringify(filters ?? null);
53
+ const connectionsKey = JSON.stringify(connections ?? null);
54
+
55
+ const { own, linked, undeclared } = useMemo(() => {
56
+ const parsed = JSON.parse(filtersKey) as FrappeFilters | null;
57
+ const declaredList = JSON.parse(connectionsKey) as FrappeConnection[] | null;
58
+ const declared = declaredList ?? [];
59
+ if (!parsed || !Array.isArray(parsed)) {
60
+ return { own: parsed ?? undefined, linked: [] as LinkedFilter[], undeclared: false };
61
+ }
62
+ let waitsOnDeclaration = false;
63
+ const ownFilters: Array<FrappeFieldFilter | FrappeDoctypeFilter> = [];
64
+ const byDoctype = new Map<string, LinkedFilter>();
65
+ for (const filter of parsed) {
66
+ if (filter.length !== 4) {
67
+ ownFilters.push(filter);
68
+ continue;
69
+ }
70
+ const [target, field, operator, value] = filter;
71
+ if (target === doctype) {
72
+ ownFilters.push([field, operator, value]);
73
+ continue;
74
+ }
75
+ const declaration = declared.find((candidate) => candidate.doctype === target);
76
+ if (!declaration) {
77
+ if (!declaredList) waitsOnDeclaration = true;
78
+ ownFilters.push(filter);
79
+ continue;
80
+ }
81
+ const entry = byDoctype.get(target) ?? { connection: declaration, conditions: [] };
82
+ entry.conditions.push([field, operator, value]);
83
+ byDoctype.set(target, entry);
84
+ }
85
+ return { own: ownFilters, linked: [...byDoctype.values()], undeclared: waitsOnDeclaration };
86
+ }, [filtersKey, connectionsKey, doctype]);
87
+
88
+ const [snapshots, setSnapshots] = useState<Record<string, Snapshot>>({});
89
+ const handlers = useRef(new Map<string, (snapshot: Snapshot) => void>());
90
+ const handlerFor = useCallback((key: string) => {
91
+ let handler = handlers.current.get(key);
92
+ if (!handler) {
93
+ handler = (snapshot: Snapshot) => setSnapshots((prev) => ({ ...prev, [key]: snapshot }));
94
+ handlers.current.set(key, handler);
95
+ }
96
+ return handler;
97
+ }, []);
98
+
99
+ const reads = useMemo(
100
+ () =>
101
+ linked.map(({ connection: link, conditions }) => ({
102
+ key: JSON.stringify([link.doctype, link.fieldname, conditions]),
103
+ link,
104
+ options: {
105
+ fields: ["name", link.fieldname],
106
+ filters: conditions,
107
+ limit: link.limit ?? 0,
108
+ },
109
+ })),
110
+ [linked],
111
+ );
112
+
113
+ return useMemo(() => {
114
+ const readers = reads.map((read) => (
115
+ <FrappeRowsReader
116
+ key={read.key}
117
+ connection={connection}
118
+ doctype={read.link.doctype}
119
+ options={read.options as never}
120
+ onChange={handlerFor(read.key)}
121
+ />
122
+ ));
123
+ if (reads.length === 0) {
124
+ return { filters: own, pending: undeclared, error: null, readers };
125
+ }
126
+ let names: Set<string> | undefined;
127
+ let pending = false;
128
+ let error: Error | null = null;
129
+ for (const read of reads) {
130
+ const snapshot = snapshots[read.key];
131
+ if (!snapshot || snapshot.isLoading) {
132
+ pending = true;
133
+ continue;
134
+ }
135
+ if (snapshot.error) {
136
+ error = error ?? snapshot.error;
137
+ continue;
138
+ }
139
+ const linkedNames = new Set(
140
+ snapshot.rows
141
+ .map((row) => row[read.link.fieldname])
142
+ .filter((value): value is string => typeof value === "string" && value !== ""),
143
+ );
144
+ names = names ? new Set([...names].filter((name) => linkedNames.has(name))) : linkedNames;
145
+ }
146
+ const ownList = Array.isArray(own)
147
+ ? own
148
+ : own
149
+ ? Object.entries(own).map(([field, value]) => [field, "=", value] as FrappeFieldFilter)
150
+ : [];
151
+ const resolved: Array<FrappeFieldFilter | FrappeDoctypeFilter> = [
152
+ ...ownList,
153
+ ["name", "in", [...(names ?? [])].sort()],
154
+ ];
155
+ return { filters: resolved, pending: (pending || undeclared) && !error, error, readers };
156
+ }, [reads, snapshots, own, undeclared, connection, handlerFor]);
157
+ }
@@ -13,21 +13,33 @@
13
13
  * return <List items={items} onLoadMore={onLoadMore} hasMore={hasMore} />;
14
14
  * ```
15
15
  *
16
- * Internally it manages an increasing `limit` that is passed to
17
- * `useFrappeCollection`. When the number of returned items equals
18
- * the limit, `hasMore` is `true`. Calling `onLoadMore` increases
19
- * the limit by `pageSize`, triggering the sync layer's
20
- * VirtualPageManager to fetch the next cursor-based batch.
16
+ * The read itself is {@link useFrappeRows} (MPO-251), so FrappeList shares
17
+ * the one implementation every other doctype view uses. On top of it this
18
+ * hook manages an increasing `limit` over the rows it returns. When the
19
+ * number of returned items equals the limit, `hasMore` is `true`. Calling
20
+ * `onLoadMore` increases the limit by `pageSize`.
21
21
  */
22
22
 
23
- import { useFrappeCollection, useLiveQuery } from "@multiplatform.one/frappe";
24
- import { useCallback, useEffect, useMemo, useState } from "react";
23
+ import { useCallback, useMemo, useState } from "react";
25
24
  import type { UseFrappeCollectionConfig } from "@multiplatform.one/frappe";
25
+ import { useFrappeRows, type UseFrappeRowsOptions } from "./useFrappeRows";
26
26
 
27
27
  export interface UseFrappePaginationOptions<TDoc> {
28
28
  fields?: readonly (keyof TDoc & string)[];
29
29
  filters?: Partial<TDoc> | Array<[keyof TDoc & string, string, unknown]>;
30
30
  pageSize?: number;
31
+ /**
32
+ * Rows the subscription reads. Omitted, the bench's own page length
33
+ * applies (20 on a stock site), which truncates any longer list.
34
+ */
35
+ limit?: number;
36
+ orderBy?: UseFrappeRowsOptions<TDoc>["orderBy"];
37
+ /**
38
+ * Rows a route loader rendered on the server for this same query. They
39
+ * stand in until the live collection's first sync lands, so the server
40
+ * page and the hydrated page match; the live rows replace them after.
41
+ */
42
+ initialRows?: readonly TDoc[];
31
43
  }
32
44
 
33
45
  export interface UseFrappePaginationResult<TDoc> {
@@ -49,6 +61,31 @@ export interface UseFrappePaginationResult<TDoc> {
49
61
 
50
62
  const defaultPageSize = 20;
51
63
 
64
+ function toError(err: unknown): Error {
65
+ return err instanceof Error ? err : new Error(String(err));
66
+ }
67
+
68
+ type OrderBy<TDoc> = NonNullable<UseFrappeRowsOptions<TDoc>["orderBy"]>;
69
+
70
+ /** Row order for an `orderBy`, missing values last, the way the bench sorts a page. */
71
+ function compareRows<TDoc>(orderBy: OrderBy<TDoc>) {
72
+ return (a: TDoc, b: TDoc): number => {
73
+ for (const { field, order } of orderBy) {
74
+ const left = (a as Record<string, unknown>)[field];
75
+ const right = (b as Record<string, unknown>)[field];
76
+ if (left === right) continue;
77
+ if (left === null || left === undefined) return 1;
78
+ if (right === null || right === undefined) return -1;
79
+ const compared =
80
+ typeof left === "number" && typeof right === "number"
81
+ ? left - right
82
+ : String(left).localeCompare(String(right));
83
+ if (compared !== 0) return String(order).toLowerCase() === "desc" ? -compared : compared;
84
+ }
85
+ return 0;
86
+ };
87
+ }
88
+
52
89
  export function useFrappePagination<TDoc extends { name: string; doctype: string }>(
53
90
  config: UseFrappeCollectionConfig | undefined,
54
91
  doctype: string,
@@ -56,31 +93,38 @@ export function useFrappePagination<TDoc extends { name: string; doctype: string
56
93
  ): UseFrappePaginationResult<TDoc> {
57
94
  const pageSize = options?.pageSize ?? defaultPageSize;
58
95
  const [limit, setLimit] = useState(pageSize);
59
- const [error, setError] = useState<Error | null>(null);
60
96
 
61
- const handleSyncError = useCallback((err: unknown) => {
62
- setError(err instanceof Error ? err : new Error(String(err)));
63
- }, []);
64
-
65
- // Create the collection with the current limit
66
- const collection = useFrappeCollection<TDoc>(config, doctype, {
97
+ // `limit: null` keeps the subscription on the bench's own page length, as
98
+ // it was before the shared read; `mapError` hands FrappeList the raw sync
99
+ // failure its isPermissionError check reads.
100
+ const {
101
+ rows: liveRows,
102
+ isLoading: isReading,
103
+ isQueryLoading,
104
+ syncError: error,
105
+ } = useFrappeRows<TDoc>(config, doctype, {
67
106
  fields: options?.fields,
68
107
  filters: options?.filters,
69
- onSyncError: handleSyncError,
108
+ orderBy: options?.orderBy,
109
+ limit: options?.limit ?? null,
110
+ mapError: toError,
70
111
  });
71
112
 
72
- // A new collection (doctype/filter change) starts with a clean slate.
73
- useEffect(() => {
74
- setError(null);
75
- }, [collection]);
76
-
77
- // Query the live data
78
- const { data: rawData, isLoading } = useLiveQuery(
79
- (q) => (collection ? q.from({ _list: collection }) : null),
80
- [collection],
113
+ // The collection holds rows by name, whatever order the page was read in,
114
+ // so an ordered read is put back in its order here.
115
+ const orderBy = options?.orderBy;
116
+ const liveItems = useMemo(
117
+ () => (orderBy?.length ? [...liveRows].sort(compareRows(orderBy)) : liveRows),
118
+ [liveRows, orderBy],
81
119
  );
82
120
 
83
- const allItems = useMemo(() => (rawData as TDoc[] | undefined) ?? [], [rawData]);
121
+ // The server-rendered page holds until the first sync answers, and past a
122
+ // failed one: rows the visitor already sees never give way to an empty
123
+ // list. SSR and the hydration pass have no collection, so both render it.
124
+ const seed = options?.initialRows;
125
+ const seeded = Boolean(seed?.length) && (isReading || (error !== null && liveItems.length === 0));
126
+ const allItems = seeded ? (seed as TDoc[]) : liveItems;
127
+ const isLoading = isQueryLoading && !seeded;
84
128
 
85
129
  // Slice to the current limit (progressive disclosure)
86
130
  const items = useMemo(() => allItems.slice(0, limit), [allItems, limit]);
@@ -98,5 +142,5 @@ export function useFrappePagination<TDoc extends { name: string; doctype: string
98
142
  setLimit(pageSize);
99
143
  }, [pageSize]);
100
144
 
101
- return { items, isLoading, hasMore, onLoadMore, limit, reset, error };
145
+ return { items, isLoading, hasMore, onLoadMore, limit, reset, error: seeded ? null : error };
102
146
  }
@@ -0,0 +1,206 @@
1
+ /**
2
+ * The shipped doctype views share ONE read (MPO-251 AC3).
3
+ *
4
+ * What this locks:
5
+ * 1. No shipped doctype view assembles useFrappeCollection + useLiveQuery
6
+ * itself; each reads through useFrappeRows (FrappeList through
7
+ * useFrappePagination, which reads through useFrappeRows).
8
+ * 2. At runtime FrappeList, FrappeImageView, FrappeDashboard and
9
+ * FrappeReportBuilder call useFrappeRows and render the rows it returns.
10
+ * 3. FrappeList's permission error still reaches its honest error state
11
+ * through the shared read.
12
+ *
13
+ * Fixture-hermetic: documents ride InMemoryFixtureProvider.
14
+ */
15
+
16
+ import { readFileSync } from "node:fs";
17
+ import { resolve } from "node:path";
18
+ import { InMemoryFixtureProvider } from "@multiplatform.one/frappe";
19
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
20
+ import { cleanup, screen, waitFor } from "@testing-library/react";
21
+ import i18next from "i18next";
22
+ import { initReactI18next } from "react-i18next";
23
+ import { Text } from "tamagui";
24
+ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
25
+ import { FrappeDashboard } from "./FrappeDashboard";
26
+ import { FrappeImageView } from "./FrappeImageView";
27
+ import { FrappeList } from "./FrappeList";
28
+ import { FrappeProvider } from "./FrappeProvider";
29
+ import { FrappeReportBuilder } from "./FrappeReportBuilder";
30
+ import { useFrappeRows } from "./useFrappeRows";
31
+
32
+ vi.mock("./useFrappeRows", async (importOriginal) => {
33
+ const actual = await importOriginal<typeof import("./useFrappeRows")>();
34
+ return { ...actual, useFrappeRows: vi.fn(actual.useFrappeRows) };
35
+ });
36
+
37
+ const readSpy = vi.mocked(useFrappeRows);
38
+
39
+ beforeAll(async () => {
40
+ await i18next.use(initReactI18next).init({
41
+ lng: "en",
42
+ interpolation: { escapeValue: false },
43
+ resources: { en: { translation: {} } },
44
+ });
45
+ });
46
+
47
+ beforeEach(() => {
48
+ readSpy.mockClear();
49
+ });
50
+
51
+ afterEach(() => {
52
+ cleanup();
53
+ vi.restoreAllMocks();
54
+ });
55
+
56
+ interface Customer {
57
+ name: string;
58
+ doctype: string;
59
+ customer_name: string;
60
+ image: string;
61
+ }
62
+
63
+ const customers: Customer[] = [
64
+ { name: "CUST-001", doctype: "Customer", customer_name: "Acme Corp", image: "" },
65
+ { name: "CUST-002", doctype: "Customer", customer_name: "Globex", image: "" },
66
+ ];
67
+
68
+ function fixtureCorpus() {
69
+ return new InMemoryFixtureProvider({
70
+ DocType: [
71
+ {
72
+ name: "Customer",
73
+ doctype: "DocType",
74
+ module: "Selling",
75
+ image_field: "image",
76
+ title_field: "customer_name",
77
+ fields: [
78
+ {
79
+ fieldname: "customer_name",
80
+ fieldtype: "Data",
81
+ label: "Customer Name",
82
+ in_list_view: 1,
83
+ },
84
+ { fieldname: "image", fieldtype: "Attach Image", label: "Image" },
85
+ ],
86
+ },
87
+ ],
88
+ Customer: customers,
89
+ });
90
+ }
91
+
92
+ const baseURL = "https://sharedpath.spec.test";
93
+
94
+ function readsOf(doctype: string) {
95
+ return readSpy.mock.calls.filter(([, calledDoctype]) => calledDoctype === doctype);
96
+ }
97
+
98
+ function source(file: string) {
99
+ return readFileSync(resolve(process.cwd(), "src", file), "utf8")
100
+ .replace(/\/\*[\s\S]*?\*\//g, "")
101
+ .replace(/\/\/.*$/gm, "");
102
+ }
103
+
104
+ describe("one implementation of the doctype read", () => {
105
+ const readers: Array<[file: string, reader: RegExp]> = [
106
+ ["FrappeTable.tsx", /\buseFrappeRows\s*[<(]/],
107
+ ["FrappeList.tsx", /\buseFrappePagination\s*[<(]/],
108
+ ["useFrappePagination.ts", /\buseFrappeRows\s*[<(]/],
109
+ ["FrappeTreeView.tsx", /\buseFrappeRows\s*[<(]/],
110
+ ["FrappeKanban.tsx", /\buseFrappeRows\s*[<(]/],
111
+ ["FrappeCalendar.tsx", /\buseFrappeRows\s*[<(]/],
112
+ ["FrappeGantt.tsx", /\buseFrappeRows\s*[<(]/],
113
+ ["FrappeImageView.tsx", /\buseFrappeRows\s*[<(]/],
114
+ ["FrappeDashboard.tsx", /\buseFrappeRows\s*[<(]/],
115
+ ["FrappeReportBuilder.tsx", /\buseFrappeRows\s*[<(]/],
116
+ ];
117
+
118
+ it.each(readers)("%s reads through the shared hook, not the raw primitives", (file, reader) => {
119
+ const code = source(file);
120
+ expect(code).toMatch(reader);
121
+ expect(code).not.toMatch(/\buseFrappeCollection\s*[<(]/);
122
+ expect(code).not.toMatch(/\buseLiveQuery\s*\(/);
123
+ });
124
+ });
125
+
126
+ describe("the shipped views render rows from useFrappeRows", () => {
127
+ it("FrappeList", async () => {
128
+ renderWithProviders(
129
+ <FrappeProvider fixtures={fixtureCorpus()}>
130
+ <FrappeList<Customer>
131
+ doctype="Customer"
132
+ fields={["name", "customer_name"]}
133
+ renderItem={(item) => <Text>{item.customer_name}</Text>}
134
+ />
135
+ </FrappeProvider>,
136
+ );
137
+ expect(await screen.findByText("Acme Corp")).toBeTruthy();
138
+ expect(readsOf("Customer")[0]?.[2]).toMatchObject({
139
+ fields: ["name", "customer_name"],
140
+ limit: null,
141
+ });
142
+ });
143
+
144
+ it("FrappeImageView", async () => {
145
+ renderWithProviders(
146
+ <FrappeProvider baseURL={baseURL} fixtures={fixtureCorpus()}>
147
+ <FrappeImageView<Customer>
148
+ doctype="Customer"
149
+ imageField="image"
150
+ titleField="customer_name"
151
+ />
152
+ </FrappeProvider>,
153
+ );
154
+ expect(await screen.findByText("Globex")).toBeTruthy();
155
+ expect(readsOf("Customer").length).toBeGreaterThan(0);
156
+ });
157
+
158
+ it("FrappeDashboard", async () => {
159
+ const received: Array<Partial<Customer>[]> = [];
160
+ renderWithProviders(
161
+ <FrappeProvider baseURL={baseURL} fixtures={fixtureCorpus()}>
162
+ <FrappeDashboard<Customer>
163
+ title="Customers"
164
+ widgets={[]}
165
+ dataSource={{ doctype: "Customer", fields: ["name", "customer_name"] }}
166
+ transformData={(data) => {
167
+ received.push(data);
168
+ return [];
169
+ }}
170
+ />
171
+ </FrappeProvider>,
172
+ );
173
+ await waitFor(() => expect(received.at(-1)).toHaveLength(2));
174
+ expect(readsOf("Customer").length).toBeGreaterThan(0);
175
+ });
176
+
177
+ it("FrappeReportBuilder", async () => {
178
+ renderWithProviders(
179
+ <FrappeProvider fixtures={fixtureCorpus()}>
180
+ <FrappeReportBuilder doctype="Customer" />
181
+ </FrappeProvider>,
182
+ );
183
+ expect(await screen.findByText("Acme Corp")).toBeTruthy();
184
+ expect(readsOf("Customer").length).toBeGreaterThan(0);
185
+ });
186
+ });
187
+
188
+ describe("FrappeList error plumbing through the shared read", () => {
189
+ it("renders a 403 as a permission error, not an empty list", async () => {
190
+ const fixtures = fixtureCorpus();
191
+ vi.spyOn(fixtures, "getList").mockRejectedValue(
192
+ Object.assign(new Error("PermissionError"), { status: 403 }),
193
+ );
194
+ renderWithProviders(
195
+ <FrappeProvider fixtures={fixtures}>
196
+ <FrappeList<Customer>
197
+ doctype="Customer"
198
+ fields={["name", "customer_name"]}
199
+ renderItem={(item) => <Text>{item.customer_name}</Text>}
200
+ />
201
+ </FrappeProvider>,
202
+ );
203
+ expect(await screen.findByText("You do not have permission to view Customer")).toBeTruthy();
204
+ expect(screen.queryByText("No Customer records found")).toBeNull();
205
+ });
206
+ });
@@ -35,10 +35,11 @@
35
35
  * that key, so passing a different error handler never splits a
36
36
  * collection.
37
37
  *
38
- * The shipped components read through this hook — FrappeTable, FrappeList's
39
- * table mode, FrappeTreeView, FrappeKanban, FrappeCalendar and FrappeGantt —
40
- * so there is ONE implementation of the read rather than a reference one and
41
- * N copies.
38
+ * The shipped doctype views read through this hook — FrappeTable,
39
+ * FrappeList (via useFrappePagination), FrappeTreeView, FrappeKanban,
40
+ * FrappeCalendar, FrappeGantt, FrappeImageView, FrappeDashboard and
41
+ * FrappeReportBuilder — so there is ONE implementation of the read rather
42
+ * than a reference one and N copies.
42
43
  *
43
44
  * @example
44
45
  * ```tsx
@@ -41,10 +41,9 @@ export interface FrappeDashboardProps<TDoc extends {
41
41
  /**
42
42
  * Thin Frappe wrapper around the generic Dashboard component.
43
43
  *
44
- * Fetches live data via `useFrappeCollection` / `useLiveQuery` if a
45
- * `dataSource` is configured, transforms it into widget data, and
46
- * passes everything to the generic `Dashboard` from
47
- * `@multiplatform.one/components`.
44
+ * Fetches live data via `useFrappeRows` if a `dataSource` is configured,
45
+ * transforms it into widget data, and passes everything to the generic
46
+ * `Dashboard` from `@multiplatform.one/components`.
48
47
  */
49
48
  export declare function FrappeDashboard<TDoc extends {
50
49
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"FrappeDashboard.d.ts","sourceRoot":"","sources":["../src/FrappeDashboard.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGhF,OAAO,KAA4D,MAAM,OAAO,CAAC;AAEjF,OAAO,EAAwB,KAAK,WAAW,EAAM,MAAM,SAAS,CAAC;AAIrE;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,IAAI;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,IAAI,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACpE,YAAY,CAAC,EAAE;QACb,KAAK,EAAE,MAAM,IAAI,GAAG,MAAM,CAAC;QAC3B,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;QACnD,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,MAAM,CAAC;KAC/B,EAAE,CAAC;CACL;AAED,MAAM,WAAW,oBAAoB,CAAC,IAAI,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAE,SAAQ,IAAI,CAChG,WAAW,EACX,UAAU,CACX;IACC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChG,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,eAAe,EAAE,CAAC;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,SAAS,CAAC;CAC3C;AAgMD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,EAC9E,OAAO,EACP,IAAI,EACJ,WAAW,EACX,KAAK,EACL,WAAW,EACX,OAAO,EAAE,aAAa,EACtB,UAAU,EACV,aAAa,EACb,OAAW,EACX,GAAQ,EACR,OAAY,EACZ,WAAmB,EACnB,eAAoB,EACpB,OAAO,EACP,KAAK,EACL,GAAG,UAAU,EACd,EAAE,oBAAoB,CAAC,IAAI,CAAC,2CAiH5B;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"FrappeDashboard.d.ts","sourceRoot":"","sources":["../src/FrappeDashboard.tsx"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGhF,OAAO,KAA4D,MAAM,OAAO,CAAC;AAEjF,OAAO,EAAwB,KAAK,WAAW,EAAM,MAAM,SAAS,CAAC;AAKrE;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,IAAI;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,IAAI,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACpE,YAAY,CAAC,EAAE;QACb,KAAK,EAAE,MAAM,IAAI,GAAG,MAAM,CAAC;QAC3B,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;QACnD,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,MAAM,CAAC;KAC/B,EAAE,CAAC;CACL;AAED,MAAM,WAAW,oBAAoB,CAAC,IAAI,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAE,SAAQ,IAAI,CAChG,WAAW,EACX,UAAU,CACX;IACC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChG,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,eAAe,EAAE,CAAC;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,SAAS,CAAC;CAC3C;AA+LD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,EAC9E,OAAO,EACP,IAAI,EACJ,WAAW,EACX,KAAK,EACL,WAAW,EACX,OAAO,EAAE,aAAa,EACtB,UAAU,EACV,aAAa,EACb,OAAW,EACX,GAAQ,EACR,OAAY,EACZ,WAAmB,EACnB,eAAoB,EACpB,OAAO,EACP,KAAK,EACL,GAAG,UAAU,EACd,EAAE,oBAAoB,CAAC,IAAI,CAAC,2CAiH5B;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -4,6 +4,9 @@ import type { HeadingLevel } from "./fields/Heading";
4
4
  import { type SidebarSection, type SidebarMetadataEntry } from "./FormSidebar";
5
5
  import type React from "react";
6
6
  import type { TFunction } from "i18next";
7
+ import { type FrappeConnection } from "./frappeConnections";
8
+ /** Linked rows per connection doctype, as the render prop receives them. */
9
+ export type FrappeConnectionRows = Record<string, Array<Record<string, unknown>>>;
7
10
  export interface FrappeFormProps<TDoc extends {
8
11
  name: string;
9
12
  doctype: string;
@@ -27,7 +30,32 @@ export interface FrappeFormProps<TDoc extends {
27
30
  meta?: DocTypeMeta;
28
31
  /** True when the form is read-only (disabled prop, or doc deleted on the server). */
29
32
  disabled: boolean;
33
+ /** The record's linked rows per connection doctype (edit mode), live. */
34
+ connections: FrappeConnectionRows;
35
+ /** A connection's rows are still being read. */
36
+ connectionsLoading: boolean;
30
37
  }) => React.ReactNode;
38
+ /**
39
+ * Doctypes linking back to this one (the desk's Connections). Defaults to
40
+ * meta.links; declare them where the reader cannot load meta (Guest).
41
+ * Schema mode shows them on a Connections tab; render-prop mode hands the
42
+ * rows to `children`.
43
+ */
44
+ connections?: readonly FrappeConnection[];
45
+ /** False leaves the Connections tab out of schema mode. */
46
+ showConnections?: boolean;
47
+ /**
48
+ * The document a route loader rendered on the server (`loadDoc`), shown
49
+ * until the live read lands so the server page and the hydrated page match.
50
+ * Ignored unless its name is `name`.
51
+ */
52
+ initialDoc?: Partial<TDoc>;
53
+ /** Replaces the skeleton while the document loads. */
54
+ loadingFallback?: React.ReactNode;
55
+ /** Replaces the not-found message for a name that does not resolve. */
56
+ notFoundFallback?: React.ReactNode;
57
+ /** Replaces the error state when the document cannot be read. */
58
+ errorFallback?: React.ReactNode;
31
59
  /** Per-field overrides for schema-driven mode (when children not provided). */
32
60
  overrides?: Record<string, FieldOverride>;
33
61
  /** Fields to hide in schema-driven mode. */
@@ -42,9 +70,31 @@ export interface FrappeFormProps<TDoc extends {
42
70
  * names are ignored. Cheaper than replacing `sections`.
43
71
  */
44
72
  order?: string[];
73
+ /**
74
+ * Session roles for permlevel resolution. Omitted: the form asks the site
75
+ * for them when the doctype has fields above permlevel 0, and a fixtures
76
+ * connection takes the conservative rule (permlevel > 0 is read-only,
77
+ * never hidden).
78
+ */
79
+ roles?: string[];
80
+ /** Called after a save; a created document carries the name the server gave it. */
45
81
  onSave?: (doc: Partial<TDoc>) => void;
46
82
  onCancel?: () => void;
47
83
  onDelete?: (doc: Partial<TDoc>) => void;
84
+ /**
85
+ * Given, the form is a read-only view of the record: its toolbar offers
86
+ * Edit (this callback) and Delete instead of Save and Cancel.
87
+ */
88
+ onEdit?: () => void;
89
+ /**
90
+ * The path the doctype's pages live under (`/moves`). Given, the form is
91
+ * the doctype's record page: it reads the record from the path through
92
+ * the FrappeProvider's navigation (`route/new` creates, `route/<name>`
93
+ * views, `route/<name>/edit` edits), carries the detail page template,
94
+ * and after a save, cancel, edit or delete moves to the matching page.
95
+ * Callbacks given alongside it replace those moves.
96
+ */
97
+ route?: string;
48
98
  showToolbar?: boolean;
49
99
  showSidebar?: boolean;
50
100
  showTimeline?: boolean;
@@ -103,14 +153,16 @@ export declare function buildSidebarSections(doc: Record<string, unknown>, share
103
153
  */
104
154
  export declare function mapDocToSidebarMetadata(doc: Record<string, unknown>, t: TFunction): SidebarMetadataEntry[];
105
155
  /**
106
- * Thin Frappe wrapper around the generic SchemaForm component.
156
+ * The form for a Frappe doctype, resolved from meta by the desk form engine.
107
157
  *
108
- * Fetches Frappe doctype metadata and document data, maps the metadata
109
- * to a generic `FormSchema`, and passes it to `SchemaForm` from
110
- * `@multiplatform.one/forms`.
158
+ * Fetches doctype metadata and the document, lays the fields out through
159
+ * `buildFormTabs` (tabs, sections, `depends_on`, `mandatory_depends_on`,
160
+ * `read_only_depends_on`, `collapsible_depends_on`, permlevel,
161
+ * `set_only_once`, `fetch_from` and docstatus), and renders each tab with
162
+ * `SchemaForm`. With a `route` it is the doctype's record page.
111
163
  */
112
164
  export declare function FrappeForm<TDoc extends {
113
165
  name: string;
114
166
  doctype: string;
115
- }>({ baseURL, auth, syncOptions, doctype, name, fields, children, overrides, hideFields, readOnlyFields, sections, order, onSave, onCancel, onDelete, showToolbar, showSidebar, showTimeline, disabled, sectionHeadingLevel, }: FrappeFormProps<TDoc>): import("react/jsx-runtime").JSX.Element;
167
+ }>(props: FrappeFormProps<TDoc>): import("react/jsx-runtime").JSX.Element;
116
168
  //# sourceMappingURL=FrappeForm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FrappeForm.d.ts","sourceRoot":"","sources":["../src/FrappeForm.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FrappeForm.d.ts","sourceRoot":"","sources":["../src/FrappeForm.tsx"],"names":[],"mappings":"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"}