@firecms/core 3.0.0-canary.16 → 3.0.0-canary.161

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 (329) 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 +19 -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 +11 -12
  12. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  13. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +7 -5
  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/internal/CollectionTableToolbar.d.ts +1 -4
  18. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  19. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +7 -4
  20. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -2
  21. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  22. package/dist/components/EntityCollectionView/utils.d.ts +3 -0
  23. package/dist/components/EntityPreview.d.ts +7 -6
  24. package/dist/components/ErrorView.d.ts +1 -1
  25. package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
  26. package/dist/components/HomePage/NavigationCardBinding.d.ts +1 -1
  27. package/dist/components/PropertyConfigBadge.d.ts +2 -1
  28. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  29. package/dist/components/ReferenceWidget.d.ts +3 -1
  30. package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
  31. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  32. package/dist/components/VirtualTable/VirtualTableProps.d.ts +15 -12
  33. package/dist/components/VirtualTable/types.d.ts +3 -3
  34. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
  35. package/dist/components/common/index.d.ts +1 -0
  36. package/dist/components/common/table_height.d.ts +5 -0
  37. package/dist/components/common/types.d.ts +4 -6
  38. package/dist/components/common/useColumnsIds.d.ts +2 -1
  39. package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +4 -1
  40. package/dist/components/index.d.ts +4 -2
  41. package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +6 -9
  42. package/dist/core/DefaultDrawer.d.ts +19 -0
  43. package/dist/core/DrawerNavigationItem.d.ts +10 -0
  44. package/dist/core/EntityEditView.d.ts +18 -4
  45. package/dist/core/FireCMS.d.ts +2 -2
  46. package/dist/core/NavigationRoutes.d.ts +3 -3
  47. package/dist/core/index.d.ts +3 -4
  48. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  49. package/dist/form/components/ErrorFocus.d.ts +1 -1
  50. package/dist/form/components/FieldHelperText.d.ts +3 -3
  51. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  52. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  53. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  54. package/dist/form/components/index.d.ts +1 -1
  55. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  56. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  57. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  58. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  59. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  60. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  61. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  62. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  63. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  64. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  65. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  66. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -5
  67. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  68. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  69. package/dist/form/index.d.ts +3 -5
  70. package/dist/form/useClearRestoreValue.d.ts +2 -2
  71. package/dist/hooks/data/delete.d.ts +4 -4
  72. package/dist/hooks/data/save.d.ts +4 -5
  73. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  74. package/dist/hooks/data/useEntityFetch.d.ts +3 -3
  75. package/dist/hooks/index.d.ts +1 -0
  76. package/dist/hooks/useAuthController.d.ts +1 -1
  77. package/dist/hooks/useBuildNavigationController.d.ts +3 -4
  78. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  79. package/dist/hooks/useProjectLog.d.ts +8 -2
  80. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  81. package/dist/hooks/useValidateAuthenticator.d.ts +5 -9
  82. package/dist/index.d.ts +1 -0
  83. package/dist/index.es.js +20199 -14111
  84. package/dist/index.es.js.map +1 -1
  85. package/dist/index.umd.js +22769 -588
  86. package/dist/index.umd.js.map +1 -1
  87. package/dist/internal/useBuildDataSource.d.ts +1 -16
  88. package/dist/preview/PropertyPreviewProps.d.ts +6 -1
  89. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  90. package/dist/preview/components/ReferencePreview.d.ts +3 -2
  91. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  92. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  93. package/dist/preview/util.d.ts +3 -3
  94. package/dist/types/auth.d.ts +8 -10
  95. package/dist/types/collections.d.ts +53 -18
  96. package/dist/types/datasource.d.ts +51 -35
  97. package/dist/types/entities.d.ts +6 -1
  98. package/dist/types/entity_actions.d.ts +18 -4
  99. package/dist/types/entity_callbacks.d.ts +16 -16
  100. package/dist/types/entity_overrides.d.ts +2 -2
  101. package/dist/types/export_import.d.ts +4 -4
  102. package/dist/types/fields.d.ts +63 -41
  103. package/dist/types/firecms.d.ts +6 -2
  104. package/dist/types/firecms_context.d.ts +1 -1
  105. package/dist/types/index.d.ts +0 -1
  106. package/dist/types/navigation.d.ts +6 -5
  107. package/dist/types/permissions.d.ts +4 -4
  108. package/dist/types/plugins.d.ts +22 -12
  109. package/dist/types/properties.d.ts +34 -21
  110. package/dist/types/property_config.d.ts +0 -2
  111. package/dist/types/side_dialogs_controller.d.ts +10 -0
  112. package/dist/types/storage.d.ts +86 -3
  113. package/dist/types/user.d.ts +1 -0
  114. package/dist/util/builders.d.ts +2 -2
  115. package/dist/util/entities.d.ts +2 -2
  116. package/dist/util/icon_list.d.ts +5 -1
  117. package/dist/util/icon_synonyms.d.ts +1 -98
  118. package/dist/util/icons.d.ts +6 -3
  119. package/dist/util/index.d.ts +1 -0
  120. package/dist/util/navigation_utils.d.ts +2 -2
  121. package/dist/util/objects.d.ts +2 -1
  122. package/dist/util/permissions.d.ts +4 -4
  123. package/dist/util/plurals.d.ts +0 -2
  124. package/dist/util/property_utils.d.ts +3 -3
  125. package/dist/util/resolutions.d.ts +30 -16
  126. package/dist/util/storage.d.ts +23 -2
  127. package/dist/util/useStorageUploadController.d.ts +3 -3
  128. package/package.json +59 -44
  129. package/src/app/AppBar.tsx +18 -0
  130. package/src/app/Drawer.tsx +24 -0
  131. package/src/app/Scaffold.tsx +243 -0
  132. package/src/app/index.ts +4 -0
  133. package/src/app/useApp.tsx +32 -0
  134. package/src/components/ArrayContainer.tsx +92 -25
  135. package/src/components/CircularProgressCenter.tsx +2 -2
  136. package/src/components/ClearFilterSortButton.tsx +41 -0
  137. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +3 -3
  138. package/src/components/DeleteEntityDialog.tsx +9 -18
  139. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +13 -20
  140. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +28 -25
  141. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +12 -8
  142. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +47 -39
  143. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  144. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +31 -17
  145. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +19 -17
  146. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +30 -35
  147. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +36 -34
  148. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
  149. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +84 -77
  150. package/src/components/EntityCollectionView/EntityCollectionView.tsx +139 -87
  151. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  152. package/src/components/EntityCollectionView/useSelectionController.tsx +19 -7
  153. package/src/components/EntityCollectionView/utils.ts +19 -0
  154. package/src/components/EntityPreview.tsx +60 -51
  155. package/src/components/EntityView.tsx +10 -10
  156. package/src/components/ErrorView.tsx +4 -4
  157. package/src/components/HomePage/DefaultHomePage.tsx +26 -19
  158. package/src/components/HomePage/FavouritesView.tsx +6 -11
  159. package/src/components/HomePage/NavigationCard.tsx +4 -4
  160. package/src/components/HomePage/NavigationCardBinding.tsx +5 -10
  161. package/src/components/HomePage/NavigationGroup.tsx +2 -2
  162. package/src/components/HomePage/SmallNavigationCard.tsx +5 -6
  163. package/src/components/PropertyConfigBadge.tsx +9 -3
  164. package/src/components/PropertyIdCopyTooltip.tsx +48 -0
  165. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +8 -7
  166. package/src/components/ReferenceWidget.tsx +22 -12
  167. package/src/components/SearchIconsView.tsx +10 -7
  168. package/src/components/SelectableTable/SelectableTable.tsx +9 -9
  169. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  170. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +25 -8
  171. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +30 -6
  172. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +92 -23
  173. package/src/components/VirtualTable/VirtualTable.tsx +77 -46
  174. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  175. package/src/components/VirtualTable/VirtualTableHeader.tsx +10 -10
  176. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  177. package/src/components/VirtualTable/VirtualTableProps.tsx +18 -14
  178. package/src/components/VirtualTable/VirtualTableRow.tsx +5 -6
  179. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +5 -5
  180. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -1
  181. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  182. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
  183. package/src/components/VirtualTable/types.tsx +2 -3
  184. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +8 -4
  185. package/src/components/common/index.ts +1 -0
  186. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  187. package/src/components/common/types.tsx +4 -6
  188. package/src/components/common/useColumnsIds.tsx +23 -2
  189. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +25 -14
  190. package/src/components/common/useTableSearchHelper.ts +53 -12
  191. package/src/components/index.tsx +4 -2
  192. package/src/contexts/DialogsProvider.tsx +2 -2
  193. package/src/contexts/SnackbarProvider.tsx +2 -0
  194. package/src/core/DefaultAppBar.tsx +178 -0
  195. package/src/core/DefaultDrawer.tsx +184 -0
  196. package/src/core/DrawerNavigationItem.tsx +66 -0
  197. package/src/core/EntityEditView.tsx +721 -156
  198. package/src/core/EntitySidePanel.tsx +1 -2
  199. package/src/core/FireCMS.tsx +57 -53
  200. package/src/core/NavigationRoutes.tsx +7 -8
  201. package/src/core/SideDialogs.tsx +2 -1
  202. package/src/core/field_configs.tsx +11 -12
  203. package/src/core/index.tsx +3 -4
  204. package/src/form/PropertyFieldBinding.tsx +74 -35
  205. package/src/form/components/CustomIdField.tsx +6 -2
  206. package/src/form/components/FieldHelperText.tsx +4 -4
  207. package/src/form/components/LabelWithIcon.tsx +27 -19
  208. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  209. package/src/form/components/StorageItemPreview.tsx +22 -12
  210. package/src/form/components/StorageUploadProgress.tsx +3 -4
  211. package/src/form/components/index.tsx +1 -1
  212. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +29 -17
  213. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +45 -35
  214. package/src/form/field_bindings/BlockFieldBinding.tsx +53 -33
  215. package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -14
  216. package/src/form/field_bindings/KeyValueFieldBinding.tsx +60 -51
  217. package/src/form/field_bindings/MapFieldBinding.tsx +67 -48
  218. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +150 -0
  219. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +25 -20
  220. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +11 -16
  221. package/src/form/field_bindings/ReferenceFieldBinding.tsx +42 -31
  222. package/src/form/field_bindings/RepeatFieldBinding.tsx +52 -34
  223. package/src/form/field_bindings/SelectFieldBinding.tsx +22 -14
  224. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +37 -47
  225. package/src/form/field_bindings/SwitchFieldBinding.tsx +28 -24
  226. package/src/form/field_bindings/TextFieldBinding.tsx +27 -24
  227. package/src/form/index.tsx +4 -9
  228. package/src/form/useClearRestoreValue.tsx +2 -2
  229. package/src/form/validation.ts +1 -17
  230. package/src/hooks/data/delete.ts +6 -5
  231. package/src/hooks/data/save.ts +12 -8
  232. package/src/hooks/data/useCollectionFetch.tsx +2 -2
  233. package/src/hooks/data/useDataSource.tsx +11 -3
  234. package/src/hooks/data/useEntityFetch.tsx +5 -5
  235. package/src/hooks/index.tsx +1 -0
  236. package/src/hooks/useAuthController.tsx +1 -1
  237. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  238. package/src/hooks/useBuildModeController.tsx +11 -5
  239. package/src/hooks/useBuildNavigationController.tsx +93 -34
  240. package/src/hooks/useFireCMSContext.tsx +5 -5
  241. package/src/hooks/useProjectLog.tsx +32 -10
  242. package/src/hooks/useResolvedNavigationFrom.tsx +6 -6
  243. package/src/hooks/useValidateAuthenticator.tsx +21 -41
  244. package/src/index.ts +1 -0
  245. package/src/internal/useBuildDataSource.ts +72 -82
  246. package/src/internal/useBuildSideDialogsController.tsx +1 -0
  247. package/src/internal/useBuildSideEntityController.tsx +102 -22
  248. package/src/internal/useUnsavedChangesDialog.tsx +5 -3
  249. package/src/preview/PropertyPreview.tsx +11 -18
  250. package/src/preview/PropertyPreviewProps.tsx +7 -1
  251. package/src/preview/components/BooleanPreview.tsx +2 -2
  252. package/src/preview/components/EmptyValue.tsx +1 -1
  253. package/src/preview/components/EnumValuesChip.tsx +2 -2
  254. package/src/preview/components/ImagePreview.tsx +25 -36
  255. package/src/preview/components/ReferencePreview.tsx +23 -34
  256. package/src/preview/components/StorageThumbnail.tsx +5 -1
  257. package/src/preview/components/UrlComponentPreview.tsx +44 -11
  258. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -3
  259. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  260. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -3
  261. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -2
  262. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -5
  263. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -5
  264. package/src/preview/property_previews/MapPropertyPreview.tsx +9 -9
  265. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
  266. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  267. package/src/preview/util.ts +10 -10
  268. package/src/types/auth.tsx +9 -13
  269. package/src/types/collections.ts +62 -20
  270. package/src/types/customization_controller.tsx +0 -1
  271. package/src/types/datasource.ts +60 -43
  272. package/src/types/entities.ts +11 -1
  273. package/src/types/entity_actions.tsx +20 -7
  274. package/src/types/entity_callbacks.ts +18 -18
  275. package/src/types/entity_overrides.tsx +2 -2
  276. package/src/types/export_import.ts +4 -4
  277. package/src/types/fields.tsx +69 -45
  278. package/src/types/firecms.tsx +7 -2
  279. package/src/types/firecms_context.tsx +1 -1
  280. package/src/types/index.ts +0 -1
  281. package/src/types/navigation.ts +7 -7
  282. package/src/types/permissions.ts +5 -5
  283. package/src/types/plugins.tsx +24 -14
  284. package/src/types/properties.ts +39 -22
  285. package/src/types/property_config.tsx +0 -2
  286. package/src/types/side_dialogs_controller.tsx +13 -0
  287. package/src/types/storage.ts +94 -3
  288. package/src/types/user.ts +2 -0
  289. package/src/util/builders.ts +6 -6
  290. package/src/util/entities.ts +6 -5
  291. package/src/util/enums.ts +1 -1
  292. package/src/util/icon_list.ts +16 -10
  293. package/src/util/icon_synonyms.ts +3 -100
  294. package/src/util/icons.tsx +17 -7
  295. package/src/util/index.ts +1 -0
  296. package/src/util/make_properties_editable.ts +13 -5
  297. package/src/util/navigation_utils.ts +6 -6
  298. package/src/util/objects.ts +45 -28
  299. package/src/util/permissions.ts +9 -8
  300. package/src/util/plurals.ts +0 -2
  301. package/src/util/property_utils.tsx +11 -4
  302. package/src/util/references.ts +11 -2
  303. package/src/util/resolutions.ts +79 -46
  304. package/src/util/storage.ts +79 -21
  305. package/src/util/strings.ts +2 -2
  306. package/src/util/useStorageUploadController.tsx +34 -8
  307. package/src/util/useTraceUpdate.tsx +1 -0
  308. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  309. package/dist/components/VirtualTable/common.d.ts +0 -2
  310. package/dist/core/Drawer.d.ts +0 -23
  311. package/dist/core/Scaffold.d.ts +0 -55
  312. package/dist/core/SideEntityView.d.ts +0 -7
  313. package/dist/form/EntityForm.d.ts +0 -77
  314. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  315. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  316. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  317. package/dist/internal/useLocaleConfig.d.ts +0 -1
  318. package/dist/types/appcheck.d.ts +0 -26
  319. package/src/components/FireCMSAppBar.tsx +0 -165
  320. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
  321. package/src/core/Drawer.tsx +0 -191
  322. package/src/core/Scaffold.tsx +0 -281
  323. package/src/core/SideEntityView.tsx +0 -38
  324. package/src/form/EntityForm.tsx +0 -728
  325. package/src/form/components/FormikArrayContainer.tsx +0 -44
  326. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  327. package/src/internal/useBuildCustomizationController.tsx +0 -5
  328. package/src/internal/useLocaleConfig.tsx +0 -18
  329. package/src/types/appcheck.ts +0 -29
@@ -8,6 +8,8 @@ import {
8
8
  Entity,
9
9
  EntityAction,
10
10
  EntityCollection,
11
+ EntityReference,
12
+ EntityTableController,
11
13
  FilterValues,
12
14
  PartialEntityCollection,
13
15
  PropertyOrBuilder,
@@ -35,6 +37,7 @@ import {
35
37
  useAuthController,
36
38
  useCustomizationController,
37
39
  useDataSource,
40
+ useFireCMSContext,
38
41
  useLargeLayout,
39
42
  useNavigationController,
40
43
  useSideEntityController
@@ -44,7 +47,8 @@ import { EntityCollectionViewActions } from "./EntityCollectionViewActions";
44
47
  import {
45
48
  AddIcon,
46
49
  Button,
47
- cn,
50
+ cls,
51
+ focusedDisabled,
48
52
  IconButton,
49
53
  KeyboardTabIcon,
50
54
  Markdown,
@@ -65,14 +69,12 @@ import {
65
69
  } from "../common";
66
70
  import { PopupFormField } from "../EntityCollectionTable/internal/popup_field/PopupFormField";
67
71
  import { GetPropertyForProps } from "../EntityCollectionTable/EntityCollectionTableProps";
68
- import {
69
- copyEntityAction,
70
- deleteEntityAction,
71
- editEntityAction
72
- } from "../EntityCollectionTable/internal/default_entity_actions";
72
+ import { copyEntityAction, deleteEntityAction, editEntityAction } from "../common/default_entity_actions";
73
73
  import { DeleteEntityDialog } from "../DeleteEntityDialog";
74
74
  import { useAnalyticsController } from "../../hooks/useAnalyticsController";
75
75
  import { useSelectionController } from "./useSelectionController";
76
+ import { EntityCollectionViewStartActions } from "./EntityCollectionViewStartActions";
77
+ import { addRecentId, getRecentIds } from "./utils";
76
78
 
77
79
  const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
78
80
 
@@ -80,10 +82,22 @@ const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
80
82
  * @group Components
81
83
  */
82
84
  export type EntityCollectionViewProps<M extends Record<string, any>> = {
83
- fullPath: string;
85
+ /**
86
+ * Complete path where this collection is located.
87
+ * It defaults to the collection path if not provided.
88
+ */
89
+ fullPath?: string;
90
+ /**
91
+ * If this is a subcollection, specify the parent collection ids.
92
+ */
84
93
  parentCollectionIds?: string[];
94
+ /**
95
+ * Whether this is a subcollection or not.
96
+ */
85
97
  isSubCollection?: boolean;
98
+
86
99
  className?: string;
100
+
87
101
  } & EntityCollection<M>;
88
102
 
89
103
  /**
@@ -107,12 +121,12 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
107
121
  *
108
122
  * @param fullPath
109
123
  * @param collection
110
- * @constructor
124
+
111
125
  * @group Components
112
126
  */
113
127
  export const EntityCollectionView = React.memo(
114
128
  function EntityCollectionView<M extends Record<string, any>>({
115
- fullPath,
129
+ fullPath: fullPathProp,
116
130
  parentCollectionIds,
117
131
  isSubCollection,
118
132
  className,
@@ -120,6 +134,8 @@ export const EntityCollectionView = React.memo(
120
134
  }: EntityCollectionViewProps<M>
121
135
  ) {
122
136
 
137
+ const context = useFireCMSContext();
138
+ const fullPath = fullPathProp ?? collectionProp.path;
123
139
  const dataSource = useDataSource(collectionProp);
124
140
  const navigation = useNavigationController();
125
141
  const sideEntityController = useSideEntityController();
@@ -128,7 +144,6 @@ export const EntityCollectionView = React.memo(
128
144
  const analyticsController = useAnalyticsController();
129
145
  const customizationController = useCustomizationController();
130
146
 
131
-
132
147
  const containerRef = React.useRef<HTMLDivElement>(null);
133
148
 
134
149
  const collection = useMemo(() => {
@@ -142,7 +157,7 @@ export const EntityCollectionView = React.memo(
142
157
  }, [collection]);
143
158
 
144
159
  const canCreateEntities = canCreateEntity(collection, authController, fullPath, null);
145
- const [selectedNavigationEntity, setSelectedNavigationEntity] = useState<Entity<M> | undefined>(undefined);
160
+ const [highlightedEntity, setHighlightedEntity] = useState<Entity<M> | undefined>(undefined);
146
161
  const [deleteEntityClicked, setDeleteEntityClicked] = React.useState<Entity<M> | Entity<M>[] | undefined>(undefined);
147
162
 
148
163
  const [lastDeleteTimestamp, setLastDeleteTimestamp] = React.useState<number>(0);
@@ -151,12 +166,12 @@ export const EntityCollectionView = React.memo(
151
166
  const [docsCount, setDocsCount] = useState<number>(0);
152
167
 
153
168
  const unselectNavigatedEntity = useCallback(() => {
154
- const currentSelection = selectedNavigationEntity;
169
+ const currentSelection = highlightedEntity;
155
170
  setTimeout(() => {
156
- if (currentSelection === selectedNavigationEntity)
157
- setSelectedNavigationEntity(undefined);
171
+ if (currentSelection === highlightedEntity)
172
+ setHighlightedEntity(undefined);
158
173
  }, 2400);
159
- }, [selectedNavigationEntity]);
174
+ }, [highlightedEntity]);
160
175
 
161
176
  const checkInlineEditing = useCallback((entity?: Entity<any>): boolean => {
162
177
  const collection = collectionRef.current;
@@ -175,19 +190,16 @@ export const EntityCollectionView = React.memo(
175
190
  const usedSelectionController = collection.selectionController ?? selectionController;
176
191
  const {
177
192
  selectedEntities,
178
- toggleEntitySelection,
179
- isEntitySelected,
180
193
  setSelectedEntities
181
194
  } = usedSelectionController;
182
195
 
183
- useEffect(() => {
184
- setDeleteEntityClicked(undefined);
185
- }, [selectedEntities]);
196
+ // useEffect(() => {
197
+ // setDeleteEntityClicked(undefined);
198
+ // }, [selectedEntities]);
186
199
 
187
200
  const tableController = useDataSourceEntityCollectionTableController<M>({
188
201
  fullPath,
189
- collection: collectionRef.current,
190
- entitiesDisplayedFirst: [],
202
+ collection,
191
203
  lastDeleteTimestamp
192
204
  });
193
205
 
@@ -199,9 +211,8 @@ export const EntityCollectionView = React.memo(
199
211
  }, [tableController.setPopupCell]);
200
212
 
201
213
  const onEntityClick = useCallback((clickedEntity: Entity<M>) => {
202
- console.log("Entity clicked", clickedEntity)
203
214
  const collection = collectionRef.current;
204
- setSelectedNavigationEntity(clickedEntity);
215
+ setHighlightedEntity(clickedEntity);
205
216
  analyticsController.onAnalyticsEvent?.("edit_entity_clicked", {
206
217
  path: clickedEntity.path,
207
218
  entityId: clickedEntity.id
@@ -257,6 +268,7 @@ export const EntityCollectionView = React.memo(
257
268
  fullPath: string,
258
269
  parentCollectionIds: string[],
259
270
  collection: EntityCollection;
271
+ tableController: EntityTableController;
260
272
  }> | undefined
261
273
 
262
274
  // we are only using the first plugin that implements this
@@ -297,17 +309,15 @@ export const EntityCollectionView = React.memo(
297
309
  value,
298
310
  property,
299
311
  entityId
300
- }) => dataSource.checkUniqueField(fullPath, name, value, entityId),
312
+ }) => dataSource.checkUniqueField(fullPath, name, value, entityId, collection),
301
313
  [fullPath]);
302
314
 
303
315
  const onValueChange: OnCellValueChange<any, any> = ({
304
- fullPath,
305
- context,
306
316
  value,
307
317
  propertyKey,
308
318
  onValueUpdated,
309
319
  setError,
310
- entity,
320
+ data: entity,
311
321
  }) => {
312
322
 
313
323
  const updatedValues = setIn({ ...entity.values }, propertyKey, value);
@@ -324,10 +334,12 @@ export const EntityCollectionView = React.memo(
324
334
  return saveEntityWithCallbacks({
325
335
  ...saveProps,
326
336
  collection,
327
- callbacks: collection.callbacks,
328
337
  dataSource,
329
338
  context,
330
- onSaveSuccess: () => onValueUpdated(),
339
+ onSaveSuccess: () => {
340
+ setError(undefined);
341
+ onValueUpdated();
342
+ },
331
343
  onSaveFailure: (e: Error) => {
332
344
  console.error("Save failure");
333
345
  console.error(e);
@@ -341,12 +353,11 @@ export const EntityCollectionView = React.memo(
341
353
  const resolvedCollection = useMemo(() => resolveCollection<M>({
342
354
  collection,
343
355
  path: fullPath,
344
- fields: customizationController.propertyConfigs
356
+ propertyConfigs: customizationController.propertyConfigs
345
357
  }), [collection, fullPath]);
346
358
 
347
359
  const getPropertyFor = useCallback(({
348
360
  propertyKey,
349
- propertyValue,
350
361
  entity
351
362
  }: GetPropertyForProps<M>) => {
352
363
  let propertyOrBuilder: PropertyOrBuilder<any, M> | undefined = getPropertyInPath<M>(collection.properties, propertyKey);
@@ -360,13 +371,12 @@ export const EntityCollectionView = React.memo(
360
371
  return resolveProperty({
361
372
  propertyKey,
362
373
  propertyOrBuilder,
363
- path: fullPath,
364
- propertyValue,
374
+ path: entity.path,
365
375
  values: entity.values,
366
376
  entityId: entity.id,
367
- fields: customizationController.propertyConfigs
377
+ propertyConfigs: customizationController.propertyConfigs
368
378
  });
369
- }, [collection.properties, customizationController.propertyConfigs, fullPath, resolvedCollection.properties]);
379
+ }, [collection.properties, customizationController.propertyConfigs, resolvedCollection.properties]);
370
380
 
371
381
  const displayedColumnIds = useColumnIds(resolvedCollection, true);
372
382
 
@@ -406,16 +416,16 @@ export const EntityCollectionView = React.memo(
406
416
  Builder: ({ entity }) => {
407
417
  const collectionsWithPath = navigation.getParentReferencesFromPath(entity.path);
408
418
  return (
409
- <>
419
+ <div className={"flex flex-col gap-2 w-full"}>
410
420
  {collectionsWithPath.map((reference) => {
411
421
  return (
412
422
  <ReferencePreview
413
423
  key={reference.path + "/" + reference.id}
414
424
  reference={reference}
415
- size={"tiny"}/>
425
+ size={"small"}/>
416
426
  );
417
427
  })}
418
- </>
428
+ </div>
419
429
  );
420
430
  }
421
431
  }]
@@ -460,19 +470,19 @@ export const EntityCollectionView = React.memo(
460
470
  return (largeLayout ? (80 + actionsWidth) : (70 + actionsWidth)) + (collapsedActions.length > 0 ? (largeLayout ? 40 : 30) : 0);
461
471
  };
462
472
 
463
- const tableRowActionsBuilder = ({
464
- entity,
465
- size,
466
- width,
467
- frozen
468
- }: {
473
+ const tableRowActionsBuilder = useCallback(({
474
+ entity,
475
+ size,
476
+ width,
477
+ frozen
478
+ }: {
469
479
  entity: Entity<any>,
470
480
  size: CollectionSize,
471
481
  width: number,
472
482
  frozen?: boolean
473
483
  }) => {
474
484
 
475
- const isSelected = isEntitySelected(entity);
485
+ const isSelected = usedSelectionController.selectedEntities.map(e => e.id).includes(entity.id);
476
486
 
477
487
  const actions = getActionsForEntity({
478
488
  entity,
@@ -487,7 +497,7 @@ export const EntityCollectionView = React.memo(
487
497
  isSelected={isSelected}
488
498
  selectionEnabled={selectionEnabled}
489
499
  size={size}
490
- highlightEntity={setSelectedNavigationEntity}
500
+ highlightEntity={setHighlightedEntity}
491
501
  unhighlightEntity={unselectNavigatedEntity}
492
502
  collection={collection}
493
503
  fullPath={fullPath}
@@ -498,7 +508,7 @@ export const EntityCollectionView = React.memo(
498
508
  />
499
509
  );
500
510
 
501
- };
511
+ }, [updateLastDeleteTimestamp, usedSelectionController]);
502
512
 
503
513
  const title = <Popover
504
514
  open={popOverOpen}
@@ -528,7 +538,7 @@ export const EntityCollectionView = React.memo(
528
538
  </div>}
529
539
  >
530
540
 
531
- {collection.description && <div className="m-4 text-gray-900 dark:text-white">
541
+ {collection.description && <div className="m-4 text-surface-900 dark:text-white">
532
542
  <Markdown source={collection.description}/>
533
543
  </div>}
534
544
 
@@ -557,6 +567,7 @@ export const EntityCollectionView = React.memo(
557
567
  property={property}
558
568
  fullPath={fullPath}
559
569
  collection={collection}
570
+ tableController={tableController}
560
571
  parentCollectionIds={parentCollectionIds ?? []}/>;
561
572
  })}
562
573
  </>;
@@ -567,7 +578,8 @@ export const EntityCollectionView = React.memo(
567
578
  if (typeof AddColumnComponent === "function")
568
579
  return <AddColumnComponent fullPath={fullPath}
569
580
  parentCollectionIds={parentCollectionIds ?? []}
570
- collection={collection}/>;
581
+ collection={collection}
582
+ tableController={tableController}/>;
571
583
  return null;
572
584
  }
573
585
  : undefined;
@@ -584,12 +596,13 @@ export const EntityCollectionView = React.memo(
584
596
  });
585
597
 
586
598
  return (
587
- <div className={cn("overflow-hidden h-full w-full rounded-md", className)}
599
+ <div className={cls("overflow-hidden h-full w-full rounded-md", className)}
588
600
  ref={containerRef}>
589
601
  <EntityCollectionTable
590
602
  key={`collection_table_${fullPath}`}
591
603
  additionalFields={additionalFields}
592
604
  tableController={tableController}
605
+ enablePopupIcon={true}
593
606
  displayedColumnIds={displayedColumnIds}
594
607
  onSizeChanged={onSizeChanged}
595
608
  onEntityClick={onEntityClick}
@@ -599,13 +612,21 @@ export const EntityCollectionView = React.memo(
599
612
  uniqueFieldValidator={uniqueFieldValidator}
600
613
  title={title}
601
614
  selectionController={usedSelectionController}
602
- highlightedEntities={selectedNavigationEntity ? [selectedNavigationEntity] : []}
615
+ highlightedEntities={highlightedEntity ? [highlightedEntity] : []}
603
616
  defaultSize={collection.defaultSize}
604
617
  properties={resolvedCollection.properties}
605
618
  getPropertyFor={getPropertyFor}
606
619
  onTextSearchClick={textSearchInitialised ? undefined : onTextSearchClick}
607
620
  textSearchLoading={textSearchLoading}
608
621
  textSearchEnabled={textSearchEnabled}
622
+ actionsStart={<EntityCollectionViewStartActions
623
+ parentCollectionIds={parentCollectionIds ?? []}
624
+ collection={collection}
625
+ tableController={tableController}
626
+ path={fullPath}
627
+ relativePath={collection.path}
628
+ selectionController={usedSelectionController}
629
+ collectionEntitiesCount={docsCount}/>}
609
630
  actions={<EntityCollectionViewActions
610
631
  parentCollectionIds={parentCollectionIds ?? []}
611
632
  collection={collection}
@@ -643,19 +664,19 @@ export const EntityCollectionView = React.memo(
643
664
  collection={collection}/>}
644
665
  />
645
666
 
646
- <PopupFormField
647
- key={`popup_form_${popupCell?.propertyKey}_${popupCell?.entity?.id}`}
667
+ {popupCell && <PopupFormField
668
+ key={`popup_form_${popupCell?.propertyKey}_${popupCell?.entityId}`}
648
669
  open={Boolean(popupCell)}
649
670
  onClose={onPopupClose}
650
671
  cellRect={popupCell?.cellRect}
651
672
  propertyKey={popupCell?.propertyKey}
652
673
  collection={collection}
653
- entity={popupCell?.entity}
674
+ entityId={popupCell.entityId}
654
675
  tableKey={tableKey.current}
655
676
  customFieldValidator={uniqueFieldValidator}
656
677
  path={resolvedFullPath}
657
678
  onCellValueChange={onValueChange}
658
- container={containerRef.current}/>
679
+ container={containerRef.current}/>}
659
680
 
660
681
  {deleteEntityClicked &&
661
682
  <DeleteEntityDialog
@@ -683,8 +704,11 @@ export const EntityCollectionView = React.memo(
683
704
  equal(a.selectionController, b.selectionController) &&
684
705
  equal(a.Actions, b.Actions) &&
685
706
  equal(a.defaultSize, b.defaultSize) &&
707
+ equal(a.initialFilter, b.initialFilter) &&
708
+ equal(a.initialSort, b.initialSort) &&
686
709
  equal(a.textSearchEnabled, b.textSearchEnabled) &&
687
710
  equal(a.additionalFields, b.additionalFields) &&
711
+ equal(a.sideDialogWidth, b.sideDialogWidth) &&
688
712
  equal(a.forceFilter, b.forceFilter);
689
713
  }) as React.FunctionComponent<EntityCollectionViewProps<any>>
690
714
 
@@ -724,6 +748,7 @@ function EntitiesCount({
724
748
 
725
749
  useEffect(() => {
726
750
  if (onCountChange) {
751
+ setError(undefined);
727
752
  onCountChange(count ?? 0);
728
753
  }
729
754
  }, [onCountChange, count]);
@@ -757,46 +782,73 @@ function EntityIdHeaderWidget({
757
782
  }) {
758
783
  const [openPopup, setOpenPopup] = React.useState(false);
759
784
  const [searchString, setSearchString] = React.useState("");
785
+ const [recentIds, setRecentIds] = React.useState<string[]>(getRecentIds(collection.id));
760
786
  const sideEntityController = useSideEntityController();
787
+
761
788
  return (
762
- <Tooltip title={!openPopup ? "Find by ID" : undefined}>
789
+ <Tooltip title={!openPopup ? "Find by ID" : undefined} asChild={false}>
763
790
  <Popover
764
791
  open={openPopup}
765
792
  onOpenChange={setOpenPopup}
793
+ sideOffset={0}
794
+ align={"start"}
795
+ alignOffset={-117}
766
796
  trigger={
767
797
  <IconButton size={"small"}>
768
798
  <SearchIcon size={"small"}/>
769
799
  </IconButton>
770
- }
771
- >
772
- <form noValidate={true}
773
- onSubmit={(e) => {
774
- e.preventDefault();
775
- if (!searchString) return;
776
- setOpenPopup(false);
777
- return sideEntityController.open({
778
- entityId: searchString,
779
- path,
780
- collection,
781
- updateUrl: true,
782
- });
783
- }}
784
- className={"text-gray-900 dark:text-white w-96 max-w-full"}>
785
-
786
- <div className="flex p-2 w-full gap-4">
787
- <input
788
- autoFocus={openPopup}
789
- placeholder={"Find entity by ID"}
790
- // size={"small"}
791
- onChange={(e) => setSearchString(e.target.value)}
792
- value={searchString}
793
- className={"flex-grow bg-transparent outline-none p-1"}/>
794
- <Button variant={"outlined"}
795
- disabled={!searchString}
796
- type={"submit"}
797
- >Go</Button>
798
- </div>
799
- </form>
800
+ }>
801
+ <div className={cls("my-2 rounded-lg bg-surface-50 dark:bg-surface-950 text-surface-900 dark:text-white")}>
802
+ <form noValidate={true}
803
+ onSubmit={(e) => {
804
+ e.preventDefault();
805
+ if (!searchString) return;
806
+ setOpenPopup(false);
807
+ setRecentIds(addRecentId(collection.id, searchString.trim()));
808
+ return sideEntityController.open({
809
+ entityId: searchString.trim(),
810
+ path,
811
+ collection,
812
+ updateUrl: true
813
+ });
814
+ }}
815
+ className={"w-96 max-w-full"}>
816
+
817
+ <div className="flex p-2 w-full gap-2">
818
+ <input
819
+ autoFocus={openPopup}
820
+ placeholder={"Find entity by ID"}
821
+ // size={"small"}
822
+ onChange={(e) => {
823
+ setSearchString(e.target.value);
824
+ }}
825
+ value={searchString}
826
+ className={"rounded-lg bg-white dark:bg-surface-800 flex-grow bg-transparent outline-none p-2 " + focusedDisabled}/>
827
+ <Button variant={"text"}
828
+ disabled={!(searchString.trim())}
829
+ type={"submit"}
830
+ ><KeyboardTabIcon/></Button>
831
+ </div>
832
+ </form>
833
+ {recentIds && recentIds.length > 0 && <div className="flex flex-col gap-2 p-2">
834
+ {recentIds.map(id => (
835
+ <ReferencePreview reference={new EntityReference(id, path)}
836
+ key={id}
837
+ hover={true}
838
+ onClick={() => {
839
+ setOpenPopup(false);
840
+ sideEntityController.open({
841
+ entityId: id,
842
+ path,
843
+ collection,
844
+ updateUrl: true
845
+ });
846
+ }}
847
+ includeEntityLink={false}
848
+ size={"small"}/>
849
+ ))}
850
+ </div>}
851
+ </div>
800
852
  </Popover>
801
853
 
802
854
  </Tooltip>
@@ -0,0 +1,68 @@
1
+ import React from "react";
2
+ import { useCustomizationController, useFireCMSContext } from "../../hooks";
3
+ import { CollectionActionsProps, EntityCollection, EntityTableController, SelectionController } from "../../types";
4
+ import { toArray } from "../../util/arrays";
5
+ import { ErrorBoundary } from "../ErrorBoundary";
6
+ import { ClearFilterSortButton } from "../ClearFilterSortButton";
7
+
8
+ export type EntityCollectionViewStartActionsProps<M extends Record<string, any>> = {
9
+ collection: EntityCollection<M>;
10
+ path: string;
11
+ relativePath: string;
12
+ parentCollectionIds: string[];
13
+ selectionController: SelectionController<M>;
14
+ tableController: EntityTableController<M>;
15
+ collectionEntitiesCount: number;
16
+ }
17
+
18
+ export function EntityCollectionViewStartActions<M extends Record<string, any>>({
19
+ collection,
20
+ relativePath,
21
+ parentCollectionIds,
22
+ path,
23
+ selectionController,
24
+ tableController,
25
+ collectionEntitiesCount
26
+ }: EntityCollectionViewStartActionsProps<M>) {
27
+
28
+ const context = useFireCMSContext();
29
+
30
+ const customizationController = useCustomizationController();
31
+ const plugins = customizationController.plugins ?? [];
32
+
33
+ const actionProps: CollectionActionsProps = {
34
+ path,
35
+ relativePath,
36
+ parentCollectionIds,
37
+ collection,
38
+ selectionController,
39
+ context,
40
+ tableController,
41
+ collectionEntitiesCount
42
+ };
43
+ const actions: React.ReactNode[] = [
44
+ <ClearFilterSortButton
45
+ key={"clear_filter"}
46
+ tableController={tableController}
47
+ enabled={!collection.forceFilter}/>
48
+ ];
49
+
50
+ if (plugins) {
51
+ plugins.forEach((plugin, i) => {
52
+ if (plugin.collectionView?.CollectionActionsStart) {
53
+ actions.push(...toArray(plugin.collectionView?.CollectionActionsStart)
54
+ .map((Action, j) => (
55
+ <ErrorBoundary key={`plugin_actions_${i}_${j}`}>
56
+ <Action {...actionProps} {...plugin.collectionView?.collectionActionsStartProps}/>
57
+ </ErrorBoundary>
58
+ )));
59
+ }
60
+ });
61
+ }
62
+
63
+ return (
64
+ <>
65
+ {actions}
66
+ </>
67
+ );
68
+ }
@@ -7,19 +7,31 @@ export function useSelectionController<M extends Record<string, any> = any>(
7
7
 
8
8
  const [selectedEntities, setSelectedEntities] = useState<Entity<M>[]>([]);
9
9
 
10
- const toggleEntitySelection = useCallback((entity: Entity<M>) => {
10
+ const toggleEntitySelection = useCallback((entity: Entity<M>, newSelectedState?: boolean) => {
11
11
  let newValue;
12
- if (selectedEntities.map(e => e.id).includes(entity.id)) {
13
- onSelectionChange?.(entity, false);
14
- newValue = selectedEntities.filter((item: Entity<M>) => item.id !== entity.id);
12
+ if (newSelectedState === undefined) {
13
+ if (selectedEntities.map(e => e.id).includes(entity.id)) {
14
+ onSelectionChange?.(entity, false);
15
+ newValue = selectedEntities.filter((item: Entity<M>) => item.id !== entity.id);
16
+ } else {
17
+ onSelectionChange?.(entity, true);
18
+ newValue = [...selectedEntities, entity];
19
+ }
15
20
  } else {
16
- onSelectionChange?.(entity, true);
17
- newValue = [...selectedEntities, entity];
21
+ if (newSelectedState) {
22
+ onSelectionChange?.(entity, true);
23
+ newValue = [...selectedEntities, entity];
24
+ } else {
25
+ onSelectionChange?.(entity, false);
26
+ newValue = selectedEntities.filter((item: Entity<M>) => item.id !== entity.id);
27
+ }
18
28
  }
19
29
  setSelectedEntities(newValue);
20
30
  }, [selectedEntities]);
21
31
 
22
- const isEntitySelected = useCallback((entity: Entity<M>) => selectedEntities.map(e => e.id).includes(entity.id), [selectedEntities]);
32
+ const isEntitySelected = useCallback((entity: Entity<M>) => {
33
+ return selectedEntities.map(e => e.id).includes(entity.id);
34
+ }, [selectedEntities]);
23
35
 
24
36
  return {
25
37
  selectedEntities,
@@ -0,0 +1,19 @@
1
+ export function addRecentId(collectionId: string, id: string) {
2
+ const recentIds = getRecentIds(collectionId);
3
+ const newRecentIds = [id, ...recentIds.filter(i => i !== id)];
4
+ if (newRecentIds.length > 5) {
5
+ newRecentIds.pop();
6
+ }
7
+ saveSearchedIdsLocally(collectionId, newRecentIds);
8
+ return newRecentIds;
9
+ }
10
+
11
+ export function saveSearchedIdsLocally(collectionId: string, ids: string[]) {
12
+ localStorage.setItem("recent_id_searches::" + collectionId, JSON.stringify(ids));
13
+ }
14
+
15
+ export function getRecentIds(collectionId: string): string[] {
16
+ const stored = localStorage.getItem("recent_id_searches::" + collectionId);
17
+ if (!stored) return [];
18
+ return JSON.parse(stored);
19
+ }