@nocobase/client-v2 2.1.0-alpha.40 → 2.1.0-alpha.45

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 (278) hide show
  1. package/es/Application.d.ts +7 -0
  2. package/es/BaseApplication.d.ts +13 -0
  3. package/es/RouterManager.d.ts +1 -0
  4. package/es/collection-field-interface/CollectionFieldInterface.d.ts +51 -15
  5. package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +82 -3
  6. package/es/collection-manager/field-configure.d.ts +80 -0
  7. package/es/collection-manager/field-validation.d.ts +43 -0
  8. package/es/collection-manager/filter-operators/index.d.ts +46 -0
  9. package/es/collection-manager/filter-operators/operators.d.ts +30 -0
  10. package/es/collection-manager/interfaces/checkbox.d.ts +1 -41
  11. package/es/collection-manager/interfaces/checkboxGroup.d.ts +12 -44
  12. package/es/collection-manager/interfaces/collection.d.ts +12 -51
  13. package/es/collection-manager/interfaces/color.d.ts +1 -16
  14. package/es/collection-manager/interfaces/createdAt.d.ts +1 -44
  15. package/es/collection-manager/interfaces/createdBy.d.ts +0 -4
  16. package/es/collection-manager/interfaces/dateOnly.d.ts +7 -44
  17. package/es/collection-manager/interfaces/datetime.d.ts +1 -44
  18. package/es/collection-manager/interfaces/datetimeNoTz.d.ts +1 -44
  19. package/es/collection-manager/interfaces/email.d.ts +1 -29
  20. package/es/collection-manager/interfaces/id.d.ts +1 -16
  21. package/es/collection-manager/interfaces/index.d.ts +2 -3
  22. package/es/collection-manager/interfaces/input.d.ts +1 -102
  23. package/es/collection-manager/interfaces/integer.d.ts +1 -95
  24. package/es/collection-manager/interfaces/json.d.ts +16 -7
  25. package/es/collection-manager/interfaces/m2m.d.ts +11 -19
  26. package/es/collection-manager/interfaces/m2o.d.ts +11 -19
  27. package/es/collection-manager/interfaces/markdown.d.ts +1 -63
  28. package/es/collection-manager/interfaces/multipleSelect.d.ts +12 -44
  29. package/es/collection-manager/interfaces/nanoid.d.ts +1 -34
  30. package/es/collection-manager/interfaces/number.d.ts +1 -87
  31. package/es/collection-manager/interfaces/o2m.d.ts +12 -24
  32. package/es/collection-manager/interfaces/obo.d.ts +207 -0
  33. package/es/collection-manager/interfaces/oho.d.ts +207 -0
  34. package/es/collection-manager/interfaces/password.d.ts +1 -56
  35. package/es/collection-manager/interfaces/percent.d.ts +1 -84
  36. package/es/collection-manager/interfaces/phone.d.ts +1 -25
  37. package/es/collection-manager/interfaces/properties/index.d.ts +0 -28
  38. package/es/collection-manager/interfaces/radioGroup.d.ts +1 -29
  39. package/es/collection-manager/interfaces/richText.d.ts +1 -63
  40. package/es/collection-manager/interfaces/select.d.ts +12 -44
  41. package/es/collection-manager/interfaces/snowflake-id.d.ts +1 -34
  42. package/es/collection-manager/interfaces/tableoid.d.ts +1 -10
  43. package/es/collection-manager/interfaces/textarea.d.ts +1 -51
  44. package/es/collection-manager/interfaces/time.d.ts +1 -16
  45. package/es/collection-manager/interfaces/types.d.ts +3 -12
  46. package/es/collection-manager/interfaces/unixTimestamp.d.ts +1 -44
  47. package/es/collection-manager/interfaces/updatedAt.d.ts +1 -44
  48. package/es/collection-manager/interfaces/updatedBy.d.ts +0 -4
  49. package/es/collection-manager/interfaces/url.d.ts +1 -20
  50. package/es/collection-manager/interfaces/uuid.d.ts +1 -34
  51. package/es/collection-manager/template-fields.d.ts +53 -0
  52. package/es/components/KeepAlive.d.ts +22 -0
  53. package/es/components/RouterBridge.d.ts +9 -0
  54. package/es/components/form/DialogFormLayout.d.ts +5 -29
  55. package/es/components/form/VariableInput.d.ts +53 -2
  56. package/es/components/form/filter/CollectionFilter.d.ts +49 -0
  57. package/es/components/form/filter/CollectionFilterItem.d.ts +49 -0
  58. package/es/components/form/filter/DateFilterDynamicComponent.d.ts +57 -0
  59. package/es/components/form/filter/FilterValueInput.d.ts +29 -0
  60. package/es/components/form/filter/index.d.ts +11 -0
  61. package/es/components/form/filter/useFilterActionProps.d.ts +96 -0
  62. package/es/components/form/index.d.ts +1 -0
  63. package/es/data-source/ExtendCollectionsProvider.d.ts +50 -0
  64. package/es/data-source/index.d.ts +9 -0
  65. package/es/flow/FlowPage.d.ts +2 -1
  66. package/es/flow/admin-shell/AdminLayoutRouteCoordinator.d.ts +8 -40
  67. package/es/flow/admin-shell/BaseLayoutModel.d.ts +89 -0
  68. package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +74 -0
  69. package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +12 -0
  70. package/es/flow/admin-shell/admin-layout/AdminLayoutModel.d.ts +7 -92
  71. package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +11 -0
  72. package/es/flow/admin-shell/admin-layout/index.d.ts +3 -0
  73. package/es/flow/admin-shell/admin-layout/useApplications.d.ts +3 -2
  74. package/es/flow/admin-shell/useAdminLayoutRoutePage.d.ts +2 -2
  75. package/es/flow/admin-shell/useLayoutRoutePage.d.ts +23 -0
  76. package/es/flow/components/FlowRoute.d.ts +10 -1
  77. package/es/flow/components/filter/index.d.ts +2 -0
  78. package/es/flow/components/filter/useFilterOptions.d.ts +66 -0
  79. package/es/flow/index.d.ts +4 -0
  80. package/es/flow/models/base/PageModel/PageModel.d.ts +3 -1
  81. package/es/flow/models/blocks/assign-form/assignFieldValuesFlow.d.ts +84 -0
  82. package/es/flow/models/blocks/assign-form/index.d.ts +1 -0
  83. package/es/flow/models/blocks/form/FormActionGroupModel.d.ts +1 -0
  84. package/es/flow/models/blocks/form/FormActionModel.d.ts +9 -2
  85. package/es/flow/models/blocks/table/TableBlockModel.d.ts +10 -0
  86. package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.d.ts +1 -1
  87. package/es/flow-compat/passwordUtils.d.ts +1 -1
  88. package/es/index.d.ts +6 -0
  89. package/es/index.mjs +552 -459
  90. package/es/layout-manager/LayoutContentRoute.d.ts +14 -0
  91. package/es/layout-manager/LayoutManager.d.ts +22 -0
  92. package/es/layout-manager/LayoutRoute.d.ts +14 -0
  93. package/es/layout-manager/index.d.ts +13 -0
  94. package/es/layout-manager/types.d.ts +20 -0
  95. package/es/layout-manager/utils.d.ts +14 -0
  96. package/es/nocobase-buildin-plugin/index.d.ts +3 -10
  97. package/es/settings-center/index.d.ts +1 -1
  98. package/es/settings-center/plugin-manager/BulkEnableButton.d.ts +15 -0
  99. package/es/settings-center/plugin-manager/PluginCard.d.ts +15 -0
  100. package/es/settings-center/plugin-manager/PluginDetail.d.ts +16 -0
  101. package/es/settings-center/{PluginManagerPage.d.ts → plugin-manager/index.d.ts} +1 -7
  102. package/es/settings-center/plugin-manager/types.d.ts +34 -0
  103. package/lib/index.js +552 -459
  104. package/package.json +8 -7
  105. package/src/Application.tsx +51 -12
  106. package/src/BaseApplication.tsx +32 -0
  107. package/src/PluginSettingsManager.ts +1 -1
  108. package/src/RouterManager.tsx +17 -1
  109. package/src/__tests__/PluginSettingsManager.test.ts +41 -2
  110. package/src/__tests__/app.test.tsx +17 -1
  111. package/src/__tests__/globalDeps.test.ts +1 -0
  112. package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +45 -2
  113. package/src/__tests__/plugin-manager.test.tsx +177 -0
  114. package/src/__tests__/settings-center.test.tsx +24 -2
  115. package/src/collection-field-interface/CollectionFieldInterface.ts +71 -77
  116. package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +201 -4
  117. package/src/collection-manager/field-configure.ts +548 -0
  118. package/src/collection-manager/field-validation.ts +195 -0
  119. package/src/collection-manager/filter-operators/index.ts +176 -0
  120. package/src/collection-manager/{interfaces/properties → filter-operators}/operators.ts +24 -13
  121. package/src/collection-manager/interfaces/checkbox.ts +2 -9
  122. package/src/collection-manager/interfaces/checkboxGroup.ts +2 -10
  123. package/src/collection-manager/interfaces/collection.ts +2 -15
  124. package/src/collection-manager/interfaces/color.ts +2 -2
  125. package/src/collection-manager/interfaces/createdAt.ts +2 -2
  126. package/src/collection-manager/interfaces/createdBy.ts +1 -12
  127. package/src/collection-manager/interfaces/dateOnly.ts +8 -2
  128. package/src/collection-manager/interfaces/datetime.ts +2 -2
  129. package/src/collection-manager/interfaces/datetimeNoTz.ts +2 -2
  130. package/src/collection-manager/interfaces/email.ts +2 -9
  131. package/src/collection-manager/interfaces/id.ts +1 -2
  132. package/src/collection-manager/interfaces/index.ts +2 -3
  133. package/src/collection-manager/interfaces/input.ts +2 -133
  134. package/src/collection-manager/interfaces/integer.ts +2 -71
  135. package/src/collection-manager/interfaces/json.tsx +17 -11
  136. package/src/collection-manager/interfaces/m2m.tsx +0 -21
  137. package/src/collection-manager/interfaces/m2o.tsx +0 -22
  138. package/src/collection-manager/interfaces/markdown.ts +2 -51
  139. package/src/collection-manager/interfaces/multipleSelect.ts +2 -14
  140. package/src/collection-manager/interfaces/nanoid.ts +2 -2
  141. package/src/collection-manager/interfaces/number.ts +2 -85
  142. package/src/collection-manager/interfaces/o2m.tsx +1 -22
  143. package/src/collection-manager/interfaces/obo.tsx +145 -0
  144. package/src/collection-manager/interfaces/oho.tsx +145 -0
  145. package/src/collection-manager/interfaces/password.ts +2 -44
  146. package/src/collection-manager/interfaces/percent.ts +2 -74
  147. package/src/collection-manager/interfaces/phone.ts +2 -2
  148. package/src/collection-manager/interfaces/properties/index.ts +0 -133
  149. package/src/collection-manager/interfaces/radioGroup.ts +2 -2
  150. package/src/collection-manager/interfaces/richText.ts +2 -51
  151. package/src/collection-manager/interfaces/select.ts +2 -14
  152. package/src/collection-manager/interfaces/snowflake-id.ts +2 -2
  153. package/src/collection-manager/interfaces/tableoid.ts +1 -2
  154. package/src/collection-manager/interfaces/textarea.ts +2 -51
  155. package/src/collection-manager/interfaces/time.ts +2 -2
  156. package/src/collection-manager/interfaces/types.ts +4 -12
  157. package/src/collection-manager/interfaces/unixTimestamp.tsx +2 -2
  158. package/src/collection-manager/interfaces/updatedAt.ts +2 -2
  159. package/src/collection-manager/interfaces/updatedBy.ts +1 -12
  160. package/src/collection-manager/interfaces/url.ts +2 -4
  161. package/src/collection-manager/interfaces/uuid.ts +2 -2
  162. package/src/collection-manager/template-fields.ts +109 -0
  163. package/src/components/KeepAlive.tsx +131 -0
  164. package/src/components/README.md +90 -6
  165. package/src/components/README.zh-CN.md +90 -7
  166. package/src/components/RouterBridge.tsx +28 -4
  167. package/src/components/__tests__/KeepAlive.test.tsx +63 -0
  168. package/src/components/__tests__/RouterBridge.test.tsx +27 -0
  169. package/src/components/form/DialogFormLayout.tsx +5 -29
  170. package/src/components/form/VariableInput.tsx +101 -28
  171. package/src/components/form/__tests__/VariableInput.test.ts +85 -0
  172. package/src/components/form/filter/CollectionFilter.tsx +111 -0
  173. package/src/components/form/filter/CollectionFilterItem.tsx +184 -0
  174. package/src/components/form/filter/DateFilterDynamicComponent.tsx +283 -0
  175. package/src/components/form/filter/FilterValueInput.tsx +198 -0
  176. package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +247 -0
  177. package/src/components/form/filter/__tests__/DateFilterDynamicComponent.test.tsx +148 -0
  178. package/src/components/form/filter/__tests__/FilterValueInput.test.tsx +243 -0
  179. package/src/components/form/filter/__tests__/compileFilterGroup.test.ts +146 -0
  180. package/src/components/form/filter/index.ts +13 -0
  181. package/src/components/form/filter/useFilterActionProps.ts +203 -0
  182. package/src/components/form/index.tsx +1 -0
  183. package/src/data-source/ExtendCollectionsProvider.tsx +144 -0
  184. package/src/data-source/__tests__/ExtendCollectionsProvider.test.tsx +264 -0
  185. package/src/data-source/index.ts +10 -0
  186. package/src/flow/FlowPage.tsx +35 -7
  187. package/src/flow/__tests__/FlowPage.test.tsx +79 -0
  188. package/src/flow/__tests__/FlowRoute.test.tsx +529 -2
  189. package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +191 -0
  190. package/src/flow/actions/__tests__/openView.subModelKey.test.tsx +33 -0
  191. package/src/flow/actions/aclCheck.tsx +4 -0
  192. package/src/flow/actions/aclCheckRefresh.tsx +4 -0
  193. package/src/flow/actions/dateTimeFormat.tsx +12 -8
  194. package/src/flow/actions/linkageRules.tsx +122 -0
  195. package/src/flow/actions/openView.tsx +28 -4
  196. package/src/flow/admin-shell/AdminLayoutRouteCoordinator.ts +11 -329
  197. package/src/flow/admin-shell/BaseLayoutModel.tsx +455 -0
  198. package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +502 -0
  199. package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +547 -3
  200. package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +35 -7
  201. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +160 -0
  202. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +0 -12
  203. package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +28 -201
  204. package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +11 -2
  205. package/src/flow/admin-shell/admin-layout/AppListRender.tsx +139 -0
  206. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +1 -26
  207. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +149 -27
  208. package/src/flow/admin-shell/admin-layout/index.ts +3 -0
  209. package/src/flow/admin-shell/admin-layout/useApplications.tsx +34 -1
  210. package/src/flow/admin-shell/useAdminLayoutRoutePage.ts +10 -26
  211. package/src/flow/admin-shell/useLayoutRoutePage.ts +61 -0
  212. package/src/flow/components/AdminLayout.tsx +4 -154
  213. package/src/flow/components/FlowRoute.tsx +105 -15
  214. package/src/flow/components/filter/index.ts +3 -0
  215. package/src/flow/components/filter/useFilterOptions.ts +102 -0
  216. package/src/flow/index.ts +4 -0
  217. package/src/flow/models/actions/UpdateRecordActionModel.tsx +14 -95
  218. package/src/flow/models/actions/UpdateRecordActionUtils.ts +4 -7
  219. package/src/flow/models/actions/__tests__/AssignFormRefill.test.ts +26 -1
  220. package/src/flow/models/base/ActionModel.tsx +8 -1
  221. package/src/flow/models/base/PageModel/PageModel.tsx +51 -18
  222. package/src/flow/models/base/PageModel/RootPageModel.tsx +6 -13
  223. package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +102 -1
  224. package/src/flow/models/base/RouteModel.tsx +1 -1
  225. package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +63 -2
  226. package/src/flow/models/blocks/assign-form/assignFieldValuesFlow.tsx +206 -0
  227. package/src/flow/models/blocks/assign-form/index.ts +1 -0
  228. package/src/flow/models/blocks/form/FormActionGroupModel.tsx +14 -0
  229. package/src/flow/models/blocks/form/FormActionModel.tsx +30 -3
  230. package/src/flow/models/blocks/form/FormItemModel.tsx +8 -1
  231. package/src/flow/models/blocks/form/__tests__/FormActionGroupModel.test.ts +46 -0
  232. package/src/flow/models/blocks/form/__tests__/submitHandler.test.ts +71 -0
  233. package/src/flow/models/blocks/form/submitHandler.ts +8 -1
  234. package/src/flow/models/blocks/form/submitValues.ts +4 -1
  235. package/src/flow/models/blocks/table/TableBlockModel.tsx +118 -16
  236. package/src/flow/models/blocks/table/__tests__/TableBlockModel.rowSelection.test.tsx +114 -0
  237. package/src/flow/models/fields/AssociationFieldModel/SubFormFieldModel.tsx +7 -1
  238. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +1 -1
  239. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -5
  240. package/src/flow/models/fields/ClickableFieldModel.tsx +9 -1
  241. package/src/flow/models/fields/CollectionSelectorFieldModel.tsx +8 -2
  242. package/src/flow/models/fields/DisplayEnumFieldModel.tsx +8 -2
  243. package/src/flow/models/fields/DisplayTimeFieldModel.tsx +1 -1
  244. package/src/flow/models/fields/TimeFieldModel.tsx +1 -1
  245. package/src/flow/models/fields/__tests__/TimeFieldModel.test.tsx +61 -0
  246. package/src/flow/models/fields/mobile-components/MobileDatePicker.tsx +19 -3
  247. package/src/flow/models/fields/mobile-components/__tests__/MobileDatePicker.test.tsx +94 -0
  248. package/src/flow/models/topbar/TopbarActionModel.tsx +1 -1
  249. package/src/flow/utils/__tests__/dateTimeFormat.test.ts +91 -0
  250. package/src/index.ts +6 -0
  251. package/src/layout-manager/LayoutContentRoute.tsx +90 -0
  252. package/src/layout-manager/LayoutManager.tsx +185 -0
  253. package/src/layout-manager/LayoutRoute.tsx +138 -0
  254. package/src/layout-manager/__tests__/LayoutManager.test.tsx +335 -0
  255. package/src/layout-manager/__tests__/LayoutRoute.test.tsx +473 -0
  256. package/src/layout-manager/index.ts +14 -0
  257. package/src/layout-manager/types.ts +22 -0
  258. package/src/layout-manager/utils.ts +37 -0
  259. package/src/nocobase-buildin-plugin/index.tsx +69 -67
  260. package/src/nocobase-buildin-plugin/plugins/LocalePlugin.ts +1 -0
  261. package/src/settings-center/index.ts +1 -1
  262. package/src/settings-center/plugin-manager/BulkEnableButton.tsx +111 -0
  263. package/src/settings-center/plugin-manager/PluginCard.tsx +270 -0
  264. package/src/settings-center/plugin-manager/PluginDetail.tsx +195 -0
  265. package/src/settings-center/plugin-manager/index.tsx +254 -0
  266. package/src/settings-center/plugin-manager/types.ts +35 -0
  267. package/src/settings-center/utils.tsx +8 -1
  268. package/src/theme/__tests__/globalStyles.test.ts +24 -0
  269. package/src/theme/globalStyles.ts +10 -0
  270. package/src/utils/globalDeps.ts +2 -0
  271. package/es/collection-manager/interfaces/linkTo.d.ts +0 -90
  272. package/es/collection-manager/interfaces/o2o.d.ts +0 -621
  273. package/es/collection-manager/interfaces/properties/operators.d.ts +0 -294
  274. package/es/collection-manager/interfaces/subTable.d.ts +0 -172
  275. package/src/collection-manager/interfaces/linkTo.ts +0 -120
  276. package/src/collection-manager/interfaces/o2o.tsx +0 -561
  277. package/src/collection-manager/interfaces/subTable.ts +0 -218
  278. package/src/settings-center/PluginManagerPage.tsx +0 -162
@@ -7,12 +7,13 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- import { FlowEngine } from '@nocobase/flow-engine';
10
+ import { FlowContext, FlowEngine } from '@nocobase/flow-engine';
11
11
  import { describe, expect, it, vi, beforeEach } from 'vitest';
12
12
  import { getViewDiffAndUpdateHidden } from '../../getViewDiffAndUpdateHidden';
13
13
  import { getOpenViewStepParams } from '../../flows/openViewFlow';
14
- import { resolveViewParamsToViewList } from '../../resolveViewParamsToViewList';
14
+ import { resolveViewParamsToViewList, updateViewListHidden } from '../../resolveViewParamsToViewList';
15
15
  import { AdminLayoutRouteCoordinator } from '../AdminLayoutRouteCoordinator';
16
+ import { BaseLayoutRouteCoordinator, toViewStack } from '../BaseLayoutRouteCoordinator';
16
17
  import { RouteModel } from '../../models/base/RouteModel';
17
18
 
18
19
  vi.mock('../../resolveViewParamsToViewList', () => ({
@@ -36,6 +37,7 @@ vi.mock('../../flows/openViewFlow', async (importOriginal) => {
36
37
  const mockResolveViewParamsToViewList = vi.mocked(resolveViewParamsToViewList);
37
38
  const mockGetViewDiffAndUpdateHidden = vi.mocked(getViewDiffAndUpdateHidden);
38
39
  const mockGetOpenViewStepParams = vi.mocked(getOpenViewStepParams);
40
+ const mockUpdateViewListHidden = vi.mocked(updateViewListHidden);
39
41
 
40
42
  function setupRouteReplay(viewParams: Record<string, any>) {
41
43
  const engine = new FlowEngine();
@@ -52,7 +54,7 @@ function setupRouteReplay(viewParams: Record<string, any>) {
52
54
  },
53
55
  });
54
56
 
55
- const dispatchEvent = vi.fn(() => Promise.resolve());
57
+ const dispatchEvent = vi.fn((_eventName: string, _payload: any) => Promise.resolve());
56
58
  const viewItem = {
57
59
  params: {
58
60
  viewUid: 'popup',
@@ -81,6 +83,10 @@ function setupRouteReplay(viewParams: Record<string, any>) {
81
83
  active: true,
82
84
  layoutContentElement: document.createElement('div'),
83
85
  });
86
+ coordinator.syncRoute({
87
+ params: { name: 'test-route' },
88
+ pathname: '/admin/popup/filterbytk/member',
89
+ });
84
90
 
85
91
  return { dispatchEvent };
86
92
  }
@@ -114,4 +120,542 @@ describe('AdminLayoutRouteCoordinator', () => {
114
120
  triggerByRouter: true,
115
121
  });
116
122
  });
123
+
124
+ it('uses layout content element before route page placeholder as view target', () => {
125
+ const engine = new FlowEngine();
126
+ engine.registerModels({ RouteModel });
127
+ engine.context.defineProperty('route', {
128
+ value: {},
129
+ });
130
+ engine.context.defineProperty('routeRepository', {
131
+ value: {
132
+ getRouteBySchemaUid: vi.fn(() => ({})),
133
+ },
134
+ });
135
+
136
+ const layoutContentElement = document.createElement('div');
137
+ const routePageElement = document.createElement('div');
138
+ const dispatchEvent = vi.fn((_eventName: string, _payload: any) => Promise.resolve());
139
+ const viewItem = {
140
+ params: { viewUid: 'test-route' },
141
+ modelUid: 'test-route',
142
+ model: { uid: 'test-route', dispatchEvent } as any,
143
+ hidden: { value: false },
144
+ index: 0,
145
+ };
146
+ mockResolveViewParamsToViewList.mockReturnValue([viewItem]);
147
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
148
+ viewsToClose: [],
149
+ viewsToOpen: [viewItem],
150
+ });
151
+ mockGetOpenViewStepParams.mockReturnValue({} as any);
152
+
153
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/admin' });
154
+ coordinator.setLayoutContentElement(layoutContentElement);
155
+ coordinator.registerPage('test-route', {
156
+ active: true,
157
+ layoutContentElement: routePageElement,
158
+ });
159
+ coordinator.syncRoute({
160
+ pageUid: 'test-route',
161
+ pathname: '/admin/test-route',
162
+ });
163
+
164
+ expect(dispatchEvent.mock.calls[0][1].target).toBe(layoutContentElement);
165
+ });
166
+
167
+ it('replaces stale non-route model before registering route page', () => {
168
+ const engine = new FlowEngine();
169
+ engine.registerModels({ RouteModel });
170
+ const staleModel = engine.createModel({
171
+ uid: 'test-route',
172
+ use: 'FlowModel',
173
+ });
174
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/admin' });
175
+
176
+ const routeModel = coordinator.registerPage('test-route', {
177
+ active: true,
178
+ layoutContentElement: document.createElement('div'),
179
+ });
180
+
181
+ expect(routeModel).toBeInstanceOf(RouteModel);
182
+ expect(engine.getModel('test-route')).toBe(routeModel);
183
+ expect(engine.getModel('test-route')).not.toBe(staleModel);
184
+ });
185
+
186
+ it('parses view stack with custom layout prefix', () => {
187
+ const engine = new FlowEngine();
188
+ engine.registerModels({ RouteModel });
189
+ engine.context.defineProperty('route', {
190
+ value: {
191
+ params: { name: 'test-route' },
192
+ pathname: '/embed/test-route/view/popup/filterbytk/member',
193
+ },
194
+ });
195
+ engine.context.defineProperty('routeRepository', {
196
+ value: {
197
+ getRouteBySchemaUid: vi.fn(() => ({})),
198
+ },
199
+ });
200
+
201
+ mockResolveViewParamsToViewList.mockReturnValue([]);
202
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
203
+ viewsToClose: [],
204
+ viewsToOpen: [],
205
+ });
206
+
207
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/embed' });
208
+ coordinator.registerPage('test-route', {
209
+ active: true,
210
+ layoutContentElement: document.createElement('div'),
211
+ });
212
+ coordinator.syncRoute({
213
+ params: { name: 'test-route' },
214
+ pathname: '/embed/test-route/view/popup/filterbytk/member',
215
+ });
216
+
217
+ expect(mockResolveViewParamsToViewList).toHaveBeenCalledWith(
218
+ engine,
219
+ [{ viewUid: 'test-route' }, { viewUid: 'popup', filterByTk: 'member' }],
220
+ expect.anything(),
221
+ );
222
+ });
223
+
224
+ it('syncs view stack from layout route pageUid', () => {
225
+ const engine = new FlowEngine();
226
+ engine.registerModels({ RouteModel });
227
+ engine.context.defineProperty('route', {
228
+ value: {},
229
+ });
230
+ engine.context.defineProperty('routeRepository', {
231
+ value: {
232
+ getRouteBySchemaUid: vi.fn(() => ({})),
233
+ },
234
+ });
235
+
236
+ mockResolveViewParamsToViewList.mockReturnValue([]);
237
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
238
+ viewsToClose: [],
239
+ viewsToOpen: [],
240
+ });
241
+
242
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/embed' });
243
+ coordinator.registerPage('test-route', {
244
+ active: false,
245
+ layoutContentElement: document.createElement('div'),
246
+ });
247
+ coordinator.syncRoute({
248
+ pageUid: 'test-route',
249
+ pathname: '/embed/test-route/view/popup/filterbytk/member',
250
+ });
251
+
252
+ expect(mockResolveViewParamsToViewList).toHaveBeenLastCalledWith(
253
+ engine,
254
+ [{ viewUid: 'test-route' }, { viewUid: 'popup', filterByTk: 'member' }],
255
+ expect.anything(),
256
+ );
257
+ });
258
+
259
+ it('notifies cached route page activation when switching pages', () => {
260
+ const engine = new FlowEngine();
261
+ engine.registerModels({ RouteModel });
262
+ engine.context.defineProperty('route', {
263
+ value: {},
264
+ });
265
+ engine.context.defineProperty('routeRepository', {
266
+ value: {
267
+ getRouteBySchemaUid: vi.fn(() => ({})),
268
+ },
269
+ });
270
+
271
+ const dispatchEvent = vi.fn((_eventName: string, payload: any) => {
272
+ payload.activateRef.current = vi.fn();
273
+ payload.deactivateRef.current = vi.fn();
274
+ return Promise.resolve();
275
+ });
276
+ const viewItem = {
277
+ params: { viewUid: 'test-route' },
278
+ modelUid: 'test-route',
279
+ model: { uid: 'test-route', dispatchEvent } as any,
280
+ hidden: { value: false },
281
+ index: 0,
282
+ };
283
+ mockResolveViewParamsToViewList.mockReturnValue([viewItem]);
284
+ mockGetViewDiffAndUpdateHidden.mockReturnValueOnce({
285
+ viewsToClose: [],
286
+ viewsToOpen: [viewItem],
287
+ });
288
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
289
+ viewsToClose: [],
290
+ viewsToOpen: [],
291
+ });
292
+
293
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/admin' });
294
+ coordinator.registerPage('test-route', {
295
+ active: false,
296
+ layoutContentElement: document.createElement('div'),
297
+ });
298
+ coordinator.syncRoute({
299
+ pageUid: 'test-route',
300
+ pathname: '/admin/test-route',
301
+ });
302
+
303
+ const payload = dispatchEvent.mock.calls[0][1];
304
+ expect(payload.pageActive).toBe(true);
305
+ expect(payload.activationControlledByLayout).toBe(true);
306
+
307
+ coordinator.syncRoute({
308
+ pageUid: 'other-route',
309
+ pathname: '/admin/other-route',
310
+ });
311
+ coordinator.syncRoute({
312
+ pageUid: 'test-route',
313
+ pathname: '/admin/test-route',
314
+ });
315
+
316
+ expect(payload.deactivateRef.current).toHaveBeenCalledTimes(1);
317
+ expect(payload.activateRef.current).toHaveBeenCalledWith(true);
318
+ });
319
+
320
+ it('syncs cached embed page visibility when switching pages', () => {
321
+ const engine = new FlowEngine();
322
+ engine.registerModels({ RouteModel });
323
+ engine.context.defineProperty('route', {
324
+ value: {},
325
+ });
326
+ engine.context.defineProperty('routeRepository', {
327
+ value: {
328
+ getRouteBySchemaUid: vi.fn(() => ({})),
329
+ },
330
+ });
331
+
332
+ const viewItemsByPageUid = new Map<string, any>();
333
+ const createViewItem = (pageUid: string) => {
334
+ const dispatchEvent = vi.fn((_eventName: string, payload: any) => {
335
+ payload.activateRef.current = vi.fn();
336
+ payload.deactivateRef.current = vi.fn();
337
+ return Promise.resolve();
338
+ });
339
+ return {
340
+ params: { viewUid: pageUid },
341
+ modelUid: pageUid,
342
+ model: { uid: pageUid, dispatchEvent } as any,
343
+ hidden: { value: false },
344
+ index: 0,
345
+ };
346
+ };
347
+
348
+ mockResolveViewParamsToViewList.mockImplementation((_engine, viewParams) => {
349
+ const pageUid = viewParams[0].viewUid;
350
+ if (!viewItemsByPageUid.has(pageUid)) {
351
+ viewItemsByPageUid.set(pageUid, createViewItem(pageUid));
352
+ }
353
+ return [viewItemsByPageUid.get(pageUid)];
354
+ });
355
+ mockGetViewDiffAndUpdateHidden.mockImplementation((prevViewList, currentViewList) => ({
356
+ viewsToClose: prevViewList.filter((prevViewItem) => !currentViewList.includes(prevViewItem)),
357
+ viewsToOpen: currentViewList.filter((currentViewItem) => !prevViewList.includes(currentViewItem)),
358
+ }));
359
+ mockUpdateViewListHidden.mockImplementation((viewItems) => {
360
+ viewItems.forEach((viewItem) => {
361
+ viewItem.hidden.value = false;
362
+ });
363
+ });
364
+
365
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/admin' });
366
+ coordinator.registerPage('page-1', {
367
+ active: false,
368
+ layoutContentElement: document.createElement('div'),
369
+ });
370
+ coordinator.registerPage('page-3', {
371
+ active: false,
372
+ layoutContentElement: document.createElement('div'),
373
+ });
374
+
375
+ coordinator.syncRoute({
376
+ pageUid: 'page-3',
377
+ pathname: '/admin/page-3',
378
+ });
379
+ const page3ViewItem = viewItemsByPageUid.get('page-3');
380
+ expect(page3ViewItem.hidden.value).toBe(false);
381
+
382
+ coordinator.syncRoute({
383
+ pageUid: 'page-1',
384
+ pathname: '/admin/page-1',
385
+ });
386
+ const page1ViewItem = viewItemsByPageUid.get('page-1');
387
+ expect(page1ViewItem.hidden.value).toBe(false);
388
+ expect(page3ViewItem.hidden.value).toBe(true);
389
+
390
+ coordinator.syncRoute({
391
+ pageUid: 'page-3',
392
+ pathname: '/admin/page-3',
393
+ });
394
+ expect(page3ViewItem.hidden.value).toBe(false);
395
+ expect(page1ViewItem.hidden.value).toBe(true);
396
+ });
397
+
398
+ it('notifies cached route page activation when page meta active changes', () => {
399
+ const engine = new FlowEngine();
400
+ engine.registerModels({ RouteModel });
401
+ engine.context.defineProperty('route', {
402
+ value: {},
403
+ });
404
+ engine.context.defineProperty('routeRepository', {
405
+ value: {
406
+ getRouteBySchemaUid: vi.fn(() => ({})),
407
+ },
408
+ });
409
+
410
+ const dispatchEvent = vi.fn((_eventName: string, payload: any) => {
411
+ payload.activateRef.current = vi.fn();
412
+ payload.deactivateRef.current = vi.fn();
413
+ return Promise.resolve();
414
+ });
415
+ const viewItem = {
416
+ params: { viewUid: 'test-route' },
417
+ modelUid: 'test-route',
418
+ model: { uid: 'test-route', dispatchEvent } as any,
419
+ hidden: { value: false },
420
+ index: 0,
421
+ };
422
+ mockResolveViewParamsToViewList.mockReturnValue([viewItem]);
423
+ mockGetViewDiffAndUpdateHidden.mockReturnValueOnce({
424
+ viewsToClose: [],
425
+ viewsToOpen: [viewItem],
426
+ });
427
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
428
+ viewsToClose: [],
429
+ viewsToOpen: [],
430
+ });
431
+
432
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/admin' });
433
+ coordinator.registerPage('test-route', {
434
+ active: true,
435
+ layoutContentElement: document.createElement('div'),
436
+ });
437
+ coordinator.syncRoute({
438
+ pageUid: 'test-route',
439
+ pathname: '/admin/test-route',
440
+ });
441
+
442
+ const payload = dispatchEvent.mock.calls[0][1];
443
+
444
+ coordinator.syncPageMeta('test-route', { active: false });
445
+ coordinator.syncPageMeta('test-route', { active: true });
446
+
447
+ expect(payload.deactivateRef.current).toHaveBeenCalledTimes(1);
448
+ expect(payload.activateRef.current).toHaveBeenCalledWith(true);
449
+ });
450
+
451
+ it('replays an initial deep link when step navigation does not trigger another route sync', async () => {
452
+ const engine = new FlowEngine();
453
+ engine.registerModels({ RouteModel });
454
+ const navigate = vi.fn();
455
+ engine.context.defineProperty('router', {
456
+ value: {
457
+ navigate,
458
+ },
459
+ });
460
+ engine.context.defineProperty('route', {
461
+ value: {},
462
+ });
463
+ engine.context.defineProperty('routeRepository', {
464
+ value: {
465
+ getRouteBySchemaUid: vi.fn(() => ({})),
466
+ },
467
+ });
468
+
469
+ const popupViewItem = {
470
+ params: { viewUid: 'popup', filterByTk: '1' },
471
+ modelUid: 'popup',
472
+ model: { uid: 'popup', dispatchEvent: vi.fn() } as any,
473
+ hidden: { value: false },
474
+ index: 1,
475
+ };
476
+ mockResolveViewParamsToViewList.mockImplementation((_engine, viewParams, routeModel) => [
477
+ {
478
+ params: viewParams[0],
479
+ modelUid: routeModel.uid,
480
+ model: routeModel,
481
+ hidden: { value: false },
482
+ index: 0,
483
+ },
484
+ popupViewItem,
485
+ ]);
486
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
487
+ viewsToClose: [],
488
+ viewsToOpen: [],
489
+ });
490
+
491
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/admin' });
492
+ coordinator.registerPage('test-route', {
493
+ active: false,
494
+ layoutContentElement: document.createElement('div'),
495
+ });
496
+ coordinator.syncRoute({
497
+ pageUid: 'test-route',
498
+ pathname: '/admin/test-route/view/popup/filterbytk/1',
499
+ });
500
+
501
+ expect(navigate).toHaveBeenCalledWith('/admin/test-route', { replace: true });
502
+ expect(mockGetViewDiffAndUpdateHidden).not.toHaveBeenCalled();
503
+
504
+ await Promise.resolve();
505
+
506
+ expect(mockResolveViewParamsToViewList).toHaveBeenCalledTimes(2);
507
+ expect(mockGetViewDiffAndUpdateHidden).toHaveBeenCalledTimes(1);
508
+ });
509
+
510
+ it('does not replay global route when a route page registers', () => {
511
+ const engine = new FlowEngine();
512
+ engine.registerModels({ RouteModel });
513
+ engine.context.defineProperty('route', {
514
+ value: {
515
+ params: { name: 'test-route' },
516
+ pathname: '/embed/test-route/view/popup',
517
+ },
518
+ });
519
+ engine.context.defineProperty('routeRepository', {
520
+ value: {
521
+ getRouteBySchemaUid: vi.fn(() => ({})),
522
+ },
523
+ });
524
+
525
+ mockResolveViewParamsToViewList.mockReturnValue([]);
526
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
527
+ viewsToClose: [],
528
+ viewsToOpen: [],
529
+ });
530
+
531
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { basePathname: '/embed' });
532
+ coordinator.registerPage('test-route', {
533
+ active: false,
534
+ layoutContentElement: document.createElement('div'),
535
+ });
536
+
537
+ expect(mockResolveViewParamsToViewList).not.toHaveBeenCalled();
538
+ expect(engine.getModel('test-route')?.context.pageActive.value).toBe(false);
539
+ });
540
+
541
+ it('parses view stack with nested basePath', () => {
542
+ expect(
543
+ toViewStack('/admin/settings/public-forms/form-1/view/popup', {
544
+ basePathname: '/admin/settings/public-forms',
545
+ }),
546
+ ).toEqual([{ viewUid: 'form-1' }, { viewUid: 'popup' }]);
547
+ });
548
+
549
+ it('parses view stack for empty nested routePath from runtime basePathname', () => {
550
+ const engine = new FlowEngine();
551
+ engine.registerModels({ RouteModel });
552
+ engine.context.defineProperty('route', {
553
+ value: {
554
+ params: { name: 'form-1' },
555
+ pathname: '/admin/settings/public-forms/form-1/view/popup/filterbytk/member',
556
+ },
557
+ });
558
+ engine.context.defineProperty('routeRepository', {
559
+ value: {
560
+ getRouteBySchemaUid: vi.fn(() => ({})),
561
+ },
562
+ });
563
+
564
+ mockResolveViewParamsToViewList.mockReturnValue([]);
565
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
566
+ viewsToClose: [],
567
+ viewsToOpen: [],
568
+ });
569
+
570
+ const coordinator = new BaseLayoutRouteCoordinator(engine, {
571
+ layout: {
572
+ routeName: 'admin.settings.publicForms.layout',
573
+ routePath: '',
574
+ rootRouteName: 'admin',
575
+ uid: 'public-form-layout-model',
576
+ layoutModelClass: 'PublicFormLayoutModel',
577
+ rootPageModelClass: 'RootPageModel',
578
+ childPageModelClass: 'ChildPageModel',
579
+ authCheck: true,
580
+ },
581
+ });
582
+ coordinator.registerPage('form-1', {
583
+ active: true,
584
+ layoutContentElement: document.createElement('div'),
585
+ });
586
+ coordinator.syncRoute({
587
+ layoutRouteName: 'admin.settings.publicForms.layout',
588
+ params: { name: 'form-1' },
589
+ pathname: '/admin/settings/public-forms/form-1/view/popup/filterbytk/member',
590
+ layoutBasePathname: '/admin/settings/public-forms',
591
+ });
592
+
593
+ expect(mockResolveViewParamsToViewList).toHaveBeenCalledWith(
594
+ engine,
595
+ [{ viewUid: 'form-1' }, { viewUid: 'popup', filterByTk: 'member' }],
596
+ expect.anything(),
597
+ );
598
+ });
599
+
600
+ it('does not parse relative layout routePath without runtime basePathname', () => {
601
+ expect(
602
+ toViewStack('/admin/settings/public-forms/form-1/view/popup', {
603
+ layout: {
604
+ routeName: 'admin.settings.publicForms',
605
+ routePath: 'public-forms',
606
+ rootRouteName: 'admin',
607
+ uid: 'public-form-layout-model',
608
+ layoutModelClass: 'PublicFormLayoutModel',
609
+ rootPageModelClass: 'RootPageModel',
610
+ childPageModelClass: 'ChildPageModel',
611
+ authCheck: true,
612
+ },
613
+ }),
614
+ ).toEqual([]);
615
+ });
616
+
617
+ it('exposes current layout on route model context', () => {
618
+ const engine = new FlowEngine();
619
+ engine.registerModels({ RouteModel });
620
+ engine.context.defineProperty('route', {
621
+ value: {
622
+ params: { name: 'test-route' },
623
+ pathname: '/embed/test-route',
624
+ },
625
+ });
626
+ engine.context.defineProperty('routeRepository', {
627
+ value: {
628
+ getRouteBySchemaUid: vi.fn(() => ({})),
629
+ },
630
+ });
631
+
632
+ mockResolveViewParamsToViewList.mockReturnValue([]);
633
+ mockGetViewDiffAndUpdateHidden.mockReturnValue({
634
+ viewsToClose: [],
635
+ viewsToOpen: [],
636
+ });
637
+
638
+ const layout = {
639
+ routeName: 'embed',
640
+ routePath: '/embed',
641
+ rootRouteName: 'embed',
642
+ uid: 'embed-layout-model',
643
+ layoutModelClass: 'EmbedLayoutModelV2',
644
+ rootPageModelClass: 'RootPageModel',
645
+ childPageModelClass: 'ChildPageModel',
646
+ authCheck: true,
647
+ };
648
+ const layoutContext = new FlowContext();
649
+ layoutContext.defineProperty('layoutMarker', { value: 'layout-context' });
650
+
651
+ const coordinator = new BaseLayoutRouteCoordinator(engine, { layout, layoutContext });
652
+ coordinator.registerPage('test-route', {
653
+ active: true,
654
+ layoutContentElement: document.createElement('div'),
655
+ });
656
+
657
+ expect(engine.getModel('test-route')?.context.layout).toBe(layout);
658
+ expect(engine.getModel('test-route')?.context.layoutContext).toBe(layoutContext);
659
+ expect(engine.getModel('test-route')?.context.layoutMarker).toBe('layout-context');
660
+ });
117
661
  });
@@ -42,6 +42,7 @@ import {
42
42
  FLOW_SETTINGS_PREFERENCE_STORAGE_KEY,
43
43
  readFlowSettingsPreference,
44
44
  } from './flowSettingsPreference';
45
+ import { useAppListRender } from './AppListRender';
45
46
 
46
47
  const className1 = css`
47
48
  height: var(--nb-header-height);
@@ -279,9 +280,9 @@ const MobileActions: FC = () => {
279
280
  * @param props
280
281
  * @returns
281
282
  */
282
- function SetIsMobileLayout(props: { isMobile: boolean; children: any }) {
283
+ function SetIsMobileLayout(props: { isMobile: boolean; children: any; model?: AdminLayoutModel }) {
283
284
  const flowEngine = useFlowEngine();
284
- const adminLayoutModel = flowEngine.getModel<AdminLayoutModel>(ADMIN_LAYOUT_MODEL_UID);
285
+ const adminLayoutModel = props.model || flowEngine.getModel<AdminLayoutModel>(ADMIN_LAYOUT_MODEL_UID);
285
286
 
286
287
  useEffect(() => {
287
288
  adminLayoutModel?.setIsMobileLayout(props.isMobile);
@@ -367,7 +368,7 @@ const renderMenuNodeWithModel = (
367
368
 
368
369
  export const AdminLayoutComponent = observer((props: any) => {
369
370
  const flowEngine = useFlowEngine();
370
- const adminLayoutModel = flowEngine.getModel<AdminLayoutModel>(ADMIN_LAYOUT_MODEL_UID);
371
+ const adminLayoutModel = props.model || flowEngine.getModel<AdminLayoutModel>(ADMIN_LAYOUT_MODEL_UID);
371
372
  const [allAccessRoutes, setAllAccessRoutes] = useState<NocoBaseDesktopRoute[]>(
372
373
  () => flowEngine.context.routeRepository?.listAccessible?.() || [],
373
374
  );
@@ -391,7 +392,8 @@ export const AdminLayoutComponent = observer((props: any) => {
391
392
  );
392
393
  const designable = !isMobileSider && preferredFlowSettingsEnabled;
393
394
  const { styles } = useHeaderStyle();
394
- const { Component: AppsComponent } = useApplications();
395
+ const { appList } = useApplications();
396
+ const appListRender = useAppListRender();
395
397
  const flowSettingsSyncRef = useRef(0);
396
398
  const desiredFlowSettingsEnabledRef = useRef(false);
397
399
  const handleLayoutContentElementChange = useCallback(
@@ -601,6 +603,31 @@ export const AdminLayoutComponent = observer((props: any) => {
601
603
  overflowedIndicatorPopupClassName: styles.headerPopup,
602
604
  };
603
605
  }, [styles.headerPopup]);
606
+ const appSwitcherStyle = useMemo(
607
+ () => css`
608
+ .ant-layout-header.ant-pro-layout-header,
609
+ .ant-pro-top-nav-header {
610
+ z-index: 101 !important;
611
+ }
612
+
613
+ .ant-pro-layout-apps-popover {
614
+ z-index: 2000 !important;
615
+ }
616
+
617
+ .ant-pro-layout-apps-icon {
618
+ color: ${customToken.colorTextHeaderMenu || 'rgba(255, 255, 255, 0.85)'};
619
+ }
620
+
621
+ .ant-pro-layout-apps-icon:hover,
622
+ .ant-pro-layout-apps-icon-active {
623
+ color: ${customToken.colorTextHeaderMenuHover ||
624
+ customToken.colorTextHeaderMenu ||
625
+ 'rgba(255, 255, 255, 0.85)'};
626
+ background: ${customToken.colorBgHeaderMenuHover || 'rgba(255, 255, 255, 0.12)'};
627
+ }
628
+ `,
629
+ [customToken.colorBgHeaderMenuHover, customToken.colorTextHeaderMenu, customToken.colorTextHeaderMenuHover],
630
+ );
604
631
 
605
632
  const closeMobileMenu = useCallback(() => {
606
633
  if (!isMobileSider) {
@@ -634,16 +661,17 @@ export const AdminLayoutComponent = observer((props: any) => {
634
661
  {...props}
635
662
  contentStyle={contentStyle}
636
663
  siderWidth={customToken.siderWidth || 200}
637
- className={resetStyle}
664
+ className={`${resetStyle} ${appSwitcherStyle}`}
638
665
  location={location}
639
666
  route={route}
640
667
  actionsRender={props.actionsRender || actionsRender}
641
668
  logo={
642
669
  <div style={{ display: 'flex', alignItems: 'center' }}>
643
- {AppsComponent && <AppsComponent />}
644
670
  <NocoBaseLogo />
645
671
  </div>
646
672
  }
673
+ appList={appList}
674
+ appListRender={appListRender}
647
675
  title={''}
648
676
  layout="mix"
649
677
  splitMenus
@@ -666,7 +694,7 @@ export const AdminLayoutComponent = observer((props: any) => {
666
694
  const { isMobile } = value;
667
695
 
668
696
  return (
669
- <SetIsMobileLayout isMobile={isMobile}>
697
+ <SetIsMobileLayout isMobile={isMobile} model={adminLayoutModel}>
670
698
  <ConfigProvider theme={isMobile ? mobileTheme : theme}>
671
699
  <GlobalStyle />
672
700
  <AdminLayoutContent onContentElementChange={handleLayoutContentElementChange} />