@multiplatform.one/backoffice 6.3.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 (414) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +310 -0
  3. package/dist/cjs/chrome/BackofficeAwesomebar.cjs +95 -0
  4. package/dist/cjs/chrome/BackofficeAwesomebar.native.js +106 -0
  5. package/dist/cjs/chrome/BackofficeAwesomebar.native.js.map +1 -0
  6. package/dist/cjs/chrome/CommandPalette.cjs +453 -0
  7. package/dist/cjs/chrome/CommandPalette.native.js +505 -0
  8. package/dist/cjs/chrome/CommandPalette.native.js.map +1 -0
  9. package/dist/cjs/chrome/HelpMenu.cjs +131 -0
  10. package/dist/cjs/chrome/HelpMenu.native.js +145 -0
  11. package/dist/cjs/chrome/HelpMenu.native.js.map +1 -0
  12. package/dist/cjs/chrome/NotificationsButton.cjs +112 -0
  13. package/dist/cjs/chrome/NotificationsButton.native.js +115 -0
  14. package/dist/cjs/chrome/NotificationsButton.native.js.map +1 -0
  15. package/dist/cjs/chrome/UserMenu.cjs +158 -0
  16. package/dist/cjs/chrome/UserMenu.native.js +186 -0
  17. package/dist/cjs/chrome/UserMenu.native.js.map +1 -0
  18. package/dist/cjs/chrome/awesomebar-data.cjs +173 -0
  19. package/dist/cjs/chrome/awesomebar-data.native.js +233 -0
  20. package/dist/cjs/chrome/awesomebar-data.native.js.map +1 -0
  21. package/dist/cjs/chrome/command-palette-model.cjs +208 -0
  22. package/dist/cjs/chrome/command-palette-model.native.js +301 -0
  23. package/dist/cjs/chrome/command-palette-model.native.js.map +1 -0
  24. package/dist/cjs/chrome/help-about-dialog.cjs +136 -0
  25. package/dist/cjs/chrome/help-about-dialog.native.js +146 -0
  26. package/dist/cjs/chrome/help-about-dialog.native.js.map +1 -0
  27. package/dist/cjs/chrome/help-shortcuts-dialog.cjs +155 -0
  28. package/dist/cjs/chrome/help-shortcuts-dialog.native.js +168 -0
  29. package/dist/cjs/chrome/help-shortcuts-dialog.native.js.map +1 -0
  30. package/dist/cjs/chrome/notifications-data.cjs +190 -0
  31. package/dist/cjs/chrome/notifications-data.native.js +271 -0
  32. package/dist/cjs/chrome/notifications-data.native.js.map +1 -0
  33. package/dist/cjs/chrome/notifications-panel.cjs +171 -0
  34. package/dist/cjs/chrome/notifications-panel.native.js +189 -0
  35. package/dist/cjs/chrome/notifications-panel.native.js.map +1 -0
  36. package/dist/cjs/chrome/notifications-utils.cjs +43 -0
  37. package/dist/cjs/chrome/notifications-utils.native.js +46 -0
  38. package/dist/cjs/chrome/notifications-utils.native.js.map +1 -0
  39. package/dist/cjs/chrome/shortcuts.cjs +58 -0
  40. package/dist/cjs/chrome/shortcuts.native.js +72 -0
  41. package/dist/cjs/chrome/shortcuts.native.js.map +1 -0
  42. package/dist/cjs/chrome/user-session.cjs +100 -0
  43. package/dist/cjs/chrome/user-session.native.js +120 -0
  44. package/dist/cjs/chrome/user-session.native.js.map +1 -0
  45. package/dist/cjs/config/BackofficeProvider.cjs +164 -0
  46. package/dist/cjs/config/BackofficeProvider.native.js +217 -0
  47. package/dist/cjs/config/BackofficeProvider.native.js.map +1 -0
  48. package/dist/cjs/config/capabilities.cjs +123 -0
  49. package/dist/cjs/config/capabilities.native.js +155 -0
  50. package/dist/cjs/config/capabilities.native.js.map +1 -0
  51. package/dist/cjs/config/events.cjs +18 -0
  52. package/dist/cjs/config/events.native.js +21 -0
  53. package/dist/cjs/config/events.native.js.map +1 -0
  54. package/dist/cjs/config/slots.cjs +18 -0
  55. package/dist/cjs/config/slots.native.js +21 -0
  56. package/dist/cjs/config/slots.native.js.map +1 -0
  57. package/dist/cjs/i18n/en.cjs +101 -0
  58. package/dist/cjs/i18n/en.native.js +104 -0
  59. package/dist/cjs/i18n/en.native.js.map +1 -0
  60. package/dist/cjs/i18n/index.cjs +77 -0
  61. package/dist/cjs/i18n/index.native.js +102 -0
  62. package/dist/cjs/i18n/index.native.js.map +1 -0
  63. package/dist/cjs/index.cjs +109 -0
  64. package/dist/cjs/index.native.js +112 -0
  65. package/dist/cjs/index.native.js.map +1 -0
  66. package/dist/cjs/navigation/navigator.cjs +144 -0
  67. package/dist/cjs/navigation/navigator.native.js +307 -0
  68. package/dist/cjs/navigation/navigator.native.js.map +1 -0
  69. package/dist/cjs/navigation/paths.cjs +103 -0
  70. package/dist/cjs/navigation/paths.native.js +143 -0
  71. package/dist/cjs/navigation/paths.native.js.map +1 -0
  72. package/dist/cjs/oneAdapter/index.cjs +53 -0
  73. package/dist/cjs/oneAdapter/index.native.js +64 -0
  74. package/dist/cjs/oneAdapter/index.native.js.map +1 -0
  75. package/dist/cjs/shared/useFrappeApp.cjs +56 -0
  76. package/dist/cjs/shared/useFrappeApp.native.js +60 -0
  77. package/dist/cjs/shared/useFrappeApp.native.js.map +1 -0
  78. package/dist/cjs/shell/BackofficeShell.cjs +194 -0
  79. package/dist/cjs/shell/BackofficeShell.native.js +223 -0
  80. package/dist/cjs/shell/BackofficeShell.native.js.map +1 -0
  81. package/dist/cjs/shell/WorkspaceSidebar.cjs +115 -0
  82. package/dist/cjs/shell/WorkspaceSidebar.native.js +143 -0
  83. package/dist/cjs/shell/WorkspaceSidebar.native.js.map +1 -0
  84. package/dist/cjs/shell/useWorkspaces.cjs +131 -0
  85. package/dist/cjs/shell/useWorkspaces.native.js +173 -0
  86. package/dist/cjs/shell/useWorkspaces.native.js.map +1 -0
  87. package/dist/cjs/shell/workspaceIcons.cjs +64 -0
  88. package/dist/cjs/shell/workspaceIcons.native.js +67 -0
  89. package/dist/cjs/shell/workspaceIcons.native.js.map +1 -0
  90. package/dist/esm/chrome/BackofficeAwesomebar.mjs +70 -0
  91. package/dist/esm/chrome/BackofficeAwesomebar.mjs.map +1 -0
  92. package/dist/esm/chrome/BackofficeAwesomebar.native.js +78 -0
  93. package/dist/esm/chrome/BackofficeAwesomebar.native.js.map +1 -0
  94. package/dist/esm/chrome/CommandPalette.mjs +428 -0
  95. package/dist/esm/chrome/CommandPalette.mjs.map +1 -0
  96. package/dist/esm/chrome/CommandPalette.native.js +477 -0
  97. package/dist/esm/chrome/CommandPalette.native.js.map +1 -0
  98. package/dist/esm/chrome/HelpMenu.mjs +106 -0
  99. package/dist/esm/chrome/HelpMenu.mjs.map +1 -0
  100. package/dist/esm/chrome/HelpMenu.native.js +117 -0
  101. package/dist/esm/chrome/HelpMenu.native.js.map +1 -0
  102. package/dist/esm/chrome/NotificationsButton.mjs +87 -0
  103. package/dist/esm/chrome/NotificationsButton.mjs.map +1 -0
  104. package/dist/esm/chrome/NotificationsButton.native.js +87 -0
  105. package/dist/esm/chrome/NotificationsButton.native.js.map +1 -0
  106. package/dist/esm/chrome/UserMenu.mjs +133 -0
  107. package/dist/esm/chrome/UserMenu.mjs.map +1 -0
  108. package/dist/esm/chrome/UserMenu.native.js +147 -0
  109. package/dist/esm/chrome/UserMenu.native.js.map +1 -0
  110. package/dist/esm/chrome/awesomebar-data.mjs +144 -0
  111. package/dist/esm/chrome/awesomebar-data.mjs.map +1 -0
  112. package/dist/esm/chrome/awesomebar-data.native.js +190 -0
  113. package/dist/esm/chrome/awesomebar-data.native.js.map +1 -0
  114. package/dist/esm/chrome/command-palette-model.mjs +183 -0
  115. package/dist/esm/chrome/command-palette-model.mjs.map +1 -0
  116. package/dist/esm/chrome/command-palette-model.native.js +273 -0
  117. package/dist/esm/chrome/command-palette-model.native.js.map +1 -0
  118. package/dist/esm/chrome/help-about-dialog.mjs +111 -0
  119. package/dist/esm/chrome/help-about-dialog.mjs.map +1 -0
  120. package/dist/esm/chrome/help-about-dialog.native.js +118 -0
  121. package/dist/esm/chrome/help-about-dialog.native.js.map +1 -0
  122. package/dist/esm/chrome/help-shortcuts-dialog.mjs +130 -0
  123. package/dist/esm/chrome/help-shortcuts-dialog.mjs.map +1 -0
  124. package/dist/esm/chrome/help-shortcuts-dialog.native.js +140 -0
  125. package/dist/esm/chrome/help-shortcuts-dialog.native.js.map +1 -0
  126. package/dist/esm/chrome/notifications-data.mjs +165 -0
  127. package/dist/esm/chrome/notifications-data.mjs.map +1 -0
  128. package/dist/esm/chrome/notifications-data.native.js +232 -0
  129. package/dist/esm/chrome/notifications-data.native.js.map +1 -0
  130. package/dist/esm/chrome/notifications-panel.mjs +146 -0
  131. package/dist/esm/chrome/notifications-panel.mjs.map +1 -0
  132. package/dist/esm/chrome/notifications-panel.native.js +161 -0
  133. package/dist/esm/chrome/notifications-panel.native.js.map +1 -0
  134. package/dist/esm/chrome/notifications-utils.mjs +17 -0
  135. package/dist/esm/chrome/notifications-utils.mjs.map +1 -0
  136. package/dist/esm/chrome/notifications-utils.native.js +17 -0
  137. package/dist/esm/chrome/notifications-utils.native.js.map +1 -0
  138. package/dist/esm/chrome/shortcuts.mjs +33 -0
  139. package/dist/esm/chrome/shortcuts.mjs.map +1 -0
  140. package/dist/esm/chrome/shortcuts.native.js +44 -0
  141. package/dist/esm/chrome/shortcuts.native.js.map +1 -0
  142. package/dist/esm/chrome/user-session.mjs +73 -0
  143. package/dist/esm/chrome/user-session.mjs.map +1 -0
  144. package/dist/esm/chrome/user-session.native.js +79 -0
  145. package/dist/esm/chrome/user-session.native.js.map +1 -0
  146. package/dist/esm/config/BackofficeProvider.mjs +132 -0
  147. package/dist/esm/config/BackofficeProvider.mjs.map +1 -0
  148. package/dist/esm/config/BackofficeProvider.native.js +171 -0
  149. package/dist/esm/config/BackofficeProvider.native.js.map +1 -0
  150. package/dist/esm/config/capabilities.mjs +97 -0
  151. package/dist/esm/config/capabilities.mjs.map +1 -0
  152. package/dist/esm/config/capabilities.native.js +126 -0
  153. package/dist/esm/config/capabilities.native.js.map +1 -0
  154. package/dist/esm/config/events.mjs +2 -0
  155. package/dist/esm/config/events.mjs.map +1 -0
  156. package/dist/esm/config/events.native.js +2 -0
  157. package/dist/esm/config/events.native.js.map +1 -0
  158. package/dist/esm/config/slots.mjs +2 -0
  159. package/dist/esm/config/slots.mjs.map +1 -0
  160. package/dist/esm/config/slots.native.js +2 -0
  161. package/dist/esm/config/slots.native.js.map +1 -0
  162. package/dist/esm/i18n/en.mjs +76 -0
  163. package/dist/esm/i18n/en.mjs.map +1 -0
  164. package/dist/esm/i18n/en.native.js +76 -0
  165. package/dist/esm/i18n/en.native.js.map +1 -0
  166. package/dist/esm/i18n/index.mjs +40 -0
  167. package/dist/esm/i18n/index.mjs.map +1 -0
  168. package/dist/esm/i18n/index.native.js +62 -0
  169. package/dist/esm/i18n/index.native.js.map +1 -0
  170. package/dist/esm/index.mjs +26 -0
  171. package/dist/esm/index.mjs.map +1 -0
  172. package/dist/esm/index.native.js +26 -0
  173. package/dist/esm/index.native.js.map +1 -0
  174. package/dist/esm/navigation/navigator.mjs +115 -0
  175. package/dist/esm/navigation/navigator.mjs.map +1 -0
  176. package/dist/esm/navigation/navigator.native.js +275 -0
  177. package/dist/esm/navigation/navigator.native.js.map +1 -0
  178. package/dist/esm/navigation/paths.mjs +66 -0
  179. package/dist/esm/navigation/paths.mjs.map +1 -0
  180. package/dist/esm/navigation/paths.native.js +103 -0
  181. package/dist/esm/navigation/paths.native.js.map +1 -0
  182. package/dist/esm/oneAdapter/index.mjs +28 -0
  183. package/dist/esm/oneAdapter/index.mjs.map +1 -0
  184. package/dist/esm/oneAdapter/index.native.js +36 -0
  185. package/dist/esm/oneAdapter/index.native.js.map +1 -0
  186. package/dist/esm/shared/useFrappeApp.mjs +31 -0
  187. package/dist/esm/shared/useFrappeApp.mjs.map +1 -0
  188. package/dist/esm/shared/useFrappeApp.native.js +32 -0
  189. package/dist/esm/shared/useFrappeApp.native.js.map +1 -0
  190. package/dist/esm/shell/BackofficeShell.mjs +169 -0
  191. package/dist/esm/shell/BackofficeShell.mjs.map +1 -0
  192. package/dist/esm/shell/BackofficeShell.native.js +195 -0
  193. package/dist/esm/shell/BackofficeShell.native.js.map +1 -0
  194. package/dist/esm/shell/WorkspaceSidebar.mjs +89 -0
  195. package/dist/esm/shell/WorkspaceSidebar.mjs.map +1 -0
  196. package/dist/esm/shell/WorkspaceSidebar.native.js +114 -0
  197. package/dist/esm/shell/WorkspaceSidebar.native.js.map +1 -0
  198. package/dist/esm/shell/useWorkspaces.mjs +104 -0
  199. package/dist/esm/shell/useWorkspaces.mjs.map +1 -0
  200. package/dist/esm/shell/useWorkspaces.native.js +143 -0
  201. package/dist/esm/shell/useWorkspaces.native.js.map +1 -0
  202. package/dist/esm/shell/workspaceIcons.mjs +39 -0
  203. package/dist/esm/shell/workspaceIcons.mjs.map +1 -0
  204. package/dist/esm/shell/workspaceIcons.native.js +39 -0
  205. package/dist/esm/shell/workspaceIcons.native.js.map +1 -0
  206. package/dist/jsx/chrome/BackofficeAwesomebar.mjs +70 -0
  207. package/dist/jsx/chrome/BackofficeAwesomebar.mjs.map +1 -0
  208. package/dist/jsx/chrome/BackofficeAwesomebar.native.js +106 -0
  209. package/dist/jsx/chrome/BackofficeAwesomebar.native.js.map +1 -0
  210. package/dist/jsx/chrome/CommandPalette.mjs +428 -0
  211. package/dist/jsx/chrome/CommandPalette.mjs.map +1 -0
  212. package/dist/jsx/chrome/CommandPalette.native.js +505 -0
  213. package/dist/jsx/chrome/CommandPalette.native.js.map +1 -0
  214. package/dist/jsx/chrome/HelpMenu.mjs +106 -0
  215. package/dist/jsx/chrome/HelpMenu.mjs.map +1 -0
  216. package/dist/jsx/chrome/HelpMenu.native.js +145 -0
  217. package/dist/jsx/chrome/HelpMenu.native.js.map +1 -0
  218. package/dist/jsx/chrome/NotificationsButton.mjs +87 -0
  219. package/dist/jsx/chrome/NotificationsButton.mjs.map +1 -0
  220. package/dist/jsx/chrome/NotificationsButton.native.js +115 -0
  221. package/dist/jsx/chrome/NotificationsButton.native.js.map +1 -0
  222. package/dist/jsx/chrome/UserMenu.mjs +133 -0
  223. package/dist/jsx/chrome/UserMenu.mjs.map +1 -0
  224. package/dist/jsx/chrome/UserMenu.native.js +186 -0
  225. package/dist/jsx/chrome/UserMenu.native.js.map +1 -0
  226. package/dist/jsx/chrome/awesomebar-data.mjs +144 -0
  227. package/dist/jsx/chrome/awesomebar-data.mjs.map +1 -0
  228. package/dist/jsx/chrome/awesomebar-data.native.js +233 -0
  229. package/dist/jsx/chrome/awesomebar-data.native.js.map +1 -0
  230. package/dist/jsx/chrome/command-palette-model.mjs +183 -0
  231. package/dist/jsx/chrome/command-palette-model.mjs.map +1 -0
  232. package/dist/jsx/chrome/command-palette-model.native.js +301 -0
  233. package/dist/jsx/chrome/command-palette-model.native.js.map +1 -0
  234. package/dist/jsx/chrome/help-about-dialog.mjs +111 -0
  235. package/dist/jsx/chrome/help-about-dialog.mjs.map +1 -0
  236. package/dist/jsx/chrome/help-about-dialog.native.js +146 -0
  237. package/dist/jsx/chrome/help-about-dialog.native.js.map +1 -0
  238. package/dist/jsx/chrome/help-shortcuts-dialog.mjs +130 -0
  239. package/dist/jsx/chrome/help-shortcuts-dialog.mjs.map +1 -0
  240. package/dist/jsx/chrome/help-shortcuts-dialog.native.js +168 -0
  241. package/dist/jsx/chrome/help-shortcuts-dialog.native.js.map +1 -0
  242. package/dist/jsx/chrome/notifications-data.mjs +165 -0
  243. package/dist/jsx/chrome/notifications-data.mjs.map +1 -0
  244. package/dist/jsx/chrome/notifications-data.native.js +271 -0
  245. package/dist/jsx/chrome/notifications-data.native.js.map +1 -0
  246. package/dist/jsx/chrome/notifications-panel.mjs +146 -0
  247. package/dist/jsx/chrome/notifications-panel.mjs.map +1 -0
  248. package/dist/jsx/chrome/notifications-panel.native.js +189 -0
  249. package/dist/jsx/chrome/notifications-panel.native.js.map +1 -0
  250. package/dist/jsx/chrome/notifications-utils.mjs +17 -0
  251. package/dist/jsx/chrome/notifications-utils.mjs.map +1 -0
  252. package/dist/jsx/chrome/notifications-utils.native.js +46 -0
  253. package/dist/jsx/chrome/notifications-utils.native.js.map +1 -0
  254. package/dist/jsx/chrome/shortcuts.mjs +33 -0
  255. package/dist/jsx/chrome/shortcuts.mjs.map +1 -0
  256. package/dist/jsx/chrome/shortcuts.native.js +72 -0
  257. package/dist/jsx/chrome/shortcuts.native.js.map +1 -0
  258. package/dist/jsx/chrome/user-session.mjs +73 -0
  259. package/dist/jsx/chrome/user-session.mjs.map +1 -0
  260. package/dist/jsx/chrome/user-session.native.js +120 -0
  261. package/dist/jsx/chrome/user-session.native.js.map +1 -0
  262. package/dist/jsx/config/BackofficeProvider.mjs +132 -0
  263. package/dist/jsx/config/BackofficeProvider.mjs.map +1 -0
  264. package/dist/jsx/config/BackofficeProvider.native.js +217 -0
  265. package/dist/jsx/config/BackofficeProvider.native.js.map +1 -0
  266. package/dist/jsx/config/capabilities.mjs +97 -0
  267. package/dist/jsx/config/capabilities.mjs.map +1 -0
  268. package/dist/jsx/config/capabilities.native.js +155 -0
  269. package/dist/jsx/config/capabilities.native.js.map +1 -0
  270. package/dist/jsx/config/events.mjs +2 -0
  271. package/dist/jsx/config/events.mjs.map +1 -0
  272. package/dist/jsx/config/events.native.js +21 -0
  273. package/dist/jsx/config/events.native.js.map +1 -0
  274. package/dist/jsx/config/slots.mjs +2 -0
  275. package/dist/jsx/config/slots.mjs.map +1 -0
  276. package/dist/jsx/config/slots.native.js +21 -0
  277. package/dist/jsx/config/slots.native.js.map +1 -0
  278. package/dist/jsx/i18n/en.mjs +76 -0
  279. package/dist/jsx/i18n/en.mjs.map +1 -0
  280. package/dist/jsx/i18n/en.native.js +104 -0
  281. package/dist/jsx/i18n/en.native.js.map +1 -0
  282. package/dist/jsx/i18n/index.mjs +40 -0
  283. package/dist/jsx/i18n/index.mjs.map +1 -0
  284. package/dist/jsx/i18n/index.native.js +102 -0
  285. package/dist/jsx/i18n/index.native.js.map +1 -0
  286. package/dist/jsx/index.js +26 -0
  287. package/dist/jsx/index.js.map +1 -0
  288. package/dist/jsx/index.mjs +26 -0
  289. package/dist/jsx/index.mjs.map +1 -0
  290. package/dist/jsx/index.native.js +112 -0
  291. package/dist/jsx/index.native.js.map +1 -0
  292. package/dist/jsx/navigation/navigator.mjs +115 -0
  293. package/dist/jsx/navigation/navigator.mjs.map +1 -0
  294. package/dist/jsx/navigation/navigator.native.js +307 -0
  295. package/dist/jsx/navigation/navigator.native.js.map +1 -0
  296. package/dist/jsx/navigation/paths.mjs +66 -0
  297. package/dist/jsx/navigation/paths.mjs.map +1 -0
  298. package/dist/jsx/navigation/paths.native.js +143 -0
  299. package/dist/jsx/navigation/paths.native.js.map +1 -0
  300. package/dist/jsx/oneAdapter/index.mjs +28 -0
  301. package/dist/jsx/oneAdapter/index.mjs.map +1 -0
  302. package/dist/jsx/oneAdapter/index.native.js +64 -0
  303. package/dist/jsx/oneAdapter/index.native.js.map +1 -0
  304. package/dist/jsx/shared/useFrappeApp.mjs +31 -0
  305. package/dist/jsx/shared/useFrappeApp.mjs.map +1 -0
  306. package/dist/jsx/shared/useFrappeApp.native.js +60 -0
  307. package/dist/jsx/shared/useFrappeApp.native.js.map +1 -0
  308. package/dist/jsx/shell/BackofficeShell.mjs +169 -0
  309. package/dist/jsx/shell/BackofficeShell.mjs.map +1 -0
  310. package/dist/jsx/shell/BackofficeShell.native.js +223 -0
  311. package/dist/jsx/shell/BackofficeShell.native.js.map +1 -0
  312. package/dist/jsx/shell/WorkspaceSidebar.mjs +89 -0
  313. package/dist/jsx/shell/WorkspaceSidebar.mjs.map +1 -0
  314. package/dist/jsx/shell/WorkspaceSidebar.native.js +143 -0
  315. package/dist/jsx/shell/WorkspaceSidebar.native.js.map +1 -0
  316. package/dist/jsx/shell/useWorkspaces.mjs +104 -0
  317. package/dist/jsx/shell/useWorkspaces.mjs.map +1 -0
  318. package/dist/jsx/shell/useWorkspaces.native.js +173 -0
  319. package/dist/jsx/shell/useWorkspaces.native.js.map +1 -0
  320. package/dist/jsx/shell/workspaceIcons.mjs +39 -0
  321. package/dist/jsx/shell/workspaceIcons.mjs.map +1 -0
  322. package/dist/jsx/shell/workspaceIcons.native.js +67 -0
  323. package/dist/jsx/shell/workspaceIcons.native.js.map +1 -0
  324. package/package.json +123 -0
  325. package/src/chrome/BackofficeAwesomebar.tsx +89 -0
  326. package/src/chrome/CommandPalette.spec.tsx +252 -0
  327. package/src/chrome/CommandPalette.tsx +520 -0
  328. package/src/chrome/HelpMenu.tsx +119 -0
  329. package/src/chrome/NotificationsButton.tsx +87 -0
  330. package/src/chrome/UserMenu.tsx +173 -0
  331. package/src/chrome/awesomebar-data.tsx +252 -0
  332. package/src/chrome/command-palette-model.ts +291 -0
  333. package/src/chrome/help-about-dialog.tsx +130 -0
  334. package/src/chrome/help-shortcuts-dialog.tsx +144 -0
  335. package/src/chrome/notifications-data.tsx +287 -0
  336. package/src/chrome/notifications-panel.tsx +175 -0
  337. package/src/chrome/notifications-utils.tsx +44 -0
  338. package/src/chrome/shortcuts.ts +53 -0
  339. package/src/chrome/user-session.tsx +116 -0
  340. package/src/config/BackofficeProvider.spec.tsx +126 -0
  341. package/src/config/BackofficeProvider.tsx +315 -0
  342. package/src/config/capabilities.ts +172 -0
  343. package/src/config/events.ts +19 -0
  344. package/src/config/slots.ts +28 -0
  345. package/src/i18n/en.ts +83 -0
  346. package/src/i18n/index.ts +69 -0
  347. package/src/index.ts +150 -0
  348. package/src/navigation/navigator.spec.ts +106 -0
  349. package/src/navigation/navigator.ts +209 -0
  350. package/src/navigation/paths.ts +146 -0
  351. package/src/oneAdapter/index.tsx +61 -0
  352. package/src/shared/useFrappeApp.ts +39 -0
  353. package/src/shell/BackofficeShell.tsx +222 -0
  354. package/src/shell/WorkspaceSidebar.tsx +119 -0
  355. package/src/shell/useWorkspaces.ts +202 -0
  356. package/src/shell/workspaceIcons.ts +76 -0
  357. package/types/chrome/BackofficeAwesomebar.d.ts +12 -0
  358. package/types/chrome/BackofficeAwesomebar.d.ts.map +1 -0
  359. package/types/chrome/CommandPalette.d.ts +6 -0
  360. package/types/chrome/CommandPalette.d.ts.map +1 -0
  361. package/types/chrome/HelpMenu.d.ts +2 -0
  362. package/types/chrome/HelpMenu.d.ts.map +1 -0
  363. package/types/chrome/NotificationsButton.d.ts +2 -0
  364. package/types/chrome/NotificationsButton.d.ts.map +1 -0
  365. package/types/chrome/UserMenu.d.ts +6 -0
  366. package/types/chrome/UserMenu.d.ts.map +1 -0
  367. package/types/chrome/awesomebar-data.d.ts +52 -0
  368. package/types/chrome/awesomebar-data.d.ts.map +1 -0
  369. package/types/chrome/command-palette-model.d.ts +47 -0
  370. package/types/chrome/command-palette-model.d.ts.map +1 -0
  371. package/types/chrome/help-about-dialog.d.ts +12 -0
  372. package/types/chrome/help-about-dialog.d.ts.map +1 -0
  373. package/types/chrome/help-shortcuts-dialog.d.ts +6 -0
  374. package/types/chrome/help-shortcuts-dialog.d.ts.map +1 -0
  375. package/types/chrome/notifications-data.d.ts +34 -0
  376. package/types/chrome/notifications-data.d.ts.map +1 -0
  377. package/types/chrome/notifications-panel.d.ts +11 -0
  378. package/types/chrome/notifications-panel.d.ts.map +1 -0
  379. package/types/chrome/notifications-utils.d.ts +21 -0
  380. package/types/chrome/notifications-utils.d.ts.map +1 -0
  381. package/types/chrome/shortcuts.d.ts +6 -0
  382. package/types/chrome/shortcuts.d.ts.map +1 -0
  383. package/types/chrome/user-session.d.ts +19 -0
  384. package/types/chrome/user-session.d.ts.map +1 -0
  385. package/types/config/BackofficeProvider.d.ts +128 -0
  386. package/types/config/BackofficeProvider.d.ts.map +1 -0
  387. package/types/config/capabilities.d.ts +109 -0
  388. package/types/config/capabilities.d.ts.map +1 -0
  389. package/types/config/events.d.ts +39 -0
  390. package/types/config/events.d.ts.map +1 -0
  391. package/types/config/slots.d.ts +32 -0
  392. package/types/config/slots.d.ts.map +1 -0
  393. package/types/i18n/en.d.ts +83 -0
  394. package/types/i18n/en.d.ts.map +1 -0
  395. package/types/i18n/index.d.ts +27 -0
  396. package/types/i18n/index.d.ts.map +1 -0
  397. package/types/index.d.ts +55 -0
  398. package/types/index.d.ts.map +1 -0
  399. package/types/navigation/navigator.d.ts +98 -0
  400. package/types/navigation/navigator.d.ts.map +1 -0
  401. package/types/navigation/paths.d.ts +60 -0
  402. package/types/navigation/paths.d.ts.map +1 -0
  403. package/types/oneAdapter/index.d.ts +8 -0
  404. package/types/oneAdapter/index.d.ts.map +1 -0
  405. package/types/shared/useFrappeApp.d.ts +10 -0
  406. package/types/shared/useFrappeApp.d.ts.map +1 -0
  407. package/types/shell/BackofficeShell.d.ts +10 -0
  408. package/types/shell/BackofficeShell.d.ts.map +1 -0
  409. package/types/shell/WorkspaceSidebar.d.ts +9 -0
  410. package/types/shell/WorkspaceSidebar.d.ts.map +1 -0
  411. package/types/shell/useWorkspaces.d.ts +43 -0
  412. package/types/shell/useWorkspaces.d.ts.map +1 -0
  413. package/types/shell/workspaceIcons.d.ts +9 -0
  414. package/types/shell/workspaceIcons.d.ts.map +1 -0
@@ -0,0 +1,291 @@
1
+ // Section model for the backoffice command palette (MOD-01) — ONE data hook
2
+ // consumed by both palette containers (centered overlay ≥sm, full sheet <sm).
3
+ //
4
+ // Composes the awesomebar data layer (catalog, global search, recents,
5
+ // ranking) into fixed-order sections:
6
+ // Recents → readRecentItems store (query-filtered while typing)
7
+ // Actions → contextual commands for the best doctype match
8
+ // ("New X", "X List / Report / Kanban" — capability-gated)
9
+ // Navigation → workspaces + doctypes from the catalog (rankNameMatches)
10
+ // Documents → frappe.utils.global_search hits (doctype badge + snippet)
11
+ //
12
+ // Empty sections are dropped; the provider's doctype scope (allow/deny)
13
+ // filters every doctype-derived row; `newDoc` and `views` capabilities gate
14
+ // the action commands.
15
+ import {
16
+ ClockIcon,
17
+ FileTextIcon,
18
+ GlobeIcon,
19
+ KanbanIcon,
20
+ ListIcon,
21
+ PlusIcon,
22
+ TableIcon,
23
+ } from "@phosphor-icons/react";
24
+ import type { FC } from "react";
25
+ import { useEffect, useMemo, useState } from "react";
26
+ import { useTranslation } from "react-i18next";
27
+ import {
28
+ useBackofficeCapabilities,
29
+ useBackofficePaths,
30
+ useIsDoctypeAllowed,
31
+ } from "../config/BackofficeProvider";
32
+ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
33
+ import {
34
+ rankNameMatches,
35
+ readRecentItems,
36
+ toContentSnippet,
37
+ useAwesomebarCatalog,
38
+ useGlobalSearch,
39
+ type RecentItem,
40
+ } from "./awesomebar-data";
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // Types
44
+ // ---------------------------------------------------------------------------
45
+
46
+ interface IconProps {
47
+ size?: number | string;
48
+ color?: string;
49
+ }
50
+
51
+ export type CommandPaletteSectionId = "recents" | "actions" | "navigation" | "documents";
52
+
53
+ export interface CommandPaletteItem {
54
+ id: string;
55
+ label: string;
56
+ /** Muted one-line detail under the label (document content snippet). */
57
+ description?: string;
58
+ /** Right-aligned type badge ("Workspace", "DocType", the hit's doctype). */
59
+ badge?: string;
60
+ icon: FC<IconProps>;
61
+ path: string;
62
+ }
63
+
64
+ export interface CommandPaletteSection {
65
+ id: CommandPaletteSectionId;
66
+ /** Translated section header. */
67
+ label: string;
68
+ items: CommandPaletteItem[];
69
+ }
70
+
71
+ export interface CommandPaletteModel {
72
+ /** Non-empty sections in fixed order (recents → actions → navigation → documents). */
73
+ sections: CommandPaletteSection[];
74
+ /** Section items flattened in render order — the roving-highlight index space. */
75
+ items: CommandPaletteItem[];
76
+ /** Global search in flight for the debounced query. */
77
+ searching: boolean;
78
+ /** The trimmed query the sections were built from. */
79
+ query: string;
80
+ /** Trimmed query is non-empty. */
81
+ hasQuery: boolean;
82
+ /** A settled non-empty query produced zero rows (honest empty state). */
83
+ noResults: boolean;
84
+ }
85
+
86
+ // ---------------------------------------------------------------------------
87
+ // Limits (desk-style caps per section)
88
+ // ---------------------------------------------------------------------------
89
+
90
+ const maxRecentsEmptyQuery = 8;
91
+ const maxRecentsWithQuery = 4;
92
+ const maxNavWorkspaces = 4;
93
+ const maxNavDoctypes = 4;
94
+
95
+ /** Action view commands for the top doctype match, in render order. */
96
+ const actionViews = ["list", "report", "kanban"] as const;
97
+
98
+ const actionViewIcons: Record<(typeof actionViews)[number], FC<IconProps>> = {
99
+ list: ListIcon,
100
+ report: TableIcon,
101
+ kanban: KanbanIcon,
102
+ };
103
+
104
+ // Explicit (greppable) i18n keys per view command.
105
+ const actionViewLabelKeys: Record<
106
+ (typeof actionViews)[number],
107
+ { key: string; defaultValue: string }
108
+ > = {
109
+ list: { key: "awesomebar.listCommand", defaultValue: "{{doctype}} List" },
110
+ report: { key: "awesomebar.reportCommand", defaultValue: "{{doctype}} Report" },
111
+ kanban: { key: "awesomebar.kanbanCommand", defaultValue: "{{doctype}} Kanban" },
112
+ };
113
+
114
+ // ---------------------------------------------------------------------------
115
+ // Hook
116
+ // ---------------------------------------------------------------------------
117
+
118
+ export interface UseCommandPaletteModelOptions {
119
+ /** Raw query (drives catalog-derived sections synchronously). */
120
+ query: string;
121
+ /** Debounced query (drives the global_search RPC). */
122
+ debouncedQuery: string;
123
+ /** Palette visibility — recents are re-read on every open. */
124
+ open: boolean;
125
+ }
126
+
127
+ export function useCommandPaletteModel({
128
+ query,
129
+ debouncedQuery,
130
+ open,
131
+ }: UseCommandPaletteModelOptions): CommandPaletteModel {
132
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
133
+ const paths = useBackofficePaths();
134
+ const capabilities = useBackofficeCapabilities();
135
+ const isDoctypeAllowed = useIsDoctypeAllowed();
136
+
137
+ const { catalog } = useAwesomebarCatalog();
138
+ const { hits, searching } = useGlobalSearch(debouncedQuery);
139
+ const [recents, setRecents] = useState<RecentItem[]>([]);
140
+
141
+ // Fresh recents on every open (another surface may have pushed a visit
142
+ // since the last open).
143
+ useEffect(() => {
144
+ if (!open) return;
145
+ let cancelled = false;
146
+ void readRecentItems().then((stored) => {
147
+ if (!cancelled) setRecents(stored);
148
+ });
149
+ return () => {
150
+ cancelled = true;
151
+ };
152
+ }, [open]);
153
+
154
+ const trimmed = query.trim();
155
+
156
+ const sections = useMemo<CommandPaletteSection[]>(() => {
157
+ const next: CommandPaletteSection[] = [];
158
+
159
+ // ── Recents ──────────────────────────────────────────────────────────
160
+ const lowerQuery = trimmed.toLowerCase();
161
+ const matchingRecents = trimmed
162
+ ? recents
163
+ .filter((recent) => recent.label.toLowerCase().includes(lowerQuery))
164
+ .slice(0, maxRecentsWithQuery)
165
+ : recents.slice(0, maxRecentsEmptyQuery);
166
+ if (matchingRecents.length > 0) {
167
+ next.push({
168
+ id: "recents",
169
+ label: t("awesomebar.recents", "Recents"),
170
+ items: matchingRecents.map((recent) => ({
171
+ id: `recent:${recent.path}`,
172
+ label: recent.label,
173
+ path: recent.path,
174
+ icon: ClockIcon,
175
+ })),
176
+ });
177
+ }
178
+
179
+ if (trimmed) {
180
+ const scopedDoctypes = (catalog?.doctypes ?? []).filter(isDoctypeAllowed);
181
+ const rankedDoctypes = rankNameMatches(trimmed, scopedDoctypes, maxNavDoctypes + 1);
182
+ const topDoctype = rankedDoctypes[0];
183
+
184
+ // ── Actions: contextual commands for the best doctype match ────────
185
+ const actionItems: CommandPaletteItem[] = [];
186
+ if (topDoctype) {
187
+ if (capabilities.newDoc.enabled) {
188
+ actionItems.push({
189
+ id: `new:${topDoctype}`,
190
+ label: t("awesomebar.newCommand", {
191
+ defaultValue: "New {{doctype}}",
192
+ doctype: topDoctype,
193
+ }),
194
+ path: paths.newDoc(topDoctype),
195
+ icon: PlusIcon,
196
+ });
197
+ }
198
+ if (capabilities.views.enabled) {
199
+ for (const view of actionViews) {
200
+ if (!capabilities.views.allow.includes(view)) continue;
201
+ const { key, defaultValue } = actionViewLabelKeys[view];
202
+ actionItems.push({
203
+ id: `${view}:${topDoctype}`,
204
+ label: t(key, { defaultValue, doctype: topDoctype }),
205
+ path: paths.view(topDoctype, view),
206
+ icon: actionViewIcons[view],
207
+ });
208
+ }
209
+ }
210
+ }
211
+ if (actionItems.length > 0) {
212
+ next.push({
213
+ id: "actions",
214
+ label: t("awesomebar.actions", "Actions"),
215
+ items: actionItems,
216
+ });
217
+ }
218
+
219
+ // ── Navigation: workspaces + further doctypes from the catalog ─────
220
+ const navigationItems: CommandPaletteItem[] = [];
221
+ const workspaces = catalog?.workspaces ?? [];
222
+ const byTitle = new Map(workspaces.map((workspace) => [workspace.title, workspace]));
223
+ for (const title of rankNameMatches(
224
+ trimmed,
225
+ workspaces.map((workspace) => workspace.title),
226
+ maxNavWorkspaces,
227
+ )) {
228
+ const workspace = byTitle.get(title);
229
+ if (!workspace) continue;
230
+ navigationItems.push({
231
+ id: `workspace:${workspace.name}`,
232
+ label: workspace.title,
233
+ badge: t("awesomebar.workspaceBadge", "Workspace"),
234
+ path: paths.workspace(workspace.name),
235
+ icon: GlobeIcon,
236
+ });
237
+ }
238
+ // The top match already owns the Actions section — list the rest.
239
+ for (const doctype of rankedDoctypes.slice(topDoctype ? 1 : 0, maxNavDoctypes + 1)) {
240
+ navigationItems.push({
241
+ id: `doctype:${doctype}`,
242
+ label: doctype,
243
+ badge: t("awesomebar.doctypeBadge", "DocType"),
244
+ path: paths.list(doctype),
245
+ icon: ListIcon,
246
+ });
247
+ }
248
+ if (navigationItems.length > 0) {
249
+ next.push({
250
+ id: "navigation",
251
+ label: t("awesomebar.navigation", "Navigation"),
252
+ items: navigationItems,
253
+ });
254
+ }
255
+
256
+ // ── Documents: global-search hits (scope-filtered) ──────────────────
257
+ const documentItems: CommandPaletteItem[] = [];
258
+ for (const hit of hits) {
259
+ if (!isDoctypeAllowed(hit.doctype)) continue;
260
+ documentItems.push({
261
+ id: `doc:${hit.doctype}:${hit.name}`,
262
+ label: hit.name,
263
+ badge: hit.doctype,
264
+ description: toContentSnippet(hit.content),
265
+ path: paths.form(hit.doctype, hit.name),
266
+ icon: FileTextIcon,
267
+ });
268
+ }
269
+ if (documentItems.length > 0) {
270
+ next.push({
271
+ id: "documents",
272
+ label: t("awesomebar.documents", "Documents"),
273
+ items: documentItems,
274
+ });
275
+ }
276
+ }
277
+
278
+ return next;
279
+ }, [trimmed, recents, catalog, hits, capabilities, paths, isDoctypeAllowed, t]);
280
+
281
+ const items = useMemo(() => sections.flatMap((section) => section.items), [sections]);
282
+
283
+ return {
284
+ sections,
285
+ items,
286
+ searching,
287
+ query: trimmed,
288
+ hasQuery: Boolean(trimmed),
289
+ noResults: Boolean(trimmed) && !searching && items.length === 0,
290
+ };
291
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * About dialog (desk "About" parity): backoffice tagline + installed app
3
+ * versions from `frappe.utils.change_log.get_versions`.
4
+ *
5
+ * RPC shape: { message: Record<appKey, { title, description, branch, version }> }
6
+ * Versions are fetched lazily on first open and kept for the dialog's
7
+ * lifetime; a failed fetch retries on the next open.
8
+ */
9
+ import {
10
+ Button,
11
+ Dialog,
12
+ DialogContent,
13
+ Paragraph,
14
+ SizableText,
15
+ Spinner,
16
+ XStack,
17
+ YStack,
18
+ } from "@multiplatform.one/components";
19
+ import { useEffect, useState } from "react";
20
+ import { useTranslation } from "react-i18next";
21
+ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
22
+ import { useFrappeApp } from "../shared/useFrappeApp";
23
+
24
+ export interface FrappeAppVersion {
25
+ title?: string;
26
+ description?: string;
27
+ branch?: string;
28
+ version?: string;
29
+ }
30
+
31
+ interface GetVersionsPayload {
32
+ message?: Record<string, FrappeAppVersion>;
33
+ }
34
+
35
+ export interface HelpAboutDialogProps {
36
+ open: boolean;
37
+ onOpenChange: (open: boolean) => void;
38
+ }
39
+
40
+ export function HelpAboutDialog({ open, onOpenChange }: HelpAboutDialogProps) {
41
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
42
+ const app = useFrappeApp();
43
+ const [versions, setVersions] = useState<Record<string, FrappeAppVersion> | undefined>(undefined);
44
+ const [loading, setLoading] = useState(false);
45
+ const [failed, setFailed] = useState(false);
46
+
47
+ useEffect(() => {
48
+ if (!open || !app || versions) return;
49
+ let cancelled = false;
50
+ setLoading(true);
51
+ setFailed(false);
52
+ app
53
+ .call()
54
+ .get<GetVersionsPayload>("frappe.utils.change_log.get_versions")
55
+ .then((response) => {
56
+ if (cancelled) return;
57
+ setVersions(response.payload?.message ?? {});
58
+ })
59
+ .catch(() => {
60
+ if (cancelled) return;
61
+ setFailed(true);
62
+ })
63
+ .finally(() => {
64
+ if (!cancelled) setLoading(false);
65
+ });
66
+ return () => {
67
+ cancelled = true;
68
+ };
69
+ }, [open, app, versions]);
70
+
71
+ const entries = versions ? Object.entries(versions) : [];
72
+ const unavailable = !app || failed || (versions !== undefined && entries.length === 0);
73
+
74
+ return (
75
+ <Dialog modal open={open} onOpenChange={onOpenChange}>
76
+ <Dialog.Portal>
77
+ <Dialog.Overlay key="overlay" backgroundColor="$shadow6" />
78
+ <DialogContent
79
+ key="content"
80
+ width={420}
81
+ maxWidth="90%"
82
+ data-testid="backoffice-help-about-dialog"
83
+ >
84
+ <Dialog.Title size="$6">{t("help.aboutTitle", "About")}</Dialog.Title>
85
+ <Dialog.Description asChild>
86
+ <Paragraph size="$3" color="$color11">
87
+ {t(
88
+ "help.aboutTagline",
89
+ "Backoffice is the multiplatform.one recreation of the Frappe Desk — one codebase across web, mobile, and desktop.",
90
+ )}
91
+ </Paragraph>
92
+ </Dialog.Description>
93
+ <YStack gap="$2" marginTop="$2">
94
+ <SizableText size="$2" fontWeight="700" color="$color10" textTransform="uppercase">
95
+ {t("help.installedApps", "Installed Apps")}
96
+ </SizableText>
97
+ {loading && (
98
+ <XStack padding="$3" justifyContent="center">
99
+ <Spinner size="small" />
100
+ </XStack>
101
+ )}
102
+ {!loading && unavailable && (
103
+ <Paragraph size="$3" color="$color10">
104
+ {t("help.versionsUnavailable", "Version information is unavailable.")}
105
+ </Paragraph>
106
+ )}
107
+ {!loading &&
108
+ entries.map(([key, info]) => (
109
+ <XStack key={key} gap="$3" alignItems="baseline" justifyContent="space-between">
110
+ <SizableText size="$3" fontWeight="600" flex={1} numberOfLines={1}>
111
+ {info.title || key}
112
+ </SizableText>
113
+ <SizableText size="$3" color="$color11" flexShrink={0}>
114
+ {info.version
115
+ ? `v${info.version}${info.branch ? ` (${info.branch})` : ""}`
116
+ : (info.branch ?? "—")}
117
+ </SizableText>
118
+ </XStack>
119
+ ))}
120
+ </YStack>
121
+ <XStack justifyContent="flex-end" marginTop="$4">
122
+ <Dialog.Close asChild>
123
+ <Button size="$3">{t("help.close", "Close")}</Button>
124
+ </Dialog.Close>
125
+ </XStack>
126
+ </DialogContent>
127
+ </Dialog.Portal>
128
+ </Dialog>
129
+ );
130
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Keyboard Shortcuts dialog (desk "Keyboard Shortcuts" parity, scoped to what
3
+ * the backoffice actually implements — keep this list honest:
4
+ * - Mod+K / Mod+G focus the search bar (chrome/shortcuts.ts, shell-wired)
5
+ * - Mod+S saves the open document (form save shortcut)
6
+ * - Esc closes dialogs and menus (overlay default + shell drawer)
7
+ */
8
+ import {
9
+ Button,
10
+ Dialog,
11
+ DialogContent,
12
+ Paragraph,
13
+ SizableText,
14
+ XStack,
15
+ YStack,
16
+ } from "@multiplatform.one/components";
17
+ import { useTranslation } from "react-i18next";
18
+ import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
19
+
20
+ export interface HelpShortcutsDialogProps {
21
+ open: boolean;
22
+ onOpenChange: (open: boolean) => void;
23
+ }
24
+
25
+ /** Platform modifier label; SSR/native-safe (defaults to "Ctrl"). */
26
+ function getModLabel(): string {
27
+ if (
28
+ typeof navigator !== "undefined" &&
29
+ /Mac|iPhone|iPad|iPod/i.test(String(navigator.platform ?? ""))
30
+ ) {
31
+ return "\u2318";
32
+ }
33
+ return "Ctrl";
34
+ }
35
+
36
+ function KeyChip({ label }: { label: string }) {
37
+ return (
38
+ <XStack
39
+ borderWidth={1}
40
+ borderColor="$borderColor"
41
+ backgroundColor="$color2"
42
+ borderRadius="$2"
43
+ paddingHorizontal="$2"
44
+ paddingVertical="$1"
45
+ minWidth={28}
46
+ justifyContent="center"
47
+ >
48
+ <SizableText size="$1" fontWeight="600">
49
+ {label}
50
+ </SizableText>
51
+ </XStack>
52
+ );
53
+ }
54
+
55
+ interface ShortcutRowProps {
56
+ /** Alternative key combos, e.g. [["Ctrl","K"],["Ctrl","G"]]. */
57
+ combos: string[][];
58
+ description: string;
59
+ }
60
+
61
+ function ShortcutRow({ combos, description }: ShortcutRowProps) {
62
+ return (
63
+ <XStack gap="$3" alignItems="center">
64
+ <XStack width={150} gap="$1" alignItems="center" flexWrap="wrap" flexShrink={0}>
65
+ {combos.map((combo, comboIndex) => (
66
+ <XStack key={combo.join("+")} gap="$1" alignItems="center">
67
+ {comboIndex > 0 && (
68
+ <SizableText size="$2" color="$color10">
69
+ /
70
+ </SizableText>
71
+ )}
72
+ {combo.map((key, keyIndex) => (
73
+ <XStack key={key} gap="$1" alignItems="center">
74
+ {keyIndex > 0 && (
75
+ <SizableText size="$2" color="$color10">
76
+ +
77
+ </SizableText>
78
+ )}
79
+ <KeyChip label={key} />
80
+ </XStack>
81
+ ))}
82
+ </XStack>
83
+ ))}
84
+ </XStack>
85
+ <SizableText size="$3" flex={1}>
86
+ {description}
87
+ </SizableText>
88
+ </XStack>
89
+ );
90
+ }
91
+
92
+ export function HelpShortcutsDialog({ open, onOpenChange }: HelpShortcutsDialogProps) {
93
+ const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
94
+ const mod = getModLabel();
95
+
96
+ const rows: ShortcutRowProps[] = [
97
+ {
98
+ combos: [
99
+ [mod, "K"],
100
+ [mod, "G"],
101
+ ],
102
+ description: t("help.shortcutFocusSearch", "Open the command palette"),
103
+ },
104
+ {
105
+ combos: [[mod, "S"]],
106
+ description: t("help.shortcutSaveForm", "Save the open document"),
107
+ },
108
+ {
109
+ combos: [["Esc"]],
110
+ description: t("help.shortcutCloseOverlays", "Close dialogs and menus"),
111
+ },
112
+ ];
113
+
114
+ return (
115
+ <Dialog modal open={open} onOpenChange={onOpenChange}>
116
+ <Dialog.Portal>
117
+ <Dialog.Overlay key="overlay" backgroundColor="$shadow6" />
118
+ <DialogContent
119
+ key="content"
120
+ width={440}
121
+ maxWidth="90%"
122
+ data-testid="backoffice-help-shortcuts-dialog"
123
+ >
124
+ <Dialog.Title size="$6">{t("help.shortcutsTitle", "Keyboard Shortcuts")}</Dialog.Title>
125
+ <Dialog.Description asChild>
126
+ <Paragraph size="$3" color="$color11">
127
+ {t("help.shortcutsIntro", "Shortcuts available across the backoffice (web).")}
128
+ </Paragraph>
129
+ </Dialog.Description>
130
+ <YStack gap="$3" marginTop="$2">
131
+ {rows.map((row) => (
132
+ <ShortcutRow key={row.description} {...row} />
133
+ ))}
134
+ </YStack>
135
+ <XStack justifyContent="flex-end" marginTop="$4">
136
+ <Dialog.Close asChild>
137
+ <Button size="$3">{t("help.close", "Close")}</Button>
138
+ </Dialog.Close>
139
+ </XStack>
140
+ </DialogContent>
141
+ </Dialog.Portal>
142
+ </Dialog>
143
+ );
144
+ }