@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
@@ -191,7 +191,7 @@ export function FormSidebar({
191
191
  aria-label={resolvedImageLabel}
192
192
  >
193
193
  <ImageSquareIcon size={iconSize * 2} color={placeholderIconColor} />
194
- <Text color={componentColors.text.muted} {...knobProps.label}>
194
+ <Text color={knobProps.textAccentColor} {...knobProps.label}>
195
195
  {t("Image failed to load")}
196
196
  </Text>
197
197
  </YStack>
@@ -213,7 +213,7 @@ export function FormSidebar({
213
213
  borderColor="$borderColor"
214
214
  >
215
215
  <ImageSquareIcon size={iconSize * 2} color={placeholderIconColor} />
216
- <Text color={componentColors.text.muted} {...knobProps.label}>
216
+ <Text color={knobProps.textAccentColor} {...knobProps.label}>
217
217
  {t("Add image")}
218
218
  </Text>
219
219
  </YStack>
@@ -257,7 +257,7 @@ export function FormSidebar({
257
257
  <XStack alignItems="center" justifyContent="space-between">
258
258
  <XStack alignItems="center" gap="$2">
259
259
  {section.icon}
260
- <Text color={componentColors.text.muted} {...knobProps.label} fontWeight="400">
260
+ <Text color={knobProps.textAccentColor} {...knobProps.label} fontWeight="400">
261
261
  {section.title}
262
262
  </Text>
263
263
  </XStack>
@@ -297,7 +297,7 @@ export function FormSidebar({
297
297
  {item.label}
298
298
  </Text>
299
299
  {item.sublabel && (
300
- <Text color={componentColors.text.muted} {...knobProps.label}>
300
+ <Text color={knobProps.textAccentColor} {...knobProps.label}>
301
301
  {item.sublabel}
302
302
  </Text>
303
303
  )}
@@ -316,7 +316,7 @@ export function FormSidebar({
316
316
  ))}
317
317
  </YStack>
318
318
  ) : (
319
- <Text color={componentColors.text.muted} {...knobProps.label}>
319
+ <Text color={knobProps.textAccentColor} {...knobProps.label}>
320
320
  {section.emptyText ?? t("None")}
321
321
  </Text>
322
322
  )}
@@ -333,7 +333,7 @@ export function FormSidebar({
333
333
  {metadata.length > 0 && (
334
334
  <YStack gap="$1">
335
335
  <Text
336
- color={componentColors.text.muted}
336
+ color={knobProps.textAccentColor}
337
337
  paddingHorizontal="$2"
338
338
  {...knobProps.label}
339
339
  fontWeight="400"
@@ -354,7 +354,7 @@ export function FormSidebar({
354
354
  )) as any
355
355
  }
356
356
  title={
357
- <Text color={componentColors.text.muted} {...knobProps.label}>
357
+ <Text color={knobProps.textAccentColor} {...knobProps.label}>
358
358
  {entry.label}
359
359
  </Text>
360
360
  }
@@ -1,4 +1,3 @@
1
- import { useFrappeCollection, useLiveQuery } from "@multiplatform.one/frappe";
2
1
  import {
3
2
  Calendar,
4
3
  eventChipTextColor,
@@ -18,6 +17,7 @@ import {
18
17
  import { FrappeConnectionIndicator } from "./FrappeConnectionIndicator";
19
18
  import { useFrappeConfig } from "./FrappeProvider";
20
19
  import { describeSyncError } from "./syncError";
20
+ import { useFrappeRows } from "./useFrappeRows";
21
21
  import { resolveFrappeEventColor } from "./frappeEventColor";
22
22
 
23
23
  export type CalendarViewType = "month" | "week" | "day";
@@ -111,9 +111,6 @@ export function FrappeCalendar<TDoc extends { name: string; doctype: string }>({
111
111
  const { knobProps } = useResolvedKnobs();
112
112
  const { t } = useTranslation();
113
113
  const [actionError, setActionError] = useState<Error | null>(null);
114
- // Honest error state: the collection swallows failed subscription fetches
115
- // (calendar would just look empty) — onSyncError reports them here.
116
- const [syncError, setSyncError] = useState<unknown>(null);
117
114
  const height =
118
115
  heightProp ?? (knobProps.sizeToken === "$3" ? 480 : knobProps.sizeToken === "$5" ? 720 : 600);
119
116
 
@@ -121,8 +118,10 @@ export function FrappeCalendar<TDoc extends { name: string; doctype: string }>({
121
118
  const finalAuth = auth ?? config?.auth;
122
119
  const finalSyncOptions = syncOptions ?? config?.syncOptions;
123
120
 
124
- if (!finalBaseURL) {
125
- throw new Error("FrappeCalendar requires baseURL prop or FrappeProvider with baseURL");
121
+ if (!finalBaseURL && !config?.fixtures) {
122
+ throw new Error(
123
+ "FrappeCalendar requires baseURL prop or FrappeProvider with baseURL or fixtures",
124
+ );
126
125
  }
127
126
 
128
127
  // Ensure required fields are fetched
@@ -163,25 +162,29 @@ export function FrappeCalendar<TDoc extends { name: string; doctype: string }>({
163
162
  ],
164
163
  );
165
164
 
166
- const collection = useFrappeCollection<TDoc>(connectionConfig, doctype, {
165
+ // The shared doctype read (MPO-251). `mapError` keeps this calendar's own
166
+ // error copy (describeSyncError); real subscription failures still win over
167
+ // the generic isError flag inside the hook, because they carry an
168
+ // actionable message. `limit: null` keeps the bench's own page length.
169
+ const mapSyncError = useCallback(
170
+ (err: unknown) => new Error(describeSyncError(err, doctype, t)),
171
+ [doctype, t],
172
+ );
173
+ const {
174
+ rows: docs,
175
+ isQueryLoading: isLoading,
176
+ error: queryError,
177
+ collection,
178
+ } = useFrappeRows<TDoc>(connectionConfig, doctype, {
167
179
  fields: effectiveFields,
168
180
  filters,
169
- onSyncError: setSyncError,
181
+ limit: null,
182
+ mapError: mapSyncError,
183
+ messages: {
184
+ permission: t("You do not have permission to view {{doctype}}", { doctype }),
185
+ generic: t("Failed to load {{doctype}} events", { doctype }),
186
+ },
170
187
  });
171
- const {
172
- data: rawData,
173
- isLoading,
174
- isError,
175
- } = useLiveQuery((q) => (collection ? q.from({ _list: collection }) : null), [collection]);
176
- const docs = useMemo(() => (rawData as TDoc[] | undefined) ?? [], [rawData]);
177
- // Real subscription failures (permission-error, network, bad doctype) win
178
- // over the generic isError flag — they carry an actionable message.
179
- const queryError =
180
- syncError != null
181
- ? new Error(describeSyncError(syncError, doctype, t))
182
- : isError
183
- ? new Error(t("Failed to load {{doctype}} events", { doctype }))
184
- : null;
185
188
 
186
189
  // Scheme-aware palette for resolving NAMED doc colors (P-15): Frappe's
187
190
  // palette references ("blue", "Red") map to sanctioned solids per scheme;
@@ -0,0 +1,179 @@
1
+ /**
2
+ * MPO-287: a `dataSource` with no data source in scope is a misconfiguration,
3
+ * not static mode — the same defect MPO-237 fixed one component over. The
4
+ * card asked for a computed series and there is nowhere to compute it, so
5
+ * `config.data` must never be painted as the series: a plausible shape
6
+ * presented confidently is worse than a visible gap, because nothing
7
+ * downstream can tell it was never computed.
8
+ *
9
+ * Static mode (no `dataSource` at all) is the documented, intended path and
10
+ * is asserted here too, so the fix cannot over-correct into it. A fixture
11
+ * corpus is a data source (MPO-228), so it stands in for a baseURL and must
12
+ * not trip the guard.
13
+ *
14
+ * The chart body itself is not assertable here: ChartSurface measures its
15
+ * own width through `onLayout`, which never fires in happy-dom, so no SVG
16
+ * reaches the DOM. Two things stand in. The card's plain title renders only
17
+ * when a series reached `ChartCard` — the skeleton, the empty surface and
18
+ * the not-configured surface each carry different text. And `formatLabel`
19
+ * is called once per computed group, so spying on it proves whether the
20
+ * aggregate ran at all.
21
+ */
22
+
23
+ import { InMemoryFixtureProvider } from "@multiplatform.one/frappe";
24
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
25
+ import { cleanup, screen, waitFor } from "@testing-library/react";
26
+ import i18next from "i18next";
27
+ import { initReactI18next } from "react-i18next";
28
+ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
29
+ import { FrappeChartCard } from "./FrappeChartCard";
30
+ import { FrappeProvider } from "./FrappeProvider";
31
+ import { __resetFrappeDevWarnSeen } from "./shared/devWarn";
32
+
33
+ beforeAll(async () => {
34
+ await i18next.use(initReactI18next).init({
35
+ lng: "en",
36
+ interpolation: { escapeValue: false },
37
+ resources: { en: { translation: {} } },
38
+ });
39
+ });
40
+
41
+ beforeEach(() => {
42
+ __resetFrappeDevWarnSeen();
43
+ });
44
+
45
+ afterEach(() => {
46
+ cleanup();
47
+ vi.restoreAllMocks();
48
+ });
49
+
50
+ const config = {
51
+ id: "todo-by-status",
52
+ title: "ToDos by Status",
53
+ type: "bar" as const,
54
+ data: [
55
+ { label: "Open", value: 41 },
56
+ { label: "Closed", value: 7 },
57
+ ],
58
+ };
59
+
60
+ const dataSource = { doctype: "ToDo", groupBy: "status" };
61
+
62
+ const todos = [
63
+ { name: "TD-1", doctype: "ToDo", status: "Open" },
64
+ { name: "TD-2", doctype: "ToDo", status: "Open" },
65
+ { name: "TD-3", doctype: "ToDo", status: "Closed" },
66
+ ];
67
+
68
+ describe("FrappeChartCard with a dataSource and no baseURL (MPO-287)", () => {
69
+ it("does not render config.data as though it were the computed series", () => {
70
+ vi.spyOn(console, "warn").mockImplementation(() => {});
71
+ renderWithProviders(<FrappeChartCard config={config} dataSource={dataSource} />);
72
+
73
+ expect(screen.queryByText("ToDos by Status")).toBeNull();
74
+ expect(screen.getByText("ToDos by Status is not configured")).toBeInTheDocument();
75
+ expect(screen.getByText(/no Frappe baseURL is in scope/)).toBeInTheDocument();
76
+ });
77
+
78
+ it("logs a development warning naming the missing baseURL", () => {
79
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
80
+ renderWithProviders(<FrappeChartCard config={config} dataSource={dataSource} />);
81
+
82
+ const line = warn.mock.calls.map((call) => String(call[0])).join("\n");
83
+ expect(line).toContain("[frappe-ui] chart-datasource-without-baseurl");
84
+ expect(line).toContain("baseURL");
85
+ expect(line).toContain("component=FrappeChartCard");
86
+ expect(line).toContain("id=todo-by-status");
87
+ expect(line).toContain("doctype=ToDo");
88
+ });
89
+
90
+ it("warns once per card, not once per render", () => {
91
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
92
+ const { rerender } = renderWithProviders(
93
+ <FrappeChartCard config={config} dataSource={dataSource} />,
94
+ );
95
+ rerender(<FrappeChartCard config={{ ...config }} dataSource={dataSource} />);
96
+ rerender(<FrappeChartCard config={{ ...config }} dataSource={dataSource} />);
97
+
98
+ const lines = warn.mock.calls.filter((call) =>
99
+ String(call[0]).includes("chart-datasource-without-baseurl"),
100
+ );
101
+ expect(lines).toHaveLength(1);
102
+ });
103
+
104
+ it("stays silent in production", () => {
105
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
106
+ const previous = process.env.NODE_ENV;
107
+ process.env.NODE_ENV = "production";
108
+ try {
109
+ renderWithProviders(<FrappeChartCard config={config} dataSource={dataSource} />);
110
+ } finally {
111
+ process.env.NODE_ENV = previous;
112
+ }
113
+
114
+ expect(
115
+ warn.mock.calls.filter((call) =>
116
+ String(call[0]).includes("chart-datasource-without-baseurl"),
117
+ ),
118
+ ).toHaveLength(0);
119
+ });
120
+ });
121
+
122
+ describe("FrappeChartCard configured paths stay untouched (MPO-287)", () => {
123
+ it("renders config.data with no warning when no dataSource is set", () => {
124
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
125
+ renderWithProviders(<FrappeChartCard config={config} />);
126
+
127
+ expect(screen.getByText("ToDos by Status")).toBeInTheDocument();
128
+ expect(screen.queryByText("ToDos by Status is not configured")).toBeNull();
129
+ expect(
130
+ warn.mock.calls.filter((call) =>
131
+ String(call[0]).includes("chart-datasource-without-baseurl"),
132
+ ),
133
+ ).toHaveLength(0);
134
+ });
135
+
136
+ it("computes the series, and does not warn, when the provider supplies a baseURL", async () => {
137
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
138
+ const formatLabel = vi.fn((label: string) => label);
139
+ renderWithProviders(
140
+ <FrappeProvider baseURL="http://test" fixtures={new InMemoryFixtureProvider({ ToDo: todos })}>
141
+ <FrappeChartCard config={config} dataSource={{ ...dataSource, formatLabel }} />
142
+ </FrappeProvider>,
143
+ );
144
+
145
+ await waitFor(() => expect(screen.getByText("ToDos by Status")).toBeInTheDocument());
146
+ expect([...new Set(formatLabel.mock.calls.map((call) => call[0]))].sort()).toEqual([
147
+ "Closed",
148
+ "Open",
149
+ ]);
150
+ expect(screen.queryByText("ToDos by Status is not configured")).toBeNull();
151
+ expect(
152
+ warn.mock.calls.filter((call) =>
153
+ String(call[0]).includes("chart-datasource-without-baseurl"),
154
+ ),
155
+ ).toHaveLength(0);
156
+ });
157
+
158
+ it("treats a fixture corpus as the data source when no baseURL is set (MPO-228)", async () => {
159
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
160
+ const formatLabel = vi.fn((label: string) => label);
161
+ renderWithProviders(
162
+ <FrappeProvider fixtures={new InMemoryFixtureProvider({ ToDo: todos })}>
163
+ <FrappeChartCard config={config} dataSource={{ ...dataSource, formatLabel }} />
164
+ </FrappeProvider>,
165
+ );
166
+
167
+ await waitFor(() => expect(screen.getByText("ToDos by Status")).toBeInTheDocument());
168
+ expect([...new Set(formatLabel.mock.calls.map((call) => call[0]))].sort()).toEqual([
169
+ "Closed",
170
+ "Open",
171
+ ]);
172
+ expect(screen.queryByText("ToDos by Status is not configured")).toBeNull();
173
+ expect(
174
+ warn.mock.calls.filter((call) =>
175
+ String(call[0]).includes("chart-datasource-without-baseurl"),
176
+ ),
177
+ ).toHaveLength(0);
178
+ });
179
+ });
@@ -15,6 +15,14 @@
15
15
  * (permission failures called out), catalog empty state when the aggregate
16
16
  * returns no groups, and a subtle stale dim while a post-event refetch is
17
17
  * in flight.
18
+ *
19
+ * A `dataSource` with no data source in scope — no `baseURL` from the prop
20
+ * or a FrappeProvider, and no fixture corpus either — is a misconfiguration,
21
+ * not static mode: the caller asked for a computed series and there is
22
+ * nowhere to compute it. The card renders the not-configured surface and
23
+ * warns in dev. It never falls back to `config.data`, which would present
24
+ * an uncomputed shape as the series. A fixture corpus answers every read
25
+ * locally, so it stands in for a baseURL (MPO-228).
18
26
  */
19
27
  import {
20
28
  AsyncBoundary,
@@ -23,12 +31,13 @@ import {
23
31
  type ChartCardProps,
24
32
  type ChartConfig,
25
33
  } from "@multiplatform.one/components";
26
- import React, { useMemo } from "react";
34
+ import React, { useEffect, useMemo } from "react";
27
35
  import { useTranslation } from "react-i18next";
28
36
  import { YStack, type YStackProps } from "tamagui";
29
37
  import { useResolvedKnobs } from "@multiplatform.one/theme";
30
38
  import { ChartCard } from "./ChartCard";
31
39
  import { useFrappeConfig } from "./FrappeProvider";
40
+ import { frappeDevWarn } from "./shared/devWarn";
32
41
  import {
33
42
  useFrappeAggregate,
34
43
  type FrappeAggregateConnection,
@@ -52,10 +61,18 @@ export interface FrappeChartDataSource {
52
61
  }
53
62
 
54
63
  export interface FrappeChartCardProps extends Omit<ChartCardProps, "config"> {
55
- /** Chart chrome (title, type, height…). In live mode `data` is overridden. */
64
+ /**
65
+ * Chart chrome (title, type, height…). In live mode `data` is overridden.
66
+ * With a `dataSource` and no data source in scope, `data` is not rendered
67
+ * at all.
68
+ */
56
69
  config: Omit<ChartConfig, "data"> & { data?: ChartConfig["data"] };
57
70
  /** When set, the chart series goes live against this doctype. */
58
71
  dataSource?: FrappeChartDataSource;
72
+ /**
73
+ * Falls back to the FrappeProvider's. Required whenever `dataSource` is
74
+ * set, unless the provider carries a fixture corpus.
75
+ */
59
76
  baseURL?: string;
60
77
  auth?: { useToken?: boolean; token?: string; type?: string };
61
78
  syncOptions?: unknown;
@@ -94,8 +111,9 @@ export function FrappeChartCard({
94
111
  const { t } = useTranslation();
95
112
 
96
113
  const finalBaseURL = baseURL ?? providerConfig?.baseURL;
114
+ const fixtures = providerConfig?.fixtures;
97
115
  const connection: FrappeAggregateConnection | undefined =
98
- dataSource && finalBaseURL
116
+ dataSource && (finalBaseURL || fixtures)
99
117
  ? {
100
118
  baseURL: finalBaseURL,
101
119
  socketPort: providerConfig?.socketPort,
@@ -104,10 +122,22 @@ export function FrappeChartCard({
104
122
  auth: auth ?? providerConfig?.auth,
105
123
  syncOptions: syncOptions ?? providerConfig?.syncOptions,
106
124
  realtime: providerConfig?.realtime,
107
- fixtures: providerConfig?.fixtures,
125
+ fixtures,
108
126
  }
109
127
  : undefined;
110
128
 
129
+ const missingConnection = !!dataSource && !connection;
130
+ const doctype = dataSource?.doctype;
131
+ useEffect(() => {
132
+ if (!missingConnection) return;
133
+ frappeDevWarn("chart-datasource-without-baseurl", {
134
+ component: "FrappeChartCard",
135
+ id: config.id,
136
+ doctype,
137
+ suggest: "set baseURL on FrappeChartCard or on the FrappeProvider above it",
138
+ });
139
+ }, [missingConnection, config.id, doctype]);
140
+
111
141
  const { groups, isLoading, isStale, error, isPermissionError } = useFrappeAggregate(connection, {
112
142
  doctype: dataSource?.doctype ?? "",
113
143
  aggregate: dataSource?.aggregate,
@@ -128,11 +158,30 @@ export function FrappeChartCard({
128
158
  return { ...config, data } as ChartConfig;
129
159
  }, [config, dataSource, groups]);
130
160
 
131
- // Static passthrough — sanitizing bridge, palette untouched.
132
- if (!dataSource || !connection) {
161
+ // Static passthrough — sanitizing bridge, palette untouched. The caller
162
+ // supplied the series and asked for no computation.
163
+ if (!dataSource) {
133
164
  return <ChartCard config={liveConfig} {...chartCardProps} />;
134
165
  }
135
166
 
167
+ // A requested series with nowhere to compute it. `config.data` is the
168
+ // caller's placeholder, so drawing it here would publish a shape nothing
169
+ // downstream could tell was never computed.
170
+ if (!connection) {
171
+ return (
172
+ <AsyncBoundary
173
+ compact
174
+ error
175
+ errorTitle={t("{{title}} is not configured", { title: config.title })}
176
+ errorDescription={t(
177
+ "This chart reads {{doctype}} live, but no Frappe baseURL is in scope, so the series was never computed.",
178
+ { doctype: dataSource.doctype },
179
+ )}
180
+ {...(chartCardProps as YStackProps)}
181
+ />
182
+ );
183
+ }
184
+
136
185
  if (isLoading) {
137
186
  return (
138
187
  <ChartCardSkeleton
@@ -171,11 +171,15 @@ export interface AssignmentTodoRow {
171
171
  reference_name?: string;
172
172
  }
173
173
 
174
- /** Resolves a Frappe file field value (e.g. `/files/x.png`) to a full URL. */
175
- export function resolveFileUrl(value: unknown, baseURL: string): string | undefined {
174
+ /**
175
+ * Resolves a Frappe file field value (e.g. `/files/x.png`) to a full URL.
176
+ * A site-relative path needs a server to hang off, so it resolves to nothing
177
+ * on a fixtures-only host (no baseURL); absolute URLs still pass through.
178
+ */
179
+ export function resolveFileUrl(value: unknown, baseURL: string | undefined): string | undefined {
176
180
  if (!value || typeof value !== "string") return undefined;
177
181
  if (value.startsWith("http://") || value.startsWith("https://")) return value;
178
- if (value.startsWith("/")) return `${baseURL.replace(/\/$/, "")}${value}`;
182
+ if (value.startsWith("/")) return baseURL ? `${baseURL.replace(/\/$/, "")}${value}` : undefined;
179
183
  return value;
180
184
  }
181
185
 
@@ -1,14 +1,13 @@
1
- import { useFrappeCollection, useLiveQuery } from "@multiplatform.one/frappe";
2
1
  import {
2
+ Alert,
3
3
  GanttView,
4
4
  type GanttItemMoveRange,
5
5
  type GanttTask,
6
6
  type GanttZoom,
7
7
  } from "@multiplatform.one/components";
8
8
  import React, { useCallback, useMemo, useState, type ReactNode } from "react";
9
- import { Text, YStack, type YStackProps } from "tamagui";
9
+ import { YStack, type YStackProps } from "tamagui";
10
10
  import { useTranslation } from "react-i18next";
11
- import { formCommonColors } from "@multiplatform.one/forms";
12
11
  import {
13
12
  formatCalendarDate,
14
13
  parseCalendarDate,
@@ -18,6 +17,7 @@ import {
18
17
  import { FrappeConnectionIndicator } from "./FrappeConnectionIndicator";
19
18
  import { useFrappeConfig } from "./FrappeProvider";
20
19
  import { describeSyncError } from "./syncError";
20
+ import { useFrappeRows } from "./useFrappeRows";
21
21
  import { resolveFrappeEventColor } from "./frappeEventColor";
22
22
 
23
23
  export interface FrappeGanttProps<TDoc extends { name: string; doctype: string }> extends Omit<
@@ -113,16 +113,13 @@ export function FrappeGantt<TDoc extends { name: string; doctype: string }>({
113
113
  const { knobProps } = useResolvedKnobs();
114
114
  const { t } = useTranslation();
115
115
  const [actionError, setActionError] = useState<Error | null>(null);
116
- // Honest error state: the collection swallows failed subscription fetches
117
- // (the chart would just look empty) — onSyncError reports them here.
118
- const [syncError, setSyncError] = useState<unknown>(null);
119
116
 
120
117
  const finalBaseURL = baseURL ?? config?.baseURL;
121
118
  const finalAuth = auth ?? config?.auth;
122
119
  const finalSyncOptions = syncOptions ?? config?.syncOptions;
123
120
 
124
- if (!finalBaseURL) {
125
- throw new Error("FrappeGantt requires baseURL prop or FrappeProvider with baseURL");
121
+ if (!finalBaseURL && !config?.fixtures) {
122
+ throw new Error("FrappeGantt requires baseURL prop or FrappeProvider with baseURL or fixtures");
126
123
  }
127
124
 
128
125
  // Ensure required fields are fetched
@@ -162,25 +159,29 @@ export function FrappeGantt<TDoc extends { name: string; doctype: string }>({
162
159
  ],
163
160
  );
164
161
 
165
- const collection = useFrappeCollection<TDoc>(connectionConfig, doctype, {
162
+ // The shared doctype read (MPO-251). `mapError` keeps this chart's own
163
+ // error copy (describeSyncError); real subscription failures still win over
164
+ // the generic isError flag inside the hook, because they carry an
165
+ // actionable message. `limit: null` keeps the bench's own page length.
166
+ const mapSyncError = useCallback(
167
+ (err: unknown) => new Error(describeSyncError(err, doctype, t)),
168
+ [doctype, t],
169
+ );
170
+ const {
171
+ rows: docs,
172
+ isQueryLoading: isLoading,
173
+ error: queryError,
174
+ collection,
175
+ } = useFrappeRows<TDoc>(connectionConfig, doctype, {
166
176
  fields: effectiveFields,
167
177
  filters,
168
- onSyncError: setSyncError,
178
+ limit: null,
179
+ mapError: mapSyncError,
180
+ messages: {
181
+ permission: t("You do not have permission to view {{doctype}}", { doctype }),
182
+ generic: t("Failed to load {{doctype}} tasks", { doctype }),
183
+ },
169
184
  });
170
- const {
171
- data: rawData,
172
- isLoading,
173
- isError,
174
- } = useLiveQuery((q) => (collection ? q.from({ _list: collection }) : null), [collection]);
175
- const docs = useMemo(() => (rawData as TDoc[] | undefined) ?? [], [rawData]);
176
- // Real subscription failures (permission-error, network, bad doctype) win
177
- // over the generic isError flag — they carry an actionable message.
178
- const queryError =
179
- syncError !== null && syncError !== undefined
180
- ? new Error(describeSyncError(syncError, doctype, t))
181
- : isError
182
- ? new Error(t("Failed to load {{doctype}} tasks", { doctype }))
183
- : null;
184
185
 
185
186
  // Scheme-aware palette for resolving NAMED doc colors (P-15 / LC-27):
186
187
  // Frappe's palette references ("blue", "Red") map to sanctioned solids per
@@ -255,23 +256,12 @@ export function FrappeGantt<TDoc extends { name: string; doctype: string }>({
255
256
  <YStack {...knobProps.gap}>
256
257
  <FrappeConnectionIndicator config={connectionConfig} />
257
258
  {actionError ? (
258
- <YStack
259
- {...knobProps.panelPadding}
260
- {...knobProps.borderRadius}
261
- backgroundColor="$red2"
262
- borderColor="$red7"
263
- borderWidth={1}
264
- >
265
- <Text color={formCommonColors.error} {...knobProps.label}>
266
- {t("Action failed")}
267
- </Text>
268
- <Text color={formCommonColors.muted} {...knobProps.label}>
269
- {actionError.message}
270
- </Text>
271
- </YStack>
259
+ <Alert intent="error" title={t("Action failed")}>
260
+ {actionError.message}
261
+ </Alert>
272
262
  ) : null}
273
263
  <GanttView
274
- {...knobProps.borderRadius}
264
+ {...knobProps.containerRadius}
275
265
  tasks={tasks}
276
266
  zoom={zoom}
277
267
  isLoading={isLoading}
@@ -4,7 +4,7 @@ import { ImageSquareIcon } from "@phosphor-icons/react";
4
4
  import React, { useMemo } from "react";
5
5
  import { useTranslation } from "react-i18next";
6
6
  import { Spinner, formCommonColors } from "@multiplatform.one/forms";
7
- import { Image, Text, YStack, type YStackProps } from "tamagui";
7
+ import { Image, Text, YStack, useTheme, type YStackProps } from "tamagui";
8
8
  import { isServer } from "@multiplatform.one/platform";
9
9
  import { useResolvedKnobs } from "@multiplatform.one/theme";
10
10
  import { useFrappeConfig } from "./FrappeProvider";
@@ -167,6 +167,7 @@ function FrappeImageViewClient<TDoc extends { name: string; doctype: string }>({
167
167
  syncOptions,
168
168
  ...stackProps
169
169
  }: FrappeImageViewProps<TDoc>) {
170
+ const theme = useTheme();
170
171
  const config = useFrappeConfig();
171
172
  const { knobProps } = useResolvedKnobs();
172
173
  const { t } = useTranslation();
@@ -273,7 +274,7 @@ function FrappeImageViewClient<TDoc extends { name: string; doctype: string }>({
273
274
  const iconSize = Number(knobProps.controlIcon?.width) || 16;
274
275
  return (
275
276
  <YStack {...knobProps.panelPadding} alignItems="center" {...knobProps.gap} {...stackProps}>
276
- <ImageSquareIcon size={iconSize * 2} color={formCommonColors.muted} />
277
+ <ImageSquareIcon size={iconSize * 2} color={theme.color11?.val ?? "currentColor"} />
277
278
  <Text color={formCommonColors.muted} {...knobProps.body}>
278
279
  {t("No image field configured for {{doctype}}", { doctype })}
279
280
  </Text>
@@ -332,6 +333,7 @@ function FrappeImageCard({
332
333
  onItemClick?: (doc: Partial<unknown>) => void;
333
334
  knobProps: ReturnType<typeof useResolvedKnobs>["knobProps"];
334
335
  }) {
336
+ const theme = useTheme();
335
337
  const imageUrl = getImageUrl(doc[imageField], baseURL);
336
338
  const title = doc[titleField] || doc.name;
337
339
  const subtitle = subtitleField ? doc[subtitleField] : undefined;
@@ -371,7 +373,7 @@ function FrappeImageCard({
371
373
  alignItems="center"
372
374
  justifyContent="center"
373
375
  >
374
- <ImageSquareIcon size={iconSize * 2} color={formCommonColors.muted} />
376
+ <ImageSquareIcon size={iconSize * 2} color={theme.color11?.val ?? "currentColor"} />
375
377
  </YStack>
376
378
  )}
377
379
  <Card.Footer>