@firecms/core 3.0.1 → 3.1.0-canary.02232f4

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 (334) hide show
  1. package/README.md +1 -1
  2. package/dist/components/AIIcon.d.ts +16 -0
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +7 -1
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +14 -0
  6. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +6 -0
  7. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -4
  8. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +6 -0
  9. package/dist/components/EntityCollectionTable/internal/popup_field/useDraggable.d.ts +2 -2
  10. package/dist/components/EntityCollectionView/Board.d.ts +2 -0
  11. package/dist/components/EntityCollectionView/BoardColumn.d.ts +42 -0
  12. package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +9 -0
  13. package/dist/components/EntityCollectionView/BoardSortableList.d.ts +14 -0
  14. package/dist/components/EntityCollectionView/CollectionDataErrorBanner.d.ts +4 -0
  15. package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +26 -0
  16. package/dist/components/EntityCollectionView/EntityCard.d.ts +19 -0
  17. package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +20 -0
  18. package/dist/components/EntityCollectionView/EntityCollectionCardView.d.ts +31 -0
  19. package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
  20. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +7 -3
  21. package/dist/components/EntityCollectionView/FiltersDialog.d.ts +14 -0
  22. package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +44 -0
  23. package/dist/components/EntityCollectionView/board_types.d.ts +105 -0
  24. package/dist/components/EntityCollectionView/useBoardDataController.d.ts +60 -0
  25. package/dist/components/ErrorBoundary.d.ts +4 -2
  26. package/dist/components/HomePage/DefaultHomePage.d.ts +0 -1
  27. package/dist/components/LanguageToggle.d.ts +1 -0
  28. package/dist/components/SelectableTable/SelectableTable.d.ts +5 -1
  29. package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -1
  30. package/dist/components/UnsavedChangesDialog.d.ts +1 -0
  31. package/dist/components/VirtualTable/VirtualTableCell.d.ts +6 -0
  32. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +4 -1
  33. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  34. package/dist/components/VirtualTable/VirtualTableProps.d.ts +17 -1
  35. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
  36. package/dist/components/VirtualTable/types.d.ts +3 -0
  37. package/dist/components/index.d.ts +4 -0
  38. package/dist/contexts/index.d.ts +10 -0
  39. package/dist/core/DrawerNavigationGroup.d.ts +45 -0
  40. package/dist/core/index.d.ts +1 -0
  41. package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
  42. package/dist/editor/components/editor-bubble-item.d.ts +8 -0
  43. package/dist/editor/components/editor-bubble.d.ts +8 -0
  44. package/dist/editor/components/image-bubble.d.ts +5 -0
  45. package/dist/editor/components/index.d.ts +16 -0
  46. package/dist/editor/components/table-bubble.d.ts +5 -0
  47. package/dist/editor/editor.d.ts +30 -0
  48. package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
  49. package/dist/editor/extensions/Image/index.d.ts +6 -0
  50. package/dist/editor/extensions/Image.d.ts +6 -0
  51. package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
  52. package/dist/editor/extensions/clipboard.d.ts +7 -0
  53. package/dist/editor/extensions/custom-keymap.d.ts +1 -0
  54. package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
  55. package/dist/editor/hooks/useProseMirror.d.ts +13 -0
  56. package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
  57. package/dist/editor/index.d.ts +2 -0
  58. package/dist/editor/markdown.d.ts +5 -0
  59. package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
  60. package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
  61. package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
  62. package/dist/editor/nodeViews/index.d.ts +6 -0
  63. package/dist/editor/plugins/index.d.ts +2 -0
  64. package/dist/editor/plugins/inputrules.d.ts +6 -0
  65. package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
  66. package/dist/editor/plugins/slashCommandPlugin.d.ts +12 -0
  67. package/dist/editor/schema.d.ts +2 -0
  68. package/dist/editor/selectors/ai-selector.d.ts +0 -0
  69. package/dist/editor/selectors/color-selector.d.ts +10 -0
  70. package/dist/editor/selectors/link-selector.d.ts +8 -0
  71. package/dist/editor/selectors/node-selector.d.ts +15 -0
  72. package/dist/editor/selectors/text-buttons.d.ts +1 -0
  73. package/dist/editor/types.d.ts +5 -0
  74. package/dist/editor/useProseMirror.d.ts +16 -0
  75. package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
  76. package/dist/editor/utils/remove_classes.d.ts +1 -0
  77. package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
  78. package/dist/form/components/ErrorFocus.d.ts +1 -1
  79. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  80. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  81. package/dist/form/validation.d.ts +3 -2
  82. package/dist/hooks/index.d.ts +1 -0
  83. package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
  84. package/dist/hooks/useBuildNavigationController.d.ts +0 -1
  85. package/dist/hooks/useCollapsedGroups.d.ts +6 -3
  86. package/dist/hooks/useTranslation.d.ts +17 -0
  87. package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
  88. package/dist/index.d.ts +5 -0
  89. package/dist/index.es.js +30146 -15178
  90. package/dist/index.es.js.map +1 -1
  91. package/dist/index.umd.js +30032 -15085
  92. package/dist/index.umd.js.map +1 -1
  93. package/dist/internal/useRestoreScroll.d.ts +1 -1
  94. package/dist/locales/de.d.ts +2 -0
  95. package/dist/locales/en.d.ts +10 -0
  96. package/dist/locales/es.d.ts +10 -0
  97. package/dist/locales/fr.d.ts +2 -0
  98. package/dist/locales/hi.d.ts +2 -0
  99. package/dist/locales/it.d.ts +2 -0
  100. package/dist/locales/pt.d.ts +7 -0
  101. package/dist/preview/PropertyPreviewProps.d.ts +5 -0
  102. package/dist/preview/components/DatePreview.d.ts +13 -3
  103. package/dist/preview/components/ImagePreview.d.ts +5 -1
  104. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  105. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  106. package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
  107. package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
  108. package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
  109. package/dist/types/analytics.d.ts +1 -1
  110. package/dist/types/collections.d.ts +88 -2
  111. package/dist/types/customization_controller.d.ts +2 -1
  112. package/dist/types/datasource.d.ts +0 -1
  113. package/dist/types/firecms.d.ts +2 -1
  114. package/dist/types/index.d.ts +1 -0
  115. package/dist/types/navigation.d.ts +2 -2
  116. package/dist/types/plugins.d.ts +69 -1
  117. package/dist/types/properties.d.ts +268 -12
  118. package/dist/types/storage.d.ts +1 -0
  119. package/dist/types/translations.d.ts +669 -0
  120. package/dist/util/__tests__/conditions.test.d.ts +1 -0
  121. package/dist/util/__tests__/objects.test.d.ts +1 -0
  122. package/dist/util/conditions.d.ts +26 -0
  123. package/dist/util/entities.d.ts +2 -3
  124. package/dist/util/index.d.ts +3 -1
  125. package/dist/util/lazy_eager.d.ts +7 -0
  126. package/dist/util/objects.d.ts +1 -0
  127. package/dist/util/property_utils.d.ts +2 -1
  128. package/dist/util/resolutions.d.ts +3 -3
  129. package/dist/util/useStorageUploadController.d.ts +10 -1
  130. package/package.json +51 -12
  131. package/src/app/Scaffold.tsx +20 -19
  132. package/src/components/AIIcon.tsx +41 -0
  133. package/src/components/ArrayContainer.tsx +7 -8
  134. package/src/components/ClearFilterSortButton.tsx +25 -19
  135. package/src/components/ConfirmationDialog.tsx +4 -4
  136. package/src/components/DeleteEntityDialog.tsx +12 -11
  137. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +82 -43
  138. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
  139. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
  140. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
  141. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
  142. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +24 -44
  143. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
  144. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
  145. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
  146. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
  147. package/src/components/EntityCollectionView/Board.tsx +324 -0
  148. package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
  149. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
  150. package/src/components/EntityCollectionView/BoardSortableList.tsx +174 -0
  151. package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
  152. package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
  153. package/src/components/EntityCollectionView/EntityCard.tsx +235 -0
  154. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +706 -0
  155. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +236 -0
  156. package/src/components/EntityCollectionView/EntityCollectionView.tsx +531 -209
  157. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +35 -22
  158. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +86 -15
  159. package/src/components/EntityCollectionView/FiltersDialog.tsx +252 -0
  160. package/src/components/EntityCollectionView/ViewModeToggle.tsx +202 -0
  161. package/src/components/EntityCollectionView/board_types.ts +113 -0
  162. package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
  163. package/src/components/EntityJsonPreview.tsx +2 -1
  164. package/src/components/EntityView.tsx +3 -2
  165. package/src/components/ErrorBoundary.tsx +27 -15
  166. package/src/components/ErrorTooltip.tsx +2 -1
  167. package/src/components/HomePage/DefaultHomePage.tsx +65 -22
  168. package/src/components/HomePage/HomePageDnD.tsx +59 -42
  169. package/src/components/HomePage/NavigationCard.tsx +20 -18
  170. package/src/components/HomePage/NavigationGroup.tsx +20 -17
  171. package/src/components/HomePage/RenameGroupDialog.tsx +15 -15
  172. package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
  173. package/src/components/LanguageToggle.tsx +66 -0
  174. package/src/components/NotFoundPage.tsx +5 -3
  175. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +12 -17
  176. package/src/components/ReferenceWidget.tsx +5 -6
  177. package/src/components/SearchIconsView.tsx +3 -1
  178. package/src/components/SelectableTable/SelectableTable.tsx +75 -67
  179. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
  180. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +50 -40
  181. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +53 -40
  182. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +60 -58
  183. package/src/components/UnsavedChangesDialog.tsx +6 -6
  184. package/src/components/UserDisplay.tsx +4 -4
  185. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +1 -0
  186. package/src/components/VirtualTable/VirtualTable.tsx +275 -119
  187. package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
  188. package/src/components/VirtualTable/VirtualTableHeader.tsx +76 -64
  189. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +163 -42
  190. package/src/components/VirtualTable/VirtualTableProps.tsx +21 -2
  191. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  192. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
  193. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +19 -6
  194. package/src/components/VirtualTable/types.tsx +3 -0
  195. package/src/components/common/default_entity_actions.tsx +4 -0
  196. package/src/components/common/useColumnsIds.tsx +95 -3
  197. package/src/components/common/useDataSourceTableController.tsx +12 -4
  198. package/src/components/index.tsx +5 -0
  199. package/src/contexts/BreacrumbsContext.tsx +15 -8
  200. package/src/contexts/index.ts +10 -0
  201. package/src/core/DefaultAppBar.tsx +49 -32
  202. package/src/core/DefaultDrawer.tsx +49 -57
  203. package/src/core/DrawerNavigationGroup.tsx +120 -0
  204. package/src/core/DrawerNavigationItem.tsx +4 -3
  205. package/src/core/EntityEditView.tsx +94 -50
  206. package/src/core/EntityEditViewFormActions.tsx +24 -17
  207. package/src/core/EntitySidePanel.tsx +34 -30
  208. package/src/core/FireCMS.tsx +33 -6
  209. package/src/core/SideDialogs.tsx +4 -2
  210. package/src/core/field_configs.tsx +18 -11
  211. package/src/core/index.tsx +1 -0
  212. package/src/editor/components/SlashCommandMenu.tsx +516 -0
  213. package/src/editor/components/editor-bubble-item.tsx +32 -0
  214. package/src/editor/components/editor-bubble.tsx +118 -0
  215. package/src/editor/components/image-bubble.tsx +156 -0
  216. package/src/editor/components/index.ts +14 -0
  217. package/src/editor/components/table-bubble.tsx +165 -0
  218. package/src/editor/editor.tsx +455 -0
  219. package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
  220. package/src/editor/extensions/Image/index.ts +133 -0
  221. package/src/editor/extensions/Image.ts +159 -0
  222. package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
  223. package/src/editor/extensions/clipboard.ts +72 -0
  224. package/src/editor/extensions/custom-keymap.ts +24 -0
  225. package/src/editor/extensions/drag-and-drop.tsx +480 -0
  226. package/src/editor/hooks/useProseMirror.ts +124 -0
  227. package/src/editor/hooks/useProseMirrorContext.ts +15 -0
  228. package/src/editor/index.ts +2 -0
  229. package/src/editor/markdown.ts +172 -0
  230. package/src/editor/nodeViews/ImageComponent.tsx +20 -0
  231. package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
  232. package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
  233. package/src/editor/nodeViews/index.ts +35 -0
  234. package/src/editor/plugins/index.ts +58 -0
  235. package/src/editor/plugins/inputrules.ts +82 -0
  236. package/src/editor/plugins/placeholderPlugin.ts +55 -0
  237. package/src/editor/plugins/slashCommandPlugin.ts +61 -0
  238. package/src/editor/schema.ts +240 -0
  239. package/src/editor/selectors/ai-selector.tsx +111 -0
  240. package/src/editor/selectors/color-selector.tsx +200 -0
  241. package/src/editor/selectors/link-selector.tsx +118 -0
  242. package/src/editor/selectors/node-selector.tsx +157 -0
  243. package/src/editor/selectors/text-buttons.tsx +86 -0
  244. package/src/editor/types.ts +6 -0
  245. package/src/editor/useProseMirror.ts +126 -0
  246. package/src/editor/utils/prosemirror-utils.ts +108 -0
  247. package/src/editor/utils/remove_classes.ts +17 -0
  248. package/src/editor/utils/useDebouncedCallback.ts +25 -0
  249. package/src/form/EntityForm.tsx +149 -67
  250. package/src/form/EntityFormActions.tsx +19 -12
  251. package/src/form/PropertyFieldBinding.tsx +68 -51
  252. package/src/form/components/ErrorFocus.tsx +3 -3
  253. package/src/form/components/LocalChangesMenu.tsx +13 -13
  254. package/src/form/components/StorageItemPreview.tsx +5 -3
  255. package/src/form/components/StorageUploadProgress.tsx +18 -3
  256. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +18 -5
  257. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +22 -10
  258. package/src/form/field_bindings/BlockFieldBinding.tsx +26 -9
  259. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -17
  260. package/src/form/field_bindings/KeyValueFieldBinding.tsx +46 -25
  261. package/src/form/field_bindings/MapFieldBinding.tsx +88 -70
  262. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +93 -52
  263. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +15 -1
  264. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +25 -11
  265. package/src/form/field_bindings/ReferenceFieldBinding.tsx +25 -11
  266. package/src/form/field_bindings/RepeatFieldBinding.tsx +21 -6
  267. package/src/form/field_bindings/SelectFieldBinding.tsx +7 -5
  268. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +110 -92
  269. package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -14
  270. package/src/form/field_bindings/TextFieldBinding.tsx +77 -38
  271. package/src/form/field_bindings/UserSelectFieldBinding.tsx +7 -5
  272. package/src/form/validation.ts +245 -160
  273. package/src/hooks/index.tsx +1 -0
  274. package/src/hooks/useBreadcrumbsController.tsx +18 -0
  275. package/src/hooks/useBuildNavigationController.tsx +91 -41
  276. package/src/hooks/useCollapsedGroups.ts +18 -9
  277. package/src/hooks/useTranslation.ts +31 -0
  278. package/src/hooks/useValidateAuthenticator.tsx +1 -1
  279. package/src/i18n/FireCMSi18nProvider.tsx +160 -0
  280. package/src/index.ts +5 -0
  281. package/src/internal/useBuildDataSource.ts +68 -34
  282. package/src/internal/useBuildSideDialogsController.tsx +11 -8
  283. package/src/internal/useBuildSideEntityController.tsx +24 -24
  284. package/src/internal/useRestoreScroll.tsx +26 -14
  285. package/src/locales/de.ts +718 -0
  286. package/src/locales/en.ts +730 -0
  287. package/src/locales/es.ts +730 -0
  288. package/src/locales/fr.ts +718 -0
  289. package/src/locales/hi.ts +718 -0
  290. package/src/locales/it.ts +718 -0
  291. package/src/locales/pt.ts +727 -0
  292. package/src/preview/PropertyPreview.tsx +43 -33
  293. package/src/preview/PropertyPreviewProps.tsx +6 -0
  294. package/src/preview/components/DatePreview.tsx +72 -4
  295. package/src/preview/components/EmptyValue.tsx +1 -1
  296. package/src/preview/components/ImagePreview.tsx +37 -21
  297. package/src/preview/components/ReferencePreview.tsx +2 -1
  298. package/src/preview/components/StorageThumbnail.tsx +16 -12
  299. package/src/preview/components/UrlComponentPreview.tsx +32 -27
  300. package/src/preview/components/UserPreview.tsx +3 -1
  301. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
  302. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
  303. package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
  304. package/src/preview/property_previews/MapPropertyPreview.tsx +49 -27
  305. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
  306. package/src/routes/CustomCMSRoute.tsx +1 -0
  307. package/src/routes/FireCMSRoute.tsx +87 -65
  308. package/src/types/analytics.ts +10 -0
  309. package/src/types/collections.ts +97 -3
  310. package/src/types/customization_controller.tsx +2 -1
  311. package/src/types/datasource.ts +54 -56
  312. package/src/types/firecms.tsx +2 -1
  313. package/src/types/index.ts +1 -0
  314. package/src/types/navigation.ts +2 -2
  315. package/src/types/plugins.tsx +77 -1
  316. package/src/types/properties.ts +359 -37
  317. package/src/types/storage.ts +2 -1
  318. package/src/types/translations.ts +752 -0
  319. package/src/util/__tests__/conditions.test.ts +506 -0
  320. package/src/util/__tests__/objects.test.ts +196 -0
  321. package/src/util/callbacks.ts +6 -3
  322. package/src/util/collections.ts +51 -6
  323. package/src/util/conditions.ts +339 -0
  324. package/src/util/entities.ts +29 -30
  325. package/src/util/entity_cache.ts +2 -1
  326. package/src/util/index.ts +3 -1
  327. package/src/util/join_collections.ts +10 -8
  328. package/src/util/lazy_eager.tsx +33 -0
  329. package/src/util/objects.ts +46 -13
  330. package/src/util/{references.ts → previews.ts} +16 -2
  331. package/src/util/property_utils.tsx +37 -11
  332. package/src/util/resolutions.ts +62 -58
  333. package/src/util/useStorageUploadController.tsx +23 -29
  334. /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
@@ -1,5 +1,6 @@
1
1
  import { useMemo } from "react";
2
2
  import { EntityCollection, ResolvedEntityCollection, ResolvedProperty } from "../../types";
3
+ import { getPropertyInPath } from "../../util";
3
4
  import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
4
5
  import { PropertyColumnConfig } from "../EntityCollectionTable/EntityCollectionTableProps";
5
6
 
@@ -16,15 +17,45 @@ export function useColumnIds<M extends Record<string, any>>(collection: Resolved
16
17
 
17
18
  function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEntityCollection<M>, keys: string[]): PropertyColumnConfig[] {
18
19
 
19
- return keys.flatMap((key) => {
20
+ // First, figure out which spread map roots have individual child keys in the order
21
+ // If so, we should NOT auto-expand them - just use the explicit child keys
22
+ const rootsWithExplicitChildren = new Set<string>();
23
+ for (const key of keys) {
24
+ if (key.includes(".")) {
25
+ const rootKey = key.split(".")[0];
26
+ const rootProperty = collection.properties[rootKey];
27
+ if (rootProperty && rootProperty.dataType === "map" && rootProperty.spreadChildren && rootProperty.properties) {
28
+ rootsWithExplicitChildren.add(rootKey);
29
+ }
30
+ }
31
+ }
32
+
33
+ // Track processed keys to avoid duplicates
34
+ const processedPropertyKeys = new Set<string>();
35
+
36
+ const result = keys.flatMap((key) => {
37
+ // Skip if already processed (handles duplicates in propertiesOrder)
38
+ if (processedPropertyKeys.has(key)) return [null];
39
+
40
+ // Check if it's a top-level property
20
41
  const property = collection.properties[key];
21
42
  if (property) {
43
+ processedPropertyKeys.add(key);
22
44
  if (property.hideFromCollection)
23
45
  return [null];
24
46
  if (property.disabled && typeof property.disabled === "object" && property.disabled.hidden)
25
47
  return [null];
48
+
26
49
  if (property.dataType === "map" && property.spreadChildren && property.properties) {
27
- return getColumnKeysForProperty(property, key);
50
+ // Check if this spread map has explicit child keys in propertiesOrder
51
+ if (rootsWithExplicitChildren.has(key)) {
52
+ // DON'T auto-expand - the children are explicitly listed elsewhere
53
+ return [null];
54
+ }
55
+ // Auto-expand all children
56
+ const childConfigs = getColumnKeysForProperty(property, key);
57
+ childConfigs.forEach(c => processedPropertyKeys.add(c.key));
58
+ return childConfigs;
28
59
  }
29
60
  return [{
30
61
  key,
@@ -32,6 +63,33 @@ function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEn
32
63
  }];
33
64
  }
34
65
 
66
+ // Check if it's a nested key like "data.mode" (for spread map properties)
67
+ if (key.includes(".")) {
68
+ const rootKey = key.split(".")[0];
69
+ const rootProperty = collection.properties[rootKey];
70
+
71
+ if (rootProperty && rootProperty.dataType === "map" && rootProperty.properties) {
72
+ const nestedProperty = getPropertyInPath(collection.properties, key) as ResolvedProperty | undefined;
73
+ if (nestedProperty) {
74
+ processedPropertyKeys.add(key);
75
+ // Mark root as seen
76
+ processedPropertyKeys.add(rootKey);
77
+
78
+ if (nestedProperty.hideFromCollection)
79
+ return [null];
80
+ if (nestedProperty.disabled && typeof nestedProperty.disabled === "object" && nestedProperty.disabled.hidden)
81
+ return [null];
82
+
83
+ return [{
84
+ key,
85
+ disabled: Boolean(rootProperty.disabled) || Boolean(rootProperty.readOnly) ||
86
+ Boolean(nestedProperty.disabled) || Boolean(nestedProperty.readOnly)
87
+ }];
88
+ }
89
+ }
90
+ }
91
+
92
+ // Check additional fields
35
93
  const additionalField = collection.additionalFields?.find(field => field.key === key);
36
94
  if (additionalField) {
37
95
  return [{
@@ -40,6 +98,7 @@ function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEn
40
98
  }];
41
99
  }
42
100
 
101
+ // Check subcollections
43
102
  if (collection.subcollections) {
44
103
  const subCollection = collection.subcollections.find(subCol => getSubcollectionColumnId(subCol) === key);
45
104
  if (subCollection) {
@@ -50,6 +109,7 @@ function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEn
50
109
  }
51
110
  }
52
111
 
112
+ // Check collection group parent
53
113
  if (collection.collectionGroup && key === COLLECTION_GROUP_PARENT_ID) {
54
114
  return [{
55
115
  key,
@@ -59,6 +119,37 @@ function hideAndExpandKeys<M extends Record<string, any>>(collection: ResolvedEn
59
119
 
60
120
  return [null];
61
121
  }).filter(Boolean) as PropertyColumnConfig[];
122
+
123
+ // Add any missing properties that weren't in propertiesOrder
124
+ // This ensures properties NEVER disappear
125
+ for (const propKey of Object.keys(collection.properties)) {
126
+ // Skip if already processed
127
+ if (processedPropertyKeys.has(propKey)) continue;
128
+
129
+ const property = collection.properties[propKey];
130
+ if (!property) continue;
131
+ if (property.hideFromCollection) continue;
132
+ if (property.disabled && typeof property.disabled === "object" && property.disabled.hidden) continue;
133
+
134
+ if (property.dataType === "map" && property.spreadChildren && property.properties) {
135
+ // For spread maps, add all children that weren't already added
136
+ const allChildConfigs = getColumnKeysForProperty(property, propKey);
137
+ for (const childConfig of allChildConfigs) {
138
+ if (!processedPropertyKeys.has(childConfig.key)) {
139
+ result.push(childConfig);
140
+ processedPropertyKeys.add(childConfig.key);
141
+ }
142
+ }
143
+ } else {
144
+ result.push({
145
+ key: propKey,
146
+ disabled: Boolean(property.disabled) || Boolean(property.readOnly)
147
+ });
148
+ processedPropertyKeys.add(propKey);
149
+ }
150
+ }
151
+
152
+ return result;
62
153
  }
63
154
 
64
155
  function getDefaultColumnKeys<M extends Record<string, any> = any>(collection: ResolvedEntityCollection<M>, includeSubCollections: boolean) {
@@ -69,7 +160,8 @@ function getDefaultColumnKeys<M extends Record<string, any> = any>(collection: R
69
160
 
70
161
  const columnIds: string[] = [
71
162
  ...propertyKeys,
72
- ...additionalFields.map((field) => field.key)
163
+ // Filter out additional fields whose key already exists in propertyKeys to avoid duplicate column keys
164
+ ...additionalFields.filter((field) => !propertyKeys.includes(field.key)).map((field) => field.key)
73
165
  ];
74
166
 
75
167
  if (includeSubCollections) {
@@ -1,4 +1,5 @@
1
1
  import React, { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { useLocation } from "react-router-dom";
2
3
 
3
4
  import { useDataSource, useFireCMSContext, useNavigationController } from "../../hooks";
4
5
  import { useDataOrder } from "../../hooks/data/useDataOrder";
@@ -94,7 +95,7 @@ export function useDataSourceTableController<M extends Record<string, any> = any
94
95
  const [searchString, setSearchString] = React.useState<string | undefined>();
95
96
 
96
97
  const checkFilterCombination = useCallback((filterValues: FilterValues<any>,
97
- sortBy?: [string, "asc" | "desc"]) => {
98
+ sortBy?: [string, "asc" | "desc"]) => {
98
99
  if (!dataSource.isFilterCombinationValid)
99
100
  return true;
100
101
  return dataSource.isFilterCombinationValid({
@@ -106,8 +107,8 @@ export function useDataSourceTableController<M extends Record<string, any> = any
106
107
  }, []);
107
108
 
108
109
  const onScroll = ({
109
- scrollOffset
110
- }: {
110
+ scrollOffset
111
+ }: {
111
112
  scrollOffset: number
112
113
  }) => {
113
114
  if (scrollRestoration) {
@@ -128,10 +129,12 @@ export function useDataSourceTableController<M extends Record<string, any> = any
128
129
  return initialSort;
129
130
  }, [initialSort, forceFilter]);
130
131
 
132
+ const location = useLocation();
133
+
131
134
  const {
132
135
  filterValues: initialFilterUrl,
133
136
  sortBy: initialSortUrl,
134
- } = parseFilterAndSort(window.location.search);
137
+ } = parseFilterAndSort(location.search);
135
138
 
136
139
  const [filterValues, setFilterValues] = React.useState<FilterValues<Extract<keyof M, string>> | undefined>(forceFilter ?? (updateUrl ? initialFilterUrl : undefined) ?? initialFilter ?? undefined);
137
140
  const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>((updateUrl ? initialSortUrl : undefined) ?? initialSortInternal);
@@ -328,6 +331,11 @@ function encodeFilterAndSort(filterValues?: FilterValues<string>, sortBy?: [stri
328
331
  } else if (val instanceof EntityReference) {
329
332
  encodedValue = encodeRef(val);
330
333
  }
334
+ } else if (typeof val === "string") {
335
+ // JSON.stringify wraps the string in quotes (e.g. "4" → '"4"')
336
+ // so that decodeString's JSON.parse restores the string type,
337
+ // not a number. Without this, "4" round-trips as the number 4.
338
+ encodedValue = JSON.stringify(val);
331
339
  }
332
340
  } catch (e) {
333
341
  encodedValue = val;
@@ -16,6 +16,8 @@ export * from "./SelectableTable/SelectableTable";
16
16
  export * from "./SelectableTable/SelectableTableContext";
17
17
  export * from "./EntityCollectionView/EntityCollectionView";
18
18
  export * from "./EntityCollectionView/EntityCollectionViewActions";
19
+ export * from "./EntityCollectionView/EntityCollectionCardView";
20
+ export * from "./EntityCollectionView/EntityCard";
19
21
  export * from "./EntityCollectionView/useSelectionController";
20
22
 
21
23
  export * from "./PropertyConfigBadge";
@@ -38,3 +40,6 @@ export * from "./SearchIconsView";
38
40
  export * from "./FieldCaption";
39
41
 
40
42
  export * from "./EntityPreview";
43
+
44
+ export * from "./AIIcon";
45
+ export * from "./LanguageToggle";
@@ -1,11 +1,11 @@
1
- import React, { useState } from "react";
1
+ import React, { useCallback, useState } from "react";
2
2
  import { BreadcrumbEntry, BreadcrumbsController } from "../hooks/useBreadcrumbsController";
3
3
 
4
- const DEFAULT_BREADCRUMBS_CONTROLLER = {
4
+ const DEFAULT_BREADCRUMBS_CONTROLLER: BreadcrumbsController = {
5
5
  breadcrumbs: [],
6
- set: (props: {
7
- breadcrumbs: BreadcrumbEntry[];
8
- }) => {
6
+ set: () => {
7
+ },
8
+ updateCount: () => {
9
9
  }
10
10
  };
11
11
 
@@ -19,17 +19,24 @@ export const BreadcrumbsProvider: React.FC<BreadcrumbsProviderProps> = ({ childr
19
19
 
20
20
  const [breadcrumbs, setBreadcrumbs] = useState<BreadcrumbEntry[]>([]);
21
21
 
22
- const set = (props: {
22
+ const set = useCallback((props: {
23
23
  breadcrumbs: BreadcrumbEntry[];
24
24
  }) => {
25
25
  setBreadcrumbs(props.breadcrumbs);
26
- };
26
+ }, []);
27
+
28
+ const updateCount = useCallback((id: string, count: number | null | undefined) => {
29
+ setBreadcrumbs(prev => prev.map(entry =>
30
+ entry.id === id ? { ...entry, count } : entry
31
+ ));
32
+ }, []);
27
33
 
28
34
  return (
29
35
  <BreadcrumbContext.Provider
30
36
  value={{
31
37
  breadcrumbs,
32
- set
38
+ set,
39
+ updateCount
33
40
  }}
34
41
  >
35
42
  {children}
@@ -1,3 +1,13 @@
1
1
  export * from "./SnackbarProvider";
2
2
  export * from "./ModeController";
3
3
  export * from "./AuthControllerContext";
4
+ export * from "./DataSourceContext";
5
+ export * from "./NavigationContext";
6
+ export * from "./CustomizationControllerContext";
7
+ export * from "./SideEntityControllerContext";
8
+ export * from "./SideDialogsControllerContext";
9
+ export * from "./AnalyticsContext";
10
+ export * from "./StorageSourceContext";
11
+ export * from "./UserConfigurationPersistenceContext";
12
+ export * from "./DialogsProvider";
13
+ export * from "./InternalUserManagementContext";
@@ -1,10 +1,11 @@
1
1
  import React from "react";
2
2
 
3
3
  import { Link, useNavigate } from "react-router-dom";
4
- import { ErrorBoundary, FireCMSLogo } from "../components";
4
+ import { ErrorBoundary, FireCMSLogo, LanguageToggle } from "../components";
5
5
  import {
6
6
  Avatar,
7
7
  BrightnessMediumIcon,
8
+ CheckIcon,
8
9
  cls,
9
10
  DarkModeIcon,
10
11
  IconButton,
@@ -15,7 +16,7 @@ import {
15
16
  Skeleton,
16
17
  Typography
17
18
  } from "@firecms/ui";
18
- import { useAuthController, useLargeLayout, useModeController, useNavigationController } from "../hooks";
19
+ import { useAuthController, useLargeLayout, useModeController, useNavigationController, useTranslation } from "../hooks";
19
20
  import { User } from "../types";
20
21
  import { useApp } from "../app/useApp";
21
22
  import { useBreadcrumbsController } from "../hooks/useBreadcrumbsController";
@@ -57,16 +58,16 @@ export type DefaultAppBarProps<ADDITIONAL_PROPS = object> = {
57
58
 
58
59
  */
59
60
  export const DefaultAppBar = function DefaultAppBar({
60
- title,
61
- endAdornment,
62
- startAdornment,
63
- dropDownActions,
64
- includeModeToggle = true,
65
- className,
66
- style,
67
- user: userProp,
68
- logo: logoProp,
69
- }: DefaultAppBarProps) {
61
+ title,
62
+ endAdornment,
63
+ startAdornment,
64
+ dropDownActions,
65
+ includeModeToggle = true,
66
+ className,
67
+ style,
68
+ user: userProp,
69
+ logo: logoProp,
70
+ }: DefaultAppBarProps) {
70
71
 
71
72
  const {
72
73
  hasDrawer,
@@ -85,6 +86,8 @@ export const DefaultAppBar = function DefaultAppBar({
85
86
  mode,
86
87
  setMode
87
88
  } = useModeController();
89
+
90
+ const { i18n, t } = useTranslation();
88
91
 
89
92
  const navigate = useNavigate();
90
93
 
@@ -92,7 +95,7 @@ export const DefaultAppBar = function DefaultAppBar({
92
95
 
93
96
  const user = userProp ?? authController.user;
94
97
 
95
- let avatarComponent: JSX.Element | null;
98
+ let avatarComponent: React.ReactElement | null;
96
99
 
97
100
  if (user) {
98
101
  const initial = user?.displayName
@@ -103,7 +106,7 @@ export const DefaultAppBar = function DefaultAppBar({
103
106
  </Avatar>;
104
107
  } else if (user === undefined || authController.initialLoading) {
105
108
  avatarComponent = <div className={"p-1 flex justify-center"}>
106
- <Skeleton className={"w-10 h-10 rounded-full"}/>
109
+ <Skeleton className={"w-10 h-10 rounded-full"} />
107
110
  </div>;
108
111
  } else {
109
112
  avatarComponent = null;
@@ -131,13 +134,13 @@ export const DefaultAppBar = function DefaultAppBar({
131
134
  <div className={"flex flex-row gap-4"}>
132
135
  {!hasDrawer && (logo
133
136
  ? <img src={logo}
134
- alt="Logo"
135
- className={cls("w-[32px] h-[32px] object-contain")}/>
136
- : <FireCMSLogo width={"32px"} height={"32px"}/>)}
137
+ alt="Logo"
138
+ className={cls("w-[32px] h-[32px] object-contain")} />
139
+ : <FireCMSLogo width={"32px"} height={"32px"} />)}
137
140
 
138
141
  {typeof title === "string"
139
142
  ? <Typography variant="subtitle1"
140
- noWrap>
143
+ noWrap>
141
144
  {title}
142
145
  </Typography>
143
146
  : title}
@@ -146,7 +149,7 @@ export const DefaultAppBar = function DefaultAppBar({
146
149
  </div>}
147
150
 
148
151
  {(breadcrumbs.breadcrumbs ?? []).length > 0 && <div className="mr-8 hidden lg:block">
149
- <div className={"flex flex-row gap-2"}>
152
+ <div className={"flex flex-row gap-2 items-center"}>
150
153
  {breadcrumbs.breadcrumbs.map((breadcrumb, index) => {
151
154
  return <React.Fragment key={breadcrumb.url + "_" + index}>
152
155
  <Typography variant={"caption"} color={"secondary"}>
@@ -157,18 +160,31 @@ export const DefaultAppBar = function DefaultAppBar({
157
160
  className="visited:text-inherit visited:dark:text-inherit block"
158
161
  to={breadcrumb.url}
159
162
  >
160
- <Typography variant={"caption"} color={"secondary"}>
161
- {breadcrumb.title}
162
- </Typography>
163
+ <div className="flex flex-row items-center gap-2 whitespace-nowrap">
164
+ <Typography variant={"body2"}>
165
+ {breadcrumb.title}
166
+ </Typography>
167
+ {/* Show count badge for collection breadcrumbs: undefined = not applicable, null = loading, number = count */}
168
+ {breadcrumb.count !== undefined && (
169
+ breadcrumb.count !== null ? (
170
+ <span className="text-xs text-surface-accent-500 dark:text-surface-accent-400 bg-surface-100 dark:bg-surface-700 px-1 py-0 rounded">
171
+ {breadcrumb.count}
172
+ </span>
173
+ ) : (
174
+ <Skeleton className="w-8 h-4 rounded-md" />
175
+ )
176
+ )}
177
+ </div>
163
178
  </Link>
164
179
  </React.Fragment>;
165
180
  })}
166
181
  </div>
167
182
  </div>}
168
183
 
184
+
169
185
  {startAdornment}
170
186
 
171
- <div className={"flex-grow"}/>
187
+ <div className={"flex-grow"} />
172
188
 
173
189
  {endAdornment &&
174
190
  <ErrorBoundary>
@@ -179,18 +195,19 @@ export const DefaultAppBar = function DefaultAppBar({
179
195
  <Menu
180
196
  trigger={<IconButton
181
197
  color="inherit"
182
- aria-label="Open drawer"
183
- size="large">
198
+ aria-label="Open drawer">
184
199
  {mode === "dark"
185
- ? <DarkModeIcon/>
186
- : <LightModeIcon/>}
200
+ ? <DarkModeIcon size="small" />
201
+ : <LightModeIcon size="small" />}
187
202
  </IconButton>}>
188
- <MenuItem onClick={() => setMode("dark")}><DarkModeIcon size={"smallest"}/> Dark</MenuItem>
189
- <MenuItem onClick={() => setMode("light")}><LightModeIcon size={"smallest"}/> Light </MenuItem>
203
+ <MenuItem onClick={() => setMode("dark")}><DarkModeIcon size={"smallest"} /> {t("dark_mode")}</MenuItem>
204
+ <MenuItem onClick={() => setMode("light")}><LightModeIcon size={"smallest"} /> {t("light_mode")}</MenuItem>
190
205
  <MenuItem onClick={() => setMode("system")}> <BrightnessMediumIcon
191
- size={"smallest"}/>System</MenuItem>
206
+ size={"smallest"} />{t("system_mode")}</MenuItem>
192
207
  </Menu>}
193
208
 
209
+ <LanguageToggle />
210
+
194
211
  <Menu trigger={avatarComponent}>
195
212
  {user && <div className={"px-4 py-2 mb-2"}>
196
213
  {user.displayName && <Typography variant={"body1"} color={"secondary"}>
@@ -208,8 +225,8 @@ export const DefaultAppBar = function DefaultAppBar({
208
225
  // replace current route with home
209
226
  navigate("/");
210
227
  }}>
211
- <LogoutIcon/>
212
- Log Out
228
+ <LogoutIcon />
229
+ {t("log_out")}
213
230
  </MenuItem>}
214
231
 
215
232
  </Menu>
@@ -1,13 +1,18 @@
1
- import React, { useCallback } from "react";
1
+ import React from "react";
2
2
 
3
- import { useLargeLayout, useNavigationController } from "../hooks";
3
+ import {
4
+ useCollapsedGroups,
5
+ useLargeLayout,
6
+ useNavigationController,
7
+ useTranslation
8
+ } from "../hooks";
4
9
 
5
10
  import { Link, useNavigate } from "react-router-dom";
6
11
  import { CMSAnalyticsEvent, NavigationEntry, NavigationResult } from "../types";
7
12
  import { IconForView } from "../util";
8
- import { cls, IconButton, Menu, MenuItem, MoreVertIcon, Tooltip, Typography } from "@firecms/ui";
13
+ import { cls, IconButton, Menu, MenuItem, MoreVertIcon, Tooltip } from "@firecms/ui";
9
14
  import { useAnalyticsController } from "../hooks/useAnalyticsController";
10
- import { DrawerNavigationItem } from "./DrawerNavigationItem";
15
+ import { DrawerNavigationGroup } from "./DrawerNavigationGroup";
11
16
  import { FireCMSLogo } from "../components";
12
17
  import { useApp } from "../app/useApp";
13
18
 
@@ -16,9 +21,9 @@ import { useApp } from "../app/useApp";
16
21
  * @group Core
17
22
  */
18
23
  export function DefaultDrawer({
19
- className,
20
- style,
21
- }: {
24
+ className,
25
+ style,
26
+ }: {
22
27
  className?: string
23
28
  style?: React.CSSProperties,
24
29
  }) {
@@ -34,6 +39,7 @@ export function DefaultDrawer({
34
39
 
35
40
  const analyticsController = useAnalyticsController();
36
41
  const navigation = useNavigationController();
42
+ const { t } = useTranslation();
37
43
 
38
44
  const tooltipsOpen = drawerHovered && !drawerOpen && !adminMenuOpen;
39
45
  const largeLayout = useLargeLayout();
@@ -50,20 +56,10 @@ export function DefaultDrawer({
50
56
  const adminViews = navigationEntries.filter(e => e.type === "admin") ?? [];
51
57
  const groupsWithoutAdmin = groups.filter(g => g !== "Admin");
52
58
 
53
- const buildGroupHeader = useCallback((group?: string) => {
54
- if (!drawerOpen) return <div className="w-full"/>;
55
- return <div
56
- className="pl-6 pr-8 py-4 flex flex-row items-center">
57
- <Typography variant={"caption"}
58
- color={"secondary"}
59
- className="font-medium flex-grow line-clamp-1">
60
- {group ? group.toUpperCase() : "Views".toUpperCase()}
61
- </Typography>
59
+ // Collapsible groups state - using "drawer" namespace for independent state from home page
60
+ const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupsWithoutAdmin, "drawer");
62
61
 
63
- </div>;
64
- }, [drawerOpen]);
65
-
66
- const onClick = (view: NavigationEntry) => {
62
+ const onItemClick = (view: NavigationEntry) => {
67
63
  const eventName: CMSAnalyticsEvent = view.type === "collection"
68
64
  ? "drawer_navigate_to_collection"
69
65
  : (view.type === "view" ? "drawer_navigate_to_view" : "unmapped_event");
@@ -76,33 +72,29 @@ export function DefaultDrawer({
76
72
  <>
77
73
  <div className={cls("flex flex-col h-full relative flex-grow w-full", className)} style={style}>
78
74
 
79
- <DrawerLogo logo={logo}/>
75
+ <DrawerLogo logo={logo} />
80
76
 
81
77
  <div className={"mt-4 flex-grow overflow-scroll no-scrollbar"}
82
- style={{
83
- maskImage: "linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)",
84
- }}>
85
-
86
- {groupsWithoutAdmin.map((group) => (
87
- <div
88
- className={"bg-surface-50 dark:bg-surface-800 dark:bg-opacity-30 my-4 rounded-lg ml-3 mr-1"}
89
- key={`drawer_group_${group}`}>
90
- {buildGroupHeader(group)}
91
- {Object.values(navigationEntries)
92
- .filter(e => e.group === group)
93
- .map((view) =>
94
- <DrawerNavigationItem
95
- key={view.id}
96
- icon={<IconForView collectionOrView={view.collection ?? view.view}
97
- size={"small"}/>}
98
- tooltipsOpen={tooltipsOpen}
99
- adminMenuOpen={adminMenuOpen}
100
- drawerOpen={drawerOpen}
101
- onClick={() => onClick(view)}
102
- url={view.url}
103
- name={view.name}/>)}
104
- </div>
105
- ))}
78
+ style={{
79
+ maskImage: "linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)",
80
+ }}>
81
+
82
+ {groupsWithoutAdmin.map((group) => {
83
+ const entriesInGroup = Object.values(navigationEntries).filter(e => e.group === group);
84
+ return (
85
+ <DrawerNavigationGroup
86
+ key={`drawer_group_${group}`}
87
+ group={group}
88
+ entries={entriesInGroup}
89
+ collapsed={isGroupCollapsed(group)}
90
+ onToggleCollapsed={() => toggleGroupCollapsed(group)}
91
+ drawerOpen={drawerOpen}
92
+ tooltipsOpen={tooltipsOpen}
93
+ adminMenuOpen={adminMenuOpen}
94
+ onItemClick={onItemClick}
95
+ />
96
+ );
97
+ })}
106
98
 
107
99
  </div>
108
100
 
@@ -115,9 +107,9 @@ export function DefaultDrawer({
115
107
  shape={"square"}
116
108
  className={"m-4 text-surface-900 dark:text-white w-fit"}>
117
109
  <Tooltip title={"Admin"}
118
- open={tooltipsOpen}
119
- side={"right"} sideOffset={28}>
120
- <MoreVertIcon/>
110
+ open={tooltipsOpen}
111
+ side={"right"} sideOffset={28}>
112
+ <MoreVertIcon />
121
113
  </Tooltip>
122
114
  {drawerOpen && <div
123
115
  className={cls(
@@ -132,11 +124,11 @@ export function DefaultDrawer({
132
124
  <MenuItem
133
125
  onClick={(event) => {
134
126
  event.preventDefault();
135
- navigate(entry.url); // Consistent use of entry.url for navigation
127
+ navigate(entry.url);
136
128
  }}
137
129
  key={entry.id}>
138
- {<IconForView collectionOrView={entry.view}/>}
139
- {entry.name}
130
+ {<IconForView collectionOrView={entry.view} />}
131
+ {t(entry.name as any)}
140
132
  </MenuItem>)}
141
133
 
142
134
  </Menu>}
@@ -167,17 +159,17 @@ export function DrawerLogo({ logo }: {
167
159
  className={cls("cursor-pointer rounded ml-3 mr-1")}>
168
160
 
169
161
  <Tooltip title={"Home"}
170
- sideOffset={20}
171
- side="right">
162
+ sideOffset={20}
163
+ side="right">
172
164
  <Link
173
165
  className={"block"}
174
166
  to={navigation.basePath}>
175
167
  {logo
176
168
  ? <img src={logo}
177
- alt="Logo"
178
- className={cls("max-w-full max-h-full transition-all object-contain",
179
- drawerOpen ? "w-[96px] h-[96px]" : "w-[32px] h-[32px]")}/>
180
- : <FireCMSLogo/>}
169
+ alt="Logo"
170
+ className={cls("max-w-full max-h-full transition-all object-contain",
171
+ drawerOpen ? "w-[96px] h-[96px]" : "w-[32px] h-[32px]")} />
172
+ : <FireCMSLogo />}
181
173
 
182
174
  </Link>
183
175
  </Tooltip>