@nocobase/client-v2 2.2.0-beta.8 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/es/APIClient.d.ts +13 -3
  2. package/es/BaseApplication.d.ts +3 -0
  3. package/es/RouteRepository.d.ts +8 -0
  4. package/es/RouterManager.d.ts +15 -0
  5. package/es/authRedirect.d.ts +1 -0
  6. package/es/collection-field-interface/CollectionFieldInterface.d.ts +1 -0
  7. package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +1 -0
  8. package/es/components/category-tabs/SortableCategoryTabs.d.ts +55 -0
  9. package/es/components/category-tabs/index.d.ts +9 -0
  10. package/es/components/form/ScanInput/useCodeScanner.d.ts +3 -2
  11. package/es/components/form/TypedVariableInput.d.ts +31 -5
  12. package/es/components/form/filter/CollectionFilter.d.ts +2 -0
  13. package/es/components/form/filter/CollectionFilterItem.d.ts +11 -1
  14. package/es/components/form/filter/CollectionFilterPanel.d.ts +2 -0
  15. package/es/components/form/filter/index.d.ts +2 -0
  16. package/es/components/form/filter/useFilterActionProps.d.ts +2 -0
  17. package/es/components/index.d.ts +1 -0
  18. package/es/entry-actions/EntryActionManager.d.ts +24 -0
  19. package/es/entry-actions/index.d.ts +9 -0
  20. package/es/flow/actions/index.d.ts +1 -1
  21. package/es/flow/actions/linkageRules.d.ts +27 -0
  22. package/es/flow/admin-shell/BaseLayoutModel.d.ts +6 -0
  23. package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +7 -0
  24. package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +1 -0
  25. package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +2 -1
  26. package/es/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.d.ts +24 -0
  27. package/es/flow/admin-shell/admin-layout/index.d.ts +1 -0
  28. package/es/flow/admin-shell/admin-layout/useApplications.d.ts +7 -2
  29. package/es/flow/components/FieldAssignExactDatePicker.d.ts +1 -0
  30. package/es/flow/components/FieldAssignValueInput.d.ts +7 -24
  31. package/es/flow/components/FlowRoute.d.ts +2 -2
  32. package/es/flow/components/RunJSValueEditor.d.ts +1 -0
  33. package/es/flow/components/field-value-variable/DateVariableEditor.d.ts +24 -0
  34. package/es/flow/components/field-value-variable/FieldValueVariableInput.d.ts +31 -0
  35. package/es/flow/components/field-value-variable/dateValue.d.ts +36 -0
  36. package/es/flow/components/field-value-variable/index.d.ts +11 -0
  37. package/es/flow/components/filter/FilterGroup.d.ts +1 -0
  38. package/es/flow/components/filter/VariableFilterItem.d.ts +6 -1
  39. package/es/flow/components/placeholders/BlockPlaceholder.d.ts +1 -0
  40. package/es/flow/index.d.ts +1 -0
  41. package/es/flow/internal/registerDeviceTypeContext.d.ts +10 -0
  42. package/es/flow/internal/utils/operatorSchemaHelper.d.ts +2 -2
  43. package/es/flow/models/actions/UpdateRecordActionUtils.d.ts +8 -2
  44. package/es/flow/models/base/ActionModelCore.d.ts +6 -2
  45. package/es/flow/models/base/BlockGridModel.d.ts +3 -0
  46. package/es/flow/models/base/CollectionBlockModel.d.ts +3 -0
  47. package/es/flow/models/base/PageModel/PageModel.d.ts +12 -0
  48. package/es/flow/models/base/PageModel/PageModelTabBar.d.ts +22 -0
  49. package/es/flow/models/base/PageModel/PageTabModel.d.ts +12 -0
  50. package/es/flow/models/blocks/details/DetailsBlockModel.d.ts +3 -0
  51. package/es/flow/models/blocks/filter-form/FilterFormGridModel.d.ts +1 -0
  52. package/es/flow/models/blocks/filter-form/FilterFormSubmitActionModel.d.ts +3 -1
  53. package/es/flow/models/blocks/form/FormBlockModel.d.ts +7 -0
  54. package/es/flow/models/blocks/form/FormGridModel.d.ts +6 -0
  55. package/es/flow/models/blocks/form/QuickEditFormModel.d.ts +17 -2
  56. package/es/flow/models/blocks/form/value-runtime/rules.d.ts +1 -0
  57. package/es/flow/models/blocks/table/JSColumnModel.d.ts +2 -0
  58. package/es/flow/models/blocks/table/TableBlockModel.d.ts +1 -0
  59. package/es/flow/models/blocks/table/TableColumnModel.d.ts +12 -0
  60. package/es/flow/models/blocks/table/utils.d.ts +1 -0
  61. package/es/flow/models/fields/AssociationFieldModel/RecordPickerFieldModel.d.ts +2 -1
  62. package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +0 -17
  63. package/es/flow/models/fields/AssociationFieldModel/recordSelectShared.d.ts +41 -0
  64. package/es/flow/models/fields/DateTimeFieldModel/dateLimit.d.ts +15 -7
  65. package/es/flow/routeTransientInputArgs.d.ts +14 -0
  66. package/es/flow-compat/fieldValidationConstants.d.ts +1 -1
  67. package/es/flow-compat/passwordUtils.d.ts +1 -1
  68. package/es/flow-compat/routeTypes.d.ts +1 -0
  69. package/es/index.d.ts +7 -0
  70. package/es/index.mjs +301 -177
  71. package/es/ui-operation/index.d.ts +15 -0
  72. package/es/ui-operation/ui-operation-codec.d.ts +10 -0
  73. package/es/utils/getRouteRuntimeVersion.d.ts +23 -0
  74. package/es/utils/index.d.ts +1 -0
  75. package/es/utils/markdownSanitize.d.ts +11 -0
  76. package/lib/index.js +313 -189
  77. package/lib/locale/languageCodes.js +3 -1
  78. package/package.json +9 -7
  79. package/src/APIClient.ts +90 -7
  80. package/src/Application.tsx +7 -1
  81. package/src/BaseApplication.tsx +13 -6
  82. package/src/RouteRepository.ts +25 -0
  83. package/src/RouterManager.tsx +142 -1
  84. package/src/__tests__/APIClient.test.tsx +58 -0
  85. package/src/__tests__/RouteRepository.test.ts +23 -0
  86. package/src/__tests__/RouterManager.test.ts +125 -0
  87. package/src/__tests__/app.test.tsx +73 -0
  88. package/src/__tests__/authRedirect.test.ts +17 -0
  89. package/src/__tests__/browserChecker.test.ts +61 -0
  90. package/src/__tests__/getRouteRuntimeVersion.test.ts +68 -0
  91. package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +35 -2
  92. package/src/__tests__/settings-center.test.tsx +270 -6
  93. package/src/acl/ACLProvider.tsx +2 -0
  94. package/src/acl/__tests__/ACLProvider.test.tsx +92 -0
  95. package/src/authRedirect.ts +38 -0
  96. package/src/collection-field-interface/CollectionFieldInterface.ts +1 -0
  97. package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +1 -0
  98. package/src/collection-manager/field-validation.ts +1 -1
  99. package/src/components/README.md +7 -1
  100. package/src/components/README.zh-CN.md +6 -1
  101. package/src/components/category-tabs/SortableCategoryTabs.tsx +210 -0
  102. package/src/components/category-tabs/index.ts +10 -0
  103. package/src/components/form/JsonTextArea.tsx +4 -0
  104. package/src/components/form/ScanInput/CodeScanner.tsx +79 -35
  105. package/src/components/form/ScanInput/__tests__/CodeScanner.test.tsx +101 -0
  106. package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +284 -11
  107. package/src/components/form/ScanInput/useCodeScanner.ts +332 -24
  108. package/src/components/form/TypedVariableInput.tsx +452 -101
  109. package/src/components/form/__tests__/TypedVariableInput.test.tsx +364 -12
  110. package/src/components/form/filter/CollectionFilter.tsx +4 -0
  111. package/src/components/form/filter/CollectionFilterItem.tsx +36 -9
  112. package/src/components/form/filter/CollectionFilterPanel.tsx +4 -0
  113. package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +55 -0
  114. package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +95 -0
  115. package/src/components/form/filter/index.ts +2 -0
  116. package/src/components/form/filter/useFilterActionProps.ts +37 -6
  117. package/src/components/form/table/Table.tsx +81 -6
  118. package/src/components/form/table/__tests__/Table.columnWidth.test.tsx +433 -0
  119. package/src/components/index.ts +1 -0
  120. package/src/entry-actions/EntryActionManager.ts +76 -0
  121. package/src/entry-actions/index.ts +10 -0
  122. package/src/flow/FlowPage.tsx +38 -3
  123. package/src/flow/__tests__/FlowPage.test.tsx +201 -27
  124. package/src/flow/__tests__/FlowRoute.test.tsx +675 -12
  125. package/src/flow/__tests__/PluginFlowEngine.test.ts +58 -0
  126. package/src/flow/actions/__tests__/actionLinkageRules.forkProps.test.ts +314 -0
  127. package/src/flow/actions/__tests__/dataScopeFilter.test.ts +62 -0
  128. package/src/flow/actions/__tests__/dataScopeFormValueClear.test.ts +102 -0
  129. package/src/flow/actions/__tests__/linkageRules.actionStates.test.ts +33 -0
  130. package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +72 -0
  131. package/src/flow/actions/__tests__/linkageRules.tab.test.ts +171 -0
  132. package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +7 -3
  133. package/src/flow/actions/__tests__/openView.defineProps.route.test.tsx +80 -20
  134. package/src/flow/actions/dataScopeFilter.ts +10 -1
  135. package/src/flow/actions/dateTimeFormat.tsx +2 -2
  136. package/src/flow/actions/index.ts +2 -0
  137. package/src/flow/actions/linkageRules.tsx +144 -26
  138. package/src/flow/actions/linkageRulesRefresh.tsx +2 -6
  139. package/src/flow/actions/openView.tsx +21 -1
  140. package/src/flow/admin-shell/BaseLayoutModel.tsx +124 -0
  141. package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +184 -42
  142. package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +1016 -119
  143. package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +41 -5
  144. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.test.tsx +177 -1
  145. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +20 -0
  146. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +78 -59
  147. package/src/flow/admin-shell/admin-layout/AppListRender.tsx +13 -2
  148. package/src/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.tsx +289 -0
  149. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +253 -6
  150. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +228 -0
  151. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +436 -2
  152. package/src/flow/admin-shell/admin-layout/__tests__/TopbarActionsBar.test.tsx +48 -0
  153. package/src/flow/admin-shell/admin-layout/index.ts +1 -0
  154. package/src/flow/admin-shell/admin-layout/useApplications.tsx +81 -12
  155. package/src/flow/common/Markdown/Display.tsx +14 -3
  156. package/src/flow/common/Markdown/Edit.tsx +19 -7
  157. package/src/flow/common/Markdown/style.ts +4 -0
  158. package/src/flow/components/BlockItemCard.tsx +2 -2
  159. package/src/flow/components/FieldAssignExactDatePicker.tsx +25 -11
  160. package/src/flow/components/FieldAssignValueInput.tsx +72 -584
  161. package/src/flow/components/FlowRoute.tsx +204 -46
  162. package/src/flow/components/RunJSValueEditor.tsx +9 -1
  163. package/src/flow/components/__tests__/FieldAssignValueInput.context.test.tsx +216 -0
  164. package/src/flow/components/field-value-variable/DateVariableEditor.tsx +181 -0
  165. package/src/flow/components/field-value-variable/FieldValueVariableInput.tsx +326 -0
  166. package/src/flow/components/field-value-variable/__tests__/FieldValueVariableInput.test.tsx +380 -0
  167. package/src/flow/components/field-value-variable/dateValue.ts +223 -0
  168. package/src/flow/components/field-value-variable/index.ts +12 -0
  169. package/src/flow/components/filter/FilterGroup.tsx +33 -5
  170. package/src/flow/components/filter/VariableFilterItem.tsx +170 -13
  171. package/src/flow/components/filter/__tests__/FilterGroup.test.tsx +45 -0
  172. package/src/flow/components/filter/__tests__/VariableFilterItem.leftMetaTree.test.tsx +9 -0
  173. package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +195 -1
  174. package/src/flow/components/placeholders/BlockPlaceholder.tsx +70 -23
  175. package/src/flow/components/placeholders/__tests__/BlockPlaceholder.test.tsx +57 -7
  176. package/src/flow/index.ts +3 -0
  177. package/src/flow/internal/components/Markdown/util.ts +2 -1
  178. package/src/flow/internal/registerDeviceTypeContext.ts +39 -0
  179. package/src/flow/internal/utils/operatorSchemaHelper.ts +3 -2
  180. package/src/flow/models/actions/UpdateRecordActionModel.tsx +18 -1
  181. package/src/flow/models/actions/UpdateRecordActionUtils.ts +18 -6
  182. package/src/flow/models/actions/__tests__/UpdateRecordActionModel.test.ts +76 -4
  183. package/src/flow/models/base/ActionModel.tsx +10 -8
  184. package/src/flow/models/base/ActionModelCore.tsx +16 -2
  185. package/src/flow/models/base/BlockGridModel.tsx +26 -0
  186. package/src/flow/models/base/CollectionBlockModel.tsx +38 -3
  187. package/src/flow/models/base/PageModel/PageModel.tsx +387 -53
  188. package/src/flow/models/base/PageModel/PageModelTabBar.tsx +114 -0
  189. package/src/flow/models/base/PageModel/PageTabModel.tsx +249 -18
  190. package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +790 -10
  191. package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.module-isolation.test.tsx +130 -0
  192. package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.test.tsx +118 -0
  193. package/src/flow/models/base/PageModel/__tests__/PageTabModel.test.ts +1075 -7
  194. package/src/flow/models/base/__tests__/ActionModelCore.render.test.tsx +49 -0
  195. package/src/flow/models/base/__tests__/BlockGridModel.selectSceneActivation.test.ts +124 -0
  196. package/src/flow/models/base/__tests__/CollectionBlockModel.addAppends.test.ts +41 -0
  197. package/src/flow/models/base/__tests__/CollectionBlockModel.initialBeforeRenderRefresh.test.ts +125 -9
  198. package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +28 -53
  199. package/src/flow/models/blocks/details/DetailsBlockModel.tsx +8 -3
  200. package/src/flow/models/blocks/details/__tests__/DetailsBlockModel.initialPaginationChangeRefresh.test.ts +32 -1
  201. package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +28 -3
  202. package/src/flow/models/blocks/filter-form/FilterFormGridModel.tsx +36 -5
  203. package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +155 -25
  204. package/src/flow/models/blocks/filter-form/FilterFormSubmitActionModel.tsx +57 -4
  205. package/src/flow/models/blocks/filter-form/__tests__/FilterFormGridModel.onModelCreated.test.ts +174 -1
  206. package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +395 -1
  207. package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.getFilterValue.test.ts +72 -0
  208. package/src/flow/models/blocks/filter-form/__tests__/FilterFormSubmitActionModel.lifecycle.test.ts +90 -0
  209. package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +66 -4
  210. package/src/flow/models/blocks/filter-manager/FilterManager.ts +5 -0
  211. package/src/flow/models/blocks/filter-manager/__tests__/FilterManager.test.ts +40 -0
  212. package/src/flow/models/blocks/form/FormBlockModel.tsx +47 -0
  213. package/src/flow/models/blocks/form/FormGridModel.tsx +4 -0
  214. package/src/flow/models/blocks/form/QuickEditFormModel.tsx +189 -36
  215. package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +8 -2
  216. package/src/flow/models/blocks/form/__tests__/QuickEditFormModel.quickEdit.test.ts +350 -2
  217. package/src/flow/models/blocks/form/__tests__/runJsFormSubmit.test.ts +131 -0
  218. package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +435 -0
  219. package/src/flow/models/blocks/form/value-runtime/rules.ts +67 -14
  220. package/src/flow/models/blocks/form/value-runtime/runtime.ts +43 -19
  221. package/src/flow/models/blocks/js-block/JSBlock.tsx +1 -1
  222. package/src/flow/models/blocks/table/JSColumnModel.tsx +10 -1
  223. package/src/flow/models/blocks/table/TableActionsColumnModel.tsx +2 -1
  224. package/src/flow/models/blocks/table/TableBlockModel.tsx +29 -3
  225. package/src/flow/models/blocks/table/TableColumnModel.tsx +54 -11
  226. package/src/flow/models/blocks/table/__tests__/JSColumnModel.test.tsx +52 -5
  227. package/src/flow/models/blocks/table/__tests__/TableBlockModel.filterReset.test.ts +78 -0
  228. package/src/flow/models/blocks/table/__tests__/TableBlockModel.quickEditRefresh.test.ts +12 -0
  229. package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +84 -0
  230. package/src/flow/models/blocks/table/utils.ts +7 -0
  231. package/src/flow/models/fields/AssociationFieldModel/CascadeSelectFieldModel.tsx +33 -1
  232. package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +10 -1
  233. package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/__tests__/popupContext.test.ts +120 -0
  234. package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/actions/PopupSubTableEditActionModel.tsx +10 -2
  235. package/src/flow/models/fields/AssociationFieldModel/RecordPickerFieldModel.tsx +24 -1
  236. package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +54 -149
  237. package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +167 -3
  238. package/src/flow/models/fields/AssociationFieldModel/recordSelectShared.tsx +156 -0
  239. package/src/flow/models/fields/DateTimeFieldModel/__tests__/DateTimeNoTzFieldModel.dateLimit.test.tsx +149 -0
  240. package/src/flow/models/fields/DateTimeFieldModel/dateLimit.ts +149 -113
  241. package/src/flow/models/fields/DisplayNumberFieldModel.tsx +1 -1
  242. package/src/flow/models/fields/JsonFieldModel.tsx +31 -8
  243. package/src/flow/models/fields/NumberFieldModel.tsx +1 -1
  244. package/src/flow/models/fields/TextareaFieldModel.tsx +42 -19
  245. package/src/flow/models/fields/VariableFieldFormModel.tsx +3 -3
  246. package/src/flow/models/fields/__tests__/DisplayNumberFieldModel.test.ts +33 -0
  247. package/src/flow/models/fields/__tests__/JsonFieldModel.test.ts +82 -0
  248. package/src/flow/models/fields/__tests__/NumberFieldModel.test.tsx +47 -0
  249. package/src/flow/models/fields/__tests__/TextareaFieldModel.test.tsx +32 -1
  250. package/src/flow/models/fields/__tests__/VariableFieldFormModel.test.tsx +51 -0
  251. package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +26 -10
  252. package/src/flow/models/fields/mobile-components/MobileSelect.tsx +51 -14
  253. package/src/flow/models/fields/mobile-components/__tests__/MobileSelect.test.tsx +139 -13
  254. package/src/flow/models/topbar/TopbarActionModel.tsx +78 -3
  255. package/src/flow/routeTransientInputArgs.ts +27 -0
  256. package/src/flow/utils/__tests__/dateTimeFormat.test.ts +42 -0
  257. package/src/flow/utils/dataScopeFormValueClear.ts +4 -3
  258. package/src/flow-compat/fieldValidationConstants.ts +1 -1
  259. package/src/flow-compat/routeTypes.ts +1 -0
  260. package/src/index.ts +7 -0
  261. package/src/layout-manager/LayoutContentRoute.tsx +2 -1
  262. package/src/layout-manager/LayoutRoute.tsx +2 -1
  263. package/src/layout-manager/__tests__/LayoutRoute.test.tsx +87 -1
  264. package/src/locale/languageCodes.ts +3 -1
  265. package/src/nocobase-buildin-plugin/index.tsx +19 -1
  266. package/src/settings-center/AdminSettingsLayout.tsx +23 -2
  267. package/src/ui-operation/index.ts +33 -0
  268. package/src/ui-operation/ui-operation-codec.ts +54 -0
  269. package/src/utils/getRouteRuntimeVersion.ts +185 -0
  270. package/src/utils/index.tsx +1 -0
  271. package/src/utils/markdownSanitize.ts +88 -0
@@ -19,6 +19,7 @@ import {
19
19
  AdminLayoutMenuItemModel,
20
20
  AdminLayoutModel,
21
21
  ADMIN_LAYOUT_MODEL_UID,
22
+ buildMenuTitleWithIcon,
22
23
  getAdminLayoutMenuMovePositionOptions,
23
24
  normalizeAdminLayoutMenuLegacyVariables,
24
25
  openAdminLayoutMenuLink,
@@ -119,6 +120,233 @@ describe('AdminLayoutModel menu items', () => {
119
120
  ...options,
120
121
  });
121
122
 
123
+ type MenuTitleOptions = {
124
+ title: string;
125
+ collapsed: boolean;
126
+ name?: React.ReactNode;
127
+ routeTitle?: string;
128
+ renderType?: 'item' | 'group';
129
+ tooltip?: string;
130
+ badgeCount?: number;
131
+ badgeIndicatorColor?: string;
132
+ badgeTextColor?: string;
133
+ depth?: number;
134
+ };
135
+
136
+ const createMenuTitle = (options: MenuTitleOptions) => {
137
+ const {
138
+ title,
139
+ collapsed,
140
+ name = title,
141
+ routeTitle = title,
142
+ renderType = 'item',
143
+ tooltip,
144
+ badgeCount,
145
+ badgeIndicatorColor,
146
+ badgeTextColor,
147
+ depth = 1,
148
+ } = options;
149
+
150
+ return React.createElement(
151
+ FlowEngineProvider,
152
+ { engine },
153
+ React.createElement(
154
+ MemoryRouter,
155
+ { initialEntries: ['/admin/current-page'] },
156
+ React.createElement(AdminLayoutMenuItemRenderer, {
157
+ renderType,
158
+ item: {
159
+ name,
160
+ path: '/admin/menu-title',
161
+ _runtimePath: '/apps/demo/v2/admin/menu-title',
162
+ _navigationMode: 'spa',
163
+ _isLegacy: false,
164
+ _depth: depth,
165
+ _route: {
166
+ type: NocoBaseDesktopRouteType.flowPage,
167
+ title: routeTitle,
168
+ tooltip,
169
+ schemaUid: 'menu-title',
170
+ options:
171
+ badgeCount == null
172
+ ? {}
173
+ : {
174
+ badge: {
175
+ count: badgeCount,
176
+ styles: badgeIndicatorColor ? { indicator: { color: badgeIndicatorColor } } : undefined,
177
+ textColor: badgeTextColor,
178
+ },
179
+ },
180
+ },
181
+ },
182
+ dom: React.createElement(
183
+ 'span',
184
+ { className: 'ant-pro-base-menu-inline-item-text' },
185
+ collapsed ? title.slice(0, 1) : title,
186
+ ),
187
+ options: { isMobile: false, collapsed },
188
+ }),
189
+ ),
190
+ );
191
+ };
192
+
193
+ const renderMenuTitle = (options: MenuTitleOptions) => render(createMenuTitle(options));
194
+
195
+ it.each([false, true])(
196
+ 'should use a native title without an extra tooltip trigger when collapsed is %s',
197
+ async (collapsed) => {
198
+ vi.useFakeTimers();
199
+ const title = 'A complete menu title that may be truncated';
200
+
201
+ try {
202
+ const { container } = renderMenuTitle({ title, collapsed });
203
+ const link = screen.getByRole('link', { name: title });
204
+ const menuItem = link.closest<HTMLElement>('[role="none"]');
205
+
206
+ expect(link).toHaveAttribute('title', title);
207
+ expect(link.parentElement).toBe(menuItem);
208
+ expect(menuItem).toHaveStyle({ width: '100%', minWidth: 0 });
209
+ expect(link).toHaveStyle({ display: 'block', width: '100%', minWidth: 0, overflow: 'hidden' });
210
+ expect(container.querySelector('.ant-tooltip')).not.toBeInTheDocument();
211
+
212
+ await act(async () => {
213
+ fireEvent.mouseEnter(link);
214
+ await vi.advanceTimersByTimeAsync(500);
215
+ });
216
+
217
+ expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
218
+ } finally {
219
+ vi.clearAllTimers();
220
+ vi.useRealTimers();
221
+ }
222
+ },
223
+ );
224
+
225
+ it('should use the translated native title for an icon-wrapped nested menu name', () => {
226
+ const title = 'A translated nested menu title';
227
+ const { name } = buildMenuTitleWithIcon(
228
+ { title: 'menu.nested.title', icon: 'AppstoreOutlined' },
229
+ () => title,
230
+ true,
231
+ );
232
+
233
+ renderMenuTitle({ title, name, collapsed: true, depth: 2 });
234
+
235
+ expect(screen.getByRole('link', { name: title })).toHaveAttribute('title', title);
236
+ });
237
+
238
+ it('should use the translated native title for an icon-wrapped nested group name', () => {
239
+ const title = 'A translated nested group title';
240
+ const { name } = buildMenuTitleWithIcon(
241
+ { title: 'menu.nested.group', icon: 'AppstoreOutlined' },
242
+ () => title,
243
+ true,
244
+ );
245
+ const { container } = renderMenuTitle({
246
+ title,
247
+ name,
248
+ routeTitle: 'menu.nested.group',
249
+ renderType: 'group',
250
+ collapsed: true,
251
+ depth: 2,
252
+ });
253
+ const group = container.querySelector('[role="none"]');
254
+
255
+ expect(group).toHaveAttribute('title', title);
256
+ expect(group).toHaveAttribute('aria-label', title);
257
+ });
258
+
259
+ it('should preserve a numeric group name as the native title', () => {
260
+ const { container } = renderMenuTitle({
261
+ title: '0',
262
+ name: 0,
263
+ routeTitle: 'menu.numeric.group',
264
+ renderType: 'group',
265
+ collapsed: true,
266
+ });
267
+ const group = container.querySelector('[role="none"]');
268
+
269
+ expect(group).toHaveAttribute('title', '0');
270
+ expect(group).toHaveAttribute('aria-label', '0');
271
+ });
272
+
273
+ it.each(['item', 'group'] as const)(
274
+ 'should let an explicit route tooltip own hover behavior for a sider %s',
275
+ (renderType) => {
276
+ const title = 'A menu title with an explicit description';
277
+ const { container } = renderMenuTitle({
278
+ title,
279
+ renderType,
280
+ collapsed: false,
281
+ tooltip: 'An explicitly configured menu description',
282
+ });
283
+ const titleTarget =
284
+ renderType === 'item' ? screen.getByRole('link', { name: title }) : container.querySelector('[role="none"]');
285
+
286
+ expect(titleTarget).not.toHaveAttribute('title');
287
+ expect(screen.getByRole('img', { name: 'question-circle' })).toBeInTheDocument();
288
+ },
289
+ );
290
+
291
+ it('should keep the same menu link when the sider expands', async () => {
292
+ vi.useFakeTimers();
293
+ const title = 'A title that fits after expanding';
294
+
295
+ try {
296
+ const { rerender } = renderMenuTitle({ title, collapsed: true });
297
+ const link = screen.getByRole('link', { name: title });
298
+
299
+ await act(async () => {
300
+ rerender(createMenuTitle({ title, collapsed: false }));
301
+ await vi.runOnlyPendingTimersAsync();
302
+ });
303
+
304
+ expect(screen.getByRole('link', { name: title })).toBe(link);
305
+ expect(link).toHaveAttribute('title', title);
306
+ } finally {
307
+ vi.clearAllTimers();
308
+ vi.useRealTimers();
309
+ }
310
+ });
311
+
312
+ it.each([true, false])(
313
+ 'should render one badge indicator for a nested menu title when collapsed is %s',
314
+ (collapsed) => {
315
+ const title = 'A nested menu title with a badge';
316
+ const { container } = renderMenuTitle({ title, collapsed, badgeCount: 7 });
317
+
318
+ expect(container.querySelectorAll('.ant-badge-count')).toHaveLength(1);
319
+ },
320
+ );
321
+
322
+ it('should render one badge indicator for a top-level collapsed menu title', () => {
323
+ const title = 'A top-level collapsed menu title with a badge';
324
+ const { container } = renderMenuTitle({
325
+ title,
326
+ collapsed: true,
327
+ badgeCount: 7,
328
+ badgeTextColor: 'rgb(1, 2, 3)',
329
+ depth: 0,
330
+ });
331
+ const indicator = container.querySelector<HTMLElement>('.ant-badge-count');
332
+
333
+ expect(container.querySelectorAll('.ant-badge-count')).toHaveLength(1);
334
+ expect(indicator).toHaveStyle({ color: 'rgb(1, 2, 3)' });
335
+ });
336
+
337
+ it('should preserve the Ant Design indicator color when collapsed badge textColor is unset', () => {
338
+ const title = 'A top-level collapsed menu title with an indicator color';
339
+ const { container } = renderMenuTitle({
340
+ title,
341
+ collapsed: true,
342
+ badgeCount: 7,
343
+ badgeIndicatorColor: 'rgb(4, 5, 6)',
344
+ depth: 0,
345
+ });
346
+
347
+ expect(container.querySelector('.ant-badge-count')).toHaveStyle({ color: 'rgb(4, 5, 6)' });
348
+ });
349
+
122
350
  it('should normalize legacy variables only inside template expressions', () => {
123
351
  expect(normalizeAdminLayoutMenuLegacyVariables('https://a.com?id={{ $user.id }}')).toBe(
124
352
  'https://a.com?id={{ ctx.user.id }}',