@webiny/app-admin-ui 0.0.0-unstable.7be00a75a9 → 0.0.0-unstable.7c2def32a7

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 (198) hide show
  1. package/Breadcrumbs/Breadcrumbs.d.ts +14 -0
  2. package/Breadcrumbs/Breadcrumbs.js +74 -0
  3. package/Breadcrumbs/Breadcrumbs.js.map +1 -0
  4. package/CommandPalette/CommandPalette.d.ts +6 -0
  5. package/CommandPalette/CommandPalette.js +202 -0
  6. package/CommandPalette/CommandPalette.js.map +1 -0
  7. package/CommandPalette/components/AiModeBadge.d.ts +3 -0
  8. package/CommandPalette/components/AiModeBadge.js +11 -0
  9. package/CommandPalette/components/AiModeBadge.js.map +1 -0
  10. package/CommandPalette/components/AiSuggestions.d.ts +9 -0
  11. package/CommandPalette/components/AiSuggestions.js +32 -0
  12. package/CommandPalette/components/AiSuggestions.js.map +1 -0
  13. package/CommandPalette/components/AiTurn.d.ts +11 -0
  14. package/CommandPalette/components/AiTurn.js +61 -0
  15. package/CommandPalette/components/AiTurn.js.map +1 -0
  16. package/CommandPalette/components/AnswerSkeleton.d.ts +6 -0
  17. package/CommandPalette/components/AnswerSkeleton.js +20 -0
  18. package/CommandPalette/components/AnswerSkeleton.js.map +1 -0
  19. package/CommandPalette/components/ApprovalPlan.d.ts +16 -0
  20. package/CommandPalette/components/ApprovalPlan.js +56 -0
  21. package/CommandPalette/components/ApprovalPlan.js.map +1 -0
  22. package/CommandPalette/components/CommandDetail.d.ts +13 -0
  23. package/CommandPalette/components/CommandDetail.js +39 -0
  24. package/CommandPalette/components/CommandDetail.js.map +1 -0
  25. package/CommandPalette/components/CommandItemRow.d.ts +5 -0
  26. package/CommandPalette/components/CommandItemRow.js +41 -0
  27. package/CommandPalette/components/CommandItemRow.js.map +1 -0
  28. package/CommandPalette/components/GroupHeading.d.ts +4 -0
  29. package/CommandPalette/components/GroupHeading.js +10 -0
  30. package/CommandPalette/components/GroupHeading.js.map +1 -0
  31. package/CommandPalette/components/HintIcon.d.ts +4 -0
  32. package/CommandPalette/components/HintIcon.js +11 -0
  33. package/CommandPalette/components/HintIcon.js.map +1 -0
  34. package/CommandPalette/components/Kbd.d.ts +4 -0
  35. package/CommandPalette/components/Kbd.js +14 -0
  36. package/CommandPalette/components/Kbd.js.map +1 -0
  37. package/CommandPalette/components/NoResults.d.ts +13 -0
  38. package/CommandPalette/components/NoResults.js +33 -0
  39. package/CommandPalette/components/NoResults.js.map +1 -0
  40. package/CommandPalette/components/PaletteFooter.d.ts +13 -0
  41. package/CommandPalette/components/PaletteFooter.js +18 -0
  42. package/CommandPalette/components/PaletteFooter.js.map +1 -0
  43. package/CommandPalette/components/ToolChip.d.ts +7 -0
  44. package/CommandPalette/components/ToolChip.js +32 -0
  45. package/CommandPalette/components/ToolChip.js.map +1 -0
  46. package/CommandPalette/components/index.d.ts +13 -0
  47. package/CommandPalette/components/index.js +13 -0
  48. package/CommandPalette/constants.d.ts +8 -0
  49. package/CommandPalette/constants.js +5 -0
  50. package/CommandPalette/constants.js.map +1 -0
  51. package/CommandPalette/deriveRows.d.ts +19 -0
  52. package/CommandPalette/deriveRows.js +100 -0
  53. package/CommandPalette/deriveRows.js.map +1 -0
  54. package/CommandPalette/modes/PaletteMode.d.ts +73 -0
  55. package/CommandPalette/modes/PaletteMode.js +0 -0
  56. package/CommandPalette/modes/createAiMode.d.ts +13 -0
  57. package/CommandPalette/modes/createAiMode.js +80 -0
  58. package/CommandPalette/modes/createAiMode.js.map +1 -0
  59. package/CommandPalette/modes/index.d.ts +2 -0
  60. package/CommandPalette/modes/index.js +1 -0
  61. package/CommandPalette/types.d.ts +15 -0
  62. package/CommandPalette/types.js +0 -0
  63. package/CommandPalette/usePaletteHotkeys.d.ts +16 -0
  64. package/CommandPalette/usePaletteHotkeys.js +38 -0
  65. package/CommandPalette/usePaletteHotkeys.js.map +1 -0
  66. package/Dashboard/Welcome.d.ts +4 -1
  67. package/Dashboard/Welcome.js +111 -24
  68. package/Dashboard/Welcome.js.map +1 -1
  69. package/Dashboard/components/DashboardToolbar.d.ts +11 -0
  70. package/Dashboard/components/DashboardToolbar.js +48 -0
  71. package/Dashboard/components/DashboardToolbar.js.map +1 -0
  72. package/Dashboard/components/addWidgetDrawer/AddToColumnMenu.d.ts +10 -0
  73. package/Dashboard/components/addWidgetDrawer/AddToColumnMenu.js +30 -0
  74. package/Dashboard/components/addWidgetDrawer/AddToColumnMenu.js.map +1 -0
  75. package/Dashboard/components/addWidgetDrawer/AddWidgetDrawer.d.ts +12 -0
  76. package/Dashboard/components/addWidgetDrawer/AddWidgetDrawer.js +61 -0
  77. package/Dashboard/components/addWidgetDrawer/AddWidgetDrawer.js.map +1 -0
  78. package/Dashboard/components/addWidgetDrawer/DrawerWidgetRow.d.ts +10 -0
  79. package/Dashboard/components/addWidgetDrawer/DrawerWidgetRow.js +38 -0
  80. package/Dashboard/components/addWidgetDrawer/DrawerWidgetRow.js.map +1 -0
  81. package/Dashboard/components/addWidgetDrawer/WidgetPreviewFrame.d.ts +7 -0
  82. package/Dashboard/components/addWidgetDrawer/WidgetPreviewFrame.js +44 -0
  83. package/Dashboard/components/addWidgetDrawer/WidgetPreviewFrame.js.map +1 -0
  84. package/Dashboard/components/addWidgetDrawer/WidgetSketch.d.ts +4 -0
  85. package/Dashboard/components/addWidgetDrawer/WidgetSketch.js +20 -0
  86. package/Dashboard/components/addWidgetDrawer/WidgetSketch.js.map +1 -0
  87. package/Dashboard/components/addWidgetDrawer/WidgetTabContent.d.ts +14 -0
  88. package/Dashboard/components/addWidgetDrawer/WidgetTabContent.js +76 -0
  89. package/Dashboard/components/addWidgetDrawer/WidgetTabContent.js.map +1 -0
  90. package/Dashboard/components/addWidgetDrawer/types.d.ts +10 -0
  91. package/Dashboard/components/addWidgetDrawer/types.js +0 -0
  92. package/Dashboard/components/dnd/ColumnCountControl.d.ts +9 -0
  93. package/Dashboard/components/dnd/ColumnCountControl.js +52 -0
  94. package/Dashboard/components/dnd/ColumnCountControl.js.map +1 -0
  95. package/Dashboard/components/dnd/ColumnEmptyState.d.ts +10 -0
  96. package/Dashboard/components/dnd/ColumnEmptyState.js +52 -0
  97. package/Dashboard/components/dnd/ColumnEmptyState.js.map +1 -0
  98. package/Dashboard/components/dnd/DashboardDragLayer.d.ts +6 -0
  99. package/Dashboard/components/dnd/DashboardDragLayer.js +28 -0
  100. package/Dashboard/components/dnd/DashboardDragLayer.js.map +1 -0
  101. package/Dashboard/components/dnd/DashboardWidgetCard.d.ts +13 -0
  102. package/Dashboard/components/dnd/DashboardWidgetCard.js +59 -0
  103. package/Dashboard/components/dnd/DashboardWidgetCard.js.map +1 -0
  104. package/Dashboard/components/dnd/DashboardWidgetColumn.d.ts +19 -0
  105. package/Dashboard/components/dnd/DashboardWidgetColumn.js +72 -0
  106. package/Dashboard/components/dnd/DashboardWidgetColumn.js.map +1 -0
  107. package/Dashboard/components/dnd/WidgetDropIndicator.d.ts +11 -0
  108. package/Dashboard/components/dnd/WidgetDropIndicator.js +29 -0
  109. package/Dashboard/components/dnd/WidgetDropIndicator.js.map +1 -0
  110. package/Dashboard/components/dnd/WidgetSlot.d.ts +6 -0
  111. package/Dashboard/components/dnd/WidgetSlot.js +9 -0
  112. package/Dashboard/components/dnd/WidgetSlot.js.map +1 -0
  113. package/Dashboard/components/dnd/dragItem.d.ts +6 -0
  114. package/Dashboard/components/dnd/dragItem.js +4 -0
  115. package/Dashboard/components/dnd/dragItem.js.map +1 -0
  116. package/Dashboard/components/dnd/useWidgetHosts.d.ts +1 -0
  117. package/Dashboard/components/dnd/useWidgetHosts.js +16 -0
  118. package/Dashboard/components/dnd/useWidgetHosts.js.map +1 -0
  119. package/Dashboard/components/layout/EditableColumns.d.ts +13 -0
  120. package/Dashboard/components/layout/EditableColumns.js +25 -0
  121. package/Dashboard/components/layout/EditableColumns.js.map +1 -0
  122. package/Dashboard/components/layout/StaticColumns.d.ts +8 -0
  123. package/Dashboard/components/layout/StaticColumns.js +20 -0
  124. package/Dashboard/components/layout/StaticColumns.js.map +1 -0
  125. package/Dashboard/components/layout/collapseColumns.d.ts +1 -0
  126. package/Dashboard/components/layout/collapseColumns.js +16 -0
  127. package/Dashboard/components/layout/collapseColumns.js.map +1 -0
  128. package/Dashboard/components/layout/layoutConstants.d.ts +2 -0
  129. package/Dashboard/components/layout/layoutConstants.js +5 -0
  130. package/Dashboard/components/layout/layoutConstants.js.map +1 -0
  131. package/Dashboard/components/layout/useColumnsThatFit.d.ts +6 -0
  132. package/Dashboard/components/layout/useColumnsThatFit.js +30 -0
  133. package/Dashboard/components/layout/useColumnsThatFit.js.map +1 -0
  134. package/Dashboard/components/layout/useWidgetPortals.d.ts +5 -0
  135. package/Dashboard/components/layout/useWidgetPortals.js +26 -0
  136. package/Dashboard/components/layout/useWidgetPortals.js.map +1 -0
  137. package/Dashboard/dashboardLayout/loadLayout/FetchDashboardLayoutUseCase.d.ts +12 -0
  138. package/Dashboard/dashboardLayout/loadLayout/FetchDashboardLayoutUseCase.js +19 -0
  139. package/Dashboard/dashboardLayout/loadLayout/FetchDashboardLayoutUseCase.js.map +1 -0
  140. package/Dashboard/dashboardLayout/loadLayout/GetCachedDashboardLayoutUseCase.d.ts +12 -0
  141. package/Dashboard/dashboardLayout/loadLayout/GetCachedDashboardLayoutUseCase.js +19 -0
  142. package/Dashboard/dashboardLayout/loadLayout/GetCachedDashboardLayoutUseCase.js.map +1 -0
  143. package/Dashboard/dashboardLayout/loadLayout/abstractions.d.ts +15 -0
  144. package/Dashboard/dashboardLayout/loadLayout/abstractions.js +6 -0
  145. package/Dashboard/dashboardLayout/loadLayout/abstractions.js.map +1 -0
  146. package/Dashboard/dashboardLayout/loadLayout/feature.d.ts +1 -0
  147. package/Dashboard/dashboardLayout/loadLayout/feature.js +13 -0
  148. package/Dashboard/dashboardLayout/loadLayout/feature.js.map +1 -0
  149. package/Dashboard/dashboardLayout/presenter/DashboardLayoutPresenter.d.ts +56 -0
  150. package/Dashboard/dashboardLayout/presenter/DashboardLayoutPresenter.js +308 -0
  151. package/Dashboard/dashboardLayout/presenter/DashboardLayoutPresenter.js.map +1 -0
  152. package/Dashboard/dashboardLayout/presenter/abstractions.d.ts +46 -0
  153. package/Dashboard/dashboardLayout/presenter/abstractions.js +5 -0
  154. package/Dashboard/dashboardLayout/presenter/abstractions.js.map +1 -0
  155. package/Dashboard/dashboardLayout/presenter/feature.d.ts +3 -0
  156. package/Dashboard/dashboardLayout/presenter/feature.js +23 -0
  157. package/Dashboard/dashboardLayout/presenter/feature.js.map +1 -0
  158. package/Dashboard/dashboardLayout/presenter/useDashboardLayoutPresenter.d.ts +1 -0
  159. package/Dashboard/dashboardLayout/presenter/useDashboardLayoutPresenter.js +6 -0
  160. package/Dashboard/dashboardLayout/presenter/useDashboardLayoutPresenter.js.map +1 -0
  161. package/Dashboard/dashboardLayout/repository/DashboardLayoutGateway.d.ts +13 -0
  162. package/Dashboard/dashboardLayout/repository/DashboardLayoutGateway.js +67 -0
  163. package/Dashboard/dashboardLayout/repository/DashboardLayoutGateway.js.map +1 -0
  164. package/Dashboard/dashboardLayout/repository/DashboardLayoutRepository.d.ts +20 -0
  165. package/Dashboard/dashboardLayout/repository/DashboardLayoutRepository.js +49 -0
  166. package/Dashboard/dashboardLayout/repository/DashboardLayoutRepository.js.map +1 -0
  167. package/Dashboard/dashboardLayout/repository/abstractions.d.ts +25 -0
  168. package/Dashboard/dashboardLayout/repository/abstractions.js +6 -0
  169. package/Dashboard/dashboardLayout/repository/abstractions.js.map +1 -0
  170. package/Dashboard/dashboardLayout/repository/feature.d.ts +1 -0
  171. package/Dashboard/dashboardLayout/repository/feature.js +13 -0
  172. package/Dashboard/dashboardLayout/repository/feature.js.map +1 -0
  173. package/Dashboard/dashboardLayout/saveLayout/SaveDashboardLayoutUseCase.d.ts +12 -0
  174. package/Dashboard/dashboardLayout/saveLayout/SaveDashboardLayoutUseCase.js +19 -0
  175. package/Dashboard/dashboardLayout/saveLayout/SaveDashboardLayoutUseCase.js.map +1 -0
  176. package/Dashboard/dashboardLayout/saveLayout/abstractions.d.ts +8 -0
  177. package/Dashboard/dashboardLayout/saveLayout/abstractions.js +5 -0
  178. package/Dashboard/dashboardLayout/saveLayout/abstractions.js.map +1 -0
  179. package/Dashboard/dashboardLayout/saveLayout/feature.d.ts +1 -0
  180. package/Dashboard/dashboardLayout/saveLayout/feature.js +11 -0
  181. package/Dashboard/dashboardLayout/saveLayout/feature.js.map +1 -0
  182. package/Dashboard/dashboardLayout/toColumnIndex.d.ts +1 -0
  183. package/Dashboard/dashboardLayout/toColumnIndex.js +7 -0
  184. package/Dashboard/dashboardLayout/toColumnIndex.js.map +1 -0
  185. package/Dashboard/dashboardLayout/types.d.ts +15 -0
  186. package/Dashboard/dashboardLayout/types.js +6 -0
  187. package/Dashboard/dashboardLayout/types.js.map +1 -0
  188. package/Layout.js +50 -21
  189. package/Layout.js.map +1 -1
  190. package/index.js +16 -5
  191. package/index.js.map +1 -1
  192. package/package.json +15 -8
  193. package/Navigation/SidebarProvider.d.ts +0 -6
  194. package/Navigation/SidebarProvider.js +0 -26
  195. package/Navigation/SidebarProvider.js.map +0 -1
  196. package/Navigation.d.ts +0 -2
  197. package/Navigation.js +0 -10
  198. package/Navigation.js.map +0 -1
@@ -0,0 +1,49 @@
1
+ import { LocalStorage } from "@webiny/app/exports/admin/local-storage.js";
2
+ import { TenantContext } from "@webiny/app-admin/exports/admin/tenancy.js";
3
+ import { DashboardLayoutGateway, DashboardLayoutRepository } from "./abstractions.js";
4
+ const CACHE_VERSION = 1;
5
+ class DashboardLayoutRepositoryImpl {
6
+ constructor(gateway, localStorage, tenantContext){
7
+ this.gateway = gateway;
8
+ this.localStorage = localStorage;
9
+ this.tenantContext = tenantContext;
10
+ }
11
+ getCached(userId) {
12
+ const key = this.cacheKey(userId);
13
+ const cached = this.localStorage.get(key);
14
+ if (!cached || cached.version !== CACHE_VERSION) return null;
15
+ return cached.layout;
16
+ }
17
+ async fetch(userId) {
18
+ const layout = await this.gateway.get();
19
+ this.writeCache(userId, layout);
20
+ return layout;
21
+ }
22
+ async save(userId, layout) {
23
+ this.writeCache(userId, layout);
24
+ await this.gateway.save(layout);
25
+ }
26
+ writeCache(userId, layout) {
27
+ const key = this.cacheKey(userId);
28
+ if (!layout) return void this.localStorage.remove(key);
29
+ this.localStorage.set(key, {
30
+ version: CACHE_VERSION,
31
+ layout
32
+ });
33
+ }
34
+ cacheKey(userId) {
35
+ const tenantId = this.tenantContext.getCurrentTenant() ?? "root";
36
+ return `dashboard:${tenantId}:${userId}`;
37
+ }
38
+ }
39
+ const DashboardLayoutRepository_DashboardLayoutRepository = DashboardLayoutRepository.createImplementation({
40
+ implementation: DashboardLayoutRepositoryImpl,
41
+ dependencies: [
42
+ DashboardLayoutGateway,
43
+ LocalStorage,
44
+ TenantContext
45
+ ]
46
+ });
47
+ export { DashboardLayoutRepository_DashboardLayoutRepository as DashboardLayoutRepository };
48
+
49
+ //# sourceMappingURL=DashboardLayoutRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard/dashboardLayout/repository/DashboardLayoutRepository.js","sources":["../../../../src/Dashboard/dashboardLayout/repository/DashboardLayoutRepository.ts"],"sourcesContent":["import { LocalStorage } from \"@webiny/app/exports/admin/local-storage.js\";\nimport { TenantContext } from \"@webiny/app-admin/exports/admin/tenancy.js\";\nimport { DashboardLayoutRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { DashboardLayoutGateway } from \"./abstractions.js\";\nimport type { DashboardLayoutData } from \"../types.js\";\n\n// Bump when the cached shape changes; older entries are then ignored and replaced on the next fetch.\nconst CACHE_VERSION = 1;\n\ninterface CachedLayout {\n version: number;\n layout: DashboardLayoutData;\n}\n\nclass DashboardLayoutRepositoryImpl implements RepositoryAbstraction.Interface {\n constructor(\n private gateway: DashboardLayoutGateway.Interface,\n private localStorage: LocalStorage.Interface,\n private tenantContext: TenantContext.Interface\n ) {}\n\n getCached(userId: string): DashboardLayoutData | null {\n const key = this.cacheKey(userId);\n const cached = this.localStorage.get<CachedLayout>(key);\n if (!cached || cached.version !== CACHE_VERSION) {\n return null;\n }\n return cached.layout;\n }\n\n async fetch(userId: string): Promise<DashboardLayoutData | null> {\n const layout = await this.gateway.get();\n this.writeCache(userId, layout);\n return layout;\n }\n\n async save(userId: string, layout: DashboardLayoutData): Promise<void> {\n // Cache first, so a reload shows the change even while the request is still in flight.\n this.writeCache(userId, layout);\n await this.gateway.save(layout);\n }\n\n private writeCache(userId: string, layout: DashboardLayoutData | null): void {\n const key = this.cacheKey(userId);\n if (!layout) {\n this.localStorage.remove(key);\n return;\n }\n this.localStorage.set<CachedLayout>(key, { version: CACHE_VERSION, layout });\n }\n\n private cacheKey(userId: string): string {\n const tenantId = this.tenantContext.getCurrentTenant() ?? \"root\";\n return `dashboard:${tenantId}:${userId}`;\n }\n}\n\nexport const DashboardLayoutRepository = RepositoryAbstraction.createImplementation({\n implementation: DashboardLayoutRepositoryImpl,\n dependencies: [DashboardLayoutGateway, LocalStorage, TenantContext]\n});\n"],"names":["CACHE_VERSION","DashboardLayoutRepositoryImpl","gateway","localStorage","tenantContext","userId","key","cached","layout","tenantId","DashboardLayoutRepository","RepositoryAbstraction","DashboardLayoutGateway","LocalStorage","TenantContext"],"mappings":";;;AAOA,MAAMA,gBAAgB;AAOtB,MAAMC;IACF,YACYC,OAAyC,EACzCC,YAAoC,EACpCC,aAAsC,CAChD;aAHUF,OAAO,GAAPA;aACAC,YAAY,GAAZA;aACAC,aAAa,GAAbA;IACT;IAEH,UAAUC,MAAc,EAA8B;QAClD,MAAMC,MAAM,IAAI,CAAC,QAAQ,CAACD;QAC1B,MAAME,SAAS,IAAI,CAAC,YAAY,CAAC,GAAG,CAAeD;QACnD,IAAI,CAACC,UAAUA,OAAO,OAAO,KAAKP,eAC9B,OAAO;QAEX,OAAOO,OAAO,MAAM;IACxB;IAEA,MAAM,MAAMF,MAAc,EAAuC;QAC7D,MAAMG,SAAS,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG;QACrC,IAAI,CAAC,UAAU,CAACH,QAAQG;QACxB,OAAOA;IACX;IAEA,MAAM,KAAKH,MAAc,EAAEG,MAA2B,EAAiB;QAEnE,IAAI,CAAC,UAAU,CAACH,QAAQG;QACxB,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAACA;IAC5B;IAEQ,WAAWH,MAAc,EAAEG,MAAkC,EAAQ;QACzE,MAAMF,MAAM,IAAI,CAAC,QAAQ,CAACD;QAC1B,IAAI,CAACG,QAAQ,YACT,IAAI,CAAC,YAAY,CAAC,MAAM,CAACF;QAG7B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAeA,KAAK;YAAE,SAASN;YAAeQ;QAAO;IAC9E;IAEQ,SAASH,MAAc,EAAU;QACrC,MAAMI,WAAW,IAAI,CAAC,aAAa,CAAC,gBAAgB,MAAM;QAC1D,OAAO,CAAC,UAAU,EAAEA,SAAS,CAAC,EAAEJ,QAAQ;IAC5C;AACJ;AAEO,MAAMK,sDAA4BC,0BAAAA,oBAA0C,CAAC;IAChF,gBAAgBV;IAChB,cAAc;QAACW;QAAwBC;QAAcC;KAAc;AACvE"}
@@ -0,0 +1,25 @@
1
+ import type { DashboardLayoutData } from "../types.js";
2
+ /**
3
+ * Talks to the API. `get` resolves to `null` when the user never customized their dashboard.
4
+ */
5
+ export interface IDashboardLayoutGateway {
6
+ get(): Promise<DashboardLayoutData | null>;
7
+ save(layout: DashboardLayoutData): Promise<DashboardLayoutData>;
8
+ }
9
+ export declare const DashboardLayoutGateway: import("@webiny/di").Abstraction<IDashboardLayoutGateway>;
10
+ export declare namespace DashboardLayoutGateway {
11
+ type Interface = IDashboardLayoutGateway;
12
+ }
13
+ /**
14
+ * Keeps a copy of each user's layout in localStorage, so the dashboard renders straight away and
15
+ * the API request only confirms or corrects it.
16
+ */
17
+ export interface IDashboardLayoutRepository {
18
+ getCached(userId: string): DashboardLayoutData | null;
19
+ fetch(userId: string): Promise<DashboardLayoutData | null>;
20
+ save(userId: string, layout: DashboardLayoutData): Promise<void>;
21
+ }
22
+ export declare const DashboardLayoutRepository: import("@webiny/di").Abstraction<IDashboardLayoutRepository>;
23
+ export declare namespace DashboardLayoutRepository {
24
+ type Interface = IDashboardLayoutRepository;
25
+ }
@@ -0,0 +1,6 @@
1
+ import { createAbstraction } from "@webiny/feature/admin";
2
+ const DashboardLayoutGateway = createAbstraction("DashboardLayoutGateway");
3
+ const DashboardLayoutRepository = createAbstraction("DashboardLayoutRepository");
4
+ export { DashboardLayoutGateway, DashboardLayoutRepository };
5
+
6
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard/dashboardLayout/repository/abstractions.js","sources":["../../../../src/Dashboard/dashboardLayout/repository/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { DashboardLayoutData } from \"../types.js\";\n\n/**\n * Talks to the API. `get` resolves to `null` when the user never customized their dashboard.\n */\nexport interface IDashboardLayoutGateway {\n get(): Promise<DashboardLayoutData | null>;\n save(layout: DashboardLayoutData): Promise<DashboardLayoutData>;\n}\n\nexport const DashboardLayoutGateway =\n createAbstraction<IDashboardLayoutGateway>(\"DashboardLayoutGateway\");\n\nexport namespace DashboardLayoutGateway {\n export type Interface = IDashboardLayoutGateway;\n}\n\n/**\n * Keeps a copy of each user's layout in localStorage, so the dashboard renders straight away and\n * the API request only confirms or corrects it.\n */\nexport interface IDashboardLayoutRepository {\n // The cached layout, or `null` if there is none for this user and tenant.\n getCached(userId: string): DashboardLayoutData | null;\n // Fetches the stored layout and refreshes the cache with it.\n fetch(userId: string): Promise<DashboardLayoutData | null>;\n save(userId: string, layout: DashboardLayoutData): Promise<void>;\n}\n\nexport const DashboardLayoutRepository = createAbstraction<IDashboardLayoutRepository>(\n \"DashboardLayoutRepository\"\n);\n\nexport namespace DashboardLayoutRepository {\n export type Interface = IDashboardLayoutRepository;\n}\n"],"names":["DashboardLayoutGateway","createAbstraction","DashboardLayoutRepository"],"mappings":";AAWO,MAAMA,yBACTC,kBAA2C;AAkBxC,MAAMC,4BAA4BD,kBACrC"}
@@ -0,0 +1 @@
1
+ export declare const DashboardLayoutRepositoryFeature: import("@webiny/feature/admin").FeatureDefinition<any, []>;
@@ -0,0 +1,13 @@
1
+ import { createFeature } from "@webiny/feature/admin";
2
+ import { DashboardLayoutGateway } from "./DashboardLayoutGateway.js";
3
+ import { DashboardLayoutRepository } from "./DashboardLayoutRepository.js";
4
+ const DashboardLayoutRepositoryFeature = createFeature({
5
+ name: "AdminUI/DashboardLayoutRepository",
6
+ register (container) {
7
+ container.register(DashboardLayoutGateway).inSingletonScope();
8
+ container.register(DashboardLayoutRepository).inSingletonScope();
9
+ }
10
+ });
11
+ export { DashboardLayoutRepositoryFeature };
12
+
13
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard/dashboardLayout/repository/feature.js","sources":["../../../../src/Dashboard/dashboardLayout/repository/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/admin\";\nimport { DashboardLayoutGateway } from \"./DashboardLayoutGateway.js\";\nimport { DashboardLayoutRepository } from \"./DashboardLayoutRepository.js\";\n\nexport const DashboardLayoutRepositoryFeature = createFeature({\n name: \"AdminUI/DashboardLayoutRepository\",\n register(container) {\n container.register(DashboardLayoutGateway).inSingletonScope();\n container.register(DashboardLayoutRepository).inSingletonScope();\n }\n});\n"],"names":["DashboardLayoutRepositoryFeature","createFeature","container","DashboardLayoutGateway","DashboardLayoutRepository"],"mappings":";;;AAIO,MAAMA,mCAAmCC,cAAc;IAC1D,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC,wBAAwB,gBAAgB;QAC3DD,UAAU,QAAQ,CAACE,2BAA2B,gBAAgB;IAClE;AACJ"}
@@ -0,0 +1,12 @@
1
+ import { DashboardLayoutRepository } from "../repository/abstractions.js";
2
+ import { SaveDashboardLayoutUseCase as UseCaseAbstraction } from "./abstractions.js";
3
+ import type { DashboardLayoutData } from "../types.js";
4
+ declare class SaveDashboardLayoutUseCaseImpl implements UseCaseAbstraction.Interface {
5
+ private repository;
6
+ constructor(repository: DashboardLayoutRepository.Interface);
7
+ execute(userId: string, layout: DashboardLayoutData): Promise<void>;
8
+ }
9
+ export declare const SaveDashboardLayoutUseCase: typeof SaveDashboardLayoutUseCaseImpl & {
10
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").ISaveDashboardLayoutUseCase>;
11
+ };
12
+ export {};
@@ -0,0 +1,19 @@
1
+ import { DashboardLayoutRepository } from "../repository/abstractions.js";
2
+ import { SaveDashboardLayoutUseCase } from "./abstractions.js";
3
+ class SaveDashboardLayoutUseCaseImpl {
4
+ constructor(repository){
5
+ this.repository = repository;
6
+ }
7
+ async execute(userId, layout) {
8
+ await this.repository.save(userId, layout);
9
+ }
10
+ }
11
+ const SaveDashboardLayoutUseCase_SaveDashboardLayoutUseCase = SaveDashboardLayoutUseCase.createImplementation({
12
+ implementation: SaveDashboardLayoutUseCaseImpl,
13
+ dependencies: [
14
+ DashboardLayoutRepository
15
+ ]
16
+ });
17
+ export { SaveDashboardLayoutUseCase_SaveDashboardLayoutUseCase as SaveDashboardLayoutUseCase };
18
+
19
+ //# sourceMappingURL=SaveDashboardLayoutUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard/dashboardLayout/saveLayout/SaveDashboardLayoutUseCase.js","sources":["../../../../src/Dashboard/dashboardLayout/saveLayout/SaveDashboardLayoutUseCase.ts"],"sourcesContent":["import { DashboardLayoutRepository } from \"../repository/abstractions.js\";\nimport { SaveDashboardLayoutUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport type { DashboardLayoutData } from \"../types.js\";\n\nclass SaveDashboardLayoutUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(private repository: DashboardLayoutRepository.Interface) {}\n\n async execute(userId: string, layout: DashboardLayoutData): Promise<void> {\n await this.repository.save(userId, layout);\n }\n}\n\nexport const SaveDashboardLayoutUseCase = UseCaseAbstraction.createImplementation({\n implementation: SaveDashboardLayoutUseCaseImpl,\n dependencies: [DashboardLayoutRepository]\n});\n"],"names":["SaveDashboardLayoutUseCaseImpl","repository","userId","layout","SaveDashboardLayoutUseCase","UseCaseAbstraction","DashboardLayoutRepository"],"mappings":";;AAIA,MAAMA;IACF,YAAoBC,UAA+C,CAAE;aAAjDA,UAAU,GAAVA;IAAkD;IAEtE,MAAM,QAAQC,MAAc,EAAEC,MAA2B,EAAiB;QACtE,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAACD,QAAQC;IACvC;AACJ;AAEO,MAAMC,wDAA6BC,2BAAAA,oBAAuC,CAAC;IAC9E,gBAAgBL;IAChB,cAAc;QAACM;KAA0B;AAC7C"}
@@ -0,0 +1,8 @@
1
+ import type { DashboardLayoutData } from "../types.js";
2
+ export interface ISaveDashboardLayoutUseCase {
3
+ execute(userId: string, layout: DashboardLayoutData): Promise<void>;
4
+ }
5
+ export declare const SaveDashboardLayoutUseCase: import("@webiny/di").Abstraction<ISaveDashboardLayoutUseCase>;
6
+ export declare namespace SaveDashboardLayoutUseCase {
7
+ type Interface = ISaveDashboardLayoutUseCase;
8
+ }
@@ -0,0 +1,5 @@
1
+ import { createAbstraction } from "@webiny/feature/admin";
2
+ const SaveDashboardLayoutUseCase = createAbstraction("SaveDashboardLayoutUseCase");
3
+ export { SaveDashboardLayoutUseCase };
4
+
5
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard/dashboardLayout/saveLayout/abstractions.js","sources":["../../../../src/Dashboard/dashboardLayout/saveLayout/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { DashboardLayoutData } from \"../types.js\";\n\nexport interface ISaveDashboardLayoutUseCase {\n execute(userId: string, layout: DashboardLayoutData): Promise<void>;\n}\n\nexport const SaveDashboardLayoutUseCase = createAbstraction<ISaveDashboardLayoutUseCase>(\n \"SaveDashboardLayoutUseCase\"\n);\n\nexport namespace SaveDashboardLayoutUseCase {\n export type Interface = ISaveDashboardLayoutUseCase;\n}\n"],"names":["SaveDashboardLayoutUseCase","createAbstraction"],"mappings":";AAOO,MAAMA,6BAA6BC,kBACtC"}
@@ -0,0 +1 @@
1
+ export declare const SaveDashboardLayoutFeature: import("@webiny/feature/admin").FeatureDefinition<any, []>;
@@ -0,0 +1,11 @@
1
+ import { createFeature } from "@webiny/feature/admin";
2
+ import { SaveDashboardLayoutUseCase } from "./SaveDashboardLayoutUseCase.js";
3
+ const SaveDashboardLayoutFeature = createFeature({
4
+ name: "AdminUI/SaveDashboardLayout",
5
+ register (container) {
6
+ container.register(SaveDashboardLayoutUseCase);
7
+ }
8
+ });
9
+ export { SaveDashboardLayoutFeature };
10
+
11
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard/dashboardLayout/saveLayout/feature.js","sources":["../../../../src/Dashboard/dashboardLayout/saveLayout/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/admin\";\nimport { SaveDashboardLayoutUseCase } from \"./SaveDashboardLayoutUseCase.js\";\n\nexport const SaveDashboardLayoutFeature = createFeature({\n name: \"AdminUI/SaveDashboardLayout\",\n register(container) {\n container.register(SaveDashboardLayoutUseCase);\n }\n});\n"],"names":["SaveDashboardLayoutFeature","createFeature","container","SaveDashboardLayoutUseCase"],"mappings":";;AAGO,MAAMA,6BAA6BC,cAAc;IACpD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
@@ -0,0 +1 @@
1
+ export declare const toColumnIndex: (column: string | number | undefined) => number;
@@ -0,0 +1,7 @@
1
+ const toColumnIndex = (column)=>{
2
+ if ("number" == typeof column) return column;
3
+ return "right" === column ? 1 : 0;
4
+ };
5
+ export { toColumnIndex };
6
+
7
+ //# sourceMappingURL=toColumnIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard/dashboardLayout/toColumnIndex.js","sources":["../../../src/Dashboard/dashboardLayout/toColumnIndex.ts"],"sourcesContent":["// Widgets register their column as a string (\"left\" or \"right\") or as a zero-based index.\nexport const toColumnIndex = (column: string | number | undefined): number => {\n if (typeof column === \"number\") {\n return column;\n }\n return column === \"right\" ? 1 : 0;\n};\n"],"names":["toColumnIndex","column"],"mappings":"AACO,MAAMA,gBAAgB,CAACC;IAC1B,IAAI,AAAkB,YAAlB,OAAOA,QACP,OAAOA;IAEX,OAAOA,AAAW,YAAXA,SAAqB,IAAI;AACpC"}
@@ -0,0 +1,15 @@
1
+ /** Default column count when a user hasn't customized their dashboard. */
2
+ export declare const DEFAULT_COLUMN_COUNT = 2;
3
+ /** Allowed range for the user-selectable column count. */
4
+ export declare const MIN_COLUMN_COUNT = 2;
5
+ export declare const MAX_COLUMN_COUNT = 4;
6
+ /**
7
+ * The persisted, per-user dashboard layout: an ordered list of widget names per column
8
+ * (`columns[i]` = column i), the widgets the user has removed (`hidden`), and how many
9
+ * columns the user has chosen.
10
+ */
11
+ export interface DashboardLayoutData {
12
+ columns: string[][];
13
+ hidden: string[];
14
+ columnCount: number;
15
+ }
@@ -0,0 +1,6 @@
1
+ const DEFAULT_COLUMN_COUNT = 2;
2
+ const MIN_COLUMN_COUNT = 2;
3
+ const MAX_COLUMN_COUNT = 4;
4
+ export { DEFAULT_COLUMN_COUNT, MAX_COLUMN_COUNT, MIN_COLUMN_COUNT };
5
+
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dashboard/dashboardLayout/types.js","sources":["../../../src/Dashboard/dashboardLayout/types.ts"],"sourcesContent":["/** Default column count when a user hasn't customized their dashboard. */\nexport const DEFAULT_COLUMN_COUNT = 2;\n\n/** Allowed range for the user-selectable column count. */\nexport const MIN_COLUMN_COUNT = 2;\nexport const MAX_COLUMN_COUNT = 4;\n\n/**\n * The persisted, per-user dashboard layout: an ordered list of widget names per column\n * (`columns[i]` = column i), the widgets the user has removed (`hidden`), and how many\n * columns the user has chosen.\n */\nexport interface DashboardLayoutData {\n columns: string[][];\n hidden: string[];\n columnCount: number;\n}\n"],"names":["DEFAULT_COLUMN_COUNT","MIN_COLUMN_COUNT","MAX_COLUMN_COUNT"],"mappings":"AACO,MAAMA,uBAAuB;AAG7B,MAAMC,mBAAmB;AACzB,MAAMC,mBAAmB"}
package/Layout.js CHANGED
@@ -1,25 +1,54 @@
1
- import react from "react";
1
+ import react, { useCallback, useMemo, useRef } from "react";
2
2
  import react_helmet from "react-helmet";
3
- import { LayoutRenderer, Navigation, TenantSelector, UserMenu } from "@webiny/app-admin";
4
- import { HeaderBar, cn, useSidebar } from "@webiny/admin-ui";
5
- const Layout_Layout = LayoutRenderer.createDecorator(()=>function({ title, startElement = null, hideNavigation = false, children }) {
6
- const { pinned } = useSidebar();
7
- const widthClassNames = {
8
- "max-w-[calc(100%-(var(--spacing-sidebar-expanded)))] ": pinned,
9
- "max-w-[calc(100%-(var(--spacing-sidebar-collapsed)))] ": !pinned
10
- };
11
- return /*#__PURE__*/ react.createElement(react.Fragment, null, title ? /*#__PURE__*/ react.createElement(react_helmet, {
12
- title: title
13
- }) : null, hideNavigation ? null : /*#__PURE__*/ react.createElement(Navigation, null), /*#__PURE__*/ react.createElement("div", {
14
- className: cn("ml-auto bg-neutral-base transition-[max-width,min-width] ease-linear w-full", hideNavigation ? void 0 : widthClassNames)
15
- }, /*#__PURE__*/ react.createElement(HeaderBar, {
16
- start: startElement,
17
- end: /*#__PURE__*/ react.createElement("div", {
18
- className: "flex gap-x-sm items-center justify-end"
19
- }, /*#__PURE__*/ react.createElement(TenantSelector, null), /*#__PURE__*/ react.createElement(UserMenu, null))
20
- }), /*#__PURE__*/ react.createElement("main", {
21
- className: "relative overflow-y-auto h-main-content"
22
- }, children)));
3
+ import { AssumedPermissionsSelector, BannerBar, DebuggerIndicator, LayoutRenderer, Navigation, TenantSelector, UserMenu } from "@webiny/app-admin";
4
+ import { HeaderBar, SidebarProvider, cn, useSidebar } from "@webiny/admin-ui";
5
+ import { useLocalStorage, useLocalStorageValue } from "@webiny/app";
6
+ import { CommandPalette } from "./CommandPalette/CommandPalette.js";
7
+ import { Breadcrumbs } from "./Breadcrumbs/Breadcrumbs.js";
8
+ const SIDEBAR_STATE_KEY = "navigation/state";
9
+ const parseSidebarState = (raw)=>{
10
+ try {
11
+ if ("object" == typeof raw && null !== raw) return raw;
12
+ if ("string" == typeof raw) return JSON.parse(raw);
13
+ } catch {}
14
+ };
15
+ const MAKE_ROOM_FOR_BANNER = "has-[>[data-admin-banner]]:[--spacing-main-content:calc(100vh_-_var(--spacing-header)_-_var(--spacing-banner))]";
16
+ const LayoutContent = ({ title, startElement = null, hideNavigation = false, children })=>{
17
+ const { pinned } = useSidebar();
18
+ const widthClassNames = {
19
+ "max-w-[calc(100%-(var(--spacing-sidebar-expanded)))] ": pinned,
20
+ "max-w-[calc(100%-(var(--spacing-sidebar-collapsed)))] ": !pinned
21
+ };
22
+ return /*#__PURE__*/ react.createElement(react.Fragment, null, title ? /*#__PURE__*/ react.createElement(react_helmet, {
23
+ title: title
24
+ }) : null, /*#__PURE__*/ react.createElement(CommandPalette, null), hideNavigation ? null : /*#__PURE__*/ react.createElement(Navigation, null), /*#__PURE__*/ react.createElement("div", {
25
+ className: cn("ml-auto bg-neutral-base transition-[max-width,min-width] ease-linear w-full", MAKE_ROOM_FOR_BANNER, hideNavigation ? void 0 : widthClassNames)
26
+ }, /*#__PURE__*/ react.createElement(BannerBar, null), /*#__PURE__*/ react.createElement(HeaderBar, {
27
+ start: /*#__PURE__*/ react.createElement("div", {
28
+ className: "flex items-center gap-sm"
29
+ }, /*#__PURE__*/ react.createElement(Breadcrumbs, null), startElement),
30
+ end: /*#__PURE__*/ react.createElement("div", {
31
+ className: "flex gap-x-sm items-center justify-end"
32
+ }, /*#__PURE__*/ react.createElement(DebuggerIndicator, null), /*#__PURE__*/ react.createElement(TenantSelector, null), /*#__PURE__*/ react.createElement(AssumedPermissionsSelector, null), /*#__PURE__*/ react.createElement(UserMenu, null))
33
+ }), /*#__PURE__*/ react.createElement("main", {
34
+ className: "relative overflow-y-auto h-main-content"
35
+ }, children)));
36
+ };
37
+ const Layout_Layout = LayoutRenderer.createDecorator(()=>function(props) {
38
+ const localStorage = useLocalStorage();
39
+ const localStorageRef = useRef(localStorage);
40
+ localStorageRef.current = localStorage;
41
+ const rawState = useLocalStorageValue(SIDEBAR_STATE_KEY);
42
+ const cachedState = useMemo(()=>parseSidebarState(rawState), [
43
+ rawState
44
+ ]);
45
+ const onChangeState = useCallback((newState)=>{
46
+ localStorageRef.current.set(SIDEBAR_STATE_KEY, JSON.stringify(newState));
47
+ }, []);
48
+ return /*#__PURE__*/ react.createElement(SidebarProvider, {
49
+ state: cachedState,
50
+ onChangeState: onChangeState
51
+ }, /*#__PURE__*/ react.createElement(LayoutContent, props));
23
52
  });
24
53
  export { Layout_Layout as Layout };
25
54
 
package/Layout.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.js","sources":["../src/Layout.tsx"],"sourcesContent":["import React from \"react\";\nimport Helmet from \"react-helmet\";\nimport type { LayoutProps } from \"@webiny/app-admin\";\nimport { LayoutRenderer, Navigation, TenantSelector, UserMenu } from \"@webiny/app-admin\";\nimport { HeaderBar, cn, useSidebar } from \"@webiny/admin-ui\";\n\nexport const Layout = LayoutRenderer.createDecorator(() => {\n return function Layout({\n title,\n startElement = null,\n hideNavigation = false,\n children\n }: LayoutProps) {\n const { pinned } = useSidebar();\n\n const widthClassNames = {\n \"max-w-[calc(100%-(var(--spacing-sidebar-expanded)))] \": pinned,\n \"max-w-[calc(100%-(var(--spacing-sidebar-collapsed)))] \": !pinned\n };\n\n return (\n <>\n {title ? <Helmet title={title} /> : null}\n {hideNavigation ? null : <Navigation />}\n <div\n className={cn(\n \"ml-auto bg-neutral-base transition-[max-width,min-width] ease-linear w-full\",\n hideNavigation ? undefined : widthClassNames\n )}\n >\n <HeaderBar\n start={startElement}\n end={\n <div className={\"flex gap-x-sm items-center justify-end\"}>\n <TenantSelector />\n <UserMenu />\n </div>\n }\n />\n <main className={\"relative overflow-y-auto h-main-content\"}>{children}</main>\n </div>\n </>\n );\n };\n});\n"],"names":["Layout","LayoutRenderer","title","startElement","hideNavigation","children","pinned","useSidebar","widthClassNames","Helmet","Navigation","cn","undefined","HeaderBar","TenantSelector","UserMenu"],"mappings":";;;;AAMO,MAAMA,gBAASC,eAAe,eAAe,CAAC,IAC1C,SAAgB,EACnBC,KAAK,EACLC,eAAe,IAAI,EACnBC,iBAAiB,KAAK,EACtBC,QAAQ,EACE;QACV,MAAM,EAAEC,MAAM,EAAE,GAAGC;QAEnB,MAAMC,kBAAkB;YACpB,yDAAyDF;YACzD,0DAA0D,CAACA;QAC/D;QAEA,OAAO,WAAP,GACI,0CACKJ,QAAQ,WAARA,GAAQ,oBAACO,cAAMA;YAAC,OAAOP;aAAY,MACnCE,iBAAiB,OAAO,WAAP,GAAO,oBAACM,YAAUA,OAAAA,WAAAA,GACpC,oBAAC;YACG,WAAWC,GACP,+EACAP,iBAAiBQ,SAAYJ;yBAGjC,oBAACK,WAASA;YACN,OAAOV;YACP,mBACI,oBAAC;gBAAI,WAAW;6BACZ,oBAACW,gBAAcA,OAAAA,WAAAA,GACf,oBAACC,UAAQA;0BAIrB,oBAAC;YAAK,WAAW;WAA4CV;IAI7E"}
1
+ {"version":3,"file":"Layout.js","sources":["../src/Layout.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useRef } from \"react\";\nimport Helmet from \"react-helmet\";\nimport type { LayoutProps } from \"@webiny/app-admin\";\nimport { AssumedPermissionsSelector } from \"@webiny/app-admin\";\nimport { BannerBar } from \"@webiny/app-admin\";\nimport { DebuggerIndicator } from \"@webiny/app-admin\";\nimport { LayoutRenderer } from \"@webiny/app-admin\";\nimport { Navigation } from \"@webiny/app-admin\";\nimport { TenantSelector } from \"@webiny/app-admin\";\nimport { UserMenu } from \"@webiny/app-admin\";\nimport { HeaderBar, SidebarProvider, cn, useSidebar } from \"@webiny/admin-ui\";\nimport { useLocalStorage, useLocalStorageValue } from \"@webiny/app\";\nimport { CommandPalette } from \"./CommandPalette/CommandPalette.js\";\nimport { Breadcrumbs } from \"./Breadcrumbs/Breadcrumbs.js\";\n\nconst SIDEBAR_STATE_KEY = \"navigation/state\";\n\ntype SidebarCachedState = {\n pinned: boolean;\n expandedSections: string[];\n pinnedItems: string[];\n};\n\nconst parseSidebarState = (raw: unknown): SidebarCachedState | undefined => {\n try {\n if (typeof raw === \"object\" && raw !== null) {\n return raw as SidebarCachedState;\n }\n if (typeof raw === \"string\") {\n return JSON.parse(raw) as SidebarCachedState;\n }\n } catch {\n // Ignore parse errors\n }\n return undefined;\n};\n\n/*\n * Views size themselves with `h-main-content`, which is the window minus the header. While the\n * banner bar shows, they have to lose its height too, or every page scrolls by exactly that much.\n * The bar is always `--spacing-banner` tall, so plain CSS can do it. Scoped to the wrapper below,\n * which holds both the bar and the views.\n *\n * TODO: Temporary. The real fix is for views to fill `main` instead of computing their own height\n * from the window: make this wrapper a full-height column and `main` `flex-1 min-h-0`, then move\n * the ~13 views that use `h-main-content` to `h-full`. That also lets the bar wrap its text.\n */\nconst MAKE_ROOM_FOR_BANNER =\n \"has-[>[data-admin-banner]]:[--spacing-main-content:calc(100vh_-_var(--spacing-header)_-_var(--spacing-banner))]\";\n\nconst LayoutContent = ({\n title,\n startElement = null,\n hideNavigation = false,\n children\n}: LayoutProps) => {\n const { pinned } = useSidebar();\n\n const widthClassNames = {\n \"max-w-[calc(100%-(var(--spacing-sidebar-expanded)))] \": pinned,\n \"max-w-[calc(100%-(var(--spacing-sidebar-collapsed)))] \": !pinned\n };\n\n return (\n <>\n {title ? <Helmet title={title} /> : null}\n <CommandPalette />\n {hideNavigation ? null : <Navigation />}\n <div\n className={cn(\n \"ml-auto bg-neutral-base transition-[max-width,min-width] ease-linear w-full\",\n MAKE_ROOM_FOR_BANNER,\n hideNavigation ? undefined : widthClassNames\n )}\n >\n <BannerBar />\n <HeaderBar\n start={\n <div className=\"flex items-center gap-sm\">\n <Breadcrumbs />\n {startElement}\n </div>\n }\n end={\n <div className={\"flex gap-x-sm items-center justify-end\"}>\n <DebuggerIndicator />\n <TenantSelector />\n <AssumedPermissionsSelector />\n <UserMenu />\n </div>\n }\n />\n <main className={\"relative overflow-y-auto h-main-content\"}>{children}</main>\n </div>\n </>\n );\n};\n\nexport const Layout = LayoutRenderer.createDecorator(() => {\n return function Layout(props: LayoutProps) {\n const localStorage = useLocalStorage();\n const localStorageRef = useRef(localStorage);\n localStorageRef.current = localStorage;\n\n const rawState = useLocalStorageValue(SIDEBAR_STATE_KEY);\n const cachedState = useMemo(() => parseSidebarState(rawState), [rawState]);\n\n const onChangeState = useCallback((newState: SidebarCachedState) => {\n localStorageRef.current.set(SIDEBAR_STATE_KEY, JSON.stringify(newState));\n }, []);\n\n return (\n <SidebarProvider state={cachedState} onChangeState={onChangeState}>\n <LayoutContent {...props} />\n </SidebarProvider>\n );\n };\n});\n"],"names":["SIDEBAR_STATE_KEY","parseSidebarState","raw","JSON","MAKE_ROOM_FOR_BANNER","LayoutContent","title","startElement","hideNavigation","children","pinned","useSidebar","widthClassNames","Helmet","CommandPalette","Navigation","cn","undefined","BannerBar","HeaderBar","Breadcrumbs","DebuggerIndicator","TenantSelector","AssumedPermissionsSelector","UserMenu","Layout","LayoutRenderer","props","localStorage","useLocalStorage","localStorageRef","useRef","rawState","useLocalStorageValue","cachedState","useMemo","onChangeState","useCallback","newState","SidebarProvider"],"mappings":";;;;;;;AAeA,MAAMA,oBAAoB;AAQ1B,MAAMC,oBAAoB,CAACC;IACvB,IAAI;QACA,IAAI,AAAe,YAAf,OAAOA,OAAoBA,AAAQ,SAARA,KAC3B,OAAOA;QAEX,IAAI,AAAe,YAAf,OAAOA,KACP,OAAOC,KAAK,KAAK,CAACD;IAE1B,EAAE,OAAM,CAER;AAEJ;AAYA,MAAME,uBACF;AAEJ,MAAMC,gBAAgB,CAAC,EACnBC,KAAK,EACLC,eAAe,IAAI,EACnBC,iBAAiB,KAAK,EACtBC,QAAQ,EACE;IACV,MAAM,EAAEC,MAAM,EAAE,GAAGC;IAEnB,MAAMC,kBAAkB;QACpB,yDAAyDF;QACzD,0DAA0D,CAACA;IAC/D;IAEA,OAAO,WAAP,GACI,0CACKJ,QAAQ,WAARA,GAAQ,oBAACO,cAAMA;QAAC,OAAOP;SAAY,oBACpC,oBAACQ,gBAAcA,OACdN,iBAAiB,OAAO,WAAP,GAAO,oBAACO,YAAUA,OAAAA,WAAAA,GACpC,oBAAC;QACG,WAAWC,GACP,+EACAZ,sBACAI,iBAAiBS,SAAYL;qBAGjC,oBAACM,WAASA,OAAAA,WAAAA,GACV,oBAACC,WAASA;QACN,qBACI,oBAAC;YAAI,WAAU;yBACX,oBAACC,aAAWA,OACXb;QAGT,mBACI,oBAAC;YAAI,WAAW;yBACZ,oBAACc,mBAAiBA,OAAAA,WAAAA,GAClB,oBAACC,gBAAcA,OAAAA,WAAAA,GACf,oBAACC,4BAA0BA,OAAAA,WAAAA,GAC3B,oBAACC,UAAQA;sBAIrB,oBAAC;QAAK,WAAW;OAA4Cf;AAI7E;AAEO,MAAMgB,gBAASC,eAAe,eAAe,CAAC,IAC1C,SAAgBC,KAAkB;QACrC,MAAMC,eAAeC;QACrB,MAAMC,kBAAkBC,OAAOH;QAC/BE,gBAAgB,OAAO,GAAGF;QAE1B,MAAMI,WAAWC,qBAAqBjC;QACtC,MAAMkC,cAAcC,QAAQ,IAAMlC,kBAAkB+B,WAAW;YAACA;SAAS;QAEzE,MAAMI,gBAAgBC,YAAY,CAACC;YAC/BR,gBAAgB,OAAO,CAAC,GAAG,CAAC9B,mBAAmBG,KAAK,SAAS,CAACmC;QAClE,GAAG,EAAE;QAEL,OAAO,WAAP,GACI,oBAACC,iBAAeA;YAAC,OAAOL;YAAa,eAAeE;yBAChD,oBAAC/B,eAAkBsB;IAG/B"}
package/index.js CHANGED
@@ -1,23 +1,34 @@
1
1
  import react from "react";
2
- import { AdminConfig } from "@webiny/app-admin";
2
+ import { AdminConfig, RegisterFeature } from "@webiny/app-admin";
3
3
  import { Layout } from "./Layout.js";
4
- import { Navigation } from "./Navigation.js";
4
+ import { Navigation } from "./Navigation/Navigation.js";
5
5
  import { UserMenu } from "./UserMenu.js";
6
6
  import { Dialog } from "./Dialog.js";
7
7
  import { NotFound } from "./NotFound.js";
8
8
  import { Dashboard } from "./Dashboard.js";
9
9
  import { Logo } from "./Logo.js";
10
10
  import { AssistanceWidget, CommunityWidget } from "./Dashboard/components/index.js";
11
- const AdminUI = ()=>/*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(AdminConfig, null, /*#__PURE__*/ react.createElement(AdminConfig.Dashboard.Widget, {
11
+ import { DashboardLayoutPresenterFeature } from "./Dashboard/dashboardLayout/presenter/feature.js";
12
+ const AdminUI = ()=>/*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(RegisterFeature, {
13
+ feature: DashboardLayoutPresenterFeature
14
+ }), /*#__PURE__*/ react.createElement(AdminConfig, null, /*#__PURE__*/ react.createElement(AdminConfig.Dashboard.Widget, {
12
15
  name: "admin.assistance",
16
+ title: "Need some assistance?",
17
+ description: "Documentation and ways to reach the Webiny team.",
18
+ group: "General",
13
19
  column: "right",
14
20
  pin: "last",
15
- element: /*#__PURE__*/ react.createElement(AssistanceWidget, null)
21
+ element: /*#__PURE__*/ react.createElement(AssistanceWidget, null),
22
+ preview: /*#__PURE__*/ react.createElement(AssistanceWidget, null)
16
23
  }), /*#__PURE__*/ react.createElement(AdminConfig.Dashboard.Widget, {
17
24
  name: "admin.community",
25
+ title: "Join our community",
26
+ description: "GitHub, Slack, YouTube and X.",
27
+ group: "General",
18
28
  pin: "last",
19
29
  column: "right",
20
- element: /*#__PURE__*/ react.createElement(CommunityWidget, null)
30
+ element: /*#__PURE__*/ react.createElement(CommunityWidget, null),
31
+ preview: /*#__PURE__*/ react.createElement(CommunityWidget, null)
21
32
  })), /*#__PURE__*/ react.createElement(Dashboard, null), /*#__PURE__*/ react.createElement(Dialog, null), /*#__PURE__*/ react.createElement(Layout, null), /*#__PURE__*/ react.createElement(Navigation, null), /*#__PURE__*/ react.createElement(NotFound, null), /*#__PURE__*/ react.createElement(UserMenu, null), /*#__PURE__*/ react.createElement(Logo, null));
22
33
  export { AdminUI };
23
34
 
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { AdminConfig } from \"@webiny/app-admin\";\nimport { Layout } from \"./Layout.js\";\nimport { Navigation } from \"./Navigation.js\";\nimport { UserMenu } from \"~/UserMenu.js\";\nimport { Dialog } from \"./Dialog.js\";\nimport { NotFound } from \"./NotFound.js\";\nimport { Dashboard } from \"./Dashboard.js\";\nimport { Logo } from \"./Logo.js\";\nimport { AssistanceWidget, CommunityWidget } from \"./Dashboard/components/index.js\";\n\nexport const AdminUI = () => {\n return (\n <>\n <AdminConfig>\n <AdminConfig.Dashboard.Widget\n name=\"admin.assistance\"\n column=\"right\"\n pin=\"last\"\n element={<AssistanceWidget />}\n />\n <AdminConfig.Dashboard.Widget\n name=\"admin.community\"\n pin=\"last\"\n column=\"right\"\n element={<CommunityWidget />}\n />\n </AdminConfig>\n <Dashboard />\n <Dialog />\n <Layout />\n <Navigation />\n <NotFound />\n <UserMenu />\n <Logo />\n </>\n );\n};\n"],"names":["AdminUI","AdminConfig","AssistanceWidget","CommunityWidget","Dashboard","Dialog","Layout","Navigation","NotFound","UserMenu","Logo"],"mappings":";;;;;;;;;;AAWO,MAAMA,UAAU,IACZ,WAAP,GACI,wDACI,oBAACC,aAAWA,MAAAA,WAAAA,GACR,oBAACA,YAAY,SAAS,CAAC,MAAM;QACzB,MAAK;QACL,QAAO;QACP,KAAI;QACJ,uBAAS,oBAACC,kBAAgBA;sBAE9B,oBAACD,YAAY,SAAS,CAAC,MAAM;QACzB,MAAK;QACL,KAAI;QACJ,QAAO;QACP,uBAAS,oBAACE,iBAAeA;uBAGjC,oBAACC,WAASA,OAAAA,WAAAA,GACV,oBAACC,QAAMA,OAAAA,WAAAA,GACP,oBAACC,QAAMA,OAAAA,WAAAA,GACP,oBAACC,YAAUA,OAAAA,WAAAA,GACX,oBAACC,UAAQA,OAAAA,WAAAA,GACT,oBAACC,UAAQA,OAAAA,WAAAA,GACT,oBAACC,MAAIA"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { AdminConfig } from \"@webiny/app-admin\";\nimport { RegisterFeature } from \"@webiny/app-admin\";\nimport { Layout } from \"./Layout.js\";\nimport { Navigation } from \"./Navigation/Navigation.js\";\nimport { UserMenu } from \"~/UserMenu.js\";\nimport { Dialog } from \"./Dialog.js\";\nimport { NotFound } from \"./NotFound.js\";\nimport { Dashboard } from \"./Dashboard.js\";\nimport { Logo } from \"./Logo.js\";\nimport { AssistanceWidget } from \"./Dashboard/components/index.js\";\nimport { CommunityWidget } from \"./Dashboard/components/index.js\";\nimport { DashboardLayoutPresenterFeature } from \"./Dashboard/dashboardLayout/presenter/feature.js\";\n\nexport const AdminUI = () => {\n return (\n <>\n <RegisterFeature feature={DashboardLayoutPresenterFeature} />\n <AdminConfig>\n <AdminConfig.Dashboard.Widget\n name=\"admin.assistance\"\n title=\"Need some assistance?\"\n description=\"Documentation and ways to reach the Webiny team.\"\n group=\"General\"\n column=\"right\"\n pin=\"last\"\n element={<AssistanceWidget />}\n preview={<AssistanceWidget />}\n />\n <AdminConfig.Dashboard.Widget\n name=\"admin.community\"\n title=\"Join our community\"\n description=\"GitHub, Slack, YouTube and X.\"\n group=\"General\"\n pin=\"last\"\n column=\"right\"\n element={<CommunityWidget />}\n preview={<CommunityWidget />}\n />\n </AdminConfig>\n <Dashboard />\n <Dialog />\n <Layout />\n <Navigation />\n <NotFound />\n <UserMenu />\n <Logo />\n </>\n );\n};\n"],"names":["AdminUI","RegisterFeature","DashboardLayoutPresenterFeature","AdminConfig","AssistanceWidget","CommunityWidget","Dashboard","Dialog","Layout","Navigation","NotFound","UserMenu","Logo"],"mappings":";;;;;;;;;;;AAcO,MAAMA,UAAU,IACZ,WAAP,GACI,wDACI,oBAACC,iBAAeA;QAAC,SAASC;sBAC1B,oBAACC,aAAWA,MAAAA,WAAAA,GACR,oBAACA,YAAY,SAAS,CAAC,MAAM;QACzB,MAAK;QACL,OAAM;QACN,aAAY;QACZ,OAAM;QACN,QAAO;QACP,KAAI;QACJ,uBAAS,oBAACC,kBAAgBA;QAC1B,uBAAS,oBAACA,kBAAgBA;sBAE9B,oBAACD,YAAY,SAAS,CAAC,MAAM;QACzB,MAAK;QACL,OAAM;QACN,aAAY;QACZ,OAAM;QACN,KAAI;QACJ,QAAO;QACP,uBAAS,oBAACE,iBAAeA;QACzB,uBAAS,oBAACA,iBAAeA;uBAGjC,oBAACC,WAASA,OAAAA,WAAAA,GACV,oBAACC,QAAMA,OAAAA,WAAAA,GACP,oBAACC,QAAMA,OAAAA,WAAAA,GACP,oBAACC,YAAUA,OAAAA,WAAAA,GACX,oBAACC,UAAQA,OAAAA,WAAAA,GACT,oBAACC,UAAQA,OAAAA,WAAAA,GACT,oBAACC,MAAIA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/app-admin-ui",
3
- "version": "0.0.0-unstable.7be00a75a9",
3
+ "version": "0.0.0-unstable.7c2def32a7",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -13,20 +13,27 @@
13
13
  "author": "Webiny Ltd.",
14
14
  "license": "MIT",
15
15
  "dependencies": {
16
- "@types/react": "18.3.29",
17
- "@webiny/admin-ui": "0.0.0-unstable.7be00a75a9",
18
- "@webiny/app": "0.0.0-unstable.7be00a75a9",
19
- "@webiny/app-admin": "0.0.0-unstable.7be00a75a9",
20
- "@webiny/icons": "0.0.0-unstable.7be00a75a9",
16
+ "@types/react": "18.3.31",
17
+ "@webiny/admin-ui": "0.0.0-unstable.7c2def32a7",
18
+ "@webiny/app": "0.0.0-unstable.7c2def32a7",
19
+ "@webiny/app-admin": "0.0.0-unstable.7c2def32a7",
20
+ "@webiny/feature": "0.0.0-unstable.7c2def32a7",
21
+ "@webiny/icons": "0.0.0-unstable.7c2def32a7",
22
+ "cmdk": "1.1.1",
23
+ "mobx": "7.0.3",
21
24
  "react": "18.3.1",
25
+ "react-dnd": "16.0.1",
26
+ "react-dnd-html5-backend": "16.0.1",
22
27
  "react-dom": "18.3.1",
23
28
  "react-helmet": "6.1.0"
24
29
  },
25
30
  "devDependencies": {
26
31
  "@types/react-helmet": "6.1.11",
27
- "@webiny/build-tools": "0.0.0-unstable.7be00a75a9",
32
+ "@webiny/build-tools": "0.0.0-unstable.7c2def32a7",
33
+ "@webiny/di": "2.0.0",
28
34
  "rimraf": "6.1.3",
29
- "typescript": "6.0.3"
35
+ "typescript": "7.0.2",
36
+ "vitest": "4.1.11"
30
37
  },
31
38
  "publishConfig": {
32
39
  "access": "public"
@@ -1,6 +0,0 @@
1
- import React from "react";
2
- interface NavigationProviderProps {
3
- children?: React.ReactNode;
4
- }
5
- export declare const SidebarProvider: (Component: React.ComponentType<NavigationProviderProps>) => (props: NavigationProviderProps) => React.JSX.Element;
6
- export {};
@@ -1,26 +0,0 @@
1
- import react, { useMemo } from "react";
2
- import { SidebarProvider as admin_ui_SidebarProvider } from "@webiny/admin-ui";
3
- import { useLocalStorage, useLocalStorageValue } from "@webiny/app";
4
- const SIDEBAR_STATE_KEY = "navigation/state";
5
- const SidebarProvider_SidebarProvider = (Component)=>function(props) {
6
- const rawState = useLocalStorageValue(SIDEBAR_STATE_KEY);
7
- const { set } = useLocalStorage();
8
- const state = useMemo(()=>{
9
- try {
10
- if ("object" == typeof rawState && null !== rawState) return rawState;
11
- if ("string" == typeof rawState) return JSON.parse(rawState);
12
- } catch {}
13
- }, [
14
- rawState
15
- ]);
16
- const onChangeState = (newState)=>{
17
- set(SIDEBAR_STATE_KEY, JSON.stringify(newState));
18
- };
19
- return /*#__PURE__*/ react.createElement(admin_ui_SidebarProvider, {
20
- state: state,
21
- onChangeState: onChangeState
22
- }, /*#__PURE__*/ react.createElement(Component, props));
23
- };
24
- export { SidebarProvider_SidebarProvider as SidebarProvider };
25
-
26
- //# sourceMappingURL=SidebarProvider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Navigation/SidebarProvider.js","sources":["../../src/Navigation/SidebarProvider.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { SidebarProvider as AdminUiSidebar } from \"@webiny/admin-ui\";\nimport { useLocalStorage, useLocalStorageValue } from \"@webiny/app\";\n\ninterface NavigationProviderProps {\n children?: React.ReactNode;\n}\n\nconst SIDEBAR_STATE_KEY = \"navigation/state\";\n\ntype SidebarState = {\n pinned: boolean;\n expandedSections: string[];\n pinnedItems: string[];\n};\n\nexport const SidebarProvider = (Component: React.ComponentType<NavigationProviderProps>) => {\n return function SidebarProvider(props: NavigationProviderProps) {\n const rawState = useLocalStorageValue(SIDEBAR_STATE_KEY);\n const { set } = useLocalStorage();\n\n const state = useMemo(() => {\n try {\n if (typeof rawState === \"object\" && rawState !== null) {\n return rawState as SidebarState;\n }\n if (typeof rawState === \"string\") {\n return JSON.parse(rawState) as SidebarState;\n }\n } catch {\n // Ignore parse errors\n }\n return undefined;\n }, [rawState]);\n\n const onChangeState = (newState: SidebarState) => {\n set(SIDEBAR_STATE_KEY, JSON.stringify(newState));\n };\n\n return (\n <AdminUiSidebar state={state} onChangeState={onChangeState}>\n <Component {...props} />\n </AdminUiSidebar>\n );\n };\n};\n"],"names":["SIDEBAR_STATE_KEY","SidebarProvider","Component","props","rawState","useLocalStorageValue","set","useLocalStorage","state","useMemo","JSON","onChangeState","newState","AdminUiSidebar"],"mappings":";;;AAQA,MAAMA,oBAAoB;AAQnB,MAAMC,kCAAkB,CAACC,YACrB,SAAyBC,KAA8B;QAC1D,MAAMC,WAAWC,qBAAqBL;QACtC,MAAM,EAAEM,GAAG,EAAE,GAAGC;QAEhB,MAAMC,QAAQC,QAAQ;YAClB,IAAI;gBACA,IAAI,AAAoB,YAApB,OAAOL,YAAyBA,AAAa,SAAbA,UAChC,OAAOA;gBAEX,IAAI,AAAoB,YAApB,OAAOA,UACP,OAAOM,KAAK,KAAK,CAACN;YAE1B,EAAE,OAAM,CAER;QAEJ,GAAG;YAACA;SAAS;QAEb,MAAMO,gBAAgB,CAACC;YACnBN,IAAIN,mBAAmBU,KAAK,SAAS,CAACE;QAC1C;QAEA,OAAO,WAAP,GACI,oBAACC,0BAAcA;YAAC,OAAOL;YAAO,eAAeG;yBACzC,oBAACT,WAAcC;IAG3B"}
package/Navigation.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import React from "react";
2
- export declare const Navigation: () => React.JSX.Element;
package/Navigation.js DELETED
@@ -1,10 +0,0 @@
1
- import react from "react";
2
- import { Provider } from "@webiny/app-admin";
3
- import { SidebarProvider } from "./Navigation/SidebarProvider.js";
4
- import { Navigation } from "./Navigation/Navigation.js";
5
- const Navigation_Navigation = ()=>/*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(Provider, {
6
- hoc: SidebarProvider
7
- }), /*#__PURE__*/ react.createElement(Navigation, null));
8
- export { Navigation_Navigation as Navigation };
9
-
10
- //# sourceMappingURL=Navigation.js.map
package/Navigation.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"Navigation.js","sources":["../src/Navigation.tsx"],"sourcesContent":["import React from \"react\";\nimport { Provider } from \"@webiny/app-admin\";\nimport { SidebarProvider } from \"./Navigation/SidebarProvider.js\";\nimport { Navigation as DecoratedNavigation } from \"./Navigation/Navigation.js\";\n\nexport const Navigation = () => {\n return (\n <>\n <Provider hoc={SidebarProvider} />\n <DecoratedNavigation />\n </>\n );\n};\n"],"names":["Navigation","Provider","SidebarProvider","DecoratedNavigation"],"mappings":";;;;AAKO,MAAMA,wBAAa,IACf,WAAP,GACI,wDACI,oBAACC,UAAQA;QAAC,KAAKC;sBACf,oBAACC,YAAmBA"}