@multiplatform.one/backoffice 6.4.0 → 6.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. package/dist/cjs/chrome/CommandPalette.cjs +20 -9
  2. package/dist/cjs/chrome/CommandPalette.native.js +18 -10
  3. package/dist/cjs/chrome/CommandPalette.native.js.map +1 -1
  4. package/dist/cjs/i18n/en.cjs +21 -0
  5. package/dist/cjs/i18n/en.native.js +21 -0
  6. package/dist/cjs/i18n/en.native.js.map +1 -1
  7. package/dist/cjs/index.cjs +49 -1
  8. package/dist/cjs/index.native.js +48 -0
  9. package/dist/cjs/index.native.js.map +1 -1
  10. package/dist/cjs/shared/types.cjs +18 -0
  11. package/dist/cjs/shared/types.native.js +21 -0
  12. package/dist/cjs/shared/types.native.js.map +1 -0
  13. package/dist/cjs/shared/useDocinfo.cjs +116 -0
  14. package/dist/cjs/shared/useDocinfo.native.js +167 -0
  15. package/dist/cjs/shared/useDocinfo.native.js.map +1 -0
  16. package/dist/cjs/shared/useDoctypeMeta.cjs +124 -0
  17. package/dist/cjs/shared/useDoctypeMeta.native.js +158 -0
  18. package/dist/cjs/shared/useDoctypeMeta.native.js.map +1 -0
  19. package/dist/cjs/shared/useRecentVisit.cjs +40 -0
  20. package/dist/cjs/shared/useRecentVisit.native.js +43 -0
  21. package/dist/cjs/shared/useRecentVisit.native.js.map +1 -0
  22. package/dist/cjs/shared/useSessionUserId.cjs +54 -0
  23. package/dist/cjs/shared/useSessionUserId.native.js +59 -0
  24. package/dist/cjs/shared/useSessionUserId.native.js.map +1 -0
  25. package/dist/cjs/shared/useSlugTarget.cjs +138 -0
  26. package/dist/cjs/shared/useSlugTarget.native.js +166 -0
  27. package/dist/cjs/shared/useSlugTarget.native.js.map +1 -0
  28. package/dist/cjs/shared/useUserRoles.cjs +72 -0
  29. package/dist/cjs/shared/useUserRoles.native.js +79 -0
  30. package/dist/cjs/shared/useUserRoles.native.js.map +1 -0
  31. package/dist/cjs/workspace/WorkspaceChartBlock.cjs +136 -0
  32. package/dist/cjs/workspace/WorkspaceChartBlock.native.js +144 -0
  33. package/dist/cjs/workspace/WorkspaceChartBlock.native.js.map +1 -0
  34. package/dist/cjs/workspace/WorkspaceGrid.cjs +91 -0
  35. package/dist/cjs/workspace/WorkspaceGrid.native.js +126 -0
  36. package/dist/cjs/workspace/WorkspaceGrid.native.js.map +1 -0
  37. package/dist/cjs/workspace/WorkspaceLinkCard.cjs +139 -0
  38. package/dist/cjs/workspace/WorkspaceLinkCard.native.js +155 -0
  39. package/dist/cjs/workspace/WorkspaceLinkCard.native.js.map +1 -0
  40. package/dist/cjs/workspace/WorkspaceLinkDirectory.cjs +110 -0
  41. package/dist/cjs/workspace/WorkspaceLinkDirectory.native.js +127 -0
  42. package/dist/cjs/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
  43. package/dist/cjs/workspace/WorkspaceNumberCard.cjs +133 -0
  44. package/dist/cjs/workspace/WorkspaceNumberCard.native.js +138 -0
  45. package/dist/cjs/workspace/WorkspaceNumberCard.native.js.map +1 -0
  46. package/dist/cjs/workspace/WorkspaceQuickList.cjs +112 -0
  47. package/dist/cjs/workspace/WorkspaceQuickList.native.js +130 -0
  48. package/dist/cjs/workspace/WorkspaceQuickList.native.js.map +1 -0
  49. package/dist/cjs/workspace/WorkspaceRecents.cjs +116 -0
  50. package/dist/cjs/workspace/WorkspaceRecents.native.js +132 -0
  51. package/dist/cjs/workspace/WorkspaceRecents.native.js.map +1 -0
  52. package/dist/cjs/workspace/WorkspaceScreen.cjs +291 -0
  53. package/dist/cjs/workspace/WorkspaceScreen.native.js +323 -0
  54. package/dist/cjs/workspace/WorkspaceScreen.native.js.map +1 -0
  55. package/dist/cjs/workspace/WorkspaceShortcut.cjs +185 -0
  56. package/dist/cjs/workspace/WorkspaceShortcut.native.js +202 -0
  57. package/dist/cjs/workspace/WorkspaceShortcut.native.js.map +1 -0
  58. package/dist/cjs/workspace/parseContent.cjs +180 -0
  59. package/dist/cjs/workspace/parseContent.native.js +299 -0
  60. package/dist/cjs/workspace/parseContent.native.js.map +1 -0
  61. package/dist/cjs/workspace/types.cjs +18 -0
  62. package/dist/cjs/workspace/types.native.js +21 -0
  63. package/dist/cjs/workspace/types.native.js.map +1 -0
  64. package/dist/cjs/workspace/useDashboardChart.cjs +96 -0
  65. package/dist/cjs/workspace/useDashboardChart.native.js +110 -0
  66. package/dist/cjs/workspace/useDashboardChart.native.js.map +1 -0
  67. package/dist/cjs/workspace/useWorkspaceDoc.cjs +103 -0
  68. package/dist/cjs/workspace/useWorkspaceDoc.native.js +120 -0
  69. package/dist/cjs/workspace/useWorkspaceDoc.native.js.map +1 -0
  70. package/dist/esm/chrome/CommandPalette.mjs +20 -9
  71. package/dist/esm/chrome/CommandPalette.mjs.map +1 -1
  72. package/dist/esm/chrome/CommandPalette.native.js +18 -10
  73. package/dist/esm/chrome/CommandPalette.native.js.map +1 -1
  74. package/dist/esm/i18n/en.mjs +21 -0
  75. package/dist/esm/i18n/en.mjs.map +1 -1
  76. package/dist/esm/i18n/en.native.js +21 -0
  77. package/dist/esm/i18n/en.native.js.map +1 -1
  78. package/dist/esm/index.mjs +19 -1
  79. package/dist/esm/index.mjs.map +1 -1
  80. package/dist/esm/index.native.js +19 -1
  81. package/dist/esm/index.native.js.map +1 -1
  82. package/dist/esm/shared/types.mjs +2 -0
  83. package/dist/esm/shared/types.mjs.map +1 -0
  84. package/dist/esm/shared/types.native.js +2 -0
  85. package/dist/esm/shared/types.native.js.map +1 -0
  86. package/dist/esm/shared/useDocinfo.mjs +90 -0
  87. package/dist/esm/shared/useDocinfo.mjs.map +1 -0
  88. package/dist/esm/shared/useDocinfo.native.js +138 -0
  89. package/dist/esm/shared/useDocinfo.native.js.map +1 -0
  90. package/dist/esm/shared/useDoctypeMeta.mjs +99 -0
  91. package/dist/esm/shared/useDoctypeMeta.mjs.map +1 -0
  92. package/dist/esm/shared/useDoctypeMeta.native.js +130 -0
  93. package/dist/esm/shared/useDoctypeMeta.native.js.map +1 -0
  94. package/dist/esm/shared/useRecentVisit.mjs +15 -0
  95. package/dist/esm/shared/useRecentVisit.mjs.map +1 -0
  96. package/dist/esm/shared/useRecentVisit.native.js +15 -0
  97. package/dist/esm/shared/useRecentVisit.native.js.map +1 -0
  98. package/dist/esm/shared/useSessionUserId.mjs +29 -0
  99. package/dist/esm/shared/useSessionUserId.mjs.map +1 -0
  100. package/dist/esm/shared/useSessionUserId.native.js +31 -0
  101. package/dist/esm/shared/useSessionUserId.native.js.map +1 -0
  102. package/dist/esm/shared/useSlugTarget.mjs +113 -0
  103. package/dist/esm/shared/useSlugTarget.mjs.map +1 -0
  104. package/dist/esm/shared/useSlugTarget.native.js +138 -0
  105. package/dist/esm/shared/useSlugTarget.native.js.map +1 -0
  106. package/dist/esm/shared/useUserRoles.mjs +47 -0
  107. package/dist/esm/shared/useUserRoles.mjs.map +1 -0
  108. package/dist/esm/shared/useUserRoles.native.js +51 -0
  109. package/dist/esm/shared/useUserRoles.native.js.map +1 -0
  110. package/dist/esm/workspace/WorkspaceChartBlock.mjs +111 -0
  111. package/dist/esm/workspace/WorkspaceChartBlock.mjs.map +1 -0
  112. package/dist/esm/workspace/WorkspaceChartBlock.native.js +116 -0
  113. package/dist/esm/workspace/WorkspaceChartBlock.native.js.map +1 -0
  114. package/dist/esm/workspace/WorkspaceGrid.mjs +66 -0
  115. package/dist/esm/workspace/WorkspaceGrid.mjs.map +1 -0
  116. package/dist/esm/workspace/WorkspaceGrid.native.js +98 -0
  117. package/dist/esm/workspace/WorkspaceGrid.native.js.map +1 -0
  118. package/dist/esm/workspace/WorkspaceLinkCard.mjs +113 -0
  119. package/dist/esm/workspace/WorkspaceLinkCard.mjs.map +1 -0
  120. package/dist/esm/workspace/WorkspaceLinkCard.native.js +126 -0
  121. package/dist/esm/workspace/WorkspaceLinkCard.native.js.map +1 -0
  122. package/dist/esm/workspace/WorkspaceLinkDirectory.mjs +84 -0
  123. package/dist/esm/workspace/WorkspaceLinkDirectory.mjs.map +1 -0
  124. package/dist/esm/workspace/WorkspaceLinkDirectory.native.js +98 -0
  125. package/dist/esm/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
  126. package/dist/esm/workspace/WorkspaceNumberCard.mjs +108 -0
  127. package/dist/esm/workspace/WorkspaceNumberCard.mjs.map +1 -0
  128. package/dist/esm/workspace/WorkspaceNumberCard.native.js +110 -0
  129. package/dist/esm/workspace/WorkspaceNumberCard.native.js.map +1 -0
  130. package/dist/esm/workspace/WorkspaceQuickList.mjs +87 -0
  131. package/dist/esm/workspace/WorkspaceQuickList.mjs.map +1 -0
  132. package/dist/esm/workspace/WorkspaceQuickList.native.js +102 -0
  133. package/dist/esm/workspace/WorkspaceQuickList.native.js.map +1 -0
  134. package/dist/esm/workspace/WorkspaceRecents.mjs +91 -0
  135. package/dist/esm/workspace/WorkspaceRecents.mjs.map +1 -0
  136. package/dist/esm/workspace/WorkspaceRecents.native.js +104 -0
  137. package/dist/esm/workspace/WorkspaceRecents.native.js.map +1 -0
  138. package/dist/esm/workspace/WorkspaceScreen.mjs +266 -0
  139. package/dist/esm/workspace/WorkspaceScreen.mjs.map +1 -0
  140. package/dist/esm/workspace/WorkspaceScreen.native.js +295 -0
  141. package/dist/esm/workspace/WorkspaceScreen.native.js.map +1 -0
  142. package/dist/esm/workspace/WorkspaceShortcut.mjs +159 -0
  143. package/dist/esm/workspace/WorkspaceShortcut.mjs.map +1 -0
  144. package/dist/esm/workspace/WorkspaceShortcut.native.js +173 -0
  145. package/dist/esm/workspace/WorkspaceShortcut.native.js.map +1 -0
  146. package/dist/esm/workspace/parseContent.mjs +148 -0
  147. package/dist/esm/workspace/parseContent.mjs.map +1 -0
  148. package/dist/esm/workspace/parseContent.native.js +264 -0
  149. package/dist/esm/workspace/parseContent.native.js.map +1 -0
  150. package/dist/esm/workspace/types.mjs +2 -0
  151. package/dist/esm/workspace/types.mjs.map +1 -0
  152. package/dist/esm/workspace/types.native.js +2 -0
  153. package/dist/esm/workspace/types.native.js.map +1 -0
  154. package/dist/esm/workspace/useDashboardChart.mjs +71 -0
  155. package/dist/esm/workspace/useDashboardChart.mjs.map +1 -0
  156. package/dist/esm/workspace/useDashboardChart.native.js +82 -0
  157. package/dist/esm/workspace/useDashboardChart.native.js.map +1 -0
  158. package/dist/esm/workspace/useWorkspaceDoc.mjs +77 -0
  159. package/dist/esm/workspace/useWorkspaceDoc.mjs.map +1 -0
  160. package/dist/esm/workspace/useWorkspaceDoc.native.js +91 -0
  161. package/dist/esm/workspace/useWorkspaceDoc.native.js.map +1 -0
  162. package/dist/jsx/chrome/CommandPalette.mjs +20 -9
  163. package/dist/jsx/chrome/CommandPalette.mjs.map +1 -1
  164. package/dist/jsx/chrome/CommandPalette.native.js +18 -10
  165. package/dist/jsx/chrome/CommandPalette.native.js.map +1 -1
  166. package/dist/jsx/i18n/en.mjs +21 -0
  167. package/dist/jsx/i18n/en.mjs.map +1 -1
  168. package/dist/jsx/i18n/en.native.js +21 -0
  169. package/dist/jsx/i18n/en.native.js.map +1 -1
  170. package/dist/jsx/index.js +19 -1
  171. package/dist/jsx/index.js.map +1 -1
  172. package/dist/jsx/index.mjs +19 -1
  173. package/dist/jsx/index.mjs.map +1 -1
  174. package/dist/jsx/index.native.js +48 -0
  175. package/dist/jsx/index.native.js.map +1 -1
  176. package/dist/jsx/shared/types.mjs +2 -0
  177. package/dist/jsx/shared/types.mjs.map +1 -0
  178. package/dist/jsx/shared/types.native.js +21 -0
  179. package/dist/jsx/shared/types.native.js.map +1 -0
  180. package/dist/jsx/shared/useDocinfo.mjs +90 -0
  181. package/dist/jsx/shared/useDocinfo.mjs.map +1 -0
  182. package/dist/jsx/shared/useDocinfo.native.js +167 -0
  183. package/dist/jsx/shared/useDocinfo.native.js.map +1 -0
  184. package/dist/jsx/shared/useDoctypeMeta.mjs +99 -0
  185. package/dist/jsx/shared/useDoctypeMeta.mjs.map +1 -0
  186. package/dist/jsx/shared/useDoctypeMeta.native.js +158 -0
  187. package/dist/jsx/shared/useDoctypeMeta.native.js.map +1 -0
  188. package/dist/jsx/shared/useRecentVisit.mjs +15 -0
  189. package/dist/jsx/shared/useRecentVisit.mjs.map +1 -0
  190. package/dist/jsx/shared/useRecentVisit.native.js +43 -0
  191. package/dist/jsx/shared/useRecentVisit.native.js.map +1 -0
  192. package/dist/jsx/shared/useSessionUserId.mjs +29 -0
  193. package/dist/jsx/shared/useSessionUserId.mjs.map +1 -0
  194. package/dist/jsx/shared/useSessionUserId.native.js +59 -0
  195. package/dist/jsx/shared/useSessionUserId.native.js.map +1 -0
  196. package/dist/jsx/shared/useSlugTarget.mjs +113 -0
  197. package/dist/jsx/shared/useSlugTarget.mjs.map +1 -0
  198. package/dist/jsx/shared/useSlugTarget.native.js +166 -0
  199. package/dist/jsx/shared/useSlugTarget.native.js.map +1 -0
  200. package/dist/jsx/shared/useUserRoles.mjs +47 -0
  201. package/dist/jsx/shared/useUserRoles.mjs.map +1 -0
  202. package/dist/jsx/shared/useUserRoles.native.js +79 -0
  203. package/dist/jsx/shared/useUserRoles.native.js.map +1 -0
  204. package/dist/jsx/workspace/WorkspaceChartBlock.mjs +111 -0
  205. package/dist/jsx/workspace/WorkspaceChartBlock.mjs.map +1 -0
  206. package/dist/jsx/workspace/WorkspaceChartBlock.native.js +144 -0
  207. package/dist/jsx/workspace/WorkspaceChartBlock.native.js.map +1 -0
  208. package/dist/jsx/workspace/WorkspaceGrid.mjs +66 -0
  209. package/dist/jsx/workspace/WorkspaceGrid.mjs.map +1 -0
  210. package/dist/jsx/workspace/WorkspaceGrid.native.js +126 -0
  211. package/dist/jsx/workspace/WorkspaceGrid.native.js.map +1 -0
  212. package/dist/jsx/workspace/WorkspaceLinkCard.mjs +113 -0
  213. package/dist/jsx/workspace/WorkspaceLinkCard.mjs.map +1 -0
  214. package/dist/jsx/workspace/WorkspaceLinkCard.native.js +155 -0
  215. package/dist/jsx/workspace/WorkspaceLinkCard.native.js.map +1 -0
  216. package/dist/jsx/workspace/WorkspaceLinkDirectory.mjs +84 -0
  217. package/dist/jsx/workspace/WorkspaceLinkDirectory.mjs.map +1 -0
  218. package/dist/jsx/workspace/WorkspaceLinkDirectory.native.js +127 -0
  219. package/dist/jsx/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
  220. package/dist/jsx/workspace/WorkspaceNumberCard.mjs +108 -0
  221. package/dist/jsx/workspace/WorkspaceNumberCard.mjs.map +1 -0
  222. package/dist/jsx/workspace/WorkspaceNumberCard.native.js +138 -0
  223. package/dist/jsx/workspace/WorkspaceNumberCard.native.js.map +1 -0
  224. package/dist/jsx/workspace/WorkspaceQuickList.mjs +87 -0
  225. package/dist/jsx/workspace/WorkspaceQuickList.mjs.map +1 -0
  226. package/dist/jsx/workspace/WorkspaceQuickList.native.js +130 -0
  227. package/dist/jsx/workspace/WorkspaceQuickList.native.js.map +1 -0
  228. package/dist/jsx/workspace/WorkspaceRecents.mjs +91 -0
  229. package/dist/jsx/workspace/WorkspaceRecents.mjs.map +1 -0
  230. package/dist/jsx/workspace/WorkspaceRecents.native.js +132 -0
  231. package/dist/jsx/workspace/WorkspaceRecents.native.js.map +1 -0
  232. package/dist/jsx/workspace/WorkspaceScreen.mjs +266 -0
  233. package/dist/jsx/workspace/WorkspaceScreen.mjs.map +1 -0
  234. package/dist/jsx/workspace/WorkspaceScreen.native.js +323 -0
  235. package/dist/jsx/workspace/WorkspaceScreen.native.js.map +1 -0
  236. package/dist/jsx/workspace/WorkspaceShortcut.mjs +159 -0
  237. package/dist/jsx/workspace/WorkspaceShortcut.mjs.map +1 -0
  238. package/dist/jsx/workspace/WorkspaceShortcut.native.js +202 -0
  239. package/dist/jsx/workspace/WorkspaceShortcut.native.js.map +1 -0
  240. package/dist/jsx/workspace/parseContent.mjs +148 -0
  241. package/dist/jsx/workspace/parseContent.mjs.map +1 -0
  242. package/dist/jsx/workspace/parseContent.native.js +299 -0
  243. package/dist/jsx/workspace/parseContent.native.js.map +1 -0
  244. package/dist/jsx/workspace/types.mjs +2 -0
  245. package/dist/jsx/workspace/types.mjs.map +1 -0
  246. package/dist/jsx/workspace/types.native.js +21 -0
  247. package/dist/jsx/workspace/types.native.js.map +1 -0
  248. package/dist/jsx/workspace/useDashboardChart.mjs +71 -0
  249. package/dist/jsx/workspace/useDashboardChart.mjs.map +1 -0
  250. package/dist/jsx/workspace/useDashboardChart.native.js +110 -0
  251. package/dist/jsx/workspace/useDashboardChart.native.js.map +1 -0
  252. package/dist/jsx/workspace/useWorkspaceDoc.mjs +77 -0
  253. package/dist/jsx/workspace/useWorkspaceDoc.mjs.map +1 -0
  254. package/dist/jsx/workspace/useWorkspaceDoc.native.js +120 -0
  255. package/dist/jsx/workspace/useWorkspaceDoc.native.js.map +1 -0
  256. package/package.json +12 -12
  257. package/src/chrome/CommandPalette.tsx +35 -15
  258. package/src/i18n/en.ts +21 -0
  259. package/src/index.ts +69 -0
  260. package/src/shared/types.ts +14 -0
  261. package/src/shared/useDocinfo.ts +163 -0
  262. package/src/shared/useDoctypeMeta.ts +243 -0
  263. package/src/shared/useRecentVisit.ts +33 -0
  264. package/src/shared/useSessionUserId.ts +42 -0
  265. package/src/shared/useSlugTarget.ts +143 -0
  266. package/src/shared/useUserRoles.ts +66 -0
  267. package/src/workspace/WorkspaceChartBlock.tsx +115 -0
  268. package/src/workspace/WorkspaceGrid.tsx +82 -0
  269. package/src/workspace/WorkspaceLinkCard.tsx +134 -0
  270. package/src/workspace/WorkspaceLinkDirectory.tsx +126 -0
  271. package/src/workspace/WorkspaceNumberCard.tsx +126 -0
  272. package/src/workspace/WorkspaceQuickList.tsx +100 -0
  273. package/src/workspace/WorkspaceRecents.tsx +100 -0
  274. package/src/workspace/WorkspaceScreen.tsx +322 -0
  275. package/src/workspace/WorkspaceShortcut.tsx +223 -0
  276. package/src/workspace/parseContent.spec.ts +327 -0
  277. package/src/workspace/parseContent.ts +240 -0
  278. package/src/workspace/types.ts +135 -0
  279. package/src/workspace/useDashboardChart.ts +115 -0
  280. package/src/workspace/useWorkspaceDoc.ts +111 -0
  281. package/types/chrome/CommandPalette.d.ts.map +1 -1
  282. package/types/i18n/en.d.ts +19 -0
  283. package/types/i18n/en.d.ts.map +1 -1
  284. package/types/index.d.ts +34 -0
  285. package/types/index.d.ts.map +1 -1
  286. package/types/shared/types.d.ts +21 -0
  287. package/types/shared/types.d.ts.map +1 -0
  288. package/types/shared/useDocinfo.d.ts +61 -0
  289. package/types/shared/useDocinfo.d.ts.map +1 -0
  290. package/types/shared/useDoctypeMeta.d.ts +118 -0
  291. package/types/shared/useDoctypeMeta.d.ts.map +1 -0
  292. package/types/shared/useRecentVisit.d.ts +10 -0
  293. package/types/shared/useRecentVisit.d.ts.map +1 -0
  294. package/types/shared/useSessionUserId.d.ts +6 -0
  295. package/types/shared/useSessionUserId.d.ts.map +1 -0
  296. package/types/shared/useSlugTarget.d.ts +18 -0
  297. package/types/shared/useSlugTarget.d.ts.map +1 -0
  298. package/types/shared/useUserRoles.d.ts +15 -0
  299. package/types/shared/useUserRoles.d.ts.map +1 -0
  300. package/types/workspace/WorkspaceChartBlock.d.ts +6 -0
  301. package/types/workspace/WorkspaceChartBlock.d.ts.map +1 -0
  302. package/types/workspace/WorkspaceGrid.d.ts +23 -0
  303. package/types/workspace/WorkspaceGrid.d.ts.map +1 -0
  304. package/types/workspace/WorkspaceLinkCard.d.ts +20 -0
  305. package/types/workspace/WorkspaceLinkCard.d.ts.map +1 -0
  306. package/types/workspace/WorkspaceLinkDirectory.d.ts +19 -0
  307. package/types/workspace/WorkspaceLinkDirectory.d.ts.map +1 -0
  308. package/types/workspace/WorkspaceNumberCard.d.ts +19 -0
  309. package/types/workspace/WorkspaceNumberCard.d.ts.map +1 -0
  310. package/types/workspace/WorkspaceQuickList.d.ts +6 -0
  311. package/types/workspace/WorkspaceQuickList.d.ts.map +1 -0
  312. package/types/workspace/WorkspaceRecents.d.ts +2 -0
  313. package/types/workspace/WorkspaceRecents.d.ts.map +1 -0
  314. package/types/workspace/WorkspaceScreen.d.ts +24 -0
  315. package/types/workspace/WorkspaceScreen.d.ts.map +1 -0
  316. package/types/workspace/WorkspaceShortcut.d.ts +27 -0
  317. package/types/workspace/WorkspaceShortcut.d.ts.map +1 -0
  318. package/types/workspace/parseContent.d.ts +77 -0
  319. package/types/workspace/parseContent.d.ts.map +1 -0
  320. package/types/workspace/types.d.ts +112 -0
  321. package/types/workspace/types.d.ts.map +1 -0
  322. package/types/workspace/useDashboardChart.d.ts +29 -0
  323. package/types/workspace/useDashboardChart.d.ts.map +1 -0
  324. package/types/workspace/useWorkspaceDoc.d.ts +18 -0
  325. package/types/workspace/useWorkspaceDoc.d.ts.map +1 -0
@@ -0,0 +1,243 @@
1
+ // Shared contract — consumed by the list, form, views, and quick-entry
2
+ // surfaces; keep signatures stable.
3
+ // This is the ONE meta loader for backoffice surfaces (form/deskMeta.ts and
4
+ // views/viewMeta.ts loaders were consolidated here): getdoctype RPC on live
5
+ // benches, the FrappeProvider fixture branch for stories/tests, one
6
+ // module-wide cache either way.
7
+ import type { FixtureProvider } from "@multiplatform.one/frappe";
8
+ import { useFrappeConfig } from "@multiplatform.one/frappe-ui";
9
+ import { useCallback, useEffect, useMemo, useState } from "react";
10
+ import { useFrappeApp } from "./useFrappeApp";
11
+
12
+ /** A single DocField row from a DocType meta (loose — server is source of truth). */
13
+ export interface DocFieldMeta {
14
+ fieldname: string;
15
+ label?: string;
16
+ fieldtype: string;
17
+ options?: string;
18
+ reqd?: 0 | 1;
19
+ hidden?: 0 | 1;
20
+ read_only?: 0 | 1;
21
+ bold?: 0 | 1;
22
+ in_list_view?: 0 | 1;
23
+ in_standard_filter?: 0 | 1;
24
+ in_global_search?: 0 | 1;
25
+ allow_in_quick_entry?: 0 | 1;
26
+ allow_on_submit?: 0 | 1;
27
+ no_copy?: 0 | 1;
28
+ collapsible?: 0 | 1;
29
+ collapsible_depends_on?: string;
30
+ depends_on?: string;
31
+ mandatory_depends_on?: string;
32
+ read_only_depends_on?: string;
33
+ fetch_from?: string;
34
+ permlevel?: number;
35
+ length?: number;
36
+ default?: string;
37
+ description?: string;
38
+ precision?: string | number;
39
+ idx?: number;
40
+ [key: string]: unknown;
41
+ }
42
+
43
+ /** DocType Link child row (Connections tab). Probed: `group` arrives null when unset. */
44
+ export interface DocLinkMeta {
45
+ name?: string;
46
+ link_doctype: string;
47
+ link_fieldname: string;
48
+ group?: string | null;
49
+ hidden?: 0 | 1;
50
+ is_child_table?: 0 | 1;
51
+ parent_doctype?: string;
52
+ table_fieldname?: string;
53
+ [key: string]: unknown;
54
+ }
55
+
56
+ /** Role permission row from the DocType meta. */
57
+ export interface DocPermissionRule {
58
+ role?: string;
59
+ permlevel?: number;
60
+ read?: 0 | 1;
61
+ write?: 0 | 1;
62
+ create?: 0 | 1;
63
+ delete?: 0 | 1;
64
+ submit?: 0 | 1;
65
+ cancel?: 0 | 1;
66
+ amend?: 0 | 1;
67
+ print?: 0 | 1;
68
+ email?: 0 | 1;
69
+ share?: 0 | 1;
70
+ if_owner?: 0 | 1;
71
+ [key: string]: unknown;
72
+ }
73
+
74
+ /** DocType meta as returned by frappe.desk.form.load.getdoctype (loose). */
75
+ export interface DoctypeMeta {
76
+ doctype?: string;
77
+ name: string;
78
+ module?: string;
79
+ issingle?: 0 | 1;
80
+ istable?: 0 | 1;
81
+ is_submittable?: 0 | 1;
82
+ is_tree?: 0 | 1;
83
+ is_virtual?: 0 | 1;
84
+ editable_grid?: 0 | 1;
85
+ track_changes?: 0 | 1;
86
+ quick_entry?: 0 | 1;
87
+ autoname?: string;
88
+ naming_rule?: string;
89
+ allow_rename?: 0 | 1;
90
+ allow_copy?: 0 | 1;
91
+ read_only?: 0 | 1;
92
+ in_create?: 0 | 1;
93
+ hide_toolbar?: 0 | 1;
94
+ max_attachments?: number;
95
+ title_field?: string;
96
+ image_field?: string;
97
+ search_fields?: string;
98
+ sort_field?: string;
99
+ sort_order?: string;
100
+ icon?: string;
101
+ document_type?: string;
102
+ fields: DocFieldMeta[];
103
+ permissions?: DocPermissionRule[];
104
+ links?: DocLinkMeta[];
105
+ states?: Array<{ title?: string; color?: string } & Record<string, unknown>>;
106
+ [key: string]: unknown;
107
+ }
108
+
109
+ export interface DoctypeMetaBundle {
110
+ /** Parent doctype meta (docs[0]) */
111
+ meta: DoctypeMeta;
112
+ /** Child table doctype metas keyed by doctype name (docs[1..]) */
113
+ childMetas: Record<string, DoctypeMeta>;
114
+ /** Parsed user_settings (list view settings etc.), when present */
115
+ userSettings?: Record<string, unknown>;
116
+ }
117
+
118
+ interface GetDoctypeResponse {
119
+ docs?: DoctypeMeta[];
120
+ user_settings?: string | Record<string, unknown>;
121
+ }
122
+
123
+ const metaCache = new Map<string, Promise<DoctypeMetaBundle>>();
124
+
125
+ function parseUserSettings(raw: GetDoctypeResponse["user_settings"]) {
126
+ if (!raw) return undefined;
127
+ if (typeof raw !== "string") return raw;
128
+ try {
129
+ return JSON.parse(raw) as Record<string, unknown>;
130
+ } catch {
131
+ return undefined;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Fixture path (stories / tests): the raw getdoctype-shaped meta doc lives in
137
+ * the fixture provider's "DocType" collection under the doctype's name
138
+ * (fields / links / permissions arrays inline).
139
+ */
140
+ async function loadBundleFromFixtures(
141
+ fixtures: FixtureProvider,
142
+ doctype: string,
143
+ ): Promise<DoctypeMetaBundle> {
144
+ const doc = await fixtures.getDoc("DocType", doctype);
145
+ if (!doc) throw new Error(`No fixture meta for DocType "${doctype}"`);
146
+ const raw = doc as Record<string, unknown>;
147
+ const meta = { ...raw, fields: (raw.fields as DocFieldMeta[] | undefined) ?? [] } as DoctypeMeta;
148
+ return { meta, childMetas: {} };
149
+ }
150
+
151
+ /**
152
+ * Load (and cache, module-wide) the meta bundle for a doctype via
153
+ * `frappe.desk.form.load.getdoctype` — or, when the ambient FrappeProvider
154
+ * carries a fixture provider, from its "DocType" collection. All backoffice
155
+ * surfaces share this cache, so meta is fetched once per doctype per session.
156
+ */
157
+ export function useDoctypeMeta(doctype?: string): {
158
+ bundle?: DoctypeMetaBundle;
159
+ meta?: DoctypeMeta;
160
+ loading: boolean;
161
+ error?: Error;
162
+ reload: () => void;
163
+ } {
164
+ const app = useFrappeApp();
165
+ const config = useFrappeConfig();
166
+ const fixtures = config?.fixtures;
167
+ const [bundle, setBundle] = useState<DoctypeMetaBundle | undefined>(undefined);
168
+ const [loading, setLoading] = useState<boolean>(Boolean(doctype));
169
+ const [error, setError] = useState<Error | undefined>(undefined);
170
+ const [generation, setGeneration] = useState(0);
171
+
172
+ // Fixture and live providers must not share cache entries (storybook mounts
173
+ // both kinds in one session); baseURL keeps multi-bench setups apart.
174
+ const cacheKey = doctype
175
+ ? `${config?.baseURL ?? ""}\u0000${fixtures ? "fixtures" : "live"}\u0000${doctype}`
176
+ : undefined;
177
+
178
+ useEffect(() => {
179
+ if ((!app && !fixtures) || !doctype || !cacheKey) {
180
+ setBundle(undefined);
181
+ setLoading(Boolean(doctype));
182
+ return;
183
+ }
184
+ let cancelled = false;
185
+ let promise = metaCache.get(cacheKey);
186
+ if (!promise) {
187
+ if (fixtures) {
188
+ promise = loadBundleFromFixtures(fixtures, doctype);
189
+ } else if (app) {
190
+ promise = app
191
+ .call()
192
+ .get<GetDoctypeResponse>("frappe.desk.form.load.getdoctype", {
193
+ doctype,
194
+ with_parent: 1,
195
+ })
196
+ .then((res) => {
197
+ const docs = res.payload?.docs ?? [];
198
+ const meta = docs.find((d) => d.name === doctype) ?? docs[0];
199
+ if (!meta) throw new Error(`No meta returned for ${doctype}`);
200
+ const childMetas: Record<string, DoctypeMeta> = {};
201
+ for (const doc of docs) {
202
+ if (doc !== meta) childMetas[doc.name] = doc;
203
+ }
204
+ return {
205
+ meta,
206
+ childMetas,
207
+ userSettings: parseUserSettings(res.payload?.user_settings),
208
+ };
209
+ });
210
+ } else {
211
+ return;
212
+ }
213
+ metaCache.set(cacheKey, promise);
214
+ promise.catch(() => metaCache.delete(cacheKey));
215
+ }
216
+ setLoading(true);
217
+ setError(undefined);
218
+ promise
219
+ .then((value) => {
220
+ if (cancelled) return;
221
+ setBundle(value);
222
+ setLoading(false);
223
+ })
224
+ .catch((err: Error) => {
225
+ if (cancelled) return;
226
+ setError(err);
227
+ setLoading(false);
228
+ });
229
+ return () => {
230
+ cancelled = true;
231
+ };
232
+ }, [app, fixtures, doctype, cacheKey, generation]);
233
+
234
+ const reload = useCallback(() => {
235
+ if (cacheKey) metaCache.delete(cacheKey);
236
+ setGeneration((g) => g + 1);
237
+ }, [cacheKey]);
238
+
239
+ return useMemo(
240
+ () => ({ bundle, meta: bundle?.meta, loading, error, reload }),
241
+ [bundle, loading, error, reload],
242
+ );
243
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Write side of the shared desk recents store ("frappe-desk-recent") for
3
+ * plain navigation. The awesomebar/command palette already writes recents
4
+ * when it navigates, but sidebar/list navigation never did — so the
5
+ * workspace "Continue where you left off" strip stayed empty for anyone who
6
+ * doesn't use the palette. Screens call this on mount (and whenever the
7
+ * visited path changes) so every doctype-list and document visit lands in
8
+ * the same store the palette, sidebar recents, and the workspace strip read.
9
+ *
10
+ * Label vocabulary follows the existing writers: doctype lists use the bare
11
+ * doctype (command-palette navigation items), documents use
12
+ * "{doctype}: {name}" (frappe-ui DeskFormPage precedent).
13
+ */
14
+ import { addToRecent } from "@multiplatform.one/frappe-ui";
15
+ import { useEffect } from "react";
16
+
17
+ export interface RecentVisit {
18
+ label: string;
19
+ path: string;
20
+ }
21
+
22
+ /**
23
+ * Record a visit in the shared recents store. Pass `undefined` to skip
24
+ * (create mode, fixture/story mode). Dedup/cap is owned by `addToRecent`.
25
+ */
26
+ export function useRecentVisit(visit: RecentVisit | undefined): void {
27
+ const label = visit?.label;
28
+ const path = visit?.path;
29
+ useEffect(() => {
30
+ if (!label || !path) return;
31
+ addToRecent({ label, path });
32
+ }, [label, path]);
33
+ }
@@ -0,0 +1,42 @@
1
+ // Session user id (for liked-hearts + "assigned to me"), cached per app.
2
+ // (The shell's useSessionUser in shell/useWorkspaces.ts is the HttpClient
3
+ // variant used by the sidebar; this one rides the FrappeApp auth module.)
4
+ import { useFrappeConfig } from "@multiplatform.one/frappe-ui";
5
+ import { useEffect, useState } from "react";
6
+ import { useFrappeApp } from "./useFrappeApp";
7
+
8
+ const userCache = new Map<string, Promise<string>>();
9
+
10
+ /**
11
+ * The logged-in user's id (`frappe.auth.get_logged_user`), or undefined
12
+ * while loading / in fixture mode (no session exists against fixtures).
13
+ */
14
+ export function useSessionUserId(): string | undefined {
15
+ const config = useFrappeConfig();
16
+ const app = useFrappeApp();
17
+ const fixtureMode = Boolean(config?.fixtures);
18
+ const [user, setUser] = useState<string | undefined>(undefined);
19
+
20
+ useEffect(() => {
21
+ if (!app || fixtureMode || !config?.baseURL) return;
22
+ let cancelled = false;
23
+ let promise = userCache.get(config.baseURL);
24
+ if (!promise) {
25
+ promise = app.auth().getLoggedInUser();
26
+ userCache.set(config.baseURL, promise);
27
+ promise.catch(() => userCache.delete(config.baseURL));
28
+ }
29
+ promise
30
+ .then((value) => {
31
+ if (!cancelled && value) setUser(value);
32
+ })
33
+ .catch(() => {
34
+ // No session — hearts render unfilled, "me" facets hidden.
35
+ });
36
+ return () => {
37
+ cancelled = true;
38
+ };
39
+ }, [app, fixtureMode, config?.baseURL]);
40
+
41
+ return user;
42
+ }
@@ -0,0 +1,143 @@
1
+ // Contract: resolve a {basePath}/[slug] segment to a workspace or doctype.
2
+ // Every backoffice route relies on this hook; keep the signature stable.
3
+ import { HttpClient, type AuthConfig, type FixtureProvider } from "@multiplatform.one/frappe";
4
+ import { useFrappeConfig, type FrappeConfig } from "@multiplatform.one/frappe-ui";
5
+ import { useEffect, useMemo, useState } from "react";
6
+ import { slugToDisplayName, toSlug } from "../navigation/paths";
7
+ import type { SlugTarget } from "./types";
8
+
9
+ /**
10
+ * Slug → proper-cased-name indexes, fetched once per session.
11
+ *
12
+ * Workspaces win over doctypes on collision (desk parity: `/app/tools` is the
13
+ * Tools workspace even though a "Tools" doctype could exist).
14
+ */
15
+ interface SlugIndex {
16
+ workspaces: Map<string, string>;
17
+ doctypes: Map<string, string>;
18
+ }
19
+
20
+ interface SlugIndexSource {
21
+ baseURL: string;
22
+ auth?: FrappeConfig["auth"];
23
+ fixtures?: FixtureProvider;
24
+ }
25
+
26
+ /** Module-level cache: one fetch per (baseURL, fixture-mode) per session. */
27
+ const slugIndexCache = new Map<string, Promise<SlugIndex>>();
28
+
29
+ function toSlugMap(names: readonly { name?: string }[]): Map<string, string> {
30
+ const map = new Map<string, string>();
31
+ for (const row of names) {
32
+ if (row.name) map.set(toSlug(row.name), row.name);
33
+ }
34
+ return map;
35
+ }
36
+
37
+ async function fetchSlugIndex(source: SlugIndexSource): Promise<SlugIndex> {
38
+ if (source.fixtures) {
39
+ const [workspaces, doctypes] = await Promise.all([
40
+ source.fixtures.getList("Workspace", { fields: ["name"] }),
41
+ source.fixtures.getList("DocType", { fields: ["name"] }),
42
+ ]);
43
+ return {
44
+ workspaces: toSlugMap(workspaces as { name?: string }[]),
45
+ doctypes: toSlugMap(doctypes as { name?: string }[]),
46
+ };
47
+ }
48
+ const client = new HttpClient(source.baseURL, source.auth as AuthConfig | undefined);
49
+ const [workspacesRes, doctypesRes] = await Promise.all([
50
+ client.get<{ data?: { name: string }[] }>("/api/resource/Workspace", {
51
+ fields: '["name"]',
52
+ limit_page_length: "0",
53
+ }),
54
+ client.get<{ message?: { name: string }[] }>("/api/method/frappe.client.get_list", {
55
+ doctype: "DocType",
56
+ fields: '["name"]',
57
+ limit_page_length: "0",
58
+ }),
59
+ ]);
60
+ return {
61
+ workspaces: toSlugMap(workspacesRes.payload?.data ?? []),
62
+ doctypes: toSlugMap(doctypesRes.payload?.message ?? []),
63
+ };
64
+ }
65
+
66
+ function getSlugIndex(source: SlugIndexSource): Promise<SlugIndex> {
67
+ const key = `${source.baseURL}:${source.fixtures ? "fixtures" : "live"}`;
68
+ let promise = slugIndexCache.get(key);
69
+ if (!promise) {
70
+ promise = fetchSlugIndex(source);
71
+ // Failed fetches are evicted so a later mount can retry.
72
+ promise.catch(() => {
73
+ if (slugIndexCache.get(key) === promise) slugIndexCache.delete(key);
74
+ });
75
+ slugIndexCache.set(key, promise);
76
+ }
77
+ return promise;
78
+ }
79
+
80
+ /**
81
+ * Resolve a URL slug ("sales-order") to its target:
82
+ * - a Workspace whose slugged name matches → workspace page (workspaces win)
83
+ * - otherwise a DocType whose slugged name matches → doctype list
84
+ * - otherwise not-found
85
+ *
86
+ * The Workspace + DocType name indexes are fetched once per session (module
87
+ * cache) via the frappe client, honoring FrappeProvider fixtures in stories
88
+ * and tests. Connection comes exclusively from the ambient FrappeProvider
89
+ * (mounted by BackofficeProvider); without one the hook degrades the same
90
+ * way a failed fetch does. SSR-safe: the fetch runs in an effect, so the
91
+ * server render (and first client paint) reports `loading`. If the fetch
92
+ * fails the hook degrades gracefully by treating the slug as a title-cased
93
+ * doctype.
94
+ */
95
+ export function useSlugTarget(slug: string | undefined): SlugTarget {
96
+ const config = useFrappeConfig();
97
+ const baseURL = config?.baseURL;
98
+ const fixtures = config?.fixtures;
99
+ const auth = config?.auth;
100
+
101
+ const [index, setIndex] = useState<SlugIndex | undefined>(undefined);
102
+ const [failed, setFailed] = useState(false);
103
+
104
+ useEffect(() => {
105
+ let cancelled = false;
106
+ // No provider config → no bench to ask; degrade like a failed fetch.
107
+ if (!baseURL && !fixtures) {
108
+ setFailed(true);
109
+ return;
110
+ }
111
+ setFailed(false);
112
+ getSlugIndex({ baseURL: baseURL ?? "", auth, fixtures })
113
+ .then((result) => {
114
+ if (!cancelled) setIndex(result);
115
+ })
116
+ .catch(() => {
117
+ if (!cancelled) setFailed(true);
118
+ });
119
+ return () => {
120
+ cancelled = true;
121
+ };
122
+ // `auth` is intentionally not a dependency: the cache is keyed by
123
+ // baseURL/fixtures and provider auth is stable for the session.
124
+ // oxlint-disable-next-line exhaustive-deps
125
+ }, [baseURL, fixtures]);
126
+
127
+ return useMemo<SlugTarget>(() => {
128
+ if (!slug) return { status: "loading" };
129
+ if (index) {
130
+ const workspace = index.workspaces.get(slug);
131
+ if (workspace) return { status: "resolved", kind: "workspace", workspace };
132
+ const doctype = index.doctypes.get(slug);
133
+ if (doctype) return { status: "resolved", kind: "doctype", doctype };
134
+ return { status: "not-found", slug };
135
+ }
136
+ if (failed) {
137
+ // Degrade gracefully: guess a title-cased doctype so deep links still
138
+ // land somewhere useful when the metadata fetch is unavailable.
139
+ return { status: "resolved", kind: "doctype", doctype: slugToDisplayName(slug) };
140
+ }
141
+ return { status: "loading" };
142
+ }, [slug, index, failed]);
143
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Session user's role list — the client-side half of desk's
3
+ * `frappe.user_roles` (bootinfo). Fetched once per session via the
4
+ * whitelisted `frappe.core.doctype.user.user.get_roles` RPC (probed:
5
+ * `?uid=<user>` → `{"message": ["Role", ...]}`), keyed off
6
+ * `frappe.auth.get_logged_user`.
7
+ *
8
+ * `roles` stays undefined while loading, in fixture mode, or when the RPC
9
+ * fails — consumers (permlevel matrix) fall back to the conservative
10
+ * "permlevel > 0 → read-only" rule in that case.
11
+ */
12
+
13
+ import { useFrappeConfig } from "@multiplatform.one/frappe-ui";
14
+ import { useEffect, useState } from "react";
15
+ import { useFrappeApp } from "./useFrappeApp";
16
+
17
+ const rolesCache = new Map<string, Promise<string[]>>();
18
+
19
+ export function useUserRoles(): { roles?: string[] } {
20
+ const app = useFrappeApp();
21
+ const config = useFrappeConfig();
22
+ const fixtures = config?.fixtures;
23
+ const baseURL = config?.baseURL;
24
+ const [roles, setRoles] = useState<string[] | undefined>(undefined);
25
+
26
+ useEffect(() => {
27
+ // Fixture mode has no session — permlevel falls back to the coarse rule.
28
+ if (!app || fixtures || !baseURL) {
29
+ setRoles(undefined);
30
+ return;
31
+ }
32
+ let cancelled = false;
33
+ let promise = rolesCache.get(baseURL);
34
+ if (!promise) {
35
+ promise = app
36
+ .call()
37
+ .get<{ message?: string }>("frappe.auth.get_logged_user")
38
+ .then((res) => {
39
+ const user = res.payload?.message;
40
+ if (!user) throw new Error("No session user");
41
+ return app.call().get<{ message?: string[] }>("frappe.core.doctype.user.user.get_roles", {
42
+ uid: user,
43
+ });
44
+ })
45
+ .then((res) => {
46
+ const list = res.payload?.message;
47
+ if (!Array.isArray(list)) throw new Error("No roles returned");
48
+ return list;
49
+ });
50
+ rolesCache.set(baseURL, promise);
51
+ promise.catch(() => rolesCache.delete(baseURL));
52
+ }
53
+ promise
54
+ .then((list) => {
55
+ if (!cancelled) setRoles(list);
56
+ })
57
+ .catch(() => {
58
+ if (!cancelled) setRoles(undefined);
59
+ });
60
+ return () => {
61
+ cancelled = true;
62
+ };
63
+ }, [app, fixtures, baseURL]);
64
+
65
+ return { roles };
66
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Workspace chart block — renders a Dashboard Chart by name using the desk
3
+ * chart RPC for real series data, drawn with the catalog ChartCard.
4
+ *
5
+ * Mappings (frappe → catalog): Line→line, Bar→bar, Pie/Donut/Percentage→pie.
6
+ * Heatmap has no catalog equivalent and falls back to bar (documented gap).
7
+ * Only the first dataset is drawn — the catalog chart is single-series
8
+ * (documented gap). In fixture mode (stories) the RPC is unavailable, so
9
+ * the block renders an informational card instead.
10
+ */
11
+ import { AsyncBoundary, Card, SizableText, Skeleton, YStack } from "@multiplatform.one/components";
12
+ import { ChartCard, type ChartConfig, type ChartType } from "@multiplatform.one/frappe-ui";
13
+ import { useResolvedKnobs } from "@multiplatform.one/theme";
14
+ import { useMemo } from "react";
15
+ import { useTranslation } from "react-i18next";
16
+ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
17
+ import type { WorkspaceChartRow } from "./types";
18
+ import { useDashboardChartData, type DashboardChartDoc } from "./useDashboardChart";
19
+ import { useFrappeDoc } from "./useWorkspaceDoc";
20
+
21
+ function toChartType(frappeType: string | undefined): ChartType {
22
+ switch (frappeType) {
23
+ case "Line":
24
+ return "line";
25
+ case "Pie":
26
+ case "Donut":
27
+ case "Percentage":
28
+ return "pie";
29
+ default:
30
+ // "Bar", "Heatmap" (no catalog heatmap yet), unknown → bar.
31
+ return "bar";
32
+ }
33
+ }
34
+
35
+ export interface WorkspaceChartBlockProps {
36
+ row: WorkspaceChartRow;
37
+ }
38
+
39
+ export function WorkspaceChartBlock({ row }: WorkspaceChartBlockProps) {
40
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
41
+ const { knobProps } = useResolvedKnobs();
42
+ const title = row.label || row.chart_name;
43
+
44
+ const {
45
+ doc: chartDoc,
46
+ isLoading: docLoading,
47
+ error: docError,
48
+ } = useFrappeDoc<DashboardChartDoc>("Dashboard Chart", row.chart_name);
49
+ const {
50
+ series,
51
+ isLoading: dataLoading,
52
+ error: dataError,
53
+ unsupported,
54
+ } = useDashboardChartData(row.chart_name);
55
+
56
+ const config = useMemo<ChartConfig | undefined>(() => {
57
+ if (!series) return undefined;
58
+ const dataset = series.datasets?.[0];
59
+ if (!dataset) return undefined;
60
+ return {
61
+ id: `workspace-chart-${row.name}`,
62
+ title,
63
+ type: toChartType(chartDoc?.type),
64
+ data: series.labels.map((label, index) => ({
65
+ label,
66
+ value: dataset.values[index] ?? 0,
67
+ })),
68
+ height: 220,
69
+ };
70
+ }, [series, chartDoc?.type, row.name, title]);
71
+
72
+ if (unsupported) {
73
+ return (
74
+ <Card flexGrow={1}>
75
+ <YStack {...knobProps.panelPadding} {...knobProps.gap}>
76
+ <SizableText size="$4" fontWeight="700">
77
+ {title}
78
+ </SizableText>
79
+ <SizableText size="$2" color="$color10">
80
+ {t(
81
+ "workspaceChartFixture",
82
+ "Chart data is only available on a live bench",
83
+ )}
84
+ </SizableText>
85
+ </YStack>
86
+ </Card>
87
+ );
88
+ }
89
+
90
+ if (docLoading || dataLoading) {
91
+ return (
92
+ <Card flexGrow={1} aria-busy aria-label={t("loading", "Loading")}>
93
+ <YStack {...knobProps.panelPadding} {...knobProps.gap}>
94
+ <Skeleton width="40%" height={16} />
95
+ <Skeleton variant="rounded" width="100%" height={220} />
96
+ </YStack>
97
+ </Card>
98
+ );
99
+ }
100
+
101
+ const error = docError ?? dataError;
102
+ if (error || !config) {
103
+ return (
104
+ <AsyncBoundary
105
+ compact
106
+ error={error ?? true}
107
+ errorTitle={t("workspaceChartError", "Couldn't load chart {{title}}", {
108
+ title,
109
+ })}
110
+ />
111
+ );
112
+ }
113
+
114
+ return <ChartCard config={config} flexGrow={1} />;
115
+ }