@firecms/core 3.0.0-canary.18 → 3.0.0-canary.180

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 (366) hide show
  1. package/README.md +3 -3
  2. package/dist/app/AppBar.d.ts +12 -0
  3. package/dist/app/Drawer.d.ts +16 -0
  4. package/dist/app/Scaffold.d.ts +30 -0
  5. package/dist/app/index.d.ts +4 -0
  6. package/dist/app/useApp.d.ts +16 -0
  7. package/dist/components/ArrayContainer.d.ts +23 -6
  8. package/dist/components/CircularProgressCenter.d.ts +1 -1
  9. package/dist/components/ClearFilterSortButton.d.ts +5 -0
  10. package/dist/components/{DeleteConfirmationDialog.d.ts → ConfirmationDialog.d.ts} +1 -1
  11. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +13 -13
  12. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  13. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +22 -6
  14. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +1 -0
  15. package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
  16. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +3 -1
  17. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  18. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
  19. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  20. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +7 -4
  21. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +16 -2
  22. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  23. package/dist/components/EntityCollectionView/utils.d.ts +3 -0
  24. package/dist/components/EntityPreview.d.ts +5 -4
  25. package/dist/components/ErrorView.d.ts +1 -1
  26. package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
  27. package/dist/components/HomePage/NavigationCardBinding.d.ts +1 -1
  28. package/dist/components/PropertyConfigBadge.d.ts +2 -1
  29. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  30. package/dist/components/ReferenceWidget.d.ts +3 -1
  31. package/dist/components/SelectableTable/SelectableTable.d.ts +13 -3
  32. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  33. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  34. package/dist/components/VirtualTable/VirtualTableProps.d.ts +28 -12
  35. package/dist/components/VirtualTable/types.d.ts +3 -3
  36. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -3
  37. package/dist/components/common/index.d.ts +2 -1
  38. package/dist/components/common/table_height.d.ts +5 -0
  39. package/dist/components/common/types.d.ts +4 -6
  40. package/dist/components/common/useColumnsIds.d.ts +3 -1
  41. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +13 -2
  42. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  43. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  44. package/dist/components/index.d.ts +4 -2
  45. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  46. package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +6 -9
  47. package/dist/core/DefaultDrawer.d.ts +19 -0
  48. package/dist/core/DrawerNavigationItem.d.ts +10 -0
  49. package/dist/core/EntityEditView.d.ts +41 -9
  50. package/dist/core/FireCMS.d.ts +2 -2
  51. package/dist/core/FireCMSRouter.d.ts +4 -0
  52. package/dist/core/NavigationRoutes.d.ts +2 -3
  53. package/dist/core/index.d.ts +4 -4
  54. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  55. package/dist/form/components/ErrorFocus.d.ts +1 -1
  56. package/dist/form/components/FieldHelperText.d.ts +3 -3
  57. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  58. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  59. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  60. package/dist/form/components/index.d.ts +1 -1
  61. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  62. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  63. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  64. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  65. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  66. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  67. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  68. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  69. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  70. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  71. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  72. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -5
  73. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  74. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  75. package/dist/form/index.d.ts +3 -5
  76. package/dist/form/useClearRestoreValue.d.ts +2 -2
  77. package/dist/hooks/data/delete.d.ts +4 -4
  78. package/dist/hooks/data/save.d.ts +4 -5
  79. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  80. package/dist/hooks/data/useEntityFetch.d.ts +4 -3
  81. package/dist/hooks/index.d.ts +1 -0
  82. package/dist/hooks/useAuthController.d.ts +1 -1
  83. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  84. package/dist/hooks/useBuildNavigationController.d.ts +3 -5
  85. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  86. package/dist/hooks/useProjectLog.d.ts +8 -2
  87. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  88. package/dist/hooks/useValidateAuthenticator.d.ts +4 -8
  89. package/dist/index.d.ts +1 -0
  90. package/dist/index.es.js +21537 -14243
  91. package/dist/index.es.js.map +1 -1
  92. package/dist/index.umd.js +23973 -588
  93. package/dist/index.umd.js.map +1 -1
  94. package/dist/internal/useBuildDataSource.d.ts +1 -16
  95. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  96. package/dist/preview/PropertyPreviewProps.d.ts +6 -1
  97. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  98. package/dist/preview/components/ReferencePreview.d.ts +3 -2
  99. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  100. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  101. package/dist/preview/util.d.ts +3 -3
  102. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  103. package/dist/routes/FireCMSRoute.d.ts +1 -0
  104. package/dist/routes/HomePageRoute.d.ts +3 -0
  105. package/dist/types/auth.d.ts +8 -10
  106. package/dist/types/collections.d.ts +71 -22
  107. package/dist/types/datasource.d.ts +52 -36
  108. package/dist/types/dialogs_controller.d.ts +7 -3
  109. package/dist/types/entities.d.ts +7 -2
  110. package/dist/types/entity_actions.d.ts +28 -4
  111. package/dist/types/entity_callbacks.d.ts +16 -16
  112. package/dist/types/entity_overrides.d.ts +2 -2
  113. package/dist/types/export_import.d.ts +4 -4
  114. package/dist/types/fields.d.ts +66 -42
  115. package/dist/types/firecms.d.ts +6 -2
  116. package/dist/types/firecms_context.d.ts +1 -1
  117. package/dist/types/index.d.ts +0 -1
  118. package/dist/types/navigation.d.ts +31 -14
  119. package/dist/types/permissions.d.ts +4 -4
  120. package/dist/types/plugins.d.ts +23 -12
  121. package/dist/types/properties.d.ts +51 -23
  122. package/dist/types/property_config.d.ts +0 -2
  123. package/dist/types/side_dialogs_controller.d.ts +10 -0
  124. package/dist/types/side_entity_controller.d.ts +1 -1
  125. package/dist/types/storage.d.ts +86 -3
  126. package/dist/types/user.d.ts +1 -0
  127. package/dist/util/builders.d.ts +3 -3
  128. package/dist/util/entities.d.ts +3 -3
  129. package/dist/util/entity_actions.d.ts +2 -0
  130. package/dist/util/entity_cache.d.ts +23 -0
  131. package/dist/util/icon_list.d.ts +5 -1
  132. package/dist/util/icon_synonyms.d.ts +1 -98
  133. package/dist/util/icons.d.ts +6 -3
  134. package/dist/util/index.d.ts +2 -0
  135. package/dist/util/navigation_from_path.d.ts +5 -1
  136. package/dist/util/navigation_utils.d.ts +14 -3
  137. package/dist/util/objects.d.ts +2 -1
  138. package/dist/util/permissions.d.ts +4 -4
  139. package/dist/util/plurals.d.ts +0 -2
  140. package/dist/util/property_utils.d.ts +3 -3
  141. package/dist/util/resolutions.d.ts +30 -16
  142. package/dist/util/storage.d.ts +23 -2
  143. package/dist/util/useStorageUploadController.d.ts +3 -3
  144. package/package.json +61 -48
  145. package/src/app/AppBar.tsx +18 -0
  146. package/src/app/Drawer.tsx +24 -0
  147. package/src/app/Scaffold.tsx +243 -0
  148. package/src/app/index.ts +4 -0
  149. package/src/app/useApp.tsx +32 -0
  150. package/src/components/ArrayContainer.tsx +126 -40
  151. package/src/components/CircularProgressCenter.tsx +2 -2
  152. package/src/components/ClearFilterSortButton.tsx +41 -0
  153. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +3 -3
  154. package/src/components/DeleteEntityDialog.tsx +10 -19
  155. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +54 -37
  156. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +38 -31
  157. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +30 -9
  158. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +47 -39
  159. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  160. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +30 -16
  161. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +19 -17
  162. package/src/components/EntityCollectionTable/index.tsx +1 -1
  163. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +31 -36
  164. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +36 -34
  165. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
  166. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +84 -77
  167. package/src/components/EntityCollectionView/EntityCollectionView.tsx +206 -112
  168. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  169. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  170. package/src/components/EntityCollectionView/useSelectionController.tsx +20 -7
  171. package/src/components/EntityCollectionView/utils.ts +19 -0
  172. package/src/components/EntityPreview.tsx +62 -52
  173. package/src/components/EntityView.tsx +10 -10
  174. package/src/components/ErrorView.tsx +4 -4
  175. package/src/components/HomePage/DefaultHomePage.tsx +26 -19
  176. package/src/components/HomePage/FavouritesView.tsx +6 -11
  177. package/src/components/HomePage/NavigationCard.tsx +3 -3
  178. package/src/components/HomePage/NavigationCardBinding.tsx +5 -10
  179. package/src/components/HomePage/NavigationGroup.tsx +2 -2
  180. package/src/components/HomePage/SmallNavigationCard.tsx +5 -6
  181. package/src/components/NotFoundPage.tsx +2 -2
  182. package/src/components/PropertyConfigBadge.tsx +9 -3
  183. package/src/components/PropertyIdCopyTooltip.tsx +47 -0
  184. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +19 -13
  185. package/src/components/ReferenceWidget.tsx +21 -11
  186. package/src/components/SearchIconsView.tsx +10 -7
  187. package/src/components/SelectableTable/SelectableTable.tsx +27 -12
  188. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  189. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +25 -8
  190. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +36 -12
  191. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +92 -23
  192. package/src/components/UnsavedChangesDialog.tsx +42 -0
  193. package/src/components/VirtualTable/VirtualTable.tsx +96 -48
  194. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  195. package/src/components/VirtualTable/VirtualTableHeader.tsx +10 -10
  196. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  197. package/src/components/VirtualTable/VirtualTableProps.tsx +33 -14
  198. package/src/components/VirtualTable/VirtualTableRow.tsx +5 -6
  199. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +5 -5
  200. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +3 -2
  201. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  202. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
  203. package/src/components/VirtualTable/types.tsx +2 -3
  204. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +33 -40
  205. package/src/components/common/index.ts +2 -1
  206. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  207. package/src/components/common/types.tsx +4 -6
  208. package/src/components/common/useColumnsIds.tsx +24 -3
  209. package/src/components/common/useDataSourceTableController.tsx +420 -0
  210. package/src/components/common/useDebouncedCallback.tsx +20 -0
  211. package/src/components/common/useScrollRestoration.tsx +68 -0
  212. package/src/components/common/useTableSearchHelper.ts +53 -12
  213. package/src/components/index.tsx +4 -2
  214. package/src/contexts/BreacrumbsContext.tsx +38 -0
  215. package/src/contexts/DialogsProvider.tsx +5 -4
  216. package/src/contexts/SnackbarProvider.tsx +2 -0
  217. package/src/core/DefaultAppBar.tsx +201 -0
  218. package/src/core/DefaultDrawer.tsx +185 -0
  219. package/src/core/DrawerNavigationItem.tsx +66 -0
  220. package/src/core/EntityEditView.tsx +1001 -213
  221. package/src/core/EntitySidePanel.tsx +80 -17
  222. package/src/core/FireCMS.tsx +56 -49
  223. package/src/core/FireCMSRouter.tsx +17 -0
  224. package/src/core/NavigationRoutes.tsx +20 -34
  225. package/src/core/SideDialogs.tsx +12 -6
  226. package/src/core/field_configs.tsx +11 -12
  227. package/src/core/index.tsx +6 -5
  228. package/src/form/PropertyFieldBinding.tsx +85 -44
  229. package/src/form/components/CustomIdField.tsx +6 -2
  230. package/src/form/components/FieldHelperText.tsx +4 -4
  231. package/src/form/components/LabelWithIcon.tsx +30 -19
  232. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  233. package/src/form/components/StorageItemPreview.tsx +22 -12
  234. package/src/form/components/StorageUploadProgress.tsx +3 -4
  235. package/src/form/components/index.tsx +1 -1
  236. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +31 -17
  237. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +47 -35
  238. package/src/form/field_bindings/BlockFieldBinding.tsx +56 -34
  239. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -14
  240. package/src/form/field_bindings/KeyValueFieldBinding.tsx +60 -51
  241. package/src/form/field_bindings/MapFieldBinding.tsx +72 -53
  242. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +150 -0
  243. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +25 -20
  244. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +11 -16
  245. package/src/form/field_bindings/ReferenceFieldBinding.tsx +42 -31
  246. package/src/form/field_bindings/RepeatFieldBinding.tsx +56 -35
  247. package/src/form/field_bindings/SelectFieldBinding.tsx +22 -14
  248. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +37 -47
  249. package/src/form/field_bindings/SwitchFieldBinding.tsx +29 -24
  250. package/src/form/field_bindings/TextFieldBinding.tsx +28 -24
  251. package/src/form/index.tsx +4 -9
  252. package/src/form/useClearRestoreValue.tsx +2 -2
  253. package/src/form/validation.ts +1 -17
  254. package/src/hooks/data/delete.ts +6 -5
  255. package/src/hooks/data/save.ts +13 -9
  256. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  257. package/src/hooks/data/useDataSource.tsx +11 -3
  258. package/src/hooks/data/useEntityFetch.tsx +10 -6
  259. package/src/hooks/index.tsx +1 -0
  260. package/src/hooks/useAuthController.tsx +1 -1
  261. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  262. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  263. package/src/hooks/useBuildModeController.tsx +11 -5
  264. package/src/hooks/useBuildNavigationController.tsx +150 -50
  265. package/src/hooks/useFireCMSContext.tsx +5 -5
  266. package/src/hooks/useLargeLayout.tsx +0 -35
  267. package/src/hooks/useProjectLog.tsx +32 -10
  268. package/src/hooks/useResolvedNavigationFrom.tsx +10 -12
  269. package/src/hooks/useValidateAuthenticator.tsx +17 -37
  270. package/src/index.ts +1 -0
  271. package/src/internal/useBuildDataSource.ts +72 -82
  272. package/src/internal/useBuildSideDialogsController.tsx +4 -2
  273. package/src/internal/useBuildSideEntityController.tsx +230 -70
  274. package/src/internal/useUnsavedChangesDialog.tsx +127 -91
  275. package/src/preview/PropertyPreview.tsx +13 -20
  276. package/src/preview/PropertyPreviewProps.tsx +7 -1
  277. package/src/preview/components/BooleanPreview.tsx +2 -2
  278. package/src/preview/components/EmptyValue.tsx +1 -1
  279. package/src/preview/components/EnumValuesChip.tsx +2 -2
  280. package/src/preview/components/ImagePreview.tsx +25 -36
  281. package/src/preview/components/ReferencePreview.tsx +22 -33
  282. package/src/preview/components/StorageThumbnail.tsx +5 -1
  283. package/src/preview/components/UrlComponentPreview.tsx +44 -11
  284. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -3
  285. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  286. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -3
  287. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -2
  288. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -5
  289. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -5
  290. package/src/preview/property_previews/MapPropertyPreview.tsx +9 -9
  291. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
  292. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  293. package/src/preview/util.ts +10 -10
  294. package/src/routes/CustomCMSRoute.tsx +21 -0
  295. package/src/routes/FireCMSRoute.tsx +230 -0
  296. package/src/routes/HomePageRoute.tsx +17 -0
  297. package/src/types/auth.tsx +9 -13
  298. package/src/types/collections.ts +87 -27
  299. package/src/types/customization_controller.tsx +0 -1
  300. package/src/types/datasource.ts +61 -43
  301. package/src/types/dialogs_controller.tsx +7 -3
  302. package/src/types/entities.ts +12 -2
  303. package/src/types/entity_actions.tsx +32 -7
  304. package/src/types/entity_callbacks.ts +18 -18
  305. package/src/types/entity_overrides.tsx +2 -2
  306. package/src/types/export_import.ts +4 -4
  307. package/src/types/fields.tsx +72 -46
  308. package/src/types/firecms.tsx +7 -2
  309. package/src/types/firecms_context.tsx +1 -1
  310. package/src/types/index.ts +0 -1
  311. package/src/types/navigation.ts +37 -18
  312. package/src/types/permissions.ts +5 -5
  313. package/src/types/plugins.tsx +25 -14
  314. package/src/types/properties.ts +59 -24
  315. package/src/types/property_config.tsx +0 -2
  316. package/src/types/side_dialogs_controller.tsx +13 -0
  317. package/src/types/side_entity_controller.tsx +1 -1
  318. package/src/types/storage.ts +94 -3
  319. package/src/types/user.ts +2 -0
  320. package/src/util/builders.ts +10 -8
  321. package/src/util/entities.ts +9 -6
  322. package/src/util/entity_actions.ts +28 -0
  323. package/src/util/entity_cache.ts +196 -0
  324. package/src/util/enums.ts +1 -1
  325. package/src/util/icon_list.ts +16 -10
  326. package/src/util/icon_synonyms.ts +3 -100
  327. package/src/util/icons.tsx +17 -7
  328. package/src/util/index.ts +2 -0
  329. package/src/util/join_collections.ts +3 -0
  330. package/src/util/make_properties_editable.ts +13 -5
  331. package/src/util/navigation_from_path.ts +10 -2
  332. package/src/util/navigation_utils.ts +59 -7
  333. package/src/util/objects.ts +45 -28
  334. package/src/util/parent_references_from_path.ts +3 -3
  335. package/src/util/permissions.ts +9 -8
  336. package/src/util/plurals.ts +0 -2
  337. package/src/util/property_utils.tsx +11 -4
  338. package/src/util/references.ts +11 -2
  339. package/src/util/resolutions.ts +79 -46
  340. package/src/util/storage.ts +79 -21
  341. package/src/util/strings.ts +2 -2
  342. package/src/util/useStorageUploadController.tsx +34 -8
  343. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  344. package/dist/components/VirtualTable/common.d.ts +0 -2
  345. package/dist/core/Drawer.d.ts +0 -23
  346. package/dist/core/Scaffold.d.ts +0 -55
  347. package/dist/core/SideEntityView.d.ts +0 -7
  348. package/dist/form/EntityForm.d.ts +0 -77
  349. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  350. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  351. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  352. package/dist/internal/useLocaleConfig.d.ts +0 -1
  353. package/dist/types/appcheck.d.ts +0 -26
  354. package/src/components/FireCMSAppBar.tsx +0 -165
  355. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
  356. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -225
  357. package/src/core/Drawer.tsx +0 -191
  358. package/src/core/Scaffold.tsx +0 -281
  359. package/src/core/SideEntityView.tsx +0 -38
  360. package/src/form/EntityForm.tsx +0 -728
  361. package/src/form/components/FormikArrayContainer.tsx +0 -44
  362. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  363. package/src/internal/useBuildCustomizationController.tsx +0 -5
  364. package/src/internal/useLocaleConfig.tsx +0 -18
  365. package/src/types/appcheck.ts +0 -29
  366. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -60,7 +60,7 @@ export interface CollectionFetchResult<M extends Record<string, any>> {
60
60
  * @param searchString
61
61
  * @group Hooks and utilities
62
62
  */
63
- export function useCollectionFetch<M extends Record<string, any>, UserType extends User>(
63
+ export function useCollectionFetch<M extends Record<string, any>, USER extends User>(
64
64
  {
65
65
  path: inputPath,
66
66
  collection,
@@ -73,12 +73,12 @@ export function useCollectionFetch<M extends Record<string, any>, UserType exten
73
73
  const dataSource = useDataSource(collection);
74
74
  const navigationController = useNavigationController();
75
75
 
76
- const path = navigationController.resolveAliasesFrom(inputPath);
76
+ const path = navigationController.resolveIdsFrom(inputPath);
77
77
 
78
78
  const sortByProperty = sortBy ? sortBy[0] : undefined;
79
79
  const currentSort = sortBy ? sortBy[1] : undefined;
80
80
 
81
- const context: FireCMSContext<UserType> = useFireCMSContext();
81
+ const context: FireCMSContext<USER> = useFireCMSContext();
82
82
 
83
83
  const [data, setData] = useState<Entity<M>[]>([]);
84
84
 
@@ -1,4 +1,4 @@
1
- import { useContext, useMemo } from "react";
1
+ import { useContext } from "react";
2
2
  import { DataSource, EntityCollection } from "../../types";
3
3
  import { DataSourceContext } from "../../contexts/DataSourceContext";
4
4
 
@@ -7,8 +7,16 @@ import { DataSourceContext } from "../../contexts/DataSourceContext";
7
7
  * @group Hooks and utilities
8
8
  */
9
9
  export const useDataSource = (collection?: EntityCollection<any, any>): DataSource => {
10
+ // const customizationController = useCustomizationController();
11
+ // const navigationController = useNavigationController();
10
12
  const defaultDataSource = useContext(DataSourceContext);
11
- if (collection?.overrides?.dataSource)
12
- return collection?.overrides.dataSource;
13
+ // if (collection?.overrides?.dataSourceDelegate) {
14
+ // console.trace("Using custom data source for collection " + collection.id);
15
+ // return useBuildDataSource({
16
+ // delegate: collection.overrides.dataSourceDelegate,
17
+ // propertyConfigs: customizationController?.propertyConfigs,
18
+ // navigationController: navigationController
19
+ // });
20
+ // }
13
21
  return defaultDataSource;
14
22
  };
@@ -7,10 +7,11 @@ import { useFireCMSContext } from "../useFireCMSContext";
7
7
  /**
8
8
  * @group Hooks and utilities
9
9
  */
10
- export interface EntityFetchProps<M extends Record<string, any>, UserType extends User = User> {
10
+ export interface EntityFetchProps<M extends Record<string, any>, USER extends User = User> {
11
11
  path: string;
12
12
  entityId?: string;
13
- collection: EntityCollection<M, UserType>;
13
+ databaseId?: string;
14
+ collection: EntityCollection<M, USER>;
14
15
  useCache?: boolean;
15
16
  }
16
17
 
@@ -35,20 +36,21 @@ const CACHE: Record<string, Entity<any> | undefined> = {};
35
36
  * @group Hooks and utilities
36
37
  */
37
38
 
38
- export function useEntityFetch<M extends Record<string, any>, UserType extends User>(
39
+ export function useEntityFetch<M extends Record<string, any>, USER extends User>(
39
40
  {
40
41
  path: inputPath,
41
42
  entityId,
42
43
  collection,
44
+ databaseId,
43
45
  useCache = false
44
- }: EntityFetchProps<M, UserType>): EntityFetchResult<M> {
46
+ }: EntityFetchProps<M, USER>): EntityFetchResult<M> {
45
47
 
46
48
  const dataSource = useDataSource(collection);
47
49
  const navigationController = useNavigationController();
48
50
 
49
- const path = navigationController.resolveAliasesFrom(inputPath);
51
+ const path = navigationController.resolveIdsFrom(inputPath);
50
52
 
51
- const context: FireCMSContext<UserType> = useFireCMSContext();
53
+ const context: FireCMSContext<USER> = useFireCMSContext();
52
54
 
53
55
  const [entity, setEntity] = useState<Entity<M> | undefined>();
54
56
  const [dataLoading, setDataLoading] = useState<boolean>(true);
@@ -96,6 +98,7 @@ export function useEntityFetch<M extends Record<string, any>, UserType extends U
96
98
  return dataSource.listenEntity<M>({
97
99
  path,
98
100
  entityId,
101
+ databaseId,
99
102
  collection,
100
103
  onUpdate: onEntityUpdate,
101
104
  onError
@@ -104,6 +107,7 @@ export function useEntityFetch<M extends Record<string, any>, UserType extends U
104
107
  dataSource.fetchEntity<M>({
105
108
  path,
106
109
  entityId,
110
+ databaseId,
107
111
  collection
108
112
  })
109
113
  .then(onEntityUpdate)
@@ -10,6 +10,7 @@ export * from "./useResolvedNavigationFrom";
10
10
 
11
11
  export * from "./useStorageSource";
12
12
  export * from "./useAuthController";
13
+ export * from "./useDialogsController";
13
14
  export * from "./useSideDialogsController";
14
15
  export * from "./useSideEntityController";
15
16
  export * from "./useFireCMSContext";
@@ -11,4 +11,4 @@ import { AuthControllerContext } from "../contexts/AuthControllerContext";
11
11
  * @see AuthController
12
12
  * @group Hooks and utilities
13
13
  */
14
- export const useAuthController = <UserType extends User = User, AuthControllerType extends AuthController<UserType> = AuthController<UserType>>(): AuthControllerType => useContext(AuthControllerContext) as AuthControllerType;
14
+ export const useAuthController = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): AuthControllerType => useContext(AuthControllerContext) as AuthControllerType;
@@ -0,0 +1,31 @@
1
+ import { useContext } from "react";
2
+ import { BreadcrumbContext } from "../contexts/BreacrumbsContext";
3
+
4
+ /**
5
+ * @group Hooks and utilities
6
+ */
7
+ export interface BreadcrumbsController {
8
+ breadcrumbs: BreadcrumbEntry[];
9
+ set: (props: {
10
+ breadcrumbs: BreadcrumbEntry[];
11
+ }) => void;
12
+ }
13
+
14
+ /**
15
+ * @group Hooks and utilities
16
+ */
17
+ export interface BreadcrumbEntry {
18
+ title: string;
19
+ url: string;
20
+ }
21
+
22
+ /**
23
+ * Hook to retrieve the BreadcrumbsController.
24
+ *
25
+ * Consider that in order to use this hook you need to have a parent
26
+ * `FireCMS`
27
+ *
28
+ * @see BreadcrumbsController
29
+ * @group Hooks and utilities
30
+ */
31
+ export const useBreadcrumbsController = (): BreadcrumbsController => useContext(BreadcrumbContext);
@@ -1,10 +1,10 @@
1
- import { useCallback, useEffect, useState } from "react";
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { PartialEntityCollection, UserConfigurationPersistence } from "../types";
3
3
  import { mergeDeep, stripCollectionPath } from "../util";
4
4
 
5
5
  export function useBuildLocalConfigurationPersistence(): UserConfigurationPersistence {
6
6
 
7
- const [configCache, setConfigCache] = useState<Record<string, PartialEntityCollection>>({});
7
+ const configCache = useRef<Record<string, PartialEntityCollection>>({});
8
8
 
9
9
  const getCollectionFromStorage = useCallback((storageKey: string) => {
10
10
  const item = localStorage.getItem(storageKey);
@@ -13,20 +13,18 @@ export function useBuildLocalConfigurationPersistence(): UserConfigurationPersis
13
13
 
14
14
  const getCollectionConfig = useCallback(<M extends Record<string, any>>(path: string): PartialEntityCollection<M> => {
15
15
  const storageKey = `collection_config::${stripCollectionPath(path)}`;
16
- if (configCache[storageKey]) {
17
- return configCache[storageKey] as PartialEntityCollection<M>;
16
+ if (configCache.current[storageKey]) {
17
+ return configCache.current[storageKey] as PartialEntityCollection<M>;
18
18
  }
19
19
  return getCollectionFromStorage(storageKey);
20
- }, [configCache, getCollectionFromStorage]);
20
+ }, [getCollectionFromStorage]);
21
21
 
22
22
  const onCollectionModified = useCallback(<M extends Record<string, any>>(path: string, data: PartialEntityCollection<M>) => {
23
23
  const storageKey = `collection_config::${stripCollectionPath(path)}`;
24
24
  localStorage.setItem(storageKey, JSON.stringify(data));
25
- setConfigCache((currentCache) => {
26
- const cachedConfig = currentCache[storageKey];
27
- const newConfig = mergeDeep(cachedConfig ?? getCollectionFromStorage(path), data);
28
- return (mergeDeep(currentCache, newConfig));
29
- });
25
+ const cachedConfig = configCache.current[storageKey];
26
+ const newConfig = mergeDeep(cachedConfig ?? getCollectionFromStorage(path), data);
27
+ configCache.current[storageKey] = mergeDeep(configCache.current[storageKey], newConfig);
30
28
  }, [getCollectionFromStorage]);
31
29
 
32
30
  const [recentlyVisitedPaths, _setRecentlyVisitedPaths] = useState<string[]>([]);
@@ -8,8 +8,13 @@ import { ModeController } from "./index";
8
8
  */
9
9
  export function useBuildModeController(): ModeController {
10
10
 
11
- const prefersDarkModeQuery = typeof window !== "undefined" &&
12
- window.matchMedia("(prefers-color-scheme: dark)");
11
+ const prefersDarkModeQuery = useCallback((): boolean => {
12
+ if (typeof window === "undefined")
13
+ return false;
14
+ const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
15
+ return mediaQueryList.matches;
16
+ }, []);
17
+
13
18
  const prefersDarkModeStorage: boolean | null = localStorage.getItem("prefers-dark-mode") != null ? localStorage.getItem("prefers-dark-mode") === "true" : null;
14
19
  const prefersDarkMode = prefersDarkModeStorage ?? prefersDarkModeQuery;
15
20
  const [mode, setMode] = useState<"light" | "dark">(prefersDarkMode ? "dark" : "light");
@@ -23,7 +28,7 @@ export function useBuildModeController(): ModeController {
23
28
  const setDarkMode = useCallback(() => {
24
29
  setMode("dark");
25
30
  setDocumentMode("dark");
26
- }, [prefersDarkModeQuery]);
31
+ }, []);
27
32
 
28
33
  const setLightMode = useCallback(() => {
29
34
  setMode("light");
@@ -37,14 +42,15 @@ export function useBuildModeController(): ModeController {
37
42
 
38
43
  const toggleMode = useCallback(() => {
39
44
 
45
+ const prefersDarkModeQueryResult = prefersDarkModeQuery();
40
46
  if (mode === "light") {
41
- if (!prefersDarkModeQuery)
47
+ if (!prefersDarkModeQueryResult)
42
48
  localStorage.setItem("prefers-dark-mode", "true");
43
49
  else
44
50
  localStorage.removeItem("prefers-dark-mode");
45
51
  setDarkMode();
46
52
  } else {
47
- if (prefersDarkModeQuery)
53
+ if (prefersDarkModeQueryResult)
48
54
  localStorage.setItem("prefers-dark-mode", "false");
49
55
  else
50
56
  localStorage.removeItem("prefers-dark-mode");
@@ -9,6 +9,7 @@ import {
9
9
  EntityCollection,
10
10
  EntityCollectionsBuilder,
11
11
  EntityReference,
12
+ NavigationBlocker,
12
13
  NavigationController,
13
14
  PermissionsBuilder,
14
15
  TopNavigationEntry,
@@ -20,19 +21,21 @@ import {
20
21
  applyPermissionsFunctionIfEmpty,
21
22
  getCollectionByPathOrId,
22
23
  mergeDeep,
24
+ removeFunctions,
23
25
  removeInitialAndTrailingSlashes,
24
26
  resolveCollectionPathIds,
25
27
  resolvePermissions
26
28
  } from "../util";
27
29
  import { getParentReferencesFromPath } from "../util/parent_references_from_path";
30
+ import { useBlocker, useNavigate } from "react-router-dom";
28
31
 
29
32
  const DEFAULT_BASE_PATH = "/";
30
33
  const DEFAULT_COLLECTION_PATH = "/c";
31
34
 
32
- type BuildNavigationContextProps<EC extends EntityCollection, UserType extends User> = {
35
+ export type BuildNavigationContextProps<EC extends EntityCollection, USER extends User> = {
33
36
  basePath?: string,
34
37
  baseCollectionPath?: string,
35
- authController: AuthController<UserType>;
38
+ authController: AuthController<USER>;
36
39
  collections?: EC[] | EntityCollectionsBuilder<EC>;
37
40
  collectionPermissions?: PermissionsBuilder;
38
41
  views?: CMSView[] | CMSViewsBuilder;
@@ -50,7 +53,7 @@ type BuildNavigationContextProps<EC extends EntityCollection, UserType extends U
50
53
  injectCollections?: (collections: EntityCollection[]) => EntityCollection[];
51
54
  };
52
55
 
53
- export function useBuildNavigationController<EC extends EntityCollection, UserType extends User>(props: BuildNavigationContextProps<EC, UserType>): NavigationController {
56
+ export function useBuildNavigationController<EC extends EntityCollection, USER extends User>(props: BuildNavigationContextProps<EC, USER>): NavigationController {
54
57
  const {
55
58
  basePath = DEFAULT_BASE_PATH,
56
59
  baseCollectionPath = DEFAULT_COLLECTION_PATH,
@@ -65,6 +68,8 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
65
68
  injectCollections
66
69
  } = props;
67
70
 
71
+ const navigate = useNavigate();
72
+
68
73
  const collectionsRef = useRef<EntityCollection[] | undefined>();
69
74
  const viewsRef = useRef<CMSView[] | undefined>();
70
75
  const adminViewsRef = useRef<CMSView[] | undefined>();
@@ -130,6 +135,30 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
130
135
  .filter(Boolean) as TopNavigationEntry[]
131
136
  ];
132
137
 
138
+ // Sort by group, entries with group "Admin" will go last, and second to last will be the group "Views"
139
+ navigationEntries = navigationEntries.sort((a, b) => {
140
+ if (a.group !== "Views" && a.group !== "Admin" && (b.group === "Views" || b.group === "Admin")) {
141
+ return -1;
142
+ }
143
+ if (b.group !== "Views" && b.group !== "Admin" && (a.group === "Views" || a.group === "Admin")) {
144
+ return 1;
145
+ }
146
+ if (a.group === "Admin" && b.group !== "Admin") {
147
+ return 1;
148
+ }
149
+ if (a.group !== "Admin" && b.group === "Admin") {
150
+ return -1;
151
+ }
152
+ if (a.group === "Views" && b.group !== "Views") {
153
+ return -1;
154
+ }
155
+ if (a.group !== "Views" && b.group === "Views") {
156
+ return 1;
157
+ }
158
+ return 0;
159
+
160
+ });
161
+
133
162
  if (viewsOrder) {
134
163
  navigationEntries = navigationEntries.sort((a, b) => {
135
164
  const aIndex = viewsOrder.indexOf(a.path);
@@ -163,8 +192,10 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
163
192
  if (authController.initialLoading)
164
193
  return;
165
194
 
195
+ console.debug("Refreshing navigation");
196
+
166
197
  try {
167
- console.debug("Refreshing navigation")
198
+
168
199
  const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([
169
200
  resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate, injectCollections),
170
201
  resolveCMSViews(viewsProp, authController, dataSourceDelegate),
@@ -172,24 +203,38 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
172
203
  ]
173
204
  );
174
205
 
175
- if (
176
- !equal(collectionsRef.current, resolvedCollections) ||
177
- !equal(viewsRef.current, resolvedViews) ||
178
- !equal(adminViewsRef.current, resolvedAdminViews) ||
179
- !equal(topLevelNavigation, computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder))
180
- ) {
206
+ let shouldUpdateTopLevelNav = false;
207
+ if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
208
+ collectionsRef.current = resolvedCollections;
209
+ console.log("Collections have changed", resolvedCollections);
210
+ shouldUpdateTopLevelNav = true;
211
+ }
212
+ if (collectionsRef.current === undefined) {
181
213
  collectionsRef.current = resolvedCollections;
214
+ shouldUpdateTopLevelNav = true;
215
+ }
216
+ if (!equal(viewsRef.current, resolvedViews)) {
182
217
  viewsRef.current = resolvedViews;
218
+ shouldUpdateTopLevelNav = true;
219
+ }
220
+ if (!equal(adminViewsRef.current, resolvedAdminViews)) {
183
221
  adminViewsRef.current = resolvedAdminViews;
184
- setTopLevelNavigation(computeTopNavigation(resolvedCollections ?? [], resolvedViews, resolvedAdminViews, viewsOrder));
222
+ shouldUpdateTopLevelNav = true;
223
+ }
224
+
225
+ const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
226
+ if (shouldUpdateTopLevelNav && !equal(topLevelNavigation, computedTopLevelNav)) {
227
+ setTopLevelNavigation(computedTopLevelNav);
185
228
  }
186
229
  } catch (e) {
187
230
  console.error(e);
188
231
  setNavigationLoadingError(e as any);
189
232
  }
190
233
 
191
- setNavigationLoading(false);
192
- setInitialised(true);
234
+ if (navigationLoading)
235
+ setNavigationLoading(false);
236
+ if (!initialised)
237
+ setInitialised(true);
193
238
 
194
239
  }, [
195
240
  collectionsProp,
@@ -208,7 +253,6 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
208
253
 
209
254
  const getCollection = useCallback((
210
255
  idOrPath: string,
211
- entityId?: string,
212
256
  includeUserOverride = false
213
257
  ): EC | undefined => {
214
258
  const collections = collectionsRef.current;
@@ -218,8 +262,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
218
262
  const baseCollection = getCollectionByPathOrId(removeInitialAndTrailingSlashes(idOrPath), collections);
219
263
 
220
264
  const userOverride = includeUserOverride ? userConfigPersistence?.getCollectionConfig(idOrPath) : undefined;
221
-
222
- const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride) : undefined;
265
+ const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride ?? {}) : undefined;
223
266
 
224
267
  let result: Partial<EntityCollection> | undefined = overriddenCollection;
225
268
 
@@ -244,9 +287,9 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
244
287
  const getCollectionFromPaths = useCallback(<EC extends EntityCollection>(pathSegments: string[]): EC | undefined => {
245
288
 
246
289
  const collections = collectionsRef.current;
290
+ if (collections === undefined)
291
+ throw Error("getCollectionFromPaths: Collections have not been initialised yet");
247
292
  let currentCollections: EntityCollection[] | undefined = [...(collections ?? [])];
248
- if (!currentCollections)
249
- throw Error("Collections have not been initialised yet");
250
293
 
251
294
  for (let i = 0; i < pathSegments.length; i++) {
252
295
  const pathSegment = pathSegments[i];
@@ -265,9 +308,9 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
265
308
  const getCollectionFromIds = useCallback(<EC extends EntityCollection>(ids: string[]): EC | undefined => {
266
309
 
267
310
  const collections = collectionsRef.current;
311
+ if (collections === undefined)
312
+ throw Error("getCollectionFromIds: Collections have not been initialised yet");
268
313
  let currentCollections: EntityCollection[] | undefined = [...(collections ?? [])];
269
- if (!currentCollections)
270
- throw Error("Collections have not been initialised yet");
271
314
 
272
315
  for (let i = 0; i < ids.length; i++) {
273
316
  const id = ids[i];
@@ -293,19 +336,8 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
293
336
  throw Error("Expected path starting with " + fullCollectionPath);
294
337
  }, [fullCollectionPath]);
295
338
 
296
- const buildUrlEditCollectionPath = useCallback(({
297
- path
298
- }: {
299
- path: string
300
- }): string => {
301
- return `s/edit/${encodePath(path)}`;
302
- },
303
- []);
304
-
305
- const resolveAliasesFrom = useCallback((path: string): string => {
306
- const collections = collectionsRef.current;
307
- if (!collections)
308
- throw Error("Collections have not been initialised yet");
339
+ const resolveIdsFrom = useCallback((path: string): string => {
340
+ const collections = collectionsRef.current ?? [];
309
341
  return resolveCollectionPathIds(path, collections);
310
342
  }, []);
311
343
 
@@ -364,24 +396,16 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
364
396
  isUrlCollectionPath,
365
397
  urlPathToDataPath,
366
398
  buildUrlCollectionPath,
367
- buildUrlEditCollectionPath,
368
- buildCMSUrlPath,
369
- resolveAliasesFrom,
399
+ resolveIdsFrom,
370
400
  topLevelNavigation,
371
401
  refreshNavigation,
372
402
  getParentReferencesFromPath: getAllParentReferencesForPath,
373
403
  getParentCollectionIds,
374
- convertIdsToPaths
404
+ convertIdsToPaths,
405
+ navigate,
375
406
  };
376
407
  }
377
408
 
378
- export function getSidePanelKey(path: string, entityId?: string) {
379
- if (entityId)
380
- return `${removeInitialAndTrailingSlashes(path)}/${removeInitialAndTrailingSlashes(entityId)}`;
381
- else
382
- return removeInitialAndTrailingSlashes(path);
383
- }
384
-
385
409
  function encodePath(input: string) {
386
410
  return encodeURIComponent(removeInitialAndTrailingSlashes(input))
387
411
  .replaceAll("%2F", "/")
@@ -390,9 +414,10 @@ function encodePath(input: string) {
390
414
 
391
415
  function filterOutNotAllowedCollections(resolvedCollections: EntityCollection[], authController: AuthController<User>): EntityCollection[] {
392
416
  return resolvedCollections
417
+ .filter((c) => Boolean(c.path))
393
418
  .filter((c) => {
394
419
  if (!c.permissions) return true;
395
- const resolvedPermissions = resolvePermissions(c, authController, c.path, null)
420
+ const resolvedPermissions = resolvePermissions(c, authController, c.path, null);
396
421
  return resolvedPermissions?.read !== false;
397
422
  })
398
423
  .map((c) => {
@@ -408,7 +433,7 @@ async function resolveCollections(collections: undefined | EntityCollection[] |
408
433
  collectionPermissions: PermissionsBuilder | undefined,
409
434
  authController: AuthController,
410
435
  dataSource: DataSourceDelegate,
411
- injectCollections?: (collections: EntityCollection[]) => EntityCollection[]) {
436
+ injectCollections?: (collections: EntityCollection[]) => EntityCollection[]): Promise<EntityCollection[]> {
412
437
  let resolvedCollections: EntityCollection[] = [];
413
438
  if (typeof collections === "function") {
414
439
  resolvedCollections = await collections({
@@ -420,14 +445,12 @@ async function resolveCollections(collections: undefined | EntityCollection[] |
420
445
  resolvedCollections = collections;
421
446
  }
422
447
 
423
- resolvedCollections = applyPermissionsFunctionIfEmpty(resolvedCollections, collectionPermissions);
424
-
425
- resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
426
-
427
448
  if (injectCollections) {
428
449
  resolvedCollections = injectCollections(resolvedCollections ?? []);
429
450
  }
430
451
 
452
+ resolvedCollections = applyPermissionsFunctionIfEmpty(resolvedCollections, collectionPermissions);
453
+ resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
431
454
  return resolvedCollections;
432
455
  }
433
456
 
@@ -452,3 +475,80 @@ function getGroup(collectionOrView: EntityCollection<any, any> | CMSView) {
452
475
  }
453
476
  return trimmed ?? "Views";
454
477
  }
478
+
479
+ function areCollectionListsEqual(a: EntityCollection[], b: EntityCollection[]) {
480
+ if (a.length !== b.length) {
481
+ return false;
482
+ }
483
+ const aCopy = [...a];
484
+ const bCopy = [...b];
485
+ const aSorted = aCopy.sort((x, y) => x.id.localeCompare(y.id));
486
+ const bSorted = bCopy.sort((x, y) => x.id.localeCompare(y.id));
487
+ return aSorted.every((value, index) => areCollectionsEqual(value, bSorted[index]));
488
+ }
489
+
490
+ function areCollectionsEqual(a: EntityCollection, b: EntityCollection) {
491
+ const {
492
+ subcollections: subcollectionsA,
493
+ ...restA
494
+ } = a;
495
+ const {
496
+ subcollections: subcollectionsB,
497
+ ...restB
498
+ } = b;
499
+ if (!areCollectionListsEqual(subcollectionsA ?? [], subcollectionsB ?? [])) {
500
+ return false;
501
+ }
502
+ return equal(removeFunctions(restA), removeFunctions(restB));
503
+ }
504
+
505
+ function useCustomBlocker(): NavigationBlocker {
506
+ const [blockListeners, setBlockListeners] = useState<Record<string, {
507
+ block: boolean,
508
+ basePath?: string
509
+ }>>({});
510
+
511
+ const shouldBlock = Object.values(blockListeners).some(b => b.block);
512
+
513
+ let blocker: any;
514
+ try {
515
+ blocker = useBlocker(({
516
+ nextLocation
517
+ }) => {
518
+ const allBasePaths = Object.values(blockListeners).map(b => b.basePath).filter(Boolean) as string[];
519
+ if (allBasePaths && allBasePaths.some(path => nextLocation.pathname.startsWith(path)))
520
+ return false;
521
+ return shouldBlock;
522
+ });
523
+ } catch (e) {
524
+ console.warn("Blocker not available, navigation will not be blocked");
525
+ }
526
+
527
+ const updateBlockListener = (path: string, block: boolean, basePath?: string) => {
528
+ setBlockListeners(prev => ({
529
+ ...prev,
530
+ [path]: {
531
+ block,
532
+ basePath
533
+ }
534
+ }));
535
+ return () => setBlockListeners(prev => {
536
+ const {
537
+ [path]: removed,
538
+ ...rest
539
+ } = prev;
540
+ return rest;
541
+ })
542
+ };
543
+
544
+ const isBlocked = (path: string) => {
545
+ return (blockListeners[path]?.block ?? false) && blocker?.state === "blocked";
546
+ }
547
+
548
+ return {
549
+ updateBlockListener,
550
+ isBlocked,
551
+ proceed: blocker?.proceed,
552
+ reset: blocker?.reset
553
+ }
554
+ }
@@ -21,9 +21,9 @@ import React, { useEffect } from "react";
21
21
  * @see FireCMSContext
22
22
  * @group Hooks and utilities
23
23
  */
24
- export const useFireCMSContext = <UserType extends User = User, AuthControllerType extends AuthController<UserType> = AuthController<UserType>>(): FireCMSContext<UserType, AuthControllerType> => {
24
+ export const useFireCMSContext = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): FireCMSContext<USER, AuthControllerType> => {
25
25
 
26
- const authController = useAuthController<UserType, AuthControllerType>();
26
+ const authController = useAuthController<USER, AuthControllerType>();
27
27
  const sideDialogsController = useSideDialogsController();
28
28
  const sideEntityController = useSideEntityController();
29
29
  const navigation = useNavigationController();
@@ -35,7 +35,7 @@ export const useFireCMSContext = <UserType extends User = User, AuthControllerTy
35
35
  const customizationController = useCustomizationController();
36
36
  const analyticsController = useAnalyticsController();
37
37
 
38
- const fireCMSContextRef = React.useRef<FireCMSContext<UserType, AuthControllerType>>({
38
+ const fireCMSContextRef = React.useRef<FireCMSContext<USER, AuthControllerType>>({
39
39
  authController,
40
40
  sideDialogsController,
41
41
  sideEntityController,
@@ -68,9 +68,9 @@ export const useFireCMSContext = <UserType extends User = User, AuthControllerTy
68
68
  return fireCMSContextRef.current;
69
69
  }
70
70
 
71
- // export const useFireCMSContext = <UserType extends User = User, AuthControllerType extends AuthController<UserType> = AuthController<UserType>>(): FireCMSContext<UserType, AuthControllerType> => {
71
+ // export const useFireCMSContext = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): FireCMSContext<USER, AuthControllerType> => {
72
72
  //
73
- // const authController = useAuthController<UserType, AuthControllerType>();
73
+ // const authController = useAuthController<USER, AuthControllerType>();
74
74
  // const sideDialogsController = useSideDialogsController();
75
75
  // const sideEntityController = useSideEntityController();
76
76
  // const navigation = useNavigationController();
@@ -63,38 +63,3 @@ function checkLargeLayout(breakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" |
63
63
  return false;
64
64
  return window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
65
65
  }
66
-
67
- // import { useEffect, useState } from "react";
68
- //
69
- // const breakpoints = {
70
- // xs: 0,
71
- // sm: 640,
72
- // md: 768,
73
- // lg: 1024,
74
- // xl: 1280,
75
- // "2xl": 1536,
76
- // "3xl": 1920
77
- // }
78
- // export const useLargeLayout = (breakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" = "lg"): boolean => {
79
- // const [isLargeLayout, setIsLargeLayout] = useState<boolean>(false);
80
- //
81
- // useEffect(() => {
82
- // const handleResize = () => {
83
- // const matched = window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
84
- // setIsLargeLayout(matched);
85
- // };
86
- //
87
- // // Set initial state
88
- // handleResize();
89
- //
90
- // // Set up event listener for resize events
91
- // window.addEventListener("resize", handleResize);
92
- //
93
- // // Clean up event listener when component unmounts
94
- // return () => {
95
- // window.removeEventListener("resize", handleResize);
96
- // };
97
- // }, []);
98
- //
99
- // return isLargeLayout;
100
- // };