@multiplatform.one/backoffice 6.3.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 (338) 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/shell/WorkspaceSidebar.cjs +4 -0
  32. package/dist/cjs/shell/WorkspaceSidebar.native.js +4 -0
  33. package/dist/cjs/shell/WorkspaceSidebar.native.js.map +1 -1
  34. package/dist/cjs/workspace/WorkspaceChartBlock.cjs +136 -0
  35. package/dist/cjs/workspace/WorkspaceChartBlock.native.js +144 -0
  36. package/dist/cjs/workspace/WorkspaceChartBlock.native.js.map +1 -0
  37. package/dist/cjs/workspace/WorkspaceGrid.cjs +91 -0
  38. package/dist/cjs/workspace/WorkspaceGrid.native.js +126 -0
  39. package/dist/cjs/workspace/WorkspaceGrid.native.js.map +1 -0
  40. package/dist/cjs/workspace/WorkspaceLinkCard.cjs +139 -0
  41. package/dist/cjs/workspace/WorkspaceLinkCard.native.js +155 -0
  42. package/dist/cjs/workspace/WorkspaceLinkCard.native.js.map +1 -0
  43. package/dist/cjs/workspace/WorkspaceLinkDirectory.cjs +110 -0
  44. package/dist/cjs/workspace/WorkspaceLinkDirectory.native.js +127 -0
  45. package/dist/cjs/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
  46. package/dist/cjs/workspace/WorkspaceNumberCard.cjs +133 -0
  47. package/dist/cjs/workspace/WorkspaceNumberCard.native.js +138 -0
  48. package/dist/cjs/workspace/WorkspaceNumberCard.native.js.map +1 -0
  49. package/dist/cjs/workspace/WorkspaceQuickList.cjs +112 -0
  50. package/dist/cjs/workspace/WorkspaceQuickList.native.js +130 -0
  51. package/dist/cjs/workspace/WorkspaceQuickList.native.js.map +1 -0
  52. package/dist/cjs/workspace/WorkspaceRecents.cjs +116 -0
  53. package/dist/cjs/workspace/WorkspaceRecents.native.js +132 -0
  54. package/dist/cjs/workspace/WorkspaceRecents.native.js.map +1 -0
  55. package/dist/cjs/workspace/WorkspaceScreen.cjs +291 -0
  56. package/dist/cjs/workspace/WorkspaceScreen.native.js +323 -0
  57. package/dist/cjs/workspace/WorkspaceScreen.native.js.map +1 -0
  58. package/dist/cjs/workspace/WorkspaceShortcut.cjs +185 -0
  59. package/dist/cjs/workspace/WorkspaceShortcut.native.js +202 -0
  60. package/dist/cjs/workspace/WorkspaceShortcut.native.js.map +1 -0
  61. package/dist/cjs/workspace/parseContent.cjs +180 -0
  62. package/dist/cjs/workspace/parseContent.native.js +299 -0
  63. package/dist/cjs/workspace/parseContent.native.js.map +1 -0
  64. package/dist/cjs/workspace/types.cjs +18 -0
  65. package/dist/cjs/workspace/types.native.js +21 -0
  66. package/dist/cjs/workspace/types.native.js.map +1 -0
  67. package/dist/cjs/workspace/useDashboardChart.cjs +96 -0
  68. package/dist/cjs/workspace/useDashboardChart.native.js +110 -0
  69. package/dist/cjs/workspace/useDashboardChart.native.js.map +1 -0
  70. package/dist/cjs/workspace/useWorkspaceDoc.cjs +103 -0
  71. package/dist/cjs/workspace/useWorkspaceDoc.native.js +120 -0
  72. package/dist/cjs/workspace/useWorkspaceDoc.native.js.map +1 -0
  73. package/dist/esm/chrome/CommandPalette.mjs +20 -9
  74. package/dist/esm/chrome/CommandPalette.mjs.map +1 -1
  75. package/dist/esm/chrome/CommandPalette.native.js +18 -10
  76. package/dist/esm/chrome/CommandPalette.native.js.map +1 -1
  77. package/dist/esm/i18n/en.mjs +21 -0
  78. package/dist/esm/i18n/en.mjs.map +1 -1
  79. package/dist/esm/i18n/en.native.js +21 -0
  80. package/dist/esm/i18n/en.native.js.map +1 -1
  81. package/dist/esm/index.mjs +19 -1
  82. package/dist/esm/index.mjs.map +1 -1
  83. package/dist/esm/index.native.js +19 -1
  84. package/dist/esm/index.native.js.map +1 -1
  85. package/dist/esm/shared/types.mjs +2 -0
  86. package/dist/esm/shared/types.mjs.map +1 -0
  87. package/dist/esm/shared/types.native.js +2 -0
  88. package/dist/esm/shared/types.native.js.map +1 -0
  89. package/dist/esm/shared/useDocinfo.mjs +90 -0
  90. package/dist/esm/shared/useDocinfo.mjs.map +1 -0
  91. package/dist/esm/shared/useDocinfo.native.js +138 -0
  92. package/dist/esm/shared/useDocinfo.native.js.map +1 -0
  93. package/dist/esm/shared/useDoctypeMeta.mjs +99 -0
  94. package/dist/esm/shared/useDoctypeMeta.mjs.map +1 -0
  95. package/dist/esm/shared/useDoctypeMeta.native.js +130 -0
  96. package/dist/esm/shared/useDoctypeMeta.native.js.map +1 -0
  97. package/dist/esm/shared/useRecentVisit.mjs +15 -0
  98. package/dist/esm/shared/useRecentVisit.mjs.map +1 -0
  99. package/dist/esm/shared/useRecentVisit.native.js +15 -0
  100. package/dist/esm/shared/useRecentVisit.native.js.map +1 -0
  101. package/dist/esm/shared/useSessionUserId.mjs +29 -0
  102. package/dist/esm/shared/useSessionUserId.mjs.map +1 -0
  103. package/dist/esm/shared/useSessionUserId.native.js +31 -0
  104. package/dist/esm/shared/useSessionUserId.native.js.map +1 -0
  105. package/dist/esm/shared/useSlugTarget.mjs +113 -0
  106. package/dist/esm/shared/useSlugTarget.mjs.map +1 -0
  107. package/dist/esm/shared/useSlugTarget.native.js +138 -0
  108. package/dist/esm/shared/useSlugTarget.native.js.map +1 -0
  109. package/dist/esm/shared/useUserRoles.mjs +47 -0
  110. package/dist/esm/shared/useUserRoles.mjs.map +1 -0
  111. package/dist/esm/shared/useUserRoles.native.js +51 -0
  112. package/dist/esm/shared/useUserRoles.native.js.map +1 -0
  113. package/dist/esm/shell/WorkspaceSidebar.mjs +4 -0
  114. package/dist/esm/shell/WorkspaceSidebar.mjs.map +1 -1
  115. package/dist/esm/shell/WorkspaceSidebar.native.js +4 -0
  116. package/dist/esm/shell/WorkspaceSidebar.native.js.map +1 -1
  117. package/dist/esm/workspace/WorkspaceChartBlock.mjs +111 -0
  118. package/dist/esm/workspace/WorkspaceChartBlock.mjs.map +1 -0
  119. package/dist/esm/workspace/WorkspaceChartBlock.native.js +116 -0
  120. package/dist/esm/workspace/WorkspaceChartBlock.native.js.map +1 -0
  121. package/dist/esm/workspace/WorkspaceGrid.mjs +66 -0
  122. package/dist/esm/workspace/WorkspaceGrid.mjs.map +1 -0
  123. package/dist/esm/workspace/WorkspaceGrid.native.js +98 -0
  124. package/dist/esm/workspace/WorkspaceGrid.native.js.map +1 -0
  125. package/dist/esm/workspace/WorkspaceLinkCard.mjs +113 -0
  126. package/dist/esm/workspace/WorkspaceLinkCard.mjs.map +1 -0
  127. package/dist/esm/workspace/WorkspaceLinkCard.native.js +126 -0
  128. package/dist/esm/workspace/WorkspaceLinkCard.native.js.map +1 -0
  129. package/dist/esm/workspace/WorkspaceLinkDirectory.mjs +84 -0
  130. package/dist/esm/workspace/WorkspaceLinkDirectory.mjs.map +1 -0
  131. package/dist/esm/workspace/WorkspaceLinkDirectory.native.js +98 -0
  132. package/dist/esm/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
  133. package/dist/esm/workspace/WorkspaceNumberCard.mjs +108 -0
  134. package/dist/esm/workspace/WorkspaceNumberCard.mjs.map +1 -0
  135. package/dist/esm/workspace/WorkspaceNumberCard.native.js +110 -0
  136. package/dist/esm/workspace/WorkspaceNumberCard.native.js.map +1 -0
  137. package/dist/esm/workspace/WorkspaceQuickList.mjs +87 -0
  138. package/dist/esm/workspace/WorkspaceQuickList.mjs.map +1 -0
  139. package/dist/esm/workspace/WorkspaceQuickList.native.js +102 -0
  140. package/dist/esm/workspace/WorkspaceQuickList.native.js.map +1 -0
  141. package/dist/esm/workspace/WorkspaceRecents.mjs +91 -0
  142. package/dist/esm/workspace/WorkspaceRecents.mjs.map +1 -0
  143. package/dist/esm/workspace/WorkspaceRecents.native.js +104 -0
  144. package/dist/esm/workspace/WorkspaceRecents.native.js.map +1 -0
  145. package/dist/esm/workspace/WorkspaceScreen.mjs +266 -0
  146. package/dist/esm/workspace/WorkspaceScreen.mjs.map +1 -0
  147. package/dist/esm/workspace/WorkspaceScreen.native.js +295 -0
  148. package/dist/esm/workspace/WorkspaceScreen.native.js.map +1 -0
  149. package/dist/esm/workspace/WorkspaceShortcut.mjs +159 -0
  150. package/dist/esm/workspace/WorkspaceShortcut.mjs.map +1 -0
  151. package/dist/esm/workspace/WorkspaceShortcut.native.js +173 -0
  152. package/dist/esm/workspace/WorkspaceShortcut.native.js.map +1 -0
  153. package/dist/esm/workspace/parseContent.mjs +148 -0
  154. package/dist/esm/workspace/parseContent.mjs.map +1 -0
  155. package/dist/esm/workspace/parseContent.native.js +264 -0
  156. package/dist/esm/workspace/parseContent.native.js.map +1 -0
  157. package/dist/esm/workspace/types.mjs +2 -0
  158. package/dist/esm/workspace/types.mjs.map +1 -0
  159. package/dist/esm/workspace/types.native.js +2 -0
  160. package/dist/esm/workspace/types.native.js.map +1 -0
  161. package/dist/esm/workspace/useDashboardChart.mjs +71 -0
  162. package/dist/esm/workspace/useDashboardChart.mjs.map +1 -0
  163. package/dist/esm/workspace/useDashboardChart.native.js +82 -0
  164. package/dist/esm/workspace/useDashboardChart.native.js.map +1 -0
  165. package/dist/esm/workspace/useWorkspaceDoc.mjs +77 -0
  166. package/dist/esm/workspace/useWorkspaceDoc.mjs.map +1 -0
  167. package/dist/esm/workspace/useWorkspaceDoc.native.js +91 -0
  168. package/dist/esm/workspace/useWorkspaceDoc.native.js.map +1 -0
  169. package/dist/jsx/chrome/CommandPalette.mjs +20 -9
  170. package/dist/jsx/chrome/CommandPalette.mjs.map +1 -1
  171. package/dist/jsx/chrome/CommandPalette.native.js +18 -10
  172. package/dist/jsx/chrome/CommandPalette.native.js.map +1 -1
  173. package/dist/jsx/i18n/en.mjs +21 -0
  174. package/dist/jsx/i18n/en.mjs.map +1 -1
  175. package/dist/jsx/i18n/en.native.js +21 -0
  176. package/dist/jsx/i18n/en.native.js.map +1 -1
  177. package/dist/jsx/index.js +19 -1
  178. package/dist/jsx/index.js.map +1 -1
  179. package/dist/jsx/index.mjs +19 -1
  180. package/dist/jsx/index.mjs.map +1 -1
  181. package/dist/jsx/index.native.js +48 -0
  182. package/dist/jsx/index.native.js.map +1 -1
  183. package/dist/jsx/shared/types.mjs +2 -0
  184. package/dist/jsx/shared/types.mjs.map +1 -0
  185. package/dist/jsx/shared/types.native.js +21 -0
  186. package/dist/jsx/shared/types.native.js.map +1 -0
  187. package/dist/jsx/shared/useDocinfo.mjs +90 -0
  188. package/dist/jsx/shared/useDocinfo.mjs.map +1 -0
  189. package/dist/jsx/shared/useDocinfo.native.js +167 -0
  190. package/dist/jsx/shared/useDocinfo.native.js.map +1 -0
  191. package/dist/jsx/shared/useDoctypeMeta.mjs +99 -0
  192. package/dist/jsx/shared/useDoctypeMeta.mjs.map +1 -0
  193. package/dist/jsx/shared/useDoctypeMeta.native.js +158 -0
  194. package/dist/jsx/shared/useDoctypeMeta.native.js.map +1 -0
  195. package/dist/jsx/shared/useRecentVisit.mjs +15 -0
  196. package/dist/jsx/shared/useRecentVisit.mjs.map +1 -0
  197. package/dist/jsx/shared/useRecentVisit.native.js +43 -0
  198. package/dist/jsx/shared/useRecentVisit.native.js.map +1 -0
  199. package/dist/jsx/shared/useSessionUserId.mjs +29 -0
  200. package/dist/jsx/shared/useSessionUserId.mjs.map +1 -0
  201. package/dist/jsx/shared/useSessionUserId.native.js +59 -0
  202. package/dist/jsx/shared/useSessionUserId.native.js.map +1 -0
  203. package/dist/jsx/shared/useSlugTarget.mjs +113 -0
  204. package/dist/jsx/shared/useSlugTarget.mjs.map +1 -0
  205. package/dist/jsx/shared/useSlugTarget.native.js +166 -0
  206. package/dist/jsx/shared/useSlugTarget.native.js.map +1 -0
  207. package/dist/jsx/shared/useUserRoles.mjs +47 -0
  208. package/dist/jsx/shared/useUserRoles.mjs.map +1 -0
  209. package/dist/jsx/shared/useUserRoles.native.js +79 -0
  210. package/dist/jsx/shared/useUserRoles.native.js.map +1 -0
  211. package/dist/jsx/shell/WorkspaceSidebar.mjs +4 -0
  212. package/dist/jsx/shell/WorkspaceSidebar.mjs.map +1 -1
  213. package/dist/jsx/shell/WorkspaceSidebar.native.js +4 -0
  214. package/dist/jsx/shell/WorkspaceSidebar.native.js.map +1 -1
  215. package/dist/jsx/workspace/WorkspaceChartBlock.mjs +111 -0
  216. package/dist/jsx/workspace/WorkspaceChartBlock.mjs.map +1 -0
  217. package/dist/jsx/workspace/WorkspaceChartBlock.native.js +144 -0
  218. package/dist/jsx/workspace/WorkspaceChartBlock.native.js.map +1 -0
  219. package/dist/jsx/workspace/WorkspaceGrid.mjs +66 -0
  220. package/dist/jsx/workspace/WorkspaceGrid.mjs.map +1 -0
  221. package/dist/jsx/workspace/WorkspaceGrid.native.js +126 -0
  222. package/dist/jsx/workspace/WorkspaceGrid.native.js.map +1 -0
  223. package/dist/jsx/workspace/WorkspaceLinkCard.mjs +113 -0
  224. package/dist/jsx/workspace/WorkspaceLinkCard.mjs.map +1 -0
  225. package/dist/jsx/workspace/WorkspaceLinkCard.native.js +155 -0
  226. package/dist/jsx/workspace/WorkspaceLinkCard.native.js.map +1 -0
  227. package/dist/jsx/workspace/WorkspaceLinkDirectory.mjs +84 -0
  228. package/dist/jsx/workspace/WorkspaceLinkDirectory.mjs.map +1 -0
  229. package/dist/jsx/workspace/WorkspaceLinkDirectory.native.js +127 -0
  230. package/dist/jsx/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
  231. package/dist/jsx/workspace/WorkspaceNumberCard.mjs +108 -0
  232. package/dist/jsx/workspace/WorkspaceNumberCard.mjs.map +1 -0
  233. package/dist/jsx/workspace/WorkspaceNumberCard.native.js +138 -0
  234. package/dist/jsx/workspace/WorkspaceNumberCard.native.js.map +1 -0
  235. package/dist/jsx/workspace/WorkspaceQuickList.mjs +87 -0
  236. package/dist/jsx/workspace/WorkspaceQuickList.mjs.map +1 -0
  237. package/dist/jsx/workspace/WorkspaceQuickList.native.js +130 -0
  238. package/dist/jsx/workspace/WorkspaceQuickList.native.js.map +1 -0
  239. package/dist/jsx/workspace/WorkspaceRecents.mjs +91 -0
  240. package/dist/jsx/workspace/WorkspaceRecents.mjs.map +1 -0
  241. package/dist/jsx/workspace/WorkspaceRecents.native.js +132 -0
  242. package/dist/jsx/workspace/WorkspaceRecents.native.js.map +1 -0
  243. package/dist/jsx/workspace/WorkspaceScreen.mjs +266 -0
  244. package/dist/jsx/workspace/WorkspaceScreen.mjs.map +1 -0
  245. package/dist/jsx/workspace/WorkspaceScreen.native.js +323 -0
  246. package/dist/jsx/workspace/WorkspaceScreen.native.js.map +1 -0
  247. package/dist/jsx/workspace/WorkspaceShortcut.mjs +159 -0
  248. package/dist/jsx/workspace/WorkspaceShortcut.mjs.map +1 -0
  249. package/dist/jsx/workspace/WorkspaceShortcut.native.js +202 -0
  250. package/dist/jsx/workspace/WorkspaceShortcut.native.js.map +1 -0
  251. package/dist/jsx/workspace/parseContent.mjs +148 -0
  252. package/dist/jsx/workspace/parseContent.mjs.map +1 -0
  253. package/dist/jsx/workspace/parseContent.native.js +299 -0
  254. package/dist/jsx/workspace/parseContent.native.js.map +1 -0
  255. package/dist/jsx/workspace/types.mjs +2 -0
  256. package/dist/jsx/workspace/types.mjs.map +1 -0
  257. package/dist/jsx/workspace/types.native.js +21 -0
  258. package/dist/jsx/workspace/types.native.js.map +1 -0
  259. package/dist/jsx/workspace/useDashboardChart.mjs +71 -0
  260. package/dist/jsx/workspace/useDashboardChart.mjs.map +1 -0
  261. package/dist/jsx/workspace/useDashboardChart.native.js +110 -0
  262. package/dist/jsx/workspace/useDashboardChart.native.js.map +1 -0
  263. package/dist/jsx/workspace/useWorkspaceDoc.mjs +77 -0
  264. package/dist/jsx/workspace/useWorkspaceDoc.mjs.map +1 -0
  265. package/dist/jsx/workspace/useWorkspaceDoc.native.js +120 -0
  266. package/dist/jsx/workspace/useWorkspaceDoc.native.js.map +1 -0
  267. package/package.json +12 -12
  268. package/src/chrome/CommandPalette.tsx +35 -15
  269. package/src/i18n/en.ts +21 -0
  270. package/src/index.ts +69 -0
  271. package/src/shared/types.ts +14 -0
  272. package/src/shared/useDocinfo.ts +163 -0
  273. package/src/shared/useDoctypeMeta.ts +243 -0
  274. package/src/shared/useRecentVisit.ts +33 -0
  275. package/src/shared/useSessionUserId.ts +42 -0
  276. package/src/shared/useSlugTarget.ts +143 -0
  277. package/src/shared/useUserRoles.ts +66 -0
  278. package/src/shell/WorkspaceSidebar.tsx +3 -0
  279. package/src/workspace/WorkspaceChartBlock.tsx +115 -0
  280. package/src/workspace/WorkspaceGrid.tsx +82 -0
  281. package/src/workspace/WorkspaceLinkCard.tsx +134 -0
  282. package/src/workspace/WorkspaceLinkDirectory.tsx +126 -0
  283. package/src/workspace/WorkspaceNumberCard.tsx +126 -0
  284. package/src/workspace/WorkspaceQuickList.tsx +100 -0
  285. package/src/workspace/WorkspaceRecents.tsx +100 -0
  286. package/src/workspace/WorkspaceScreen.tsx +322 -0
  287. package/src/workspace/WorkspaceShortcut.tsx +223 -0
  288. package/src/workspace/parseContent.spec.ts +327 -0
  289. package/src/workspace/parseContent.ts +240 -0
  290. package/src/workspace/types.ts +135 -0
  291. package/src/workspace/useDashboardChart.ts +115 -0
  292. package/src/workspace/useWorkspaceDoc.ts +111 -0
  293. package/types/chrome/CommandPalette.d.ts.map +1 -1
  294. package/types/i18n/en.d.ts +19 -0
  295. package/types/i18n/en.d.ts.map +1 -1
  296. package/types/index.d.ts +34 -0
  297. package/types/index.d.ts.map +1 -1
  298. package/types/shared/types.d.ts +21 -0
  299. package/types/shared/types.d.ts.map +1 -0
  300. package/types/shared/useDocinfo.d.ts +61 -0
  301. package/types/shared/useDocinfo.d.ts.map +1 -0
  302. package/types/shared/useDoctypeMeta.d.ts +118 -0
  303. package/types/shared/useDoctypeMeta.d.ts.map +1 -0
  304. package/types/shared/useRecentVisit.d.ts +10 -0
  305. package/types/shared/useRecentVisit.d.ts.map +1 -0
  306. package/types/shared/useSessionUserId.d.ts +6 -0
  307. package/types/shared/useSessionUserId.d.ts.map +1 -0
  308. package/types/shared/useSlugTarget.d.ts +18 -0
  309. package/types/shared/useSlugTarget.d.ts.map +1 -0
  310. package/types/shared/useUserRoles.d.ts +15 -0
  311. package/types/shared/useUserRoles.d.ts.map +1 -0
  312. package/types/shell/WorkspaceSidebar.d.ts.map +1 -1
  313. package/types/workspace/WorkspaceChartBlock.d.ts +6 -0
  314. package/types/workspace/WorkspaceChartBlock.d.ts.map +1 -0
  315. package/types/workspace/WorkspaceGrid.d.ts +23 -0
  316. package/types/workspace/WorkspaceGrid.d.ts.map +1 -0
  317. package/types/workspace/WorkspaceLinkCard.d.ts +20 -0
  318. package/types/workspace/WorkspaceLinkCard.d.ts.map +1 -0
  319. package/types/workspace/WorkspaceLinkDirectory.d.ts +19 -0
  320. package/types/workspace/WorkspaceLinkDirectory.d.ts.map +1 -0
  321. package/types/workspace/WorkspaceNumberCard.d.ts +19 -0
  322. package/types/workspace/WorkspaceNumberCard.d.ts.map +1 -0
  323. package/types/workspace/WorkspaceQuickList.d.ts +6 -0
  324. package/types/workspace/WorkspaceQuickList.d.ts.map +1 -0
  325. package/types/workspace/WorkspaceRecents.d.ts +2 -0
  326. package/types/workspace/WorkspaceRecents.d.ts.map +1 -0
  327. package/types/workspace/WorkspaceScreen.d.ts +24 -0
  328. package/types/workspace/WorkspaceScreen.d.ts.map +1 -0
  329. package/types/workspace/WorkspaceShortcut.d.ts +27 -0
  330. package/types/workspace/WorkspaceShortcut.d.ts.map +1 -0
  331. package/types/workspace/parseContent.d.ts +77 -0
  332. package/types/workspace/parseContent.d.ts.map +1 -0
  333. package/types/workspace/types.d.ts +112 -0
  334. package/types/workspace/types.d.ts.map +1 -0
  335. package/types/workspace/useDashboardChart.d.ts +29 -0
  336. package/types/workspace/useDashboardChart.d.ts.map +1 -0
  337. package/types/workspace/useWorkspaceDoc.d.ts +18 -0
  338. package/types/workspace/useWorkspaceDoc.d.ts.map +1 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Workspace number card block — renders a Number Card doc by name.
3
+ *
4
+ * "Document Type" cards (the default) map cleanly onto the live aggregate
5
+ * widget: `function` (Count/Sum/Average/Minimum/Maximum) +
6
+ * `aggregate_function_based_on` + `filters_json` become a FrappeKPICard
7
+ * data source, so the value is realtime like desk. "Report" and "Custom"
8
+ * cards need server-side evaluation
9
+ * (`frappe.desk.doctype.number_card.number_card.get_result`) and are
10
+ * rendered as an informational card for now (documented gap).
11
+ */
12
+ import { Card, SizableText, Skeleton, YStack } from "@multiplatform.one/components";
13
+ import {
14
+ FrappeKPICard,
15
+ type FrappeAggregateOperation,
16
+ type FrappeKPIDataSource,
17
+ } from "@multiplatform.one/frappe-ui";
18
+ import { useResolvedKnobs } from "@multiplatform.one/theme";
19
+ import { useMemo } from "react";
20
+ import { useTranslation } from "react-i18next";
21
+ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
22
+ import { parseFrappeFilters } from "./parseContent";
23
+ import type { WorkspaceNumberCardRow } from "./types";
24
+ import { useFrappeDoc } from "./useWorkspaceDoc";
25
+
26
+ export interface NumberCardDoc {
27
+ name: string;
28
+ doctype: string;
29
+ label?: string;
30
+ /** "Document Type" | "Report" | "Custom" */
31
+ type?: string;
32
+ document_type?: string;
33
+ /** "Count" | "Sum" | "Average" | "Minimum" | "Maximum" */
34
+ function?: string;
35
+ aggregate_function_based_on?: string;
36
+ filters_json?: string;
37
+ [key: string]: unknown;
38
+ }
39
+
40
+ const FUNCTION_MAP: Record<string, FrappeAggregateOperation> = {
41
+ Count: "count",
42
+ Sum: "sum",
43
+ Average: "avg",
44
+ Minimum: "min",
45
+ Maximum: "max",
46
+ };
47
+
48
+ export interface WorkspaceNumberCardProps {
49
+ row: WorkspaceNumberCardRow;
50
+ }
51
+
52
+ export function WorkspaceNumberCard({ row }: WorkspaceNumberCardProps) {
53
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
54
+ const { knobProps } = useResolvedKnobs();
55
+ const { doc, isLoading, error } = useFrappeDoc<NumberCardDoc>(
56
+ "Number Card",
57
+ row.number_card_name,
58
+ );
59
+
60
+ const title = row.label || doc?.label || row.number_card_name;
61
+
62
+ const dataSource = useMemo<FrappeKPIDataSource | undefined>(() => {
63
+ if (!doc?.document_type) return undefined;
64
+ if (doc.type && doc.type !== "Document Type") return undefined;
65
+ const aggregate = FUNCTION_MAP[doc.function ?? "Count"] ?? "count";
66
+ return {
67
+ doctype: doc.document_type,
68
+ aggregate,
69
+ field: aggregate === "count" ? undefined : doc.aggregate_function_based_on,
70
+ filters: parseFrappeFilters(doc.filters_json),
71
+ };
72
+ }, [doc]);
73
+
74
+ if (isLoading) {
75
+ return (
76
+ <Card flexGrow={1} aria-busy aria-label={t("loading", "Loading")}>
77
+ <YStack {...knobProps.panelPadding} {...knobProps.gap}>
78
+ <Skeleton width="60%" height={12} />
79
+ <Skeleton width="40%" height={28} />
80
+ </YStack>
81
+ </Card>
82
+ );
83
+ }
84
+
85
+ if (error || !doc) {
86
+ return (
87
+ <Card flexGrow={1}>
88
+ <YStack {...knobProps.panelPadding} {...knobProps.gap}>
89
+ <SizableText size="$3" fontWeight="600">
90
+ {title}
91
+ </SizableText>
92
+ <SizableText size="$2" color="$color10">
93
+ {t("workspaceNumberCardError", "Couldn't load number card")}
94
+ </SizableText>
95
+ </YStack>
96
+ </Card>
97
+ );
98
+ }
99
+
100
+ if (!dataSource) {
101
+ // Report / Custom cards need server-side evaluation — not wired yet.
102
+ return (
103
+ <Card flexGrow={1}>
104
+ <YStack {...knobProps.panelPadding} {...knobProps.gap}>
105
+ <SizableText size="$3" fontWeight="600">
106
+ {title}
107
+ </SizableText>
108
+ <SizableText size="$2" color="$color10">
109
+ {t(
110
+ "workspaceNumberCardUnsupported",
111
+ "This card type is only available in desk",
112
+ )}
113
+ </SizableText>
114
+ </YStack>
115
+ </Card>
116
+ );
117
+ }
118
+
119
+ return (
120
+ <FrappeKPICard
121
+ config={{ id: `workspace-number-card-${row.name}`, title, value: "—" }}
122
+ dataSource={dataSource}
123
+ flexGrow={1}
124
+ />
125
+ );
126
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Workspace quick list block — a compact live list of a doctype with the
3
+ * row's `quick_list_filter` applied, plus a "View All" jump to the full
4
+ * list page. Rows navigate to the document form. Rows show the document
5
+ * name — desk shows the meta title field, which needs a DocType meta
6
+ * fetch (documented simplification).
7
+ */
8
+ import { Card, Separator, SizableText, XStack, YStack } from "@multiplatform.one/components";
9
+ import { FrappeList } from "@multiplatform.one/frappe-ui";
10
+ import { useResolvedKnobs } from "@multiplatform.one/theme";
11
+ import { useMemo } from "react";
12
+ import { useTranslation } from "react-i18next";
13
+ import { useBackofficeNavigator, useBackofficePaths } from "../config/BackofficeProvider";
14
+ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
15
+ import { parseFrappeFilters } from "./parseContent";
16
+ import type { WorkspaceQuickListRow } from "./types";
17
+
18
+ interface QuickListDoc {
19
+ name: string;
20
+ doctype: string;
21
+ }
22
+
23
+ // Generic JSX (`<FrappeList<QuickListDoc> …/>`) breaks one-dev's source
24
+ // annotation transform; instantiate the type argument outside JSX instead.
25
+ const QuickList = FrappeList<QuickListDoc>;
26
+
27
+ /** Fixed viewport for the compact list (~4 rows + load-more headroom). */
28
+ const QUICK_LIST_HEIGHT = 220;
29
+
30
+ export interface WorkspaceQuickListProps {
31
+ row: WorkspaceQuickListRow;
32
+ }
33
+
34
+ export function WorkspaceQuickList({ row }: WorkspaceQuickListProps) {
35
+ const navigator = useBackofficeNavigator();
36
+ const paths = useBackofficePaths();
37
+ const { knobProps } = useResolvedKnobs();
38
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
39
+
40
+ const filters = useMemo(() => parseFrappeFilters(row.quick_list_filter), [row.quick_list_filter]);
41
+
42
+ const title = row.label || row.document_type;
43
+
44
+ return (
45
+ <Card flexGrow={1}>
46
+ <YStack {...knobProps.panelPadding} {...knobProps.gap}>
47
+ <XStack justifyContent="space-between" alignItems="center" {...knobProps.gap}>
48
+ <SizableText size="$4" fontWeight="700" numberOfLines={1} flexShrink={1}>
49
+ {title}
50
+ </SizableText>
51
+ <SizableText
52
+ size="$2"
53
+ color="$color11"
54
+ cursor="pointer"
55
+ role="link"
56
+ hoverStyle={{ color: "$color12" }}
57
+ onPress={() => navigator.navigate(paths.list(row.document_type))}
58
+ >
59
+ {t("workspaceQuickListViewAll", "View All")}
60
+ </SizableText>
61
+ </XStack>
62
+ <Separator />
63
+ {/* Fixed-height box: FrappeList's internal flex-basis:0 stack
64
+ contributes no intrinsic height, so an unclamped Card collapses
65
+ and the rows paint past the frame (LC-10). The box gives the
66
+ flex chain a definite height to fill. */}
67
+ <YStack height={QUICK_LIST_HEIGHT} overflow="hidden">
68
+ <QuickList
69
+ doctype={row.document_type}
70
+ fields={["name"]}
71
+ filters={filters as Array<["name", string, unknown]> | undefined}
72
+ pageSize={4}
73
+ height={QUICK_LIST_HEIGHT}
74
+ estimateSize={44}
75
+ aria-label={title}
76
+ renderItem={(item) => (
77
+ <XStack
78
+ paddingVertical="$2"
79
+ paddingHorizontal="$2"
80
+ alignItems="center"
81
+ cursor="pointer"
82
+ borderRadius="$2"
83
+ hoverStyle={{ backgroundColor: "$color3" }}
84
+ onPress={() =>
85
+ item.name && navigator.navigate(paths.form(row.document_type, item.name))
86
+ }
87
+ role="link"
88
+ aria-label={item.name}
89
+ >
90
+ <SizableText size="$3" numberOfLines={1} flexShrink={1}>
91
+ {item.name}
92
+ </SizableText>
93
+ </XStack>
94
+ )}
95
+ />
96
+ </YStack>
97
+ </YStack>
98
+ </Card>
99
+ );
100
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * "Continue where you left off" strip (MOD-11) — a wrapping band of chips
3
+ * for the most recent backoffice visits, read from the shared desk recents
4
+ * store (chrome/awesomebar-data's readRecentItems over the same
5
+ * "frappe-desk-recent" key frappe-ui's addToRecent writes — one list across
6
+ * navbar recents, sidebar recents, and this strip; no new store).
7
+ *
8
+ * Renders nothing while the store is unread or empty — the strip is
9
+ * discovery chrome, not data the page promised (no skeleton, D-10).
10
+ * Refreshes on mount and on window focus (web); paths outside the
11
+ * provider's basePath (e.g. the frappe-ui `/desk` demo shell writes there
12
+ * too) are filtered out so every chip stays navigable in this app.
13
+ */
14
+ import { ClockCounterClockwiseIcon } from "@phosphor-icons/react";
15
+ import { Card, PageSection, SizableText, XStack, useTheme } from "@multiplatform.one/components";
16
+ import { useResolvedKnobs } from "@multiplatform.one/theme";
17
+ import { useCallback, useEffect, useRef, useState } from "react";
18
+ import { useTranslation } from "react-i18next";
19
+ import { readRecentItems, type RecentItem } from "../chrome/awesomebar-data";
20
+ import { useBackofficeNavigator, useBackofficePaths } from "../config/BackofficeProvider";
21
+ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
22
+
23
+ /** Last N visits shown (MOD-11: "last 5 items from the shared recents store"). */
24
+ const MAX_RECENTS = 5;
25
+
26
+ export function WorkspaceRecents() {
27
+ const navigator = useBackofficeNavigator();
28
+ const paths = useBackofficePaths();
29
+ const { knobProps } = useResolvedKnobs();
30
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
31
+ const theme = useTheme();
32
+ // Phosphor icons take a resolved color string, not a tamagui token —
33
+ // read the theme value so native/GTK get a real color (not a CSS var).
34
+ const iconColor = typeof theme.color11?.val === "string" ? theme.color11.val : undefined;
35
+ const [recents, setRecents] = useState<RecentItem[]>([]);
36
+
37
+ const mountedRef = useRef(true);
38
+ useEffect(() => {
39
+ mountedRef.current = true;
40
+ return () => {
41
+ mountedRef.current = false;
42
+ };
43
+ }, []);
44
+
45
+ const base = paths.base;
46
+ const refresh = useCallback(() => {
47
+ void readRecentItems().then((stored) => {
48
+ if (!mountedRef.current) return;
49
+ setRecents(stored.filter((item) => item.path.startsWith(base)).slice(0, MAX_RECENTS));
50
+ });
51
+ }, [base]);
52
+
53
+ // Fresh on mount and whenever the window regains focus (another surface
54
+ // may have pushed a visit since) — same staleness contract as the
55
+ // awesomebar's refresh-on-open.
56
+ useEffect(() => {
57
+ refresh();
58
+ if (typeof window === "undefined" || typeof window.addEventListener !== "function") {
59
+ return undefined;
60
+ }
61
+ const onFocus = () => refresh();
62
+ window.addEventListener("focus", onFocus);
63
+ return () => window.removeEventListener("focus", onFocus);
64
+ }, [refresh]);
65
+
66
+ if (recents.length === 0) return null;
67
+
68
+ return (
69
+ // Section heading on the shared sectionHeading scale (LC-17); no
70
+ // divider rule over a chip band (Axiom 16 chrome-earns-role).
71
+ <PageSection
72
+ title={t("workspaceRecents", "Continue where you left off")}
73
+ divider={false}
74
+ >
75
+ <XStack flexWrap="wrap" {...knobProps.gap}>
76
+ {recents.map((item) => (
77
+ <Card
78
+ key={item.path}
79
+ // Chip-scale surface: eject the Card's default panelPadding —
80
+ // the inner row owns the compact inset (LC-18 eject-last).
81
+ padding={0}
82
+ onPress={() => navigator.navigate(item.path)}
83
+ cursor="pointer"
84
+ hoverStyle={{ borderColor: "$accentBackground" }}
85
+ pressStyle={{ scale: 0.98 }}
86
+ role="link"
87
+ aria-label={item.label}
88
+ >
89
+ <XStack paddingHorizontal="$3" minHeight={44} alignItems="center" {...knobProps.gap}>
90
+ <ClockCounterClockwiseIcon size={14} color={iconColor} aria-hidden />
91
+ <SizableText size="$3" numberOfLines={1} flexShrink={1}>
92
+ {item.label}
93
+ </SizableText>
94
+ </XStack>
95
+ </Card>
96
+ ))}
97
+ </XStack>
98
+ </PageSection>
99
+ );
100
+ }
@@ -0,0 +1,322 @@
1
+ // Contract: renders a frappe Workspace document (shortcuts, link cards,
2
+ // charts, number cards, quick lists) by workspace name.
3
+ /**
4
+ * Dashboard-first workspace page (MOD-11). The Workspace doc's `content`
5
+ * JSON declares the blocks; the composition is ours, not desk's authoring
6
+ * order (owner mandate: desk is a capability reference, not a design
7
+ * constraint): recents strip, then live data widgets (number cards →
8
+ * charts → quick lists), then narrative text, then a compact shortcut chip
9
+ * band, then the grouped link cards behind a searchable "Browse all"
10
+ * disclosure. Each widget resolves its definition from the doc's child
11
+ * tables (`shortcuts`, `links`, `charts`, `number_cards`, `quick_lists`)
12
+ * — shapes verified against a real bench (see types.ts).
13
+ *
14
+ * Skipped block types (rendered as nothing, by design): `onboarding`
15
+ * (module onboarding widget needs its own RPC surface), `custom_block`
16
+ * (arbitrary HTML — unsafe cross-platform), and `spacer` (the section
17
+ * composition owns vertical rhythm now).
18
+ */
19
+ import {
20
+ AsyncBoundary,
21
+ H2,
22
+ H3,
23
+ H4,
24
+ H5,
25
+ H6,
26
+ PageHeader,
27
+ PageSection,
28
+ Paragraph,
29
+ Screen,
30
+ Skeleton,
31
+ XStack,
32
+ YStack,
33
+ } from "@multiplatform.one/components";
34
+ import { useResolvedKnobs } from "@multiplatform.one/theme";
35
+ import { useMemo, type ReactNode } from "react";
36
+ import { useTranslation } from "react-i18next";
37
+ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
38
+ import {
39
+ composeWorkspaceBlocks,
40
+ findLinkGroup,
41
+ findShortcut,
42
+ groupLinks,
43
+ headerLevel,
44
+ parseWorkspaceContent,
45
+ stripHtml,
46
+ } from "./parseContent";
47
+ import type { WorkspaceBlock, WorkspaceDoc, WorkspaceShortcutRow } from "./types";
48
+ import { useWorkspaceDoc } from "./useWorkspaceDoc";
49
+ import { WorkspaceChartBlock } from "./WorkspaceChartBlock";
50
+ import { WorkspaceGrid, type WorkspaceGridItem } from "./WorkspaceGrid";
51
+ import { WorkspaceLinkDirectory, type WorkspaceLinkDirectoryItem } from "./WorkspaceLinkDirectory";
52
+ import { WorkspaceNumberCard } from "./WorkspaceNumberCard";
53
+ import { WorkspaceQuickList } from "./WorkspaceQuickList";
54
+ import { WorkspaceRecents } from "./WorkspaceRecents";
55
+ import { WorkspaceShortcut } from "./WorkspaceShortcut";
56
+
57
+ /** Block classes a host can hide from the workspace composition. */
58
+ export type WorkspaceBlockKind =
59
+ | "shortcuts"
60
+ | "links"
61
+ | "charts"
62
+ | "numbers"
63
+ | "quickLists"
64
+ | "recents";
65
+
66
+ export interface WorkspaceScreenProps {
67
+ /** Workspace document name (proper case, e.g. "Home", "Users") */
68
+ workspace: string;
69
+ /** Hide whole block classes from the composition. */
70
+ hiddenBlocks?: readonly WorkspaceBlockKind[];
71
+ /** Override the default shortcut-chip navigation. */
72
+ onShortcutPress?: (row: WorkspaceShortcutRow) => void;
73
+ /**
74
+ * Replace the rendering of individual grid blocks (data widgets and
75
+ * narrative text). Shortcut chips and link cards have their own
76
+ * composition and are controlled via `hiddenBlocks`/`onShortcutPress`.
77
+ */
78
+ renderBlock?: (context: {
79
+ block: WorkspaceBlock;
80
+ doc: WorkspaceDoc;
81
+ defaultContent: ReactNode;
82
+ }) => ReactNode;
83
+ }
84
+
85
+ // Section headers step under the page H1; visual scale follows desk's
86
+ // small workspace section headings.
87
+ const HEADER_TAGS = { 1: H2, 2: H2, 3: H3, 4: H4, 5: H5, 6: H6 } as const;
88
+
89
+ /**
90
+ * Map a text or data block to a grid item. Shortcut and card blocks never
91
+ * reach this — the composition renders them as the chip band and the
92
+ * "Browse all" directory instead.
93
+ */
94
+ function blockToGridItem(block: WorkspaceBlock, doc: WorkspaceDoc): WorkspaceGridItem | undefined {
95
+ const key = block.id || JSON.stringify(block.data);
96
+ switch (block.type) {
97
+ case "header": {
98
+ const text = stripHtml(block.data.text);
99
+ if (!text) return undefined;
100
+ const Tag = HEADER_TAGS[headerLevel(block.data.text)];
101
+ return {
102
+ key,
103
+ col: 12,
104
+ node: (
105
+ <Tag margin={0} marginTop="$3">
106
+ {text}
107
+ </Tag>
108
+ ),
109
+ };
110
+ }
111
+ case "paragraph": {
112
+ const text = stripHtml(block.data.text);
113
+ if (!text) return undefined;
114
+ return {
115
+ key,
116
+ col: 12,
117
+ node: <Paragraph margin={0}>{text}</Paragraph>,
118
+ };
119
+ }
120
+ case "chart": {
121
+ const row = doc.charts?.find(
122
+ (chart) =>
123
+ chart.chart_name === block.data.chart_name || chart.label === block.data.chart_name,
124
+ );
125
+ if (!row) return undefined;
126
+ return { key, col: block.data.col ?? 12, node: <WorkspaceChartBlock row={row} /> };
127
+ }
128
+ case "number_card": {
129
+ const row = doc.number_cards?.find(
130
+ (card) =>
131
+ card.number_card_name === block.data.number_card_name ||
132
+ card.label === block.data.number_card_name,
133
+ );
134
+ if (!row) return undefined;
135
+ return { key, col: block.data.col ?? 3, node: <WorkspaceNumberCard row={row} /> };
136
+ }
137
+ case "quick_list": {
138
+ const row = doc.quick_lists?.find(
139
+ (list) =>
140
+ list.document_type === block.data.quick_list_name ||
141
+ list.label === block.data.quick_list_name,
142
+ );
143
+ if (!row) return undefined;
144
+ return { key, col: block.data.col ?? 4, node: <WorkspaceQuickList row={row} /> };
145
+ }
146
+ default:
147
+ return undefined;
148
+ }
149
+ }
150
+
151
+ function WorkspaceSkeleton() {
152
+ const { knobProps } = useResolvedKnobs();
153
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
154
+ // Mirrors the dashboard-first anatomy (LC-20): title line, shortcut chip
155
+ // band (44px chips, deterministic widths), then the content card region.
156
+ return (
157
+ <YStack {...knobProps.gapLg} aria-busy aria-label={t("loading", "Loading")}>
158
+ <Skeleton width="30%" height={32} />
159
+ <XStack {...knobProps.gap}>
160
+ <Skeleton variant="rounded" width={128} height={44} />
161
+ <Skeleton variant="rounded" width={104} height={44} />
162
+ <Skeleton variant="rounded" width={144} height={44} />
163
+ <Skeleton variant="rounded" width={112} height={44} />
164
+ </XStack>
165
+ <XStack {...knobProps.gap}>
166
+ <Skeleton variant="rounded" width="32%" height={200} />
167
+ <Skeleton variant="rounded" width="32%" height={200} />
168
+ <Skeleton variant="rounded" width="32%" height={200} />
169
+ </XStack>
170
+ </YStack>
171
+ );
172
+ }
173
+
174
+ interface WorkspaceSections {
175
+ /** Data widgets first: number cards → charts → quick lists. */
176
+ data: WorkspaceGridItem[];
177
+ /** Narrative headers/paragraphs (e.g. the text-only Welcome Workspace). */
178
+ text: WorkspaceGridItem[];
179
+ /** Resolved shortcut rows for the chip band. */
180
+ shortcuts: WorkspaceShortcutRow[];
181
+ /** Resolved link groups (with authored spans) for the directory. */
182
+ links: WorkspaceLinkDirectoryItem[];
183
+ }
184
+
185
+ const DATA_KIND_BY_TYPE: Record<string, WorkspaceBlockKind> = {
186
+ chart: "charts",
187
+ number_card: "numbers",
188
+ quick_list: "quickLists",
189
+ };
190
+
191
+ function buildSections(
192
+ doc: WorkspaceDoc,
193
+ hidden: ReadonlySet<WorkspaceBlockKind>,
194
+ renderBlock?: WorkspaceScreenProps["renderBlock"],
195
+ ): WorkspaceSections {
196
+ const composition = composeWorkspaceBlocks(parseWorkspaceContent(doc.content));
197
+ const toGridItems = (blocks: WorkspaceBlock[]) =>
198
+ blocks
199
+ .map((block) => {
200
+ const item = blockToGridItem(block, doc);
201
+ if (!item || !renderBlock) return item;
202
+ return { ...item, node: renderBlock({ block, doc, defaultContent: item.node }) };
203
+ })
204
+ .filter((item): item is WorkspaceGridItem => item !== undefined);
205
+ const groups = groupLinks(doc.links);
206
+ const dataBlocks = composition.data.filter((block) => {
207
+ const kind = DATA_KIND_BY_TYPE[block.type];
208
+ return !kind || !hidden.has(kind);
209
+ });
210
+ return {
211
+ data: toGridItems(dataBlocks),
212
+ text: toGridItems(composition.text),
213
+ shortcuts: hidden.has("shortcuts")
214
+ ? []
215
+ : composition.shortcuts.flatMap((block) => {
216
+ const row = findShortcut(doc, block.data.shortcut_name);
217
+ return row ? [row] : [];
218
+ }),
219
+ links: hidden.has("links")
220
+ ? []
221
+ : composition.cards.flatMap((block) => {
222
+ const group = findLinkGroup(groups, block.data.card_name);
223
+ if (!group) return [];
224
+ return [{ key: block.id || group.label, col: block.data.col ?? 4, group }];
225
+ }),
226
+ };
227
+ }
228
+
229
+ export function WorkspaceScreen({
230
+ workspace,
231
+ hiddenBlocks,
232
+ onShortcutPress,
233
+ renderBlock,
234
+ }: WorkspaceScreenProps) {
235
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
236
+ const { knobProps } = useResolvedKnobs();
237
+ const { doc, isLoading, error, isPermissionError, refresh } = useWorkspaceDoc(workspace);
238
+
239
+ const hidden = useMemo(() => new Set(hiddenBlocks ?? []), [hiddenBlocks]);
240
+ const sections = useMemo(
241
+ () => (doc ? buildSections(doc, hidden, renderBlock) : undefined),
242
+ [doc, hidden, renderBlock],
243
+ );
244
+
245
+ if (isLoading) {
246
+ return (
247
+ <Screen>
248
+ <WorkspaceSkeleton />
249
+ </Screen>
250
+ );
251
+ }
252
+
253
+ if (error || !doc || !sections) {
254
+ return (
255
+ <Screen>
256
+ <AsyncBoundary
257
+ error={error ?? true}
258
+ onRetry={refresh}
259
+ errorTitle={
260
+ isPermissionError
261
+ ? t(
262
+ "workspacePermissionError",
263
+ "You do not have permission to view {{workspace}}",
264
+ { workspace },
265
+ )
266
+ : t("workspaceError", "Couldn't load workspace {{workspace}}", {
267
+ workspace,
268
+ })
269
+ }
270
+ />
271
+ </Screen>
272
+ );
273
+ }
274
+
275
+ const isEmpty =
276
+ sections.data.length === 0 &&
277
+ sections.text.length === 0 &&
278
+ sections.shortcuts.length === 0 &&
279
+ sections.links.length === 0;
280
+
281
+ return (
282
+ <Screen>
283
+ {/* D-11 page-title dial: moderate (32px) — a workspace title is
284
+ wayfinding, not display copy. No divider: the rule under the title
285
+ earned no role (Axiom 16 chrome-earns-role). */}
286
+ <PageHeader
287
+ title={doc.title || doc.label || workspace}
288
+ titleScale="moderate"
289
+ divider={false}
290
+ />
291
+ {hidden.has("recents") ? null : <WorkspaceRecents />}
292
+ {isEmpty ? (
293
+ <AsyncBoundary
294
+ empty
295
+ emptyTitle={t("workspaceEmpty", "This workspace is empty")}
296
+ emptyDescription={t(
297
+ "workspaceEmptyDescription",
298
+ "No blocks have been added to {{workspace}} yet",
299
+ { workspace },
300
+ )}
301
+ />
302
+ ) : (
303
+ <>
304
+ {sections.data.length > 0 ? <WorkspaceGrid items={sections.data} /> : null}
305
+ {sections.text.length > 0 ? <WorkspaceGrid items={sections.text} /> : null}
306
+ {sections.shortcuts.length > 0 ? (
307
+ // Section heading on the shared sectionHeading scale (LC-17) —
308
+ // PageSection owns it; no divider rule over a chip band.
309
+ <PageSection title={t("workspaceShortcuts", "Shortcuts")} divider={false}>
310
+ <XStack flexWrap="wrap" {...knobProps.gap}>
311
+ {sections.shortcuts.map((row) => (
312
+ <WorkspaceShortcut key={row.name} row={row} onPress={onShortcutPress} />
313
+ ))}
314
+ </XStack>
315
+ </PageSection>
316
+ ) : null}
317
+ {sections.links.length > 0 ? <WorkspaceLinkDirectory items={sections.links} /> : null}
318
+ </>
319
+ )}
320
+ </Screen>
321
+ );
322
+ }