@multiplatform.one/frappe-ui 7.7.6 → 7.10.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 (538) hide show
  1. package/dist/cjs/ChartCard.native.js.map +1 -1
  2. package/dist/cjs/FileBrowser/AttachLibrary.native.js.map +1 -1
  3. package/dist/cjs/FileBrowser/folderTree.native.js.map +1 -1
  4. package/dist/cjs/FileBrowser/index.native.js.map +1 -1
  5. package/dist/cjs/FileBrowser/types.native.js.map +1 -1
  6. package/dist/cjs/FileBrowser/viewPersistence.native.js.map +1 -1
  7. package/dist/cjs/FormSidebar.cjs +7 -7
  8. package/dist/cjs/FormSidebar.native.js +7 -7
  9. package/dist/cjs/FormSidebar.native.js.map +1 -1
  10. package/dist/cjs/FrappeAssignment.native.js.map +1 -1
  11. package/dist/cjs/FrappeCalendar.cjs +20 -17
  12. package/dist/cjs/FrappeCalendar.native.js +22 -21
  13. package/dist/cjs/FrappeCalendar.native.js.map +1 -1
  14. package/dist/cjs/FrappeChartCard.cjs +29 -3
  15. package/dist/cjs/FrappeChartCard.native.js +29 -3
  16. package/dist/cjs/FrappeChartCard.native.js.map +1 -1
  17. package/dist/cjs/FrappeConnectionIndicator.native.js.map +1 -1
  18. package/dist/cjs/FrappeDashboard.native.js.map +1 -1
  19. package/dist/cjs/FrappeForm.cjs +1 -1
  20. package/dist/cjs/FrappeForm.native.js +2 -2
  21. package/dist/cjs/FrappeForm.native.js.map +1 -1
  22. package/dist/cjs/FrappeGantt.cjs +25 -34
  23. package/dist/cjs/FrappeGantt.native.js +27 -38
  24. package/dist/cjs/FrappeGantt.native.js.map +1 -1
  25. package/dist/cjs/FrappeImageView.cjs +4 -2
  26. package/dist/cjs/FrappeImageView.native.js +8 -4
  27. package/dist/cjs/FrappeImageView.native.js.map +1 -1
  28. package/dist/cjs/FrappeKPICard.cjs +29 -3
  29. package/dist/cjs/FrappeKPICard.native.js +29 -3
  30. package/dist/cjs/FrappeKPICard.native.js.map +1 -1
  31. package/dist/cjs/FrappeKanban.cjs +16 -17
  32. package/dist/cjs/FrappeKanban.native.js +18 -21
  33. package/dist/cjs/FrappeKanban.native.js.map +1 -1
  34. package/dist/cjs/FrappeLikedBy.cjs +1 -1
  35. package/dist/cjs/FrappeLikedBy.native.js +1 -1
  36. package/dist/cjs/FrappeLikedBy.native.js.map +1 -1
  37. package/dist/cjs/FrappeList.cjs +2 -2
  38. package/dist/cjs/FrappeList.native.js +2 -2
  39. package/dist/cjs/FrappeList.native.js.map +1 -1
  40. package/dist/cjs/FrappeListView.cjs +6 -6
  41. package/dist/cjs/FrappeListView.native.js +6 -6
  42. package/dist/cjs/FrappeListView.native.js.map +1 -1
  43. package/dist/cjs/FrappeProvider.native.js.map +1 -1
  44. package/dist/cjs/FrappeReconnectIndicator.native.js.map +1 -1
  45. package/dist/cjs/FrappeReportBuilder.cjs +2 -2
  46. package/dist/cjs/FrappeReportBuilder.native.js +2 -2
  47. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  48. package/dist/cjs/FrappeReportView.native.js +3 -3
  49. package/dist/cjs/FrappeReportView.native.js.map +1 -1
  50. package/dist/cjs/FrappeTable.cjs +35 -38
  51. package/dist/cjs/FrappeTable.native.js +38 -39
  52. package/dist/cjs/FrappeTable.native.js.map +1 -1
  53. package/dist/cjs/FrappeTreeView.cjs +85 -50
  54. package/dist/cjs/FrappeTreeView.native.js +129 -50
  55. package/dist/cjs/FrappeTreeView.native.js.map +1 -1
  56. package/dist/cjs/SyncErrorNotice.native.js.map +1 -1
  57. package/dist/cjs/commentActions.cjs +1 -1
  58. package/dist/cjs/commentActions.native.js +1 -1
  59. package/dist/cjs/commentActions.native.js.map +1 -1
  60. package/dist/cjs/components/attachments.native.js.map +1 -1
  61. package/dist/cjs/components/tags.native.js.map +1 -1
  62. package/dist/cjs/components/timeline.cjs +1 -1
  63. package/dist/cjs/components/timeline.native.js +1 -1
  64. package/dist/cjs/components/timeline.native.js.map +1 -1
  65. package/dist/cjs/dependsOn.native.js.map +1 -1
  66. package/dist/cjs/desk/DeskFormPage.native.js.map +1 -1
  67. package/dist/cjs/desk/DeskFormSidebar.native.js.map +1 -1
  68. package/dist/cjs/desk/DeskListPage.native.js.map +1 -1
  69. package/dist/cjs/desk/DeskShell.cjs +2 -0
  70. package/dist/cjs/desk/DeskShell.native.js +2 -0
  71. package/dist/cjs/desk/DeskShell.native.js.map +1 -1
  72. package/dist/cjs/desk/DeskSidebar.native.js.map +1 -1
  73. package/dist/cjs/desk/awesomebar.cjs +1 -1
  74. package/dist/cjs/desk/awesomebar.native.js +1 -1
  75. package/dist/cjs/desk/awesomebar.native.js.map +1 -1
  76. package/dist/cjs/fieldOverrides.native.js.map +1 -1
  77. package/dist/cjs/fieldRegistry.native.js +31 -31
  78. package/dist/cjs/fieldRegistry.native.js.map +1 -1
  79. package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
  80. package/dist/cjs/fields/Check/index.native.js.map +1 -1
  81. package/dist/cjs/fields/CodeEditor/index.native.js.map +1 -1
  82. package/dist/cjs/fields/Color/index.native.js.map +1 -1
  83. package/dist/cjs/fields/Data/index.native.js.map +1 -1
  84. package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
  85. package/dist/cjs/fields/Date/types.native.js.map +1 -1
  86. package/dist/cjs/fields/Date/wire.native.js.map +1 -1
  87. package/dist/cjs/fields/DateRange/index.cjs +30 -2
  88. package/dist/cjs/fields/DateRange/index.native.js +34 -2
  89. package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
  90. package/dist/cjs/fields/Duration/index.native.js.map +1 -1
  91. package/dist/cjs/fields/DynamicLink.native.js.map +1 -1
  92. package/dist/cjs/fields/FileUpload.native.js.map +1 -1
  93. package/dist/cjs/fields/FileUploadField/index.native.js.map +1 -1
  94. package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
  95. package/dist/cjs/fields/HTML/index.native.js.map +1 -1
  96. package/dist/cjs/fields/Heading/index.native.js.map +1 -1
  97. package/dist/cjs/fields/Icon/index.native.js.map +1 -1
  98. package/dist/cjs/fields/Link.native.js.map +1 -1
  99. package/dist/cjs/fields/LinkTree.native.js.map +1 -1
  100. package/dist/cjs/fields/LongText/index.native.js.map +1 -1
  101. package/dist/cjs/fields/MentionInput/index.cjs +4 -1
  102. package/dist/cjs/fields/MentionInput/index.native.js +4 -1
  103. package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
  104. package/dist/cjs/fields/Numeric/index.native.js.map +1 -1
  105. package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
  106. package/dist/cjs/fields/Password/index.native.js.map +1 -1
  107. package/dist/cjs/fields/Phone/index.native.js.map +1 -1
  108. package/dist/cjs/fields/Progress/index.native.js.map +1 -1
  109. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  110. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  111. package/dist/cjs/fields/ReadOnly/index.native.js.map +1 -1
  112. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  113. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  114. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  115. package/dist/cjs/fields/SmallText/index.native.js.map +1 -1
  116. package/dist/cjs/fields/Switch/index.native.js.map +1 -1
  117. package/dist/cjs/fields/TableMultiSelect.native.js.map +1 -1
  118. package/dist/cjs/fields/TextEditor/types.native.js.map +1 -1
  119. package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
  120. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  121. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  122. package/dist/cjs/filterFields.native.js.map +1 -1
  123. package/dist/cjs/formEngine/createPrefill.native.js.map +1 -1
  124. package/dist/cjs/formEngine/dirtyTracking.native.js.map +1 -1
  125. package/dist/cjs/formEngine/doctypeMeta.native.js.map +1 -1
  126. package/dist/cjs/formEngine/fetchFrom.native.js.map +1 -1
  127. package/dist/cjs/formEngine/fieldPermissions.native.js.map +1 -1
  128. package/dist/cjs/formEngine/formActions.native.js.map +1 -1
  129. package/dist/cjs/formEngine/formLayout.native.js.map +1 -1
  130. package/dist/cjs/formEngine/index.native.js.map +1 -1
  131. package/dist/cjs/formEngine/useFormEngine.native.js.map +1 -1
  132. package/dist/cjs/frappeEventColor.native.js.map +1 -1
  133. package/dist/cjs/frappeStoryTarget.native.js.map +1 -1
  134. package/dist/cjs/frappeUsers.native.js.map +1 -1
  135. package/dist/cjs/index.cjs +4 -0
  136. package/dist/cjs/index.native.js +38 -34
  137. package/dist/cjs/index.native.js.map +1 -1
  138. package/dist/cjs/liveErrors.native.js.map +1 -1
  139. package/dist/cjs/resolveControl.native.js.map +1 -1
  140. package/dist/cjs/schemaForm/SchemaWizard.native.js.map +1 -1
  141. package/dist/cjs/schemaForm/applyFieldOrder.native.js.map +1 -1
  142. package/dist/cjs/schemaForm/index.cjs +10 -9
  143. package/dist/cjs/schemaForm/index.native.js +11 -10
  144. package/dist/cjs/schemaForm/index.native.js.map +1 -1
  145. package/dist/cjs/shared/devWarn.cjs +40 -0
  146. package/dist/cjs/shared/devWarn.native.js +45 -0
  147. package/dist/cjs/shared/devWarn.native.js.map +1 -0
  148. package/dist/cjs/shared/useKeyboardInset.native.js.map +1 -1
  149. package/dist/cjs/syncError.native.js.map +1 -1
  150. package/dist/cjs/useFrappeAggregate.cjs +15 -8
  151. package/dist/cjs/useFrappeAggregate.native.js +15 -9
  152. package/dist/cjs/useFrappeAggregate.native.js.map +1 -1
  153. package/dist/cjs/useFrappeFacets.cjs +10 -9
  154. package/dist/cjs/useFrappeFacets.native.js +10 -10
  155. package/dist/cjs/useFrappeFacets.native.js.map +1 -1
  156. package/dist/cjs/useFrappePagination.native.js.map +1 -1
  157. package/dist/cjs/useFrappeRows.cjs +113 -0
  158. package/dist/cjs/useFrappeRows.native.js +129 -0
  159. package/dist/cjs/useFrappeRows.native.js.map +1 -0
  160. package/dist/esm/ChartCard.native.js.map +1 -1
  161. package/dist/esm/FileBrowser/AttachLibrary.native.js.map +1 -1
  162. package/dist/esm/FileBrowser/folderTree.native.js.map +1 -1
  163. package/dist/esm/FileBrowser/index.native.js.map +1 -1
  164. package/dist/esm/FileBrowser/types.native.js.map +1 -1
  165. package/dist/esm/FileBrowser/viewPersistence.native.js.map +1 -1
  166. package/dist/esm/FormSidebar.mjs +7 -7
  167. package/dist/esm/FormSidebar.mjs.map +1 -1
  168. package/dist/esm/FormSidebar.native.js +7 -7
  169. package/dist/esm/FormSidebar.native.js.map +1 -1
  170. package/dist/esm/FrappeAssignment.native.js.map +1 -1
  171. package/dist/esm/FrappeCalendar.mjs +20 -17
  172. package/dist/esm/FrappeCalendar.mjs.map +1 -1
  173. package/dist/esm/FrappeCalendar.native.js +22 -21
  174. package/dist/esm/FrappeCalendar.native.js.map +1 -1
  175. package/dist/esm/FrappeChartCard.mjs +30 -4
  176. package/dist/esm/FrappeChartCard.mjs.map +1 -1
  177. package/dist/esm/FrappeChartCard.native.js +30 -4
  178. package/dist/esm/FrappeChartCard.native.js.map +1 -1
  179. package/dist/esm/FrappeConnectionIndicator.native.js.map +1 -1
  180. package/dist/esm/FrappeDashboard.native.js.map +1 -1
  181. package/dist/esm/FrappeForm.mjs +1 -1
  182. package/dist/esm/FrappeForm.mjs.map +1 -1
  183. package/dist/esm/FrappeForm.native.js +1 -1
  184. package/dist/esm/FrappeForm.native.js.map +1 -1
  185. package/dist/esm/FrappeGantt.mjs +27 -36
  186. package/dist/esm/FrappeGantt.mjs.map +1 -1
  187. package/dist/esm/FrappeGantt.native.js +29 -40
  188. package/dist/esm/FrappeGantt.native.js.map +1 -1
  189. package/dist/esm/FrappeImageView.mjs +5 -3
  190. package/dist/esm/FrappeImageView.mjs.map +1 -1
  191. package/dist/esm/FrappeImageView.native.js +9 -5
  192. package/dist/esm/FrappeImageView.native.js.map +1 -1
  193. package/dist/esm/FrappeKPICard.mjs +30 -4
  194. package/dist/esm/FrappeKPICard.mjs.map +1 -1
  195. package/dist/esm/FrappeKPICard.native.js +30 -4
  196. package/dist/esm/FrappeKPICard.native.js.map +1 -1
  197. package/dist/esm/FrappeKanban.mjs +16 -17
  198. package/dist/esm/FrappeKanban.mjs.map +1 -1
  199. package/dist/esm/FrappeKanban.native.js +18 -21
  200. package/dist/esm/FrappeKanban.native.js.map +1 -1
  201. package/dist/esm/FrappeLikedBy.mjs +1 -1
  202. package/dist/esm/FrappeLikedBy.mjs.map +1 -1
  203. package/dist/esm/FrappeLikedBy.native.js +1 -1
  204. package/dist/esm/FrappeLikedBy.native.js.map +1 -1
  205. package/dist/esm/FrappeList.mjs +2 -2
  206. package/dist/esm/FrappeList.mjs.map +1 -1
  207. package/dist/esm/FrappeList.native.js +2 -2
  208. package/dist/esm/FrappeList.native.js.map +1 -1
  209. package/dist/esm/FrappeListView.mjs +6 -6
  210. package/dist/esm/FrappeListView.mjs.map +1 -1
  211. package/dist/esm/FrappeListView.native.js +6 -6
  212. package/dist/esm/FrappeListView.native.js.map +1 -1
  213. package/dist/esm/FrappeProvider.mjs.map +1 -1
  214. package/dist/esm/FrappeProvider.native.js.map +1 -1
  215. package/dist/esm/FrappeReconnectIndicator.native.js.map +1 -1
  216. package/dist/esm/FrappeReportBuilder.mjs +2 -2
  217. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  218. package/dist/esm/FrappeReportBuilder.native.js +2 -2
  219. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  220. package/dist/esm/FrappeReportView.native.js.map +1 -1
  221. package/dist/esm/FrappeTable.mjs +36 -39
  222. package/dist/esm/FrappeTable.mjs.map +1 -1
  223. package/dist/esm/FrappeTable.native.js +39 -40
  224. package/dist/esm/FrappeTable.native.js.map +1 -1
  225. package/dist/esm/FrappeTreeView.mjs +89 -55
  226. package/dist/esm/FrappeTreeView.mjs.map +1 -1
  227. package/dist/esm/FrappeTreeView.native.js +133 -55
  228. package/dist/esm/FrappeTreeView.native.js.map +1 -1
  229. package/dist/esm/SyncErrorNotice.native.js.map +1 -1
  230. package/dist/esm/commentActions.mjs +1 -1
  231. package/dist/esm/commentActions.mjs.map +1 -1
  232. package/dist/esm/commentActions.native.js +1 -1
  233. package/dist/esm/commentActions.native.js.map +1 -1
  234. package/dist/esm/components/attachments.native.js.map +1 -1
  235. package/dist/esm/components/tags.native.js.map +1 -1
  236. package/dist/esm/components/timeline.mjs +1 -1
  237. package/dist/esm/components/timeline.mjs.map +1 -1
  238. package/dist/esm/components/timeline.native.js +1 -1
  239. package/dist/esm/components/timeline.native.js.map +1 -1
  240. package/dist/esm/dependsOn.native.js.map +1 -1
  241. package/dist/esm/desk/DeskFormPage.native.js.map +1 -1
  242. package/dist/esm/desk/DeskFormSidebar.native.js.map +1 -1
  243. package/dist/esm/desk/DeskListPage.native.js.map +1 -1
  244. package/dist/esm/desk/DeskShell.mjs +2 -0
  245. package/dist/esm/desk/DeskShell.mjs.map +1 -1
  246. package/dist/esm/desk/DeskShell.native.js +2 -0
  247. package/dist/esm/desk/DeskShell.native.js.map +1 -1
  248. package/dist/esm/desk/DeskSidebar.native.js.map +1 -1
  249. package/dist/esm/desk/awesomebar.mjs +1 -1
  250. package/dist/esm/desk/awesomebar.mjs.map +1 -1
  251. package/dist/esm/desk/awesomebar.native.js +1 -1
  252. package/dist/esm/desk/awesomebar.native.js.map +1 -1
  253. package/dist/esm/fieldOverrides.native.js.map +1 -1
  254. package/dist/esm/fieldRegistry.native.js.map +1 -1
  255. package/dist/esm/fields/Barcode/index.native.js.map +1 -1
  256. package/dist/esm/fields/Check/index.native.js.map +1 -1
  257. package/dist/esm/fields/CodeEditor/index.native.js.map +1 -1
  258. package/dist/esm/fields/Color/index.native.js.map +1 -1
  259. package/dist/esm/fields/Data/index.native.js.map +1 -1
  260. package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
  261. package/dist/esm/fields/Date/types.native.js.map +1 -1
  262. package/dist/esm/fields/Date/wire.native.js.map +1 -1
  263. package/dist/esm/fields/DateRange/index.mjs +30 -2
  264. package/dist/esm/fields/DateRange/index.mjs.map +1 -1
  265. package/dist/esm/fields/DateRange/index.native.js +34 -2
  266. package/dist/esm/fields/DateRange/index.native.js.map +1 -1
  267. package/dist/esm/fields/Duration/index.native.js.map +1 -1
  268. package/dist/esm/fields/DynamicLink.native.js.map +1 -1
  269. package/dist/esm/fields/FileUpload.native.js.map +1 -1
  270. package/dist/esm/fields/FileUploadField/index.native.js.map +1 -1
  271. package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
  272. package/dist/esm/fields/HTML/index.native.js.map +1 -1
  273. package/dist/esm/fields/Heading/index.native.js.map +1 -1
  274. package/dist/esm/fields/Icon/index.native.js.map +1 -1
  275. package/dist/esm/fields/Link.native.js.map +1 -1
  276. package/dist/esm/fields/LinkTree.native.js.map +1 -1
  277. package/dist/esm/fields/LongText/index.native.js.map +1 -1
  278. package/dist/esm/fields/MentionInput/index.mjs +4 -1
  279. package/dist/esm/fields/MentionInput/index.mjs.map +1 -1
  280. package/dist/esm/fields/MentionInput/index.native.js +4 -1
  281. package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
  282. package/dist/esm/fields/Numeric/index.native.js.map +1 -1
  283. package/dist/esm/fields/OTPInput/index.native.js.map +1 -1
  284. package/dist/esm/fields/Password/index.native.js.map +1 -1
  285. package/dist/esm/fields/Phone/index.native.js.map +1 -1
  286. package/dist/esm/fields/Progress/index.native.js.map +1 -1
  287. package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
  288. package/dist/esm/fields/Rating/index.native.js.map +1 -1
  289. package/dist/esm/fields/ReadOnly/index.native.js.map +1 -1
  290. package/dist/esm/fields/Select/index.native.js.map +1 -1
  291. package/dist/esm/fields/Signature/index.native.js.map +1 -1
  292. package/dist/esm/fields/Slider/index.native.js.map +1 -1
  293. package/dist/esm/fields/SmallText/index.native.js.map +1 -1
  294. package/dist/esm/fields/Switch/index.native.js.map +1 -1
  295. package/dist/esm/fields/TableMultiSelect.native.js.map +1 -1
  296. package/dist/esm/fields/TextEditor/types.native.js.map +1 -1
  297. package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
  298. package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
  299. package/dist/esm/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  300. package/dist/esm/filterFields.native.js.map +1 -1
  301. package/dist/esm/formEngine/createPrefill.native.js.map +1 -1
  302. package/dist/esm/formEngine/dirtyTracking.native.js.map +1 -1
  303. package/dist/esm/formEngine/doctypeMeta.native.js.map +1 -1
  304. package/dist/esm/formEngine/fetchFrom.native.js.map +1 -1
  305. package/dist/esm/formEngine/fieldPermissions.native.js.map +1 -1
  306. package/dist/esm/formEngine/formActions.native.js.map +1 -1
  307. package/dist/esm/formEngine/formLayout.native.js.map +1 -1
  308. package/dist/esm/formEngine/index.native.js.map +1 -1
  309. package/dist/esm/formEngine/useFormEngine.native.js.map +1 -1
  310. package/dist/esm/frappeEventColor.native.js.map +1 -1
  311. package/dist/esm/frappeStoryTarget.native.js.map +1 -1
  312. package/dist/esm/frappeUsers.native.js.map +1 -1
  313. package/dist/esm/index.mjs +2 -1
  314. package/dist/esm/index.mjs.map +1 -1
  315. package/dist/esm/index.native.js +2 -1
  316. package/dist/esm/index.native.js.map +1 -1
  317. package/dist/esm/liveErrors.native.js.map +1 -1
  318. package/dist/esm/resolveControl.native.js.map +1 -1
  319. package/dist/esm/schemaForm/SchemaWizard.native.js.map +1 -1
  320. package/dist/esm/schemaForm/applyFieldOrder.native.js.map +1 -1
  321. package/dist/esm/schemaForm/index.mjs +8 -7
  322. package/dist/esm/schemaForm/index.mjs.map +1 -1
  323. package/dist/esm/schemaForm/index.native.js +8 -7
  324. package/dist/esm/schemaForm/index.native.js.map +1 -1
  325. package/dist/esm/shared/devWarn.mjs +14 -0
  326. package/dist/esm/shared/devWarn.mjs.map +1 -0
  327. package/dist/esm/shared/devWarn.native.js +16 -0
  328. package/dist/esm/shared/devWarn.native.js.map +1 -0
  329. package/dist/esm/shared/useKeyboardInset.native.js.map +1 -1
  330. package/dist/esm/syncError.native.js.map +1 -1
  331. package/dist/esm/useFrappeAggregate.mjs +15 -8
  332. package/dist/esm/useFrappeAggregate.mjs.map +1 -1
  333. package/dist/esm/useFrappeAggregate.native.js +15 -9
  334. package/dist/esm/useFrappeAggregate.native.js.map +1 -1
  335. package/dist/esm/useFrappeFacets.mjs +10 -9
  336. package/dist/esm/useFrappeFacets.mjs.map +1 -1
  337. package/dist/esm/useFrappeFacets.native.js +10 -10
  338. package/dist/esm/useFrappeFacets.native.js.map +1 -1
  339. package/dist/esm/useFrappePagination.native.js.map +1 -1
  340. package/dist/esm/useFrappeRows.mjs +86 -0
  341. package/dist/esm/useFrappeRows.mjs.map +1 -0
  342. package/dist/esm/useFrappeRows.native.js +99 -0
  343. package/dist/esm/useFrappeRows.native.js.map +1 -0
  344. package/dist/jsx/FormSidebar.mjs +7 -7
  345. package/dist/jsx/FormSidebar.mjs.map +1 -1
  346. package/dist/jsx/FormSidebar.native.js +7 -7
  347. package/dist/jsx/FormSidebar.native.js.map +1 -1
  348. package/dist/jsx/FrappeCalendar.mjs +20 -17
  349. package/dist/jsx/FrappeCalendar.mjs.map +1 -1
  350. package/dist/jsx/FrappeCalendar.native.js +22 -21
  351. package/dist/jsx/FrappeCalendar.native.js.map +1 -1
  352. package/dist/jsx/FrappeChartCard.mjs +30 -4
  353. package/dist/jsx/FrappeChartCard.mjs.map +1 -1
  354. package/dist/jsx/FrappeChartCard.native.js +29 -3
  355. package/dist/jsx/FrappeChartCard.native.js.map +1 -1
  356. package/dist/jsx/FrappeForm.mjs +1 -1
  357. package/dist/jsx/FrappeForm.mjs.map +1 -1
  358. package/dist/jsx/FrappeForm.native.js +1 -1
  359. package/dist/jsx/FrappeForm.native.js.map +1 -1
  360. package/dist/jsx/FrappeGantt.mjs +27 -36
  361. package/dist/jsx/FrappeGantt.mjs.map +1 -1
  362. package/dist/jsx/FrappeGantt.native.js +27 -38
  363. package/dist/jsx/FrappeGantt.native.js.map +1 -1
  364. package/dist/jsx/FrappeImageView.mjs +5 -3
  365. package/dist/jsx/FrappeImageView.mjs.map +1 -1
  366. package/dist/jsx/FrappeImageView.native.js +8 -4
  367. package/dist/jsx/FrappeImageView.native.js.map +1 -1
  368. package/dist/jsx/FrappeKPICard.mjs +30 -4
  369. package/dist/jsx/FrappeKPICard.mjs.map +1 -1
  370. package/dist/jsx/FrappeKPICard.native.js +29 -3
  371. package/dist/jsx/FrappeKPICard.native.js.map +1 -1
  372. package/dist/jsx/FrappeKanban.mjs +16 -17
  373. package/dist/jsx/FrappeKanban.mjs.map +1 -1
  374. package/dist/jsx/FrappeKanban.native.js +18 -21
  375. package/dist/jsx/FrappeKanban.native.js.map +1 -1
  376. package/dist/jsx/FrappeLikedBy.mjs +1 -1
  377. package/dist/jsx/FrappeLikedBy.mjs.map +1 -1
  378. package/dist/jsx/FrappeLikedBy.native.js +1 -1
  379. package/dist/jsx/FrappeLikedBy.native.js.map +1 -1
  380. package/dist/jsx/FrappeList.mjs +2 -2
  381. package/dist/jsx/FrappeList.mjs.map +1 -1
  382. package/dist/jsx/FrappeList.native.js +2 -2
  383. package/dist/jsx/FrappeList.native.js.map +1 -1
  384. package/dist/jsx/FrappeListView.mjs +6 -6
  385. package/dist/jsx/FrappeListView.mjs.map +1 -1
  386. package/dist/jsx/FrappeListView.native.js +6 -6
  387. package/dist/jsx/FrappeListView.native.js.map +1 -1
  388. package/dist/jsx/FrappeProvider.mjs.map +1 -1
  389. package/dist/jsx/FrappeProvider.native.js.map +1 -1
  390. package/dist/jsx/FrappeReportBuilder.mjs +2 -2
  391. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  392. package/dist/jsx/FrappeReportBuilder.native.js +2 -2
  393. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  394. package/dist/jsx/FrappeTable.mjs +36 -39
  395. package/dist/jsx/FrappeTable.mjs.map +1 -1
  396. package/dist/jsx/FrappeTable.native.js +38 -39
  397. package/dist/jsx/FrappeTable.native.js.map +1 -1
  398. package/dist/jsx/FrappeTreeView.mjs +89 -55
  399. package/dist/jsx/FrappeTreeView.mjs.map +1 -1
  400. package/dist/jsx/FrappeTreeView.native.js +129 -50
  401. package/dist/jsx/FrappeTreeView.native.js.map +1 -1
  402. package/dist/jsx/commentActions.mjs +1 -1
  403. package/dist/jsx/commentActions.mjs.map +1 -1
  404. package/dist/jsx/commentActions.native.js +1 -1
  405. package/dist/jsx/commentActions.native.js.map +1 -1
  406. package/dist/jsx/components/timeline.mjs +1 -1
  407. package/dist/jsx/components/timeline.mjs.map +1 -1
  408. package/dist/jsx/components/timeline.native.js +1 -1
  409. package/dist/jsx/desk/DeskShell.mjs +2 -0
  410. package/dist/jsx/desk/DeskShell.mjs.map +1 -1
  411. package/dist/jsx/desk/DeskShell.native.js +2 -0
  412. package/dist/jsx/desk/DeskShell.native.js.map +1 -1
  413. package/dist/jsx/desk/awesomebar.mjs +1 -1
  414. package/dist/jsx/desk/awesomebar.mjs.map +1 -1
  415. package/dist/jsx/desk/awesomebar.native.js +1 -1
  416. package/dist/jsx/desk/awesomebar.native.js.map +1 -1
  417. package/dist/jsx/fields/DateRange/index.mjs +30 -2
  418. package/dist/jsx/fields/DateRange/index.mjs.map +1 -1
  419. package/dist/jsx/fields/DateRange/index.native.js +34 -2
  420. package/dist/jsx/fields/DateRange/index.native.js.map +1 -1
  421. package/dist/jsx/fields/MentionInput/index.mjs +4 -1
  422. package/dist/jsx/fields/MentionInput/index.mjs.map +1 -1
  423. package/dist/jsx/fields/MentionInput/index.native.js +4 -1
  424. package/dist/jsx/fields/MentionInput/index.native.js.map +1 -1
  425. package/dist/jsx/index.js +2 -1
  426. package/dist/jsx/index.js.map +1 -1
  427. package/dist/jsx/index.mjs +2 -1
  428. package/dist/jsx/index.mjs.map +1 -1
  429. package/dist/jsx/index.native.js +4 -0
  430. package/dist/jsx/index.native.js.map +1 -1
  431. package/dist/jsx/schemaForm/index.mjs +8 -7
  432. package/dist/jsx/schemaForm/index.mjs.map +1 -1
  433. package/dist/jsx/schemaForm/index.native.js +10 -9
  434. package/dist/jsx/schemaForm/index.native.js.map +1 -1
  435. package/dist/jsx/shared/devWarn.mjs +14 -0
  436. package/dist/jsx/shared/devWarn.mjs.map +1 -0
  437. package/dist/jsx/shared/devWarn.native.js +45 -0
  438. package/dist/jsx/shared/devWarn.native.js.map +1 -0
  439. package/dist/jsx/useFrappeAggregate.mjs +15 -8
  440. package/dist/jsx/useFrappeAggregate.mjs.map +1 -1
  441. package/dist/jsx/useFrappeAggregate.native.js +15 -9
  442. package/dist/jsx/useFrappeAggregate.native.js.map +1 -1
  443. package/dist/jsx/useFrappeFacets.mjs +10 -9
  444. package/dist/jsx/useFrappeFacets.mjs.map +1 -1
  445. package/dist/jsx/useFrappeFacets.native.js +10 -10
  446. package/dist/jsx/useFrappeFacets.native.js.map +1 -1
  447. package/dist/jsx/useFrappeRows.mjs +86 -0
  448. package/dist/jsx/useFrappeRows.mjs.map +1 -0
  449. package/dist/jsx/useFrappeRows.native.js +129 -0
  450. package/dist/jsx/useFrappeRows.native.js.map +1 -0
  451. package/package.json +17 -16
  452. package/src/FileBrowser/FileBrowser.spec.tsx +11 -1
  453. package/src/FormSidebar.tsx +7 -7
  454. package/src/FrappeCalendar.tsx +25 -22
  455. package/src/FrappeChartCard.spec.tsx +179 -0
  456. package/src/FrappeChartCard.tsx +55 -6
  457. package/src/FrappeForm.tsx +7 -3
  458. package/src/FrappeGantt.tsx +29 -39
  459. package/src/FrappeImageView.tsx +5 -3
  460. package/src/FrappeKPICard.spec.tsx +153 -0
  461. package/src/FrappeKPICard.tsx +52 -6
  462. package/src/FrappeKanban.tsx +24 -17
  463. package/src/FrappeLikedBy.tsx +1 -1
  464. package/src/FrappeList.tsx +3 -2
  465. package/src/FrappeListView.tsx +6 -6
  466. package/src/FrappeProvider.fixturesOnly.spec.tsx +129 -0
  467. package/src/FrappeProvider.tsx +16 -6
  468. package/src/FrappeReportBuilder.tsx +4 -2
  469. package/src/FrappeTable.autoHeight.spec.tsx +142 -0
  470. package/src/FrappeTable.rowAccumulator.spec.tsx +110 -0
  471. package/src/FrappeTable.tsx +75 -48
  472. package/src/FrappeTreeView.stories.tsx +59 -0
  473. package/src/FrappeTreeView.tsx +166 -56
  474. package/src/commentActions.ts +1 -1
  475. package/src/components/timeline.tsx +1 -1
  476. package/src/desk/DeskShell.tsx +2 -0
  477. package/src/desk/awesomebar.tsx +5 -2
  478. package/src/fields/CodeEditor/CodeEditor.spec.tsx +10 -9
  479. package/src/fields/Date/Date.spec.tsx +8 -1
  480. package/src/fields/Date/nativePresentation.spec.tsx +8 -1
  481. package/src/fields/Date/typeParity.spec.tsx +27 -10
  482. package/src/fields/DateRange/DateRange.spec.tsx +87 -15
  483. package/src/fields/DateRange/index.tsx +47 -3
  484. package/src/fields/Duration/Duration.spec.tsx +73 -0
  485. package/src/fields/MentionInput/MentionInput.spec.tsx +110 -0
  486. package/src/fields/MentionInput/index.tsx +4 -1
  487. package/src/fields/Password/index.tsx +1 -1
  488. package/src/fields/Progress/Progress.spec.tsx +9 -0
  489. package/src/fields/RadioGroup/RadioGroup.spec.tsx +93 -0
  490. package/src/fields/Signature/Signature.spec.tsx +105 -0
  491. package/src/fields/Slider/Slider.spec.tsx +73 -0
  492. package/src/fields/Switch/Switch.spec.tsx +65 -0
  493. package/src/fields/TextEditor/TextEditor.spec.tsx +2 -3
  494. package/src/fields/TextEditor/TextEditor.stories.tsx +31 -1
  495. package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +110 -0
  496. package/src/frappeViews.designLaw.spec.ts +11 -7
  497. package/src/index.ts +13 -0
  498. package/src/schemaForm/index.tsx +6 -7
  499. package/src/shared/devWarn.ts +44 -0
  500. package/src/useFrappeAggregate.ts +17 -11
  501. package/src/useFrappeFacets.ts +17 -10
  502. package/src/useFrappeRows.spec.tsx +176 -0
  503. package/src/useFrappeRows.ts +293 -0
  504. package/types/FrappeCalendar.d.ts.map +1 -1
  505. package/types/FrappeChartCard.d.ts +17 -1
  506. package/types/FrappeChartCard.d.ts.map +1 -1
  507. package/types/FrappeForm.d.ts +6 -2
  508. package/types/FrappeForm.d.ts.map +1 -1
  509. package/types/FrappeGantt.d.ts.map +1 -1
  510. package/types/FrappeImageView.d.ts.map +1 -1
  511. package/types/FrappeKPICard.d.ts +14 -1
  512. package/types/FrappeKPICard.d.ts.map +1 -1
  513. package/types/FrappeKanban.d.ts.map +1 -1
  514. package/types/FrappeList.d.ts.map +1 -1
  515. package/types/FrappeProvider.d.ts +16 -6
  516. package/types/FrappeProvider.d.ts.map +1 -1
  517. package/types/FrappeReportBuilder.d.ts.map +1 -1
  518. package/types/FrappeTable.d.ts +20 -1
  519. package/types/FrappeTable.d.ts.map +1 -1
  520. package/types/FrappeTreeView.d.ts +38 -1
  521. package/types/FrappeTreeView.d.ts.map +1 -1
  522. package/types/desk/DeskShell.d.ts.map +1 -1
  523. package/types/desk/awesomebar.d.ts.map +1 -1
  524. package/types/fields/DateRange/index.d.ts.map +1 -1
  525. package/types/fields/MentionInput/index.d.ts.map +1 -1
  526. package/types/fields/Password/index.d.ts +1 -1
  527. package/types/fields/Password/index.d.ts.map +1 -1
  528. package/types/index.d.ts +1 -0
  529. package/types/index.d.ts.map +1 -1
  530. package/types/schemaForm/index.d.ts.map +1 -1
  531. package/types/shared/devWarn.d.ts +23 -0
  532. package/types/shared/devWarn.d.ts.map +1 -0
  533. package/types/useFrappeAggregate.d.ts +2 -1
  534. package/types/useFrappeAggregate.d.ts.map +1 -1
  535. package/types/useFrappeFacets.d.ts +2 -1
  536. package/types/useFrappeFacets.d.ts.map +1 -1
  537. package/types/useFrappeRows.d.ts +186 -0
  538. package/types/useFrappeRows.d.ts.map +1 -0
@@ -0,0 +1,142 @@
1
+ /**
2
+ * MPO-229: FrappeTable must not collapse to a sliver in an auto-height parent.
3
+ *
4
+ * The wrapper YStack used `flex={1}`, which in React Native's flex model is
5
+ * `1 1 0` with a basis of ZERO. A basis-0 chain inside a parent that has no
6
+ * height of its own resolves to 0, so the whole table rendered as a one-row
7
+ * sliver. DataTableRoot's own root already avoids exactly this (grow 1 /
8
+ * shrink 1 / basis auto / minHeight 0, and it carries the note saying why).
9
+ * The FrappeTable wrapper sitting above it reintroduced the trap.
10
+ *
11
+ * Two halves here. The render cases pin the behaviour a caller sees: 12 rows
12
+ * in a plain auto-height parent, and the same table in a fixed-height parent.
13
+ * The source cases are the mechanical guard, because happy-dom runs no flex
14
+ * layout, so a basis-0 regression is invisible to a rendered assertion and
15
+ * only the geometry itself can be checked.
16
+ */
17
+
18
+ import fs from "node:fs";
19
+ import path from "node:path";
20
+ import { InMemoryFixtureProvider } from "@multiplatform.one/frappe";
21
+ import type { DataTableColumn } from "@multiplatform.one/table";
22
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
23
+ import { cleanup, screen } from "@testing-library/react";
24
+ import i18next from "i18next";
25
+ import { initReactI18next } from "react-i18next";
26
+ import { YStack } from "tamagui";
27
+ import { afterEach, beforeAll, describe, expect, it } from "vitest";
28
+ import { FrappeProvider } from "./FrappeProvider";
29
+ import { FrappeTable } from "./FrappeTable";
30
+
31
+ beforeAll(async () => {
32
+ if (!i18next.isInitialized) {
33
+ await i18next.use(initReactI18next).init({
34
+ lng: "en",
35
+ interpolation: { escapeValue: false },
36
+ resources: { en: { translation: {} } },
37
+ });
38
+ }
39
+ });
40
+
41
+ afterEach(() => {
42
+ cleanup();
43
+ });
44
+
45
+ interface Customer {
46
+ name: string;
47
+ doctype: string;
48
+ customer_name: string;
49
+ }
50
+
51
+ const customers: Customer[] = Array.from({ length: 12 }, (_, index) => ({
52
+ name: `CUST-${String(index + 1).padStart(3, "0")}`,
53
+ doctype: "Customer",
54
+ customer_name: `Customer ${index + 1}`,
55
+ }));
56
+
57
+ const columns: DataTableColumn<Partial<Customer>>[] = [
58
+ { id: "name", accessorKey: "name", header: "ID" },
59
+ { id: "customer_name", accessorKey: "customer_name", header: "Customer Name" },
60
+ ];
61
+
62
+ // Supplied so the table does not go to useDocTypeMeta for the filter list.
63
+ const filterFields = [{ id: "customer_name", label: "Customer Name", type: "text" as const }];
64
+
65
+ function renderInParent(parent: React.ReactElement) {
66
+ return renderWithProviders(
67
+ <FrappeProvider
68
+ baseURL="https://frappetable-autoheight.spec.test"
69
+ fixtures={new InMemoryFixtureProvider({ Customer: customers })}
70
+ >
71
+ {parent}
72
+ </FrappeProvider>,
73
+ );
74
+ }
75
+
76
+ const table = (
77
+ <FrappeTable<Customer>
78
+ doctype="Customer"
79
+ columns={columns}
80
+ filterableFields={filterFields}
81
+ layout="table"
82
+ enablePagination={false}
83
+ />
84
+ );
85
+
86
+ const srcDir = path.resolve(__dirname, ".");
87
+
88
+ function read(file: string): string {
89
+ return fs.readFileSync(path.resolve(srcDir, file), "utf-8");
90
+ }
91
+
92
+ function codeOnly(source: string): string {
93
+ return source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
94
+ }
95
+
96
+ describe("FrappeTable in an auto-height parent (MPO-229)", () => {
97
+ it("renders every row inside a plain auto-height YStack", async () => {
98
+ renderInParent(<YStack>{table}</YStack>);
99
+ await screen.findByText("Customer 1");
100
+ for (const customer of customers) {
101
+ expect(screen.getByText(customer.customer_name)).toBeTruthy();
102
+ }
103
+ expect(screen.queryByText(/No Customer records found/i)).toBeNull();
104
+ });
105
+
106
+ it("still renders every row inside a fixed-height parent", async () => {
107
+ renderInParent(<YStack height={400}>{table}</YStack>);
108
+ await screen.findByText("Customer 1");
109
+ for (const customer of customers) {
110
+ expect(screen.getByText(customer.customer_name)).toBeTruthy();
111
+ }
112
+ });
113
+
114
+ it("roots grow and shrink on a basis of auto, the same geometry as DataTableRoot", () => {
115
+ const source = codeOnly(read("FrappeTable.tsx"));
116
+
117
+ // flex={1} is 1 1 0 in RN. Basis 0 in an auto-height parent resolves to 0
118
+ // and the table collapses to a one-row sliver.
119
+ expect(source).not.toContain("flex={1}");
120
+
121
+ const tags = source.match(/<YStack\b[^>]*>/g) ?? [];
122
+ const roots = tags.filter((tag) => tag.includes("flexBasis"));
123
+ expect(roots.length).toBe(2);
124
+ for (const root of roots) {
125
+ expect(root).toContain("flexGrow={1}");
126
+ expect(root).toContain("flexShrink={1}");
127
+ expect(root).toContain('flexBasis="auto"');
128
+ expect(root).toContain("minHeight={0}");
129
+ }
130
+ });
131
+
132
+ it("DataTableRoot still carries the geometry FrappeTable copies", () => {
133
+ const source = codeOnly(read("../../table/src/components/DataTable/DataTableRoot.tsx"));
134
+ const tags = source.match(/<View\b[^>]*>/g) ?? [];
135
+ const root = tags.find((tag) => tag.includes("flexBasis"));
136
+ expect(root).toBeTruthy();
137
+ expect(root).toContain("flexGrow={1}");
138
+ expect(root).toContain("flexShrink={1}");
139
+ expect(root).toContain('flexBasis="auto"');
140
+ expect(root).toContain("minHeight={0}");
141
+ });
142
+ });
@@ -0,0 +1,110 @@
1
+ /**
2
+ * A running balance on a FrappeTable (MPO-250).
3
+ *
4
+ * The gap this closes: `FrappeTableProps` omits `data`, so before the row
5
+ * accumulator existed there was NO prop that reached the rows. A consumer who
6
+ * wanted a folded column on a Frappe doctype had to fetch the doctype again
7
+ * itself and hand the folded rows to a bare DataTable — a second read path, a
8
+ * second error path, and no saved filters or refresh channel.
9
+ *
10
+ * What this locks: `rowAccumulator` passes through FrappeTable to the table,
11
+ * folds the rows FrappeTable already fetched, and the figures continue onto
12
+ * page two.
13
+ *
14
+ * Fixture-hermetic: postings ride InMemoryFixtureProvider.
15
+ */
16
+
17
+ import { InMemoryFixtureProvider } from "@multiplatform.one/frappe";
18
+ import type { DataTableColumn, RowAccumulator } from "@multiplatform.one/table";
19
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
20
+ import { cleanup, screen, waitFor } from "@testing-library/react";
21
+ import userEvent from "@testing-library/user-event";
22
+ import i18next from "i18next";
23
+ import { initReactI18next } from "react-i18next";
24
+ import { afterEach, beforeAll, describe, expect, it } from "vitest";
25
+ import { FrappeProvider } from "./FrappeProvider";
26
+ import { FrappeTable } from "./FrappeTable";
27
+
28
+ beforeAll(async () => {
29
+ await i18next.use(initReactI18next).init({
30
+ lng: "en",
31
+ interpolation: { escapeValue: false },
32
+ resources: { en: { translation: {} } },
33
+ });
34
+ });
35
+
36
+ afterEach(() => cleanup());
37
+
38
+ interface Posting {
39
+ name: string;
40
+ doctype: string;
41
+ date: string;
42
+ payee: string;
43
+ amount: number;
44
+ /** Derived by the accumulator — declared on the doc type so a column can
45
+ * name it in accessorKey. */
46
+ running?: number;
47
+ }
48
+
49
+ const postings: Posting[] = Array.from({ length: 8 }, (_, i) => ({
50
+ name: `POST-${String(i + 1).padStart(2, "0")}`,
51
+ doctype: "Posting",
52
+ date: `2026-02-${String(i + 1).padStart(2, "0")}`,
53
+ payee: `Payee ${i + 1}`,
54
+ amount: 10,
55
+ }));
56
+
57
+ const runningBalance: RowAccumulator<Partial<Posting>, number> = {
58
+ initial: 0,
59
+ reduce: (carried, row) => carried + (row.amount ?? 0),
60
+ derive: (carried) => ({ running: carried }),
61
+ order: (a, b) => String(a.date).localeCompare(String(b.date)),
62
+ };
63
+
64
+ const columns: DataTableColumn<Partial<Posting>>[] = [
65
+ { id: "name", accessorKey: "name", header: "ID" },
66
+ { id: "amount", accessorKey: "amount", header: "Amount" },
67
+ {
68
+ id: "running",
69
+ accessorKey: "running",
70
+ header: "Balance",
71
+ sortable: false,
72
+ // Marked so an assertion can tell a balance of 10 from an amount of 10.
73
+ cell: ({ row }) => `bal ${row.original.running}`,
74
+ },
75
+ ];
76
+
77
+ const filterFields = [{ id: "payee", label: "Payee", type: "text" as const }];
78
+
79
+ describe("FrappeTable rowAccumulator", () => {
80
+ it("folds the rows FrappeTable fetched, and page two continues", async () => {
81
+ const user = userEvent.setup();
82
+ renderWithProviders(
83
+ <FrappeProvider
84
+ baseURL="https://frappetable-fold.spec.test"
85
+ fixtures={new InMemoryFixtureProvider({ Posting: postings })}
86
+ >
87
+ <FrappeTable<Posting>
88
+ doctype="Posting"
89
+ columns={columns}
90
+ fields={["name", "date", "payee", "amount"]}
91
+ filterableFields={filterFields}
92
+ rowAccumulator={runningBalance}
93
+ layout="table"
94
+ initialState={{ pagination: { pageIndex: 0, pageSize: 4 } }}
95
+ />
96
+ </FrappeProvider>,
97
+ );
98
+
99
+ await waitFor(() => expect(screen.getByText("POST-01")).toBeTruthy());
100
+ expect(screen.getByText("bal 10")).toBeTruthy();
101
+ expect(screen.getByText("bal 40")).toBeTruthy();
102
+ expect(screen.queryByText("bal 50")).toBeNull();
103
+
104
+ await user.click(screen.getByLabelText("Go to next page"));
105
+ await waitFor(() => expect(screen.getByText("POST-05")).toBeTruthy());
106
+ expect(screen.getByText("bal 50"), "page two continues the fold").toBeTruthy();
107
+ expect(screen.getByText("bal 80")).toBeTruthy();
108
+ expect(screen.queryByText("bal 10"), "page one's opening balance is gone").toBeNull();
109
+ });
110
+ });
@@ -3,9 +3,7 @@ import {
3
3
  Order,
4
4
  matchesFilters,
5
5
  useDocTypeMeta,
6
- useFrappeCollection,
7
6
  useFrappeDoctypeEvents,
8
- useLiveQuery,
9
7
  } from "@multiplatform.one/frappe";
10
8
  import {
11
9
  DataTable,
@@ -25,12 +23,31 @@ import { FilterManager, SavedFilterDropdown, useSavedFilters } from "@multiplatf
25
23
  import { useFrappeConfig } from "./FrappeProvider";
26
24
  import { FrappeReconnectIndicator } from "./FrappeReconnectIndicator";
27
25
  import { docFieldsToFilterFields } from "./filterFields";
28
- import { toLiveLoadError } from "./liveErrors";
26
+ import { useFrappeRows } from "./useFrappeRows";
29
27
 
30
28
  /**
31
29
  * Props for the FrappeTable component.
32
30
  *
33
- * @typeParam TDoc - The document type with at least name and doctype fields
31
+ * `data` is omitted because FrappeTable fetches its own rows. Everything else
32
+ * on `DataTableProps` passes straight through — including `rowAccumulator`
33
+ * (MPO-250), so a Frappe-bound table CAN carry a folded column (a running
34
+ * balance, a per-row cumulative count) without the caller re-fetching the
35
+ * doctype and hand-assembling a DataTable. Declare the derived field on
36
+ * `TDoc` so a column can name it in `accessorKey`:
37
+ *
38
+ * ```tsx
39
+ * const balance: RowAccumulator<Partial<Posting>, string> = {
40
+ * initial: "0",
41
+ * reduce: (carried, row) => addMoney(carried, row.amount ?? "0"),
42
+ * derive: (carried) => ({ running: carried }),
43
+ * order: (a, b) => compareByDateThenName(a, b),
44
+ * };
45
+ * <FrappeTable<Posting & { running?: string }> doctype="Posting" rowAccumulator={balance} … />
46
+ * ```
47
+ *
48
+ * The fold runs over the rows the table HOLDS, before pagination. In
49
+ * `serverSide` mode that is one page, so a running balance there needs the
50
+ * server to send the figure — the fold cannot invent rows it never got.
34
51
  */
35
52
  export interface FrappeTableProps<TDoc extends { name: string; doctype: string }> extends Omit<
36
53
  DataTableProps<Partial<TDoc>>,
@@ -310,8 +327,10 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
310
327
  const finalAuth = auth ?? config?.auth;
311
328
  const finalSyncOptions = syncOptions ?? config?.syncOptions;
312
329
 
313
- if (!finalBaseURL) {
314
- throw new Error("FrappeTable requires baseURL prop or FrappeProvider with baseURL");
330
+ // A fixture corpus is a complete data source, so it satisfies the same
331
+ // requirement a baseURL does: fixture mode never dials a server.
332
+ if (!finalBaseURL && !config?.fixtures) {
333
+ throw new Error("FrappeTable requires baseURL prop or FrappeProvider with baseURL or fixtures");
315
334
  }
316
335
 
317
336
  // One connection config for the live subscription (client mode), the
@@ -594,32 +613,31 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
594
613
  // Always call the hook — toggling `savedFilters` must not change hook order (SB-M-012).
595
614
  const savedFiltersHook = useSavedFilters({ userId });
596
615
 
597
- // Honest error surface: the collection swallows initial-sync failures
598
- // (renders as empty otherwise); onSyncError turns 403/PermissionError and
599
- // network failures into a visible error state.
600
- const handleSyncError = useCallback(
601
- (err: unknown) => {
602
- setErrorState(
603
- toLiveLoadError(err, {
604
- permissionMessage: t("You do not have permission to view {{doctype}}", { doctype }),
605
- genericMessage: t("Error loading {{doctype}}", { doctype }),
606
- }),
607
- );
608
- },
616
+ // The client/live-collection read is the SHARED one (MPO-251): collection
617
+ // + live query + the honest error surface a bare collection swallows
618
+ // (without onSyncError a 403 or a dead server renders as an empty table).
619
+ // `limit: null` keeps the bench's own page length rather than the hook's
620
+ // default — FrappeTable paginates on the rows it is handed, and moving its
621
+ // row ceiling here would move it for every existing consumer.
622
+ const rowsMessages = useMemo(
623
+ () => ({
624
+ permission: t("You do not have permission to view {{doctype}}", { doctype }),
625
+ generic: t("Error loading {{doctype}}", { doctype }),
626
+ queryFailed: t("Failed to load {{doctype}}", { doctype }),
627
+ }),
609
628
  [doctype, t],
610
629
  );
611
-
612
- const collection = useFrappeCollection<TDoc>(
613
- serverSide ? undefined : connectionConfig,
614
- serverSide ? "" : doctype,
615
- serverSide ? undefined : { fields, filters: activeFilters, onSyncError: handleSyncError },
616
- );
617
630
  const {
618
- data: rawData,
619
- isLoading: isRowsLoading,
620
- isError: isLiveError,
621
- } = useLiveQuery((q) => (collection ? q.from({ _list: collection }) : null), [collection]);
622
- const clientRows = useMemo(() => (rawData as TDoc[] | undefined) ?? [], [rawData]);
631
+ rows: clientRows,
632
+ isQueryLoading: isRowsLoading,
633
+ error: liveError,
634
+ } = useFrappeRows<TDoc>(serverSide ? undefined : connectionConfig, doctype, {
635
+ fields,
636
+ filters: activeFilters,
637
+ limit: null,
638
+ enabled: !serverSide,
639
+ messages: rowsMessages,
640
+ });
623
641
 
624
642
  // Keep-rows-and-reconcile for client/live-collection mode: a filter change
625
643
  // swaps the collection (new subscription), which reports loading from
@@ -661,19 +679,6 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
661
679
  ? !infiniteServerMode && serverLoading && hasLoadedOnce
662
680
  : isRowsLoading && lastGoodClientRows.current !== null;
663
681
 
664
- // Reset stale errors when the underlying collection changes (new doctype
665
- // or filters) so a recovered query doesn't keep showing the old failure.
666
- useEffect(() => {
667
- if (!serverSide) setErrorState(null);
668
- }, [collection, serverSide]);
669
-
670
- // Fallback surface for live-query failures the collection itself reports
671
- // (onSyncError above carries the specific message when available).
672
- useEffect(() => {
673
- if (serverSide || !isLiveError) return;
674
- setErrorState((prev) => prev ?? new Error(t("Failed to load {{doctype}}", { doctype })));
675
- }, [serverSide, isLiveError, doctype, t]);
676
-
677
682
  const handleSelectFilter = (filter: any) => {
678
683
  if (filter) {
679
684
  setActiveFilters(filter.filters);
@@ -697,8 +702,12 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
697
702
  await savedFiltersHook.deleteFilter(name);
698
703
  };
699
704
 
700
- if (errorState && error) {
701
- return <>{error(errorState)}</>;
705
+ // serverSide failures come from the fetch above; client/live failures come
706
+ // from useFrappeRows. Only one path is ever live at a time.
707
+ const resolvedError = serverSide ? errorState : liveError;
708
+
709
+ if (resolvedError && error) {
710
+ return <>{error(resolvedError)}</>;
702
711
  }
703
712
 
704
713
  const rowData = rows ?? [];
@@ -706,8 +715,8 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
706
715
  // Infinite serverSide delegates loading/empty chrome to DataTable.
707
716
  // After the first load, NEVER replace DataTable with empty/loading chrome
708
717
  // while a refetch is in flight — that was the named blank-the-list defect.
709
- const boundaryState = errorState
710
- ? { error: errorState }
718
+ const boundaryState = resolvedError
719
+ ? { error: resolvedError }
711
720
  : isRowsLoadingResolved
712
721
  ? { loading: loading ?? true }
713
722
  : rowData.length === 0 && !infiniteServerMode && !isFetching
@@ -715,7 +724,16 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
715
724
  : null;
716
725
  if (boundaryState) {
717
726
  return (
718
- <YStack {...knobProps.gap} flex={1}>
727
+ <YStack
728
+ {...knobProps.gap}
729
+ // flexBasis auto, not flex={1}: a basis-0 chain resolves to 0 in an
730
+ // auto-height parent and collapses the table to a sliver. Same
731
+ // geometry as DataTableRoot's own root.
732
+ flexGrow={1}
733
+ flexShrink={1}
734
+ flexBasis="auto"
735
+ minHeight={0}
736
+ >
719
737
  <FrappeReconnectIndicator config={connectionConfig} />
720
738
  <AsyncBoundary
721
739
  layout={layout === "list" || layout === "cards" ? "list" : "table"}
@@ -728,7 +746,16 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
728
746
  }
729
747
 
730
748
  return (
731
- <YStack {...knobProps.gap} flex={1}>
749
+ <YStack
750
+ {...knobProps.gap}
751
+ // flexBasis auto, not flex={1}: a basis-0 chain resolves to 0 in an
752
+ // auto-height parent and collapses the table to a sliver. Same
753
+ // geometry as DataTableRoot's own root.
754
+ flexGrow={1}
755
+ flexShrink={1}
756
+ flexBasis="auto"
757
+ minHeight={0}
758
+ >
732
759
  <FrappeReconnectIndicator config={connectionConfig} />
733
760
  {savedFilters && savedFiltersHook && (
734
761
  <XStack {...knobProps.gap} padding="$2">
@@ -75,10 +75,23 @@ function regionMeta(name: string, isTree: boolean) {
75
75
  };
76
76
  }
77
77
 
78
+ /** A chart of accounts: no parent field, no is_tree, the name is the path. */
79
+ function accountMeta(name: string) {
80
+ return {
81
+ name,
82
+ module: "QA",
83
+ title_field: "name",
84
+ is_tree: 0,
85
+ fields: [{ fieldname: "balance", fieldtype: "Currency", label: "Balance", in_list_view: 1 }],
86
+ permissions: [{ role: "All", read: 1 }],
87
+ };
88
+ }
89
+
78
90
  function handleMetaRequest(url: URL): Response | null {
79
91
  const metaMatch = url.pathname.match(/^\/api\/resource\/DocType\/(.+)$/);
80
92
  if (!metaMatch) return null;
81
93
  const name = decodeURIComponent(metaMatch[1]);
94
+ if (name === "QaAccount") return jsonResponse({ data: accountMeta(name) });
82
95
  return jsonResponse({ data: regionMeta(name, name !== "QaFlatDoc") });
83
96
  }
84
97
 
@@ -143,6 +156,52 @@ export const NotATree = () => (
143
156
  </FrappeProvider>
144
157
  );
145
158
 
159
+ interface Account {
160
+ name: string;
161
+ doctype: string;
162
+ balance: string;
163
+ }
164
+
165
+ /**
166
+ * Seven rows, and every one of them is a leaf. "Assets", "Assets:Personal"
167
+ * and "Assets:Personal:Bank" are not documents at all.
168
+ */
169
+ const accountDocs: Account[] = [
170
+ { name: "Assets:Personal:Bank:Checking", doctype: "QaAccount", balance: "4,120.55" },
171
+ { name: "Assets:Personal:Bank:Savings", doctype: "QaAccount", balance: "18,300.00" },
172
+ { name: "Assets:Personal:Cash", doctype: "QaAccount", balance: "260.00" },
173
+ { name: "Expenses:Groceries", doctype: "QaAccount", balance: "612.40" },
174
+ { name: "Expenses:Utilities:Power", doctype: "QaAccount", balance: "148.90" },
175
+ { name: "Income:Salary", doctype: "QaAccount", balance: "9,000.00" },
176
+ { name: "Liabilities:Credit Card", doctype: "QaAccount", balance: "-732.10" },
177
+ ];
178
+
179
+ /** Colon-path doctype: is_tree is 0, there is no parent field, tree renders. */
180
+ export const ColonPath = () => (
181
+ <FrappeProvider
182
+ baseURL={MOCK_HOST}
183
+ fixtures={new InMemoryFixtureProvider({ QaAccount: accountDocs })}
184
+ >
185
+ <FrappeTreeView
186
+ doctype="QaAccount"
187
+ pathSeparator=":"
188
+ pathField="name"
189
+ valueField="balance"
190
+ expandByDefault
191
+ onNodeClick={action("onNodeClick")}
192
+ onPathSelect={action("onPathSelect")}
193
+ />
194
+ </FrappeProvider>
195
+ );
196
+ ColonPath.parameters = {
197
+ docs: {
198
+ description: {
199
+ story:
200
+ "The account IS its path (Assets:Personal:Bank:Checking). Meta reports is_tree 0 and the doctype has no parent field, so the parent-field path would paint the unsupported state instead. pathSeparator synthesises the branches client-side from each row's own key. A synthesised branch carries no document: clicking it fires onPathSelect with the path and no doc, and onNodeClick stays silent. The balances hang off the leaves, which are the only real rows.",
201
+ },
202
+ },
203
+ };
204
+
146
205
  /** Tree doctype with zero root nodes: empty message. */
147
206
  export const EmptyTree = () => (
148
207
  <FrappeProvider baseURL={MOCK_HOST} fixtures={new InMemoryFixtureProvider({ QaRegionEmpty: [] })}>