@firecms/core 3.0.0-canary.29 → 3.0.0-canary.292

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 (433) 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 +34 -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 +31 -12
  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 +14 -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 +20 -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/EntityJsonPreview.d.ts +3 -0
  25. package/dist/components/EntityPreview.d.ts +10 -7
  26. package/dist/components/ErrorView.d.ts +1 -1
  27. package/dist/components/HomePage/DefaultHomePage.d.ts +2 -15
  28. package/dist/components/HomePage/HomePageDnD.d.ts +77 -0
  29. package/dist/components/HomePage/NavigationCard.d.ts +3 -1
  30. package/dist/components/HomePage/NavigationCardBinding.d.ts +4 -3
  31. package/dist/components/HomePage/NavigationGroup.d.ts +8 -1
  32. package/dist/components/HomePage/RenameGroupDialog.d.ts +9 -0
  33. package/dist/components/PropertyCollectionView.d.ts +23 -0
  34. package/dist/components/PropertyConfigBadge.d.ts +2 -1
  35. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  36. package/dist/components/ReferenceWidget.d.ts +3 -1
  37. package/dist/components/SelectableTable/SelectableTable.d.ts +14 -4
  38. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  39. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  40. package/dist/components/UserDisplay.d.ts +7 -0
  41. package/dist/components/VirtualTable/VirtualTableProps.d.ts +24 -12
  42. package/dist/components/VirtualTable/fields/VirtualTableUserSelect.d.ts +12 -0
  43. package/dist/components/VirtualTable/types.d.ts +3 -3
  44. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -3
  45. package/dist/components/common/index.d.ts +2 -1
  46. package/dist/components/common/table_height.d.ts +5 -0
  47. package/dist/components/common/types.d.ts +4 -6
  48. package/dist/components/common/useColumnsIds.d.ts +3 -1
  49. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +13 -2
  50. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  51. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  52. package/dist/components/index.d.ts +5 -2
  53. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  54. package/dist/contexts/InternalUserManagementContext.d.ts +3 -0
  55. package/dist/core/DefaultAppBar.d.ts +29 -0
  56. package/dist/core/DefaultDrawer.d.ts +19 -0
  57. package/dist/core/DrawerNavigationItem.d.ts +10 -0
  58. package/dist/core/EntityEditView.d.ts +49 -11
  59. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  60. package/dist/core/FireCMS.d.ts +2 -3
  61. package/dist/core/FireCMSRouter.d.ts +4 -0
  62. package/dist/core/NavigationRoutes.d.ts +2 -3
  63. package/dist/core/SideDialogs.d.ts +4 -2
  64. package/dist/core/field_configs.d.ts +1 -1
  65. package/dist/core/index.d.ts +4 -4
  66. package/dist/form/EntityForm.d.ts +40 -64
  67. package/dist/form/EntityFormActions.d.ts +21 -0
  68. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  69. package/dist/form/components/ErrorFocus.d.ts +1 -1
  70. package/dist/form/components/FieldHelperText.d.ts +3 -3
  71. package/dist/form/components/FormEntry.d.ts +6 -0
  72. package/dist/form/components/FormLayout.d.ts +5 -0
  73. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  74. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  75. package/dist/form/components/LocalChangesMenu.d.ts +11 -0
  76. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  77. package/dist/form/components/index.d.ts +3 -1
  78. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  79. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  80. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  81. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  82. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  83. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  84. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  85. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  86. package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +9 -0
  87. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  88. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  89. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  90. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +5 -13
  91. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  92. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  93. package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +12 -0
  94. package/dist/form/index.d.ts +18 -18
  95. package/dist/form/useClearRestoreValue.d.ts +2 -2
  96. package/dist/hooks/data/delete.d.ts +4 -4
  97. package/dist/hooks/data/save.d.ts +4 -5
  98. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  99. package/dist/hooks/data/useEntityFetch.d.ts +4 -3
  100. package/dist/hooks/index.d.ts +3 -0
  101. package/dist/hooks/useAuthController.d.ts +1 -1
  102. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  103. package/dist/hooks/useBuildNavigationController.d.ts +57 -13
  104. package/dist/hooks/useCollapsedGroups.d.ts +9 -0
  105. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  106. package/dist/hooks/useInternalUserManagementController.d.ts +12 -0
  107. package/dist/hooks/useModeController.d.ts +1 -2
  108. package/dist/hooks/useProjectLog.d.ts +8 -2
  109. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  110. package/dist/hooks/useValidateAuthenticator.d.ts +4 -8
  111. package/dist/index.d.ts +1 -0
  112. package/dist/index.es.js +24546 -13965
  113. package/dist/index.es.js.map +1 -1
  114. package/dist/index.umd.js +27256 -588
  115. package/dist/index.umd.js.map +1 -1
  116. package/dist/internal/useBuildDataSource.d.ts +3 -17
  117. package/dist/internal/useBuildSideEntityController.d.ts +3 -3
  118. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  119. package/dist/preview/PropertyPreviewProps.d.ts +6 -1
  120. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  121. package/dist/preview/components/ReferencePreview.d.ts +4 -3
  122. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  123. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  124. package/dist/preview/components/UserPreview.d.ts +8 -0
  125. package/dist/preview/index.d.ts +1 -0
  126. package/dist/preview/util.d.ts +3 -3
  127. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  128. package/dist/routes/FireCMSRoute.d.ts +1 -0
  129. package/dist/routes/HomePageRoute.d.ts +3 -0
  130. package/dist/types/analytics.d.ts +1 -1
  131. package/dist/types/auth.d.ts +8 -10
  132. package/dist/types/collections.d.ts +123 -25
  133. package/dist/types/customization_controller.d.ts +8 -0
  134. package/dist/types/datasource.d.ts +52 -36
  135. package/dist/types/dialogs_controller.d.ts +7 -3
  136. package/dist/types/entities.d.ts +12 -3
  137. package/dist/types/entity_actions.d.ts +72 -8
  138. package/dist/types/entity_callbacks.d.ts +16 -16
  139. package/dist/types/entity_overrides.d.ts +2 -2
  140. package/dist/types/export_import.d.ts +4 -4
  141. package/dist/types/fields.d.ts +79 -39
  142. package/dist/types/firecms.d.ts +31 -3
  143. package/dist/types/firecms_context.d.ts +17 -1
  144. package/dist/types/index.d.ts +1 -1
  145. package/dist/types/internal_user_management.d.ts +20 -0
  146. package/dist/types/navigation.d.ts +62 -19
  147. package/dist/types/permissions.d.ts +4 -4
  148. package/dist/types/plugins.d.ts +58 -13
  149. package/dist/types/properties.d.ts +122 -31
  150. package/dist/types/property_config.d.ts +1 -3
  151. package/dist/types/roles.d.ts +3 -0
  152. package/dist/types/side_dialogs_controller.d.ts +10 -0
  153. package/dist/types/side_entity_controller.d.ts +14 -1
  154. package/dist/types/storage.d.ts +75 -0
  155. package/dist/types/user.d.ts +2 -1
  156. package/dist/util/builders.d.ts +3 -3
  157. package/dist/util/callbacks.d.ts +2 -0
  158. package/dist/util/collections.d.ts +1 -0
  159. package/dist/util/createFormexStub.d.ts +2 -0
  160. package/dist/util/entities.d.ts +3 -3
  161. package/dist/util/entity_actions.d.ts +2 -0
  162. package/dist/util/entity_cache.d.ts +28 -0
  163. package/dist/util/icon_list.d.ts +5 -1
  164. package/dist/util/icon_synonyms.d.ts +1 -98
  165. package/dist/util/icons.d.ts +7 -4
  166. package/dist/util/index.d.ts +3 -0
  167. package/dist/util/make_properties_editable.d.ts +1 -2
  168. package/dist/util/navigation_from_path.d.ts +10 -1
  169. package/dist/util/navigation_utils.d.ts +15 -3
  170. package/dist/util/objects.d.ts +3 -1
  171. package/dist/util/permissions.d.ts +4 -4
  172. package/dist/util/plurals.d.ts +0 -2
  173. package/dist/util/property_utils.d.ts +4 -4
  174. package/dist/util/references.d.ts +2 -2
  175. package/dist/util/resolutions.d.ts +42 -17
  176. package/dist/util/storage.d.ts +23 -2
  177. package/dist/util/useStorageUploadController.d.ts +4 -3
  178. package/package.json +70 -53
  179. package/src/app/AppBar.tsx +18 -0
  180. package/src/app/Drawer.tsx +24 -0
  181. package/src/app/Scaffold.tsx +253 -0
  182. package/src/app/index.ts +4 -0
  183. package/src/app/useApp.tsx +32 -0
  184. package/src/components/ArrayContainer.tsx +447 -229
  185. package/src/components/CircularProgressCenter.tsx +2 -2
  186. package/src/components/ClearFilterSortButton.tsx +41 -0
  187. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +12 -11
  188. package/src/components/DeleteEntityDialog.tsx +13 -20
  189. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +87 -62
  190. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +38 -31
  191. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +30 -9
  192. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +84 -42
  193. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  194. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +30 -16
  195. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +19 -17
  196. package/src/components/EntityCollectionTable/index.tsx +1 -1
  197. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +34 -39
  198. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +49 -36
  199. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
  200. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +135 -105
  201. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +9 -9
  202. package/src/components/EntityCollectionView/EntityCollectionView.tsx +241 -119
  203. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +7 -4
  204. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  205. package/src/components/EntityCollectionView/useSelectionController.tsx +20 -7
  206. package/src/components/EntityCollectionView/utils.ts +19 -0
  207. package/src/components/EntityJsonPreview.tsx +66 -0
  208. package/src/components/EntityPreview.tsx +83 -62
  209. package/src/components/EntityView.tsx +34 -42
  210. package/src/components/ErrorView.tsx +4 -4
  211. package/src/components/FireCMSLogo.tsx +7 -51
  212. package/src/components/HomePage/DefaultHomePage.tsx +516 -158
  213. package/src/components/HomePage/FavouritesView.tsx +9 -14
  214. package/src/components/HomePage/HomePageDnD.tsx +702 -0
  215. package/src/components/HomePage/NavigationCard.tsx +48 -39
  216. package/src/components/HomePage/NavigationCardBinding.tsx +17 -16
  217. package/src/components/HomePage/NavigationGroup.tsx +144 -30
  218. package/src/components/HomePage/RenameGroupDialog.tsx +123 -0
  219. package/src/components/HomePage/SmallNavigationCard.tsx +5 -6
  220. package/src/components/NotFoundPage.tsx +2 -2
  221. package/src/components/PropertyCollectionView.tsx +329 -0
  222. package/src/components/PropertyConfigBadge.tsx +10 -4
  223. package/src/components/PropertyIdCopyTooltip.tsx +47 -0
  224. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +23 -13
  225. package/src/components/ReferenceWidget.tsx +21 -11
  226. package/src/components/SearchIconsView.tsx +10 -7
  227. package/src/components/SelectableTable/SelectableTable.tsx +157 -157
  228. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  229. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +27 -9
  230. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +36 -12
  231. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +92 -24
  232. package/src/components/UnsavedChangesDialog.tsx +46 -0
  233. package/src/components/UserDisplay.tsx +55 -0
  234. package/src/components/VirtualTable/VirtualTable.tsx +105 -51
  235. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  236. package/src/components/VirtualTable/VirtualTableHeader.tsx +10 -10
  237. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  238. package/src/components/VirtualTable/VirtualTableProps.tsx +28 -14
  239. package/src/components/VirtualTable/VirtualTableRow.tsx +5 -6
  240. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +5 -5
  241. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -2
  242. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  243. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
  244. package/src/components/VirtualTable/fields/VirtualTableUserSelect.tsx +99 -0
  245. package/src/components/VirtualTable/types.tsx +2 -3
  246. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +64 -44
  247. package/src/components/common/index.ts +2 -1
  248. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  249. package/src/components/common/types.tsx +4 -6
  250. package/src/components/common/useColumnsIds.tsx +16 -2
  251. package/src/components/common/useDataSourceTableController.tsx +420 -0
  252. package/src/components/common/useDebouncedCallback.tsx +20 -0
  253. package/src/components/common/useScrollRestoration.tsx +68 -0
  254. package/src/components/common/useTableSearchHelper.ts +53 -12
  255. package/src/components/index.tsx +6 -2
  256. package/src/contexts/BreacrumbsContext.tsx +38 -0
  257. package/src/contexts/DialogsProvider.tsx +5 -4
  258. package/src/contexts/InternalUserManagementContext.tsx +4 -0
  259. package/src/contexts/ModeController.tsx +1 -3
  260. package/src/contexts/SnackbarProvider.tsx +2 -0
  261. package/src/core/DefaultAppBar.tsx +219 -0
  262. package/src/core/DefaultDrawer.tsx +185 -0
  263. package/src/core/DrawerNavigationItem.tsx +66 -0
  264. package/src/core/EntityEditView.tsx +447 -469
  265. package/src/core/EntityEditViewFormActions.tsx +344 -0
  266. package/src/core/EntitySidePanel.tsx +96 -23
  267. package/src/core/FireCMS.tsx +85 -60
  268. package/src/core/FireCMSRouter.tsx +17 -0
  269. package/src/core/NavigationRoutes.tsx +28 -38
  270. package/src/core/SideDialogs.tsx +22 -12
  271. package/src/core/field_configs.tsx +41 -14
  272. package/src/core/index.tsx +6 -5
  273. package/src/form/EntityForm.tsx +740 -523
  274. package/src/form/EntityFormActions.tsx +226 -0
  275. package/src/form/PropertyFieldBinding.tsx +88 -41
  276. package/src/form/components/CustomIdField.tsx +9 -3
  277. package/src/form/components/ErrorFocus.tsx +22 -29
  278. package/src/form/components/FieldHelperText.tsx +4 -4
  279. package/src/form/components/FormEntry.tsx +22 -0
  280. package/src/form/components/FormLayout.tsx +16 -0
  281. package/src/form/components/LabelWithIcon.tsx +30 -19
  282. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  283. package/src/form/components/LocalChangesMenu.tsx +144 -0
  284. package/src/form/components/StorageItemPreview.tsx +23 -13
  285. package/src/form/components/StorageUploadProgress.tsx +5 -6
  286. package/src/form/components/index.tsx +3 -1
  287. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +34 -19
  288. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +50 -36
  289. package/src/form/field_bindings/BlockFieldBinding.tsx +56 -33
  290. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -14
  291. package/src/form/field_bindings/KeyValueFieldBinding.tsx +61 -52
  292. package/src/form/field_bindings/MapFieldBinding.tsx +73 -55
  293. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +159 -0
  294. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +26 -21
  295. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +11 -16
  296. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +135 -0
  297. package/src/form/field_bindings/ReferenceFieldBinding.tsx +42 -31
  298. package/src/form/field_bindings/RepeatFieldBinding.tsx +62 -35
  299. package/src/form/field_bindings/SelectFieldBinding.tsx +24 -15
  300. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +257 -199
  301. package/src/form/field_bindings/SwitchFieldBinding.tsx +29 -24
  302. package/src/form/field_bindings/TextFieldBinding.tsx +28 -24
  303. package/src/form/field_bindings/UserSelectFieldBinding.tsx +94 -0
  304. package/src/form/index.tsx +21 -37
  305. package/src/form/useClearRestoreValue.tsx +2 -2
  306. package/src/form/validation.ts +13 -23
  307. package/src/hooks/data/delete.ts +6 -5
  308. package/src/hooks/data/save.ts +26 -33
  309. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  310. package/src/hooks/data/useDataSource.tsx +11 -3
  311. package/src/hooks/data/useEntityFetch.tsx +10 -6
  312. package/src/hooks/index.tsx +4 -0
  313. package/src/hooks/useAuthController.tsx +1 -1
  314. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  315. package/src/hooks/useBrowserTitleAndIcon.tsx +1 -1
  316. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  317. package/src/hooks/useBuildModeController.tsx +22 -29
  318. package/src/hooks/useBuildNavigationController.tsx +515 -121
  319. package/src/hooks/useCollapsedGroups.ts +64 -0
  320. package/src/hooks/useFireCMSContext.tsx +9 -35
  321. package/src/hooks/useInternalUserManagementController.tsx +16 -0
  322. package/src/hooks/useLargeLayout.tsx +0 -35
  323. package/src/hooks/useModeController.tsx +1 -2
  324. package/src/hooks/useProjectLog.tsx +32 -10
  325. package/src/hooks/useResolvedNavigationFrom.tsx +10 -12
  326. package/src/hooks/useValidateAuthenticator.tsx +17 -37
  327. package/src/index.ts +1 -0
  328. package/src/internal/useBuildDataSource.ts +79 -85
  329. package/src/internal/useBuildSideDialogsController.tsx +4 -2
  330. package/src/internal/useBuildSideEntityController.tsx +204 -77
  331. package/src/internal/useUnsavedChangesDialog.tsx +127 -91
  332. package/src/preview/PropertyPreview.tsx +42 -25
  333. package/src/preview/PropertyPreviewProps.tsx +7 -1
  334. package/src/preview/components/BooleanPreview.tsx +2 -2
  335. package/src/preview/components/EmptyValue.tsx +1 -1
  336. package/src/preview/components/EnumValuesChip.tsx +2 -2
  337. package/src/preview/components/ImagePreview.tsx +26 -37
  338. package/src/preview/components/ReferencePreview.tsx +30 -38
  339. package/src/preview/components/StorageThumbnail.tsx +5 -1
  340. package/src/preview/components/UrlComponentPreview.tsx +60 -28
  341. package/src/preview/components/UserPreview.tsx +27 -0
  342. package/src/preview/index.ts +1 -0
  343. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +6 -6
  344. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +7 -5
  345. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +5 -4
  346. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -4
  347. package/src/preview/property_previews/ArrayOneOfPreview.tsx +7 -6
  348. package/src/preview/property_previews/ArrayPropertyPreview.tsx +8 -7
  349. package/src/preview/property_previews/MapPropertyPreview.tsx +14 -13
  350. package/src/preview/property_previews/NumberPropertyPreview.tsx +2 -2
  351. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +13 -13
  352. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  353. package/src/preview/util.ts +10 -10
  354. package/src/routes/CustomCMSRoute.tsx +21 -0
  355. package/src/routes/FireCMSRoute.tsx +246 -0
  356. package/src/routes/HomePageRoute.tsx +17 -0
  357. package/src/types/analytics.ts +3 -0
  358. package/src/types/auth.tsx +9 -13
  359. package/src/types/collections.ts +146 -30
  360. package/src/types/customization_controller.tsx +9 -1
  361. package/src/types/datasource.ts +61 -43
  362. package/src/types/dialogs_controller.tsx +7 -3
  363. package/src/types/entities.ts +19 -3
  364. package/src/types/entity_actions.tsx +86 -10
  365. package/src/types/entity_callbacks.ts +18 -18
  366. package/src/types/entity_overrides.tsx +2 -2
  367. package/src/types/export_import.ts +4 -4
  368. package/src/types/fields.tsx +91 -42
  369. package/src/types/firecms.tsx +34 -4
  370. package/src/types/firecms_context.tsx +18 -1
  371. package/src/types/index.ts +1 -1
  372. package/src/types/internal_user_management.ts +24 -0
  373. package/src/types/navigation.ts +77 -24
  374. package/src/types/permissions.ts +5 -5
  375. package/src/types/plugins.tsx +69 -15
  376. package/src/types/properties.ts +141 -33
  377. package/src/types/property_config.tsx +2 -2
  378. package/src/types/roles.ts +3 -0
  379. package/src/types/side_dialogs_controller.tsx +15 -0
  380. package/src/types/side_entity_controller.tsx +16 -1
  381. package/src/types/storage.ts +83 -1
  382. package/src/types/user.ts +3 -1
  383. package/src/util/builders.ts +10 -8
  384. package/src/util/callbacks.ts +119 -0
  385. package/src/util/collections.ts +8 -0
  386. package/src/util/createFormexStub.tsx +66 -0
  387. package/src/util/entities.ts +11 -8
  388. package/src/util/entity_actions.ts +28 -0
  389. package/src/util/entity_cache.ts +223 -0
  390. package/src/util/enums.ts +1 -1
  391. package/src/util/icon_list.ts +16 -10
  392. package/src/util/icon_synonyms.ts +3 -100
  393. package/src/util/icons.tsx +36 -11
  394. package/src/util/index.ts +3 -0
  395. package/src/util/join_collections.ts +11 -4
  396. package/src/util/make_properties_editable.ts +5 -19
  397. package/src/util/navigation_from_path.ts +33 -12
  398. package/src/util/navigation_utils.ts +141 -25
  399. package/src/util/objects.ts +128 -33
  400. package/src/util/parent_references_from_path.ts +3 -3
  401. package/src/util/permissions.ts +9 -8
  402. package/src/util/plurals.ts +0 -2
  403. package/src/util/property_utils.tsx +17 -6
  404. package/src/util/references.ts +19 -8
  405. package/src/util/resolutions.ts +122 -48
  406. package/src/util/storage.ts +79 -21
  407. package/src/util/strings.ts +2 -2
  408. package/src/util/useStorageUploadController.tsx +162 -62
  409. package/dist/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.d.ts +0 -5
  410. package/dist/components/FireCMSAppBar.d.ts +0 -26
  411. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  412. package/dist/components/VirtualTable/common.d.ts +0 -2
  413. package/dist/core/Drawer.d.ts +0 -23
  414. package/dist/core/Scaffold.d.ts +0 -55
  415. package/dist/core/SideEntityView.d.ts +0 -7
  416. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  417. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  418. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  419. package/dist/internal/useLocaleConfig.d.ts +0 -1
  420. package/dist/types/appcheck.d.ts +0 -26
  421. package/src/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.tsx +0 -59
  422. package/src/components/FireCMSAppBar.tsx +0 -165
  423. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
  424. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -225
  425. package/src/core/Drawer.tsx +0 -191
  426. package/src/core/Scaffold.tsx +0 -281
  427. package/src/core/SideEntityView.tsx +0 -38
  428. package/src/form/components/FormikArrayContainer.tsx +0 -44
  429. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  430. package/src/internal/useBuildCustomizationController.tsx +0 -5
  431. package/src/internal/useLocaleConfig.tsx +0 -18
  432. package/src/types/appcheck.ts +0 -29
  433. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -3,12 +3,13 @@ import { EntityCollection, ResolvedEntityCollection, ResolvedProperty } from "..
3
3
  import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
4
4
  import { PropertyColumnConfig } from "../EntityCollectionTable/EntityCollectionTableProps";
5
5
 
6
- const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
6
+ export const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
7
7
 
8
8
  export function useColumnIds<M extends Record<string, any>>(collection: ResolvedEntityCollection<M>, includeSubcollections: boolean): PropertyColumnConfig[] {
9
9
  return useMemo(() => {
10
- if (collection.propertiesOrder)
10
+ if (collection.propertiesOrder) {
11
11
  return hideAndExpandKeys(collection, collection.propertiesOrder);
12
+ }
12
13
  return getDefaultColumnKeys(collection, includeSubcollections);
13
14
  }, [collection, includeSubcollections]);
14
15
  }
@@ -98,3 +99,16 @@ export function getColumnKeysForProperty(property: ResolvedProperty, key: string
98
99
  disabled: disabled || Boolean(property.disabled) || Boolean(property.readOnly)
99
100
  }];
100
101
  }
102
+
103
+ export function getFormFieldKeys(collection: EntityCollection): string[] {
104
+ const propertyKeys = Object.keys(collection.properties);
105
+ const additionalFields = collection.additionalFields ?? [];
106
+ const allKeys = [
107
+ ...propertyKeys,
108
+ ...additionalFields.map((field) => field.key)
109
+ ];
110
+ if (collection.propertiesOrder) {
111
+ return collection.propertiesOrder.filter(key => allKeys.includes(key));
112
+ }
113
+ return allKeys;
114
+ }
@@ -0,0 +1,420 @@
1
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
2
+
3
+ import { useDataSource, useFireCMSContext, useNavigationController } from "../../hooks";
4
+ import { useDataOrder } from "../../hooks/data/useDataOrder";
5
+ import {
6
+ Entity,
7
+ EntityCollection,
8
+ EntityReference,
9
+ EntityTableController,
10
+ FilterValues,
11
+ FireCMSContext,
12
+ SelectedCellProps,
13
+ User,
14
+ WhereFilterOp
15
+ } from "../../types";
16
+ import { useDebouncedData } from "./useDebouncedData";
17
+ import { ScrollRestorationController } from "./useScrollRestoration";
18
+
19
+ const DEFAULT_PAGE_SIZE = 50;
20
+
21
+ export type DataSourceTableControllerProps<M extends Record<string, any> = any> = {
22
+ /**
23
+ * Full path where the data of this table is located
24
+ */
25
+ fullPath: string;
26
+ /**
27
+ * The collection that is represented by this config.
28
+ */
29
+ collection: EntityCollection<M>;
30
+ /**
31
+ * List of entities that will be displayed on top, no matter the ordering.
32
+ * This is used for reference fields selection
33
+ */
34
+ entitiesDisplayedFirst?: Entity<M>[];
35
+
36
+ lastDeleteTimestamp?: number;
37
+
38
+ /**
39
+ * Force filter to be applied to the table.
40
+ */
41
+ forceFilter?: FilterValues<string>;
42
+
43
+ scrollRestoration?: ScrollRestorationController;
44
+
45
+ /**
46
+ * When set to true the filters and sort will be updated in the URL
47
+ */
48
+ updateUrl?: boolean;
49
+
50
+ }
51
+
52
+ /**
53
+ * Use this hook to build a controller for the {@link EntityCollectionTable}.
54
+ * This controller is bound to data in a path in your specified datasource.
55
+ *
56
+ * Note that you can build your own hook returning a {@link EntityTableController}
57
+ * if you would like to display different data.
58
+ *
59
+ * @param fullPath
60
+ * @param collection
61
+ * @param scrollRestoration
62
+ * @param entitiesDisplayedFirst
63
+ * @param lastDeleteTimestamp
64
+ * @param forceFilterFromProps
65
+ * @param updateUrl
66
+ */
67
+ export function useDataSourceTableController<M extends Record<string, any> = any, USER extends User = User>(
68
+ {
69
+ fullPath,
70
+ collection,
71
+ scrollRestoration,
72
+ entitiesDisplayedFirst,
73
+ lastDeleteTimestamp,
74
+ forceFilter: forceFilterFromProps,
75
+ updateUrl
76
+ }: DataSourceTableControllerProps<M>)
77
+ : EntityTableController<M> {
78
+
79
+ const {
80
+ initialFilter,
81
+ initialSort,
82
+ forceFilter: forceFilterFromCollection
83
+ } = collection;
84
+
85
+ const [popupCell, setPopupCell] = React.useState<SelectedCellProps<M> | undefined>(undefined);
86
+ const navigation = useNavigationController();
87
+ const dataSource = useDataSource(collection);
88
+ const resolvedPath = useMemo(() => navigation.resolveIdsFrom(fullPath), [fullPath, navigation.resolveIdsFrom]);
89
+
90
+ const forceFilter = forceFilterFromProps ?? forceFilterFromCollection;
91
+ const paginationEnabled = collection.pagination === undefined || Boolean(collection.pagination);
92
+ const pageSize = typeof collection.pagination === "number" ? collection.pagination : DEFAULT_PAGE_SIZE;
93
+
94
+ const [searchString, setSearchString] = React.useState<string | undefined>();
95
+
96
+ const checkFilterCombination = useCallback((filterValues: FilterValues<any>,
97
+ sortBy?: [string, "asc" | "desc"]) => {
98
+ if (!dataSource.isFilterCombinationValid)
99
+ return true;
100
+ return dataSource.isFilterCombinationValid({
101
+ path: resolvedPath,
102
+ collection,
103
+ filterValues,
104
+ sortBy
105
+ })
106
+ }, []);
107
+
108
+ const onScroll = ({
109
+ scrollOffset
110
+ }: {
111
+ scrollOffset: number
112
+ }) => {
113
+ if (scrollRestoration) {
114
+ scrollRestoration.updateCollectionScroll({
115
+ fullPath: resolvedPath,
116
+ scrollOffset,
117
+ data: rawData,
118
+ filters: filterValues
119
+ });
120
+ }
121
+ }
122
+
123
+ const initialSortInternal = useMemo(() => {
124
+ if (initialSort && forceFilter && !checkFilterCombination(forceFilter, initialSort)) {
125
+ console.warn("Initial sort is not compatible with the force filter. Ignoring initial sort");
126
+ return undefined;
127
+ }
128
+ return initialSort;
129
+ }, [initialSort, forceFilter]);
130
+
131
+ const {
132
+ filterValues: initialFilterUrl,
133
+ sortBy: initialSortUrl,
134
+ } = parseFilterAndSort(window.location.search);
135
+
136
+ const [filterValues, setFilterValues] = React.useState<FilterValues<Extract<keyof M, string>> | undefined>(forceFilter ?? (updateUrl ? initialFilterUrl : undefined) ?? initialFilter ?? undefined);
137
+ const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>((updateUrl ? initialSortUrl : undefined) ?? initialSortInternal);
138
+
139
+ useUpdateUrl(filterValues, sortBy, searchString, updateUrl);
140
+
141
+ const collectionScroll = scrollRestoration?.getCollectionScroll(fullPath, filterValues);
142
+ const initialItemCount = collectionScroll?.data.length ?? pageSize;
143
+
144
+ useEffect(() => {
145
+ if (scrollRestoration) {
146
+ scrollRestoration.updateCollectionScroll({
147
+ fullPath: resolvedPath,
148
+ scrollOffset: collectionScroll?.scrollOffset ?? 0,
149
+ data: rawData,
150
+ filters: filterValues
151
+ });
152
+ }
153
+ }, []);
154
+
155
+ const [itemCount, setItemCount] = React.useState<number | undefined>(paginationEnabled ? initialItemCount : undefined);
156
+
157
+ const sortByProperty = sortBy ? sortBy[0] : undefined;
158
+ const currentSort = sortBy ? sortBy[1] : undefined;
159
+
160
+ const context: FireCMSContext<USER> = useFireCMSContext();
161
+
162
+ const [rawData, setRawData] = useState<Entity<M>[]>(collectionScroll?.data ?? []);
163
+
164
+ const [dataLoading, setDataLoading] = useState<boolean>(false);
165
+ const [dataLoadingError, setDataLoadingError] = useState<Error | undefined>();
166
+ const [noMoreToLoad, setNoMoreToLoad] = useState<boolean>(false);
167
+
168
+ const clearFilter = useCallback(() => setFilterValues(forceFilter ?? undefined), [forceFilter]);
169
+
170
+ const updateFilterValues = useCallback((updatedFilter: FilterValues<Extract<keyof M, string>> | undefined) => {
171
+ if (forceFilter) {
172
+ console.warn("Filter is not compatible with the force filter. Ignoring filter");
173
+ return;
174
+ }
175
+ if (updatedFilter && Object.keys(updatedFilter).length === 0) {
176
+ setFilterValues(undefined);
177
+ } else {
178
+ setFilterValues(updatedFilter);
179
+ }
180
+ }, [forceFilter]);
181
+
182
+ useEffect(() => {
183
+
184
+ setDataLoading(true);
185
+
186
+ const onEntitiesUpdate = async (entities: Entity<M>[]) => {
187
+ if (collection.callbacks?.onFetch) {
188
+ try {
189
+ entities = await Promise.all(
190
+ entities.map((entity) =>
191
+ collection.callbacks!.onFetch!({
192
+ collection,
193
+ path: resolvedPath,
194
+ entity,
195
+ context
196
+ })));
197
+ } catch (e: any) {
198
+ console.error(e);
199
+ }
200
+ }
201
+ setDataLoading(false);
202
+ setDataLoadingError(undefined);
203
+ setRawData(entities.map(e => ({
204
+ ...e,
205
+ // values: sanitizeData(e.values, resolvedCollection.properties)
206
+ })));
207
+ setNoMoreToLoad(!itemCount || entities.length < itemCount);
208
+ };
209
+
210
+ const onError = (error: Error) => {
211
+ console.error("ERROR", error);
212
+ setDataLoading(false);
213
+ setRawData([]);
214
+ setDataLoadingError(error);
215
+ };
216
+
217
+ if (dataSource.listenCollection) {
218
+ return dataSource.listenCollection<M>({
219
+ path: resolvedPath,
220
+ collection,
221
+ onUpdate: onEntitiesUpdate,
222
+ onError,
223
+ searchString,
224
+ filter: filterValues,
225
+ limit: itemCount,
226
+ startAfter: undefined,
227
+ orderBy: sortByProperty,
228
+ order: currentSort
229
+ });
230
+ } else {
231
+ dataSource.fetchCollection<M>({
232
+ path: resolvedPath,
233
+ collection,
234
+ searchString,
235
+ filter: filterValues,
236
+ limit: itemCount,
237
+ startAfter: undefined,
238
+ orderBy: sortByProperty,
239
+ order: currentSort
240
+ })
241
+ .then(onEntitiesUpdate)
242
+ .catch(onError);
243
+ return () => {
244
+ };
245
+ }
246
+ }, [resolvedPath, itemCount, currentSort, sortByProperty, filterValues, searchString]);
247
+
248
+ const orderedData = useDataOrder({
249
+ data: rawData,
250
+ entitiesDisplayedFirst
251
+ });
252
+
253
+ // hack to fix Firestore listeners firing with incomplete data
254
+ const data = useDebouncedData(orderedData, {
255
+ filterValues,
256
+ sortBy,
257
+ searchString,
258
+ lastDeleteTimestamp
259
+ });
260
+
261
+ return {
262
+ data,
263
+ dataLoading,
264
+ noMoreToLoad,
265
+ dataLoadingError,
266
+ filterValues,
267
+ setFilterValues: updateFilterValues,
268
+ sortBy,
269
+ setSortBy,
270
+ searchString,
271
+ setSearchString,
272
+ clearFilter,
273
+ itemCount,
274
+ setItemCount,
275
+ initialScroll: collectionScroll?.scrollOffset,
276
+ onScroll,
277
+ paginationEnabled,
278
+ pageSize,
279
+ checkFilterCombination,
280
+ popupCell,
281
+ setPopupCell
282
+ }
283
+ }
284
+
285
+ function useUpdateUrl<M extends Record<string, any> = any>(
286
+ filterValues: FilterValues<Extract<keyof M, string>> | undefined,
287
+ sortBy: [Extract<keyof M, string>, "asc" | "desc"] | undefined,
288
+ searchString: string | undefined,
289
+ updateUrl: boolean | undefined
290
+ ) {
291
+
292
+ useEffect(() => {
293
+ if (updateUrl) {
294
+ const newUrl = encodeFilterAndSort(filterValues, sortBy);
295
+ const search = searchString ? `&search=${encodeURIComponent(searchString)}` : "";
296
+ const state = `${newUrl}${search}`;
297
+ const hash = window.location.hash;
298
+ if (state === "")
299
+ window.history.replaceState({}, "", `${window.location.pathname}${hash}`);
300
+ else
301
+ window.history.replaceState({}, "", `?${state}${hash}`);
302
+ }
303
+ }, [filterValues, sortBy, searchString, updateUrl]);
304
+ }
305
+
306
+ function encodeFilterAndSort(filterValues?: FilterValues<string>, sortBy?: [string, "asc" | "desc"] | undefined) {
307
+ const entries: Record<string, string> = {};
308
+ if (sortBy) {
309
+ entries["__sort"] = encodeURIComponent(sortBy[0]);
310
+ entries["__sort_order"] = encodeURIComponent(sortBy[1]);
311
+ }
312
+ if (filterValues) {
313
+ Object.entries(filterValues).forEach(([key, value]) => {
314
+ if (value) {
315
+ const [op, val] = value;
316
+ let encodedValue: any = val;
317
+ try {
318
+ if (typeof val === "object") {
319
+ if (val instanceof Date) {
320
+ encodedValue = val.toISOString();
321
+ } else if (Array.isArray(val)) {
322
+ encodedValue = JSON.stringify(val, (key, value) => {
323
+ if (value instanceof EntityReference) {
324
+ return encodeRef(value);
325
+ }
326
+ return value;
327
+ });
328
+ } else if (val instanceof EntityReference) {
329
+ encodedValue = encodeRef(val);
330
+ }
331
+ }
332
+ } catch (e) {
333
+ encodedValue = val;
334
+ }
335
+ if (encodedValue !== undefined) {
336
+ entries[encodeURIComponent(`${key}_op`)] = encodeURIComponent(op);
337
+ entries[encodeURIComponent(`${key}_value`)] = encodedValue ? encodeURIComponent(encodedValue.toString()) : "null";
338
+ }
339
+ }
340
+ });
341
+ }
342
+ if (!Object.keys(entries).length) {
343
+ return "";
344
+ }
345
+ return Object.entries(entries).map(([key, value]) => `${key}=${value}`).join("&");
346
+ }
347
+
348
+ function parseFilterAndSort<M>(search: string): {
349
+ filterValues: FilterValues<string> | undefined,
350
+ sortBy?: [Extract<keyof M, string>, "asc" | "desc"]
351
+ } {
352
+ const entries = new URLSearchParams(search);
353
+ const filterValues: FilterValues<string> = {};
354
+ let sortBy: [string, "asc" | "desc"] | undefined = undefined;
355
+ entries.forEach((value, key) => {
356
+ if (key === "__sort") {
357
+ sortBy = [decodeURIComponent(value), entries.get("__sort_order") as "asc" | "desc"];
358
+ } else if (key.endsWith("_op")) {
359
+ const field = key.replace("_op", "");
360
+ const filterOp = decodeURIComponent(value) as WhereFilterOp;
361
+ const filterValStr = entries.get(`${field}_value`);
362
+ if (filterValStr !== null) {
363
+ filterValues[field] = [filterOp, decodeString(filterValStr)];
364
+ }
365
+ }
366
+ });
367
+
368
+ return {
369
+ filterValues: Object.keys(filterValues).length ? filterValues : undefined,
370
+ sortBy
371
+ }
372
+ }
373
+
374
+ function isDate(dateString: string): boolean {
375
+ // Define a regex pattern that matches the exact date format: 2025-01-07T23:00:00.000Z
376
+ const regexPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
377
+
378
+ // Test the dateString against the regex pattern
379
+ if (!regexPattern.test(dateString)) {
380
+ return false;
381
+ }
382
+
383
+ // If the regex matches, further validate if it is a valid UTC date
384
+ const date = new Date(dateString);
385
+ return date.toISOString() === dateString;
386
+ }
387
+
388
+ function encodeRef(val: EntityReference) {
389
+ return `ref::${val.path}/${val.id}`;
390
+ }
391
+
392
+ function decodeString(val: string): EntityReference | Date | string {
393
+ let parsedFilterVal: any = val;
394
+ if (isDate(val)) {
395
+ try {
396
+ parsedFilterVal = new Date(val);
397
+ } catch (e) {
398
+ // ignore
399
+ }
400
+ }
401
+ if (typeof parsedFilterVal === "string") {
402
+ try {
403
+ parsedFilterVal = JSON.parse(parsedFilterVal, (key, value) => {
404
+ if (typeof value === "string" && value.startsWith("ref::")) {
405
+ const [path, id] = value.substring(5).split("/");
406
+ return new EntityReference(id, path);
407
+ }
408
+ return value;
409
+ });
410
+ } catch (e) {
411
+ // ignore
412
+ }
413
+ }
414
+
415
+ if (typeof parsedFilterVal === "string" && parsedFilterVal.startsWith("ref::")) {
416
+ const [path, id] = parsedFilterVal.substring(5).split("/");
417
+ return new EntityReference(id, path);
418
+ }
419
+ return parsedFilterVal;
420
+ }
@@ -0,0 +1,20 @@
1
+ import { useCallback, useRef } from "react";
2
+
3
+ export function useDebounceCallback<T extends (...args: any[]) => any>(
4
+ callback?: T,
5
+ delay?: number
6
+ ): T {
7
+ const timeoutRef = useRef<number | null>(null);
8
+
9
+ const debouncedCallback = useCallback((...args: Parameters<T>) => {
10
+ if (timeoutRef.current !== null) {
11
+ clearTimeout(timeoutRef.current);
12
+ }
13
+
14
+ timeoutRef.current = window.setTimeout(() => {
15
+ callback?.(...args);
16
+ }, delay ?? 200);
17
+ }, [callback, delay]);
18
+
19
+ return debouncedCallback as T;
20
+ }
@@ -0,0 +1,68 @@
1
+ import { Entity, FilterValues } from "../../types";
2
+
3
+ const collectionScrollCache = new Map<string, { scrollOffset: number, data: Entity<any>[] }>();
4
+
5
+ export type ScrollRestorationController = {
6
+
7
+ getCollectionScroll: (fullPath: string,
8
+ filters?: FilterValues<any>) => {
9
+ scrollOffset: number,
10
+ data: Entity<any>[]
11
+ } | undefined;
12
+
13
+ updateCollectionScroll: (props: {
14
+ fullPath: string,
15
+ scrollOffset: number,
16
+ filters?: FilterValues<any>;
17
+ data: Entity<any>[]
18
+ }) => void;
19
+
20
+ }
21
+
22
+ export function useScrollRestoration(): ScrollRestorationController {
23
+
24
+ const updateCollectionScroll = ({
25
+ fullPath,
26
+ filters,
27
+ scrollOffset,
28
+ data
29
+ }: {
30
+ fullPath: string;
31
+ filters?: FilterValues<any>;
32
+ sort?: [string, "asc" | "desc"];
33
+ scrollOffset: number;
34
+ data: Entity<any>[]
35
+ }) => {
36
+ collectionScrollCache.set(
37
+ createCacheKey(fullPath, filters),
38
+ {
39
+ scrollOffset,
40
+ data
41
+ })
42
+ }
43
+
44
+ const getCollectionScroll = (fullPath: string,
45
+ filters?: FilterValues<any>) => {
46
+ return collectionScrollCache.get(createCacheKey(fullPath, filters));
47
+ }
48
+
49
+ return {
50
+ getCollectionScroll,
51
+ updateCollectionScroll
52
+ }
53
+ }
54
+
55
+ function createCacheKey(fullPath: string, filters?: FilterValues<any>) {
56
+
57
+ if (!filters) {
58
+ return fullPath;
59
+ }
60
+
61
+ // codify the filters into a url friendly string
62
+ const filtersString = filters ? Object.keys(filters).map(key => {
63
+ const value = JSON.stringify(filters[key]);
64
+ return `${key}=${value}`;
65
+ }).join("&") : "";
66
+
67
+ return `${fullPath}?${filtersString}`;
68
+ }
@@ -1,7 +1,7 @@
1
1
  import { useState } from "react";
2
2
 
3
3
  import { EntityCollection } from "../../types";
4
- import { useCustomizationController, useFireCMSContext } from "../../hooks";
4
+ import { useCustomizationController, useDataSource, useFireCMSContext } from "../../hooks";
5
5
 
6
6
  export interface UseTableSearchHelperParams<M extends Record<string, any>> {
7
7
  collection: EntityCollection<M>;
@@ -9,27 +9,58 @@ export interface UseTableSearchHelperParams<M extends Record<string, any>> {
9
9
  parentCollectionIds?: string[];
10
10
  }
11
11
 
12
- export function useTableSearchHelper<M extends Record<string, any>>({ collection, fullPath, parentCollectionIds }: UseTableSearchHelperParams<M>) {
12
+ export function useTableSearchHelper<M extends Record<string, any>>({
13
+ collection,
14
+ fullPath,
15
+ parentCollectionIds
16
+ }: UseTableSearchHelperParams<M>) {
13
17
 
14
18
  const context = useFireCMSContext();
15
19
  const customizationController = useCustomizationController();
20
+ const dataSource = useDataSource();
16
21
 
17
22
  const [textSearchLoading, setTextSearchLoading] = useState<boolean>(false);
18
23
  const [textSearchInitialised, setTextSearchInitialised] = useState<boolean>(false);
24
+
19
25
  let onTextSearchClick: (() => void) | undefined;
20
26
  let textSearchEnabled = Boolean(collection.textSearchEnabled);
21
- if (customizationController?.plugins) {
22
- const addTextSearchClickListener = customizationController.plugins?.find(p => Boolean(p.collectionView?.onTextSearchClick));
27
+
28
+ const props = {
29
+ context,
30
+ path: fullPath,
31
+ databaseId: collection.databaseId,
32
+ collection,
33
+ parentCollectionIds
34
+ };
35
+
36
+ const searchBlocked = customizationController.plugins?.find(p => {
37
+ return p.collectionView?.blockSearch?.(props);
38
+ });
39
+
40
+ const addTextSearchClickListener = Boolean(dataSource?.initTextSearch) || customizationController.plugins?.find(p => Boolean(p.collectionView?.onTextSearchClick));
41
+
42
+ if (addTextSearchClickListener) {
23
43
 
24
44
  onTextSearchClick = addTextSearchClickListener
25
45
  ? () => {
26
46
  setTextSearchLoading(true);
27
- Promise.all(customizationController.plugins?.map(p => {
28
- if (p.collectionView?.onTextSearchClick)
29
- return p.collectionView.onTextSearchClick({ context, path: fullPath, collection, parentCollectionIds });
30
- return Promise.resolve(true);
31
- }) as Promise<boolean>[])
32
- .then((res) => {
47
+ const promises: Promise<boolean>[] = [];
48
+ if (dataSource?.initTextSearch && !searchBlocked) {
49
+ promises.push(dataSource.initTextSearch(props));
50
+ }
51
+ if (searchBlocked) {
52
+ customizationController.plugins?.forEach(p => {
53
+ if (p.collectionView?.onTextSearchClick)
54
+ promises.push(p.collectionView.onTextSearchClick({
55
+ context,
56
+ path: fullPath,
57
+ collection,
58
+ parentCollectionIds
59
+ }));
60
+ })
61
+ }
62
+ return Promise.all(promises)
63
+ .then((res: boolean[]) => {
33
64
  if (res.every(Boolean)) setTextSearchInitialised(true);
34
65
  })
35
66
  .finally(() => setTextSearchLoading(false));
@@ -39,9 +70,19 @@ export function useTableSearchHelper<M extends Record<string, any>>({ collection
39
70
  customizationController.plugins?.forEach(p => {
40
71
  if (!textSearchEnabled)
41
72
  if (p.collectionView?.showTextSearchBar) {
42
- textSearchEnabled = p.collectionView.showTextSearchBar({ context, path: fullPath, collection, parentCollectionIds });
73
+ textSearchEnabled = p.collectionView.showTextSearchBar({
74
+ context,
75
+ path: fullPath,
76
+ collection,
77
+ parentCollectionIds
78
+ });
43
79
  }
44
80
  })
45
81
  }
46
- return { textSearchLoading, textSearchInitialised, onTextSearchClick, textSearchEnabled };
82
+ return {
83
+ textSearchLoading,
84
+ textSearchInitialised,
85
+ onTextSearchClick,
86
+ textSearchEnabled
87
+ };
47
88
  }
@@ -13,24 +13,28 @@ export * from "./common";
13
13
 
14
14
  export * from "./HomePage";
15
15
  export * from "./SelectableTable/SelectableTable";
16
+ export * from "./SelectableTable/SelectableTableContext";
16
17
  export * from "./EntityCollectionView/EntityCollectionView";
17
18
  export * from "./EntityCollectionView/EntityCollectionViewActions";
18
19
  export * from "./EntityCollectionView/useSelectionController";
19
20
 
20
21
  export * from "./PropertyConfigBadge";
22
+ export * from "./PropertyIdCopyTooltip";
21
23
 
22
24
  export * from "./EntityCollectionTable";
23
25
  export * from "./NotFoundPage";
24
26
 
25
27
  export * from "./VirtualTable";
26
28
  export * from "./ErrorBoundary";
27
- export * from "./DeleteConfirmationDialog";
29
+ export * from "./ConfirmationDialog";
28
30
 
29
31
  export * from "./FireCMSLogo";
30
32
 
31
- export * from "./FireCMSAppBar";
33
+ export * from "../core/DefaultAppBar";
32
34
 
33
35
  export * from "./ArrayContainer";
34
36
  export * from "./ReferenceWidget";
35
37
  export * from "./SearchIconsView";
36
38
  export * from "./FieldCaption";
39
+
40
+ export * from "./EntityPreview";