@rebasepro/admin 0.1.0 → 0.2.1

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 (242) hide show
  1. package/LICENSE +21 -6
  2. package/dist/{CollectionEditorDialog-MbvXGzEq.js → CollectionEditorDialog-BXIh2AXg.js} +40 -31
  3. package/dist/CollectionEditorDialog-BXIh2AXg.js.map +1 -0
  4. package/dist/{CollectionsStudioView-D9X6aiAr.js → CollectionsStudioView-jR8iz_ja.js} +6 -8
  5. package/dist/CollectionsStudioView-jR8iz_ja.js.map +1 -0
  6. package/dist/{ContentHomePage-CfVB1eUo.js → ContentHomePage-BQZWuOFb.js} +5 -7
  7. package/dist/ContentHomePage-BQZWuOFb.js.map +1 -0
  8. package/dist/{ExportCollectionAction-CUwJg4F9.js → ExportCollectionAction-CMdiiv1L.js} +36 -38
  9. package/dist/ExportCollectionAction-CMdiiv1L.js.map +1 -0
  10. package/dist/{ImportCollectionAction-DGa_SF_8.js → ImportCollectionAction-C05lE0IW.js} +5 -7
  11. package/dist/ImportCollectionAction-C05lE0IW.js.map +1 -0
  12. package/dist/{PropertyEditView-C4nlYmAc.js → PropertyEditView-BB5xjnhZ.js} +261 -165
  13. package/dist/PropertyEditView-BB5xjnhZ.js.map +1 -0
  14. package/dist/{RolesView-CNWxnR8e.js → RolesView-CULIHWZ9.js} +22 -11
  15. package/dist/RolesView-CULIHWZ9.js.map +1 -0
  16. package/dist/{UsersView-YiTIcXkA.js → UsersView-D7_AtJ44.js} +7 -71
  17. package/dist/UsersView-D7_AtJ44.js.map +1 -0
  18. package/dist/collection_editor/ui/collection_editor/LayoutModeSwitch.d.ts +2 -2
  19. package/dist/collection_editor/ui/collection_editor/properties/VectorPropertyField.d.ts +3 -0
  20. package/dist/collection_editor_ui.js +5 -5
  21. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
  22. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
  23. package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
  24. package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
  25. package/dist/components/EntityDetailView.d.ts +31 -0
  26. package/dist/components/EntityEditView.d.ts +3 -2
  27. package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
  28. package/dist/components/admin/CreationResultDialog.d.ts +5 -0
  29. package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
  30. package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
  31. package/dist/components/common/default_entity_actions.d.ts +7 -1
  32. package/dist/components/field_configs.d.ts +1 -1
  33. package/dist/components/index.d.ts +1 -0
  34. package/dist/data_import/utils/data.d.ts +1 -1
  35. package/dist/data_import/utils/file_headers.d.ts +6 -1
  36. package/dist/data_import/utils/file_to_json.d.ts +1 -11
  37. package/dist/data_import/utils/transforms.d.ts +11 -0
  38. package/dist/editor.js +2 -4
  39. package/dist/editor.js.map +1 -1
  40. package/dist/form/EntityForm.d.ts +1 -1
  41. package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
  42. package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
  43. package/dist/form/index.d.ts +1 -0
  44. package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
  45. package/dist/{index-CtzpHzMQ.js → index-BAM9KCmM.js} +4 -6
  46. package/dist/index-BAM9KCmM.js.map +1 -0
  47. package/dist/{index-DKlrVD1m.js → index-CoSNm3e3.js} +3 -3
  48. package/dist/index-CoSNm3e3.js.map +1 -0
  49. package/dist/{index-kHJXfLNI.js → index-D5OQhv-T.js} +3 -3
  50. package/dist/index-D5OQhv-T.js.map +1 -0
  51. package/dist/index.d.ts +4 -1
  52. package/dist/index.js +352 -148
  53. package/dist/index.js.map +1 -1
  54. package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
  55. package/dist/types/components/EntityFormProps.d.ts +2 -1
  56. package/dist/types/fields.d.ts +3 -3
  57. package/dist/util/navigation_utils.d.ts +1 -1
  58. package/dist/{util-CwLmSpGp.js → util-DtbWD7LF.js} +5312 -2580
  59. package/dist/util-DtbWD7LF.js.map +1 -0
  60. package/package.json +45 -39
  61. package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
  62. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
  63. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
  64. package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
  65. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
  66. package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
  67. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
  68. package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
  69. package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
  70. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
  71. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
  72. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
  73. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +22 -7
  74. package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
  75. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
  76. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
  77. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
  78. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
  79. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
  80. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
  81. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
  82. package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
  83. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
  84. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
  85. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
  86. package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
  87. package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
  88. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
  89. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
  90. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
  91. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
  92. package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
  93. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
  94. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
  95. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
  96. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
  97. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
  98. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
  99. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
  100. package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
  101. package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
  102. package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
  103. package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
  104. package/src/collection_editor/validateCollectionJson.ts +9 -9
  105. package/src/components/AdminModeSyncer.tsx +1 -1
  106. package/src/components/ArrayContainer.tsx +19 -15
  107. package/src/components/ClearFilterSortButton.tsx +1 -2
  108. package/src/components/CollectionEditorDialogs.tsx +1 -1
  109. package/src/components/DefaultAppBar.tsx +15 -3
  110. package/src/components/DefaultDrawer.tsx +3 -3
  111. package/src/components/DrawerNavigationGroup.tsx +1 -2
  112. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +19 -9
  113. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +2 -2
  114. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
  115. package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
  116. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
  117. package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
  118. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
  119. package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
  120. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
  121. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +3 -4
  122. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
  123. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
  124. package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
  125. package/src/components/EntityCollectionView/Board.tsx +1 -2
  126. package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
  127. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
  128. package/src/components/EntityCollectionView/EntityCard.tsx +2 -2
  129. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
  130. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
  131. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +90 -21
  132. package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
  133. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
  134. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
  135. package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
  136. package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
  137. package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
  138. package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
  139. package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
  140. package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
  141. package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
  142. package/src/components/EntityDetailView.tsx +619 -0
  143. package/src/components/EntityEditView.tsx +29 -10
  144. package/src/components/EntityEditViewFormActions.tsx +20 -7
  145. package/src/components/EntityPreview.tsx +14 -5
  146. package/src/components/EntitySidePanel.tsx +116 -62
  147. package/src/components/EntityView.tsx +1 -2
  148. package/src/components/HomePage/ContentHomePage.tsx +1 -1
  149. package/src/components/HomePage/FavouritesView.tsx +1 -2
  150. package/src/components/HomePage/NavigationCard.tsx +1 -2
  151. package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
  152. package/src/components/HomePage/NavigationGroup.tsx +1 -2
  153. package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
  154. package/src/components/PropertyIdCopyTooltip.tsx +1 -2
  155. package/src/components/RebaseAuthGate.tsx +2 -2
  156. package/src/components/RebaseNavigation.tsx +9 -7
  157. package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
  158. package/src/components/RelationSelector.tsx +34 -6
  159. package/src/components/SearchIconsView.tsx +10 -2
  160. package/src/components/SelectableTable/SelectableTable.tsx +4 -4
  161. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
  162. package/src/components/SideDialogs.tsx +63 -38
  163. package/src/components/UserSelector.tsx +30 -6
  164. package/src/components/admin/CreationResultDialog.tsx +135 -0
  165. package/src/components/admin/RolesFilterSelect.tsx +45 -0
  166. package/src/components/admin/RolesView.tsx +53 -14
  167. package/src/components/admin/UserRolesSelectField.tsx +50 -0
  168. package/src/components/admin/UsersView.tsx +41 -124
  169. package/src/components/app/Scaffold.tsx +1 -2
  170. package/src/components/common/default_entity_actions.tsx +119 -12
  171. package/src/components/field_configs.tsx +39 -3
  172. package/src/components/history/EntityHistoryEntry.tsx +1 -2
  173. package/src/components/history/EntityHistoryView.tsx +1 -2
  174. package/src/components/index.ts +2 -0
  175. package/src/data_export/export/BasicExportAction.tsx +35 -38
  176. package/src/data_export/export/ExportCollectionAction.tsx +39 -40
  177. package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
  178. package/src/data_import/components/ImportFileUpload.tsx +1 -2
  179. package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
  180. package/src/data_import/import/ImportCollectionAction.tsx +21 -8
  181. package/src/data_import/utils/data.ts +23 -5
  182. package/src/data_import/utils/file_headers.ts +13 -89
  183. package/src/data_import/utils/file_to_json.ts +43 -68
  184. package/src/data_import/utils/transforms.ts +47 -0
  185. package/src/editor/components/SlashCommandMenu.tsx +17 -2
  186. package/src/editor/components/editor-bubble-item.tsx +1 -1
  187. package/src/editor/extensions/Image/index.ts +1 -1
  188. package/src/editor/extensions/Image.ts +1 -1
  189. package/src/editor/selectors/color-selector.tsx +1 -2
  190. package/src/editor/selectors/link-selector.tsx +1 -2
  191. package/src/editor/selectors/node-selector.tsx +16 -2
  192. package/src/editor/selectors/text-buttons.tsx +1 -2
  193. package/src/editor/utils/prosemirror-utils.ts +1 -1
  194. package/src/form/EntityForm.tsx +16 -6
  195. package/src/form/EntityFormActions.tsx +11 -3
  196. package/src/form/PropertyFieldBinding.tsx +5 -12
  197. package/src/form/components/FieldHelperText.tsx +1 -2
  198. package/src/form/components/LocalChangesMenu.tsx +17 -2
  199. package/src/form/components/StorageItemPreview.tsx +1 -2
  200. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
  201. package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
  202. package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
  203. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
  204. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
  205. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
  206. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
  207. package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
  208. package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
  209. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
  210. package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
  211. package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
  212. package/src/form/index.tsx +1 -0
  213. package/src/form/validation.ts +54 -2
  214. package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
  215. package/src/hooks/navigation/useResolvedViews.tsx +30 -15
  216. package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
  217. package/src/index.ts +6 -0
  218. package/src/preview/PropertyPreview.tsx +1 -1
  219. package/src/preview/components/ImagePreview.tsx +1 -1
  220. package/src/preview/components/UrlComponentPreview.tsx +1 -2
  221. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
  222. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
  223. package/src/routes/RebaseRoute.tsx +64 -35
  224. package/src/types/components/EntityFormActionsProps.tsx +1 -1
  225. package/src/types/components/EntityFormProps.tsx +3 -1
  226. package/src/types/fields.tsx +4 -3
  227. package/src/util/navigation_utils.ts +4 -3
  228. package/src/util/previews.ts +1 -1
  229. package/src/util/property_utils.tsx +22 -6
  230. package/src/util/resolutions.ts +2 -2
  231. package/dist/CollectionEditorDialog-MbvXGzEq.js.map +0 -1
  232. package/dist/CollectionsStudioView-D9X6aiAr.js.map +0 -1
  233. package/dist/ContentHomePage-CfVB1eUo.js.map +0 -1
  234. package/dist/ExportCollectionAction-CUwJg4F9.js.map +0 -1
  235. package/dist/ImportCollectionAction-DGa_SF_8.js.map +0 -1
  236. package/dist/PropertyEditView-C4nlYmAc.js.map +0 -1
  237. package/dist/RolesView-CNWxnR8e.js.map +0 -1
  238. package/dist/UsersView-YiTIcXkA.js.map +0 -1
  239. package/dist/index-CtzpHzMQ.js.map +0 -1
  240. package/dist/index-DKlrVD1m.js.map +0 -1
  241. package/dist/index-kHJXfLNI.js.map +0 -1
  242. package/dist/util-CwLmSpGp.js.map +0 -1
@@ -4,8 +4,15 @@ import { CSS } from "@dnd-kit/utilities";
4
4
  import { BoardSortableList } from "./BoardSortableList";
5
5
  import { BoardColumnTitle } from "./BoardColumnTitle";
6
6
  import { BoardItem, BoardItemViewProps } from "./board_types";
7
- import { ChipColorKey, ChipColorScheme, cls, defaultBorderMixin, IconButton , iconSize } from "@rebasepro/ui";
8
- import { PlusIcon } from "lucide-react";
7
+ import {
8
+ ChipColorKey,
9
+ ChipColorScheme,
10
+ cls,
11
+ defaultBorderMixin,
12
+ IconButton,
13
+ iconSize,
14
+ PlusIcon
15
+ } from "@rebasepro/ui";
9
16
 
10
17
  export interface BoardColumnProps<M extends Record<string, unknown>> {
11
18
  id: string;
@@ -1,4 +1,4 @@
1
- import { ChipColorKey, ChipColorScheme, getColorSchemeForKey, cls } from "@rebasepro/ui";
1
+ import { ChipColorKey, ChipColorScheme, getColorSchemeForKey, cls, Typography } from "@rebasepro/ui";
2
2
  import React, { useMemo } from "react";
3
3
 
4
4
  export interface BoardColumnTitleProps {
@@ -23,10 +23,11 @@ export function BoardColumnTitle({
23
23
  }, [color]);
24
24
 
25
25
  return (
26
- <h4
26
+ <Typography
27
+ variant="subtitle2"
28
+ component="h4"
27
29
  className={
28
30
  cls("py-3 px-3 transition-colors duration-200 flex-grow select-none relative outline-none focus:outline focus:outline-2 focus:outline-offset-2 flex items-center gap-3",
29
- "text-sm font-semibold text-surface-900 dark:text-surface-200",
30
31
  className)
31
32
  }
32
33
  {...props}
@@ -40,6 +41,6 @@ export function BoardColumnTitle({
40
41
  />
41
42
  )}
42
43
  {children}
43
- </h4>
44
+ </Typography>
44
45
  );
45
46
  }
@@ -94,8 +94,8 @@ export function EntityCard<M extends Record<string, unknown> = Record<string, un
94
94
  "cursor-pointer overflow-hidden group relative",
95
95
  "transition-all duration-200",
96
96
  "hover:shadow-lg hover:-translate-y-0.5",
97
- selected && "ring-2 ring-primary bg-surface-accent-50 dark:bg-surface-accent-950",
98
- highlighted && !selected && "ring-2 ring-primary ring-opacity-50 bg-surface-accent-50/50 dark:bg-surface-accent-950/50"
97
+ selected && "ring-2 ring-primary bg-surface-accent-50 dark:bg-surface-accent-900",
98
+ highlighted && !selected && "ring-2 ring-primary ring-opacity-50 bg-surface-accent-50/50 dark:bg-surface-accent-900"
99
99
  )}
100
100
  onClick={handleClick}
101
101
  >
@@ -1,13 +1,25 @@
1
1
 
2
2
  import type { EntityCollection } from "@rebasepro/types";
3
- import type { Property } from "@rebasepro/types";
4
3
  import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
- import { Entity, EntityTableController, EnumValueConfig, FilterValues, SaveEntityProps, SelectionController } from "@rebasepro/types";
4
+ import { Entity, EntityTableController, EnumValueConfig, SaveEntityProps, SelectionController } from "@rebasepro/types";
6
5
  import { Board } from "./Board";
7
6
  import { BoardItem, BoardItemViewProps, ColumnLoadingState } from "./board_types";
8
7
  import { EntityBoardCard } from "./EntityBoardCard";
9
- import { Button, ChipColorKey, ChipColorScheme, CircularProgress, Dialog, DialogActions, DialogContent, getColorSchemeForSeed, IconButton, Tooltip, Typography , iconSize } from "@rebasepro/ui";
10
- import { RefreshCwIcon } from "lucide-react";
8
+ import {
9
+ Button,
10
+ ChipColorKey,
11
+ ChipColorScheme,
12
+ CircularProgress,
13
+ Dialog,
14
+ DialogActions,
15
+ DialogContent,
16
+ getColorSchemeForSeed,
17
+ IconButton,
18
+ iconSize,
19
+ RefreshCwIcon,
20
+ Tooltip,
21
+ Typography
22
+ } from "@rebasepro/ui";
11
23
  import { resolveEnumValues } from "@rebasepro/common";
12
24
  import { getPropertyInPath } from "../../util/property_utils";
13
25
  import {
@@ -58,7 +70,6 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
58
70
  emptyComponent,
59
71
  deletedEntities
60
72
  }: EntityCollectionBoardViewProps<M>) {
61
- const authController = useAuthController();
62
73
  const customizationController = useCustomizationController();
63
74
  const context = useRebaseContext();
64
75
  const dataClient = useData();
@@ -245,7 +256,6 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
245
256
 
246
257
  useEffect(() => {
247
258
  const currentDataClient = dataClientRef.current;
248
- const currentCollection = collectionRef.current;
249
259
  const accessor = currentDataClient.collection(fullPath);
250
260
 
251
261
  if (!orderProperty || !accessor.count) {
@@ -351,9 +361,7 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
351
361
 
352
362
  // Backfill order values for all entities
353
363
  const handleBackfill = useCallback(async () => {
354
- console.log("handleBackfill called", { orderProperty });
355
364
  if (!orderProperty) {
356
- console.log("No orderProperty, returning");
357
365
  return;
358
366
  }
359
367
  analyticsController.onAnalyticsEvent?.("kanban_backfill_order", {
@@ -363,19 +371,16 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
363
371
 
364
372
  try {
365
373
  // Fetch ALL documents from collection (not relying on loaded entities)
366
- console.log("Fetching all documents from collection...");
367
374
  const allDocsRes = await dataClient.collection(fullPath).find({
368
375
  limit: 10000 // Fetch all
369
376
  });
370
377
  const allDocs = allDocsRes.data as Entity<M>[];
371
- console.log(`Fetched ${allDocs.length} documents`);
372
378
 
373
379
  // Find entities missing order property
374
380
  const entitiesToUpdate = allDocs.filter((entity: Entity<M>) => {
375
381
  const orderValue = entity.values?.[orderProperty];
376
382
  return orderValue === undefined || orderValue === null;
377
383
  });
378
- console.log(`${entitiesToUpdate.length} entities need order values`);
379
384
 
380
385
  // Generate string fractional keys for all entities that need them
381
386
  const keys = generateNKeysBetween(null, null, entitiesToUpdate.length);
@@ -404,9 +409,7 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
404
409
  );
405
410
  });
406
411
 
407
- console.log(`Total updates to run: ${updates.length}`);
408
412
  await Promise.all(updates);
409
- console.log("All updates complete");
410
413
  setShowBackfillDialog(false);
411
414
 
412
415
  // Reset missing count to hide banner
@@ -456,7 +459,6 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
456
459
  // Uses refs for ALL dynamic values so the component type never changes.
457
460
  // When ItemComponent identity changes, React.memo'd SortableItem remounts
458
461
  // the card → DOM is destroyed/recreated → CSS :hover state is lost → flicker.
459
- // eslint-disable-next-line react-hooks/exhaustive-deps
460
462
  const ItemComponent = useMemo(() => {
461
463
  const Comp = (props: BoardItemViewProps<M>) => (
462
464
  <EntityBoardCard
@@ -479,7 +481,7 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
479
481
  parentCollectionSlugs,
480
482
  parentEntityIds
481
483
  });
482
- const KanbanSetupComponent = kanbanSetupSlots.length > 0 ? () => <>{kanbanSetupSlots[0]}</> : null;
484
+
483
485
 
484
486
  // Get AddKanbanColumnComponent from plugin slots
485
487
  const addKanbanColumnSlots = useSlot("kanban.add-column", {
@@ -488,7 +490,7 @@ export function EntityCollectionBoardView<M extends Record<string, unknown> = Re
488
490
  parentCollectionSlugs, parentEntityIds,
489
491
  columnProperty
490
492
  });
491
- const AddKanbanColumnComponent = addKanbanColumnSlots.length > 0 ? () => <>{addKanbanColumnSlots[0]}</> : null;
493
+
492
494
 
493
495
  // Check for loading error
494
496
  const hasError = Boolean(dataLoadingError);
@@ -7,7 +7,6 @@ import {
7
7
  CircularProgress,
8
8
  Typography
9
9
  } from "@rebasepro/ui";
10
- import { useAuthController, useCustomizationController } from "@rebasepro/core";
11
10
 
12
11
  export type EntityCollectionCardViewProps<M extends Record<string, unknown> = Record<string, unknown>> = {
13
12
  collection: EntityCollection<M>;
@@ -77,8 +76,6 @@ export function EntityCollectionCardView<M extends Record<string, unknown> = Rec
77
76
  initialScroll,
78
77
  size = "m"
79
78
  }: EntityCollectionCardViewProps<M>) {
80
- const authController = useAuthController();
81
- const customizationController = useCustomizationController();
82
79
 
83
80
  const containerRef = useRef<HTMLDivElement>(null);
84
81
  const loadMoreRef = useRef<HTMLDivElement>(null);
@@ -98,28 +95,30 @@ export function EntityCollectionCardView<M extends Record<string, unknown> = Rec
98
95
  // Track if we're currently loading to prevent multiple simultaneous load requests
99
96
  const isLoadingMore = useRef(false);
100
97
 
101
- // Infinite scroll with Intersection Observer
98
+ // Keep mutable refs for values used in the IntersectionObserver callback
99
+ // to avoid re-creating the observer every time pagination state changes.
100
+ const paginationStateRef = useRef({ paginationEnabled, noMoreToLoad, dataLoading, itemCount, pageSize });
102
101
  useEffect(() => {
103
- if (!paginationEnabled || noMoreToLoad || dataLoading) {
104
- return;
105
- }
102
+ paginationStateRef.current = { paginationEnabled, noMoreToLoad, dataLoading, itemCount, pageSize };
103
+ }, [paginationEnabled, noMoreToLoad, dataLoading, itemCount, pageSize]);
106
104
 
107
- // Reset loading flag when dataLoading becomes false
108
- if (!dataLoading) {
109
- isLoadingMore.current = false;
110
- }
105
+ // Reset loading flag when new data arrives (separate effect, like list view)
106
+ useEffect(() => {
107
+ if (!dataLoading) isLoadingMore.current = false;
108
+ }, [dataLoading]);
111
109
 
110
+ // Infinite scroll with Intersection Observer — stable deps only
111
+ useEffect(() => {
112
112
  const observer = new IntersectionObserver(
113
113
  (entries) => {
114
- if (entries[0].isIntersecting && !dataLoading && !noMoreToLoad && !isLoadingMore.current) {
115
- // Prevent multiple load requests
114
+ const { paginationEnabled: pe, noMoreToLoad: nm, dataLoading: dl, itemCount: ic, pageSize: ps } = paginationStateRef.current;
115
+ if (entries[0].isIntersecting && pe && !dl && !nm && !isLoadingMore.current) {
116
116
  isLoadingMore.current = true;
117
- // Load more items
118
- setItemCount?.((itemCount ?? pageSize) + pageSize);
117
+ setItemCount?.((ic ?? ps) + ps);
119
118
  }
120
119
  },
121
120
  {
122
- root: containerRef.current, // Use the scroll container, not viewport
121
+ root: containerRef.current,
123
122
  rootMargin: "400px",
124
123
  threshold: 0
125
124
  }
@@ -130,7 +129,7 @@ export function EntityCollectionCardView<M extends Record<string, unknown> = Rec
130
129
  }
131
130
 
132
131
  return () => observer.disconnect();
133
- }, [paginationEnabled, noMoreToLoad, dataLoading, itemCount, pageSize, setItemCount]);
132
+ }, [setItemCount]);
134
133
 
135
134
  // Scroll restoration — deferred to after layout paint
136
135
  useEffect(() => {
@@ -1,14 +1,15 @@
1
1
 
2
2
  import type { EntityCollection, Property } from "@rebasepro/types";
3
3
  import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
- import { CollectionSize, Entity, EntityTableController, SelectionController } from "@rebasepro/types";
5
- import { getEntityImagePreviewPropertyKey } from "@rebasepro/common";
4
+ import { CollectionSize, Entity, EntityAction, EntityTableController, SelectionController } from "@rebasepro/types";
6
5
  import {
7
6
  Checkbox,
8
7
  Chip,
9
8
  CircularProgress,
10
9
  cls,
11
10
  defaultBorderMixin,
11
+ IconButton,
12
+ Tooltip,
12
13
  Typography
13
14
  } from "@rebasepro/ui";
14
15
  import { PropertyPreview } from "../../preview";
@@ -17,10 +18,12 @@ import {
17
18
  useCustomizationController
18
19
  } from "@rebasepro/core";
19
20
  import { useAnalyticsController } from "@rebasepro/core";
20
- import { getEntityTitlePropertyKey, getEntityPreviewKeys } from "../../util/previews";
21
+ import { getEntityPreviewKeys } from "../../util/previews";
21
22
  import { IconForView } from "@rebasepro/core";
22
23
  import { getValueInPath } from "@rebasepro/utils";
23
24
  import { useCollectionSlotKeys, resolveEntitySlots, type CollectionSlotKeys } from "./useEntityPreviewSlots";
25
+ import { useCMSContext } from "../../hooks/useCMSContext";
26
+ import { resolveEntityAction } from "../../util/resolutions";
24
27
 
25
28
  export type EntityCollectionListViewProps<M extends Record<string, unknown> = Record<string, unknown>> = {
26
29
  collection: EntityCollection<M>;
@@ -45,6 +48,22 @@ export type EntityCollectionListViewProps<M extends Record<string, unknown> = Re
45
48
  * row is visually highlighted with a primary accent.
46
49
  */
47
50
  selectedEntityId?: string | number;
51
+
52
+ /**
53
+ * Callback to get entity actions for a given entity.
54
+ * Only actions with `showActionsInListView: true` will be rendered.
55
+ */
56
+ getActionsForEntity?: (params: { entity?: Entity<M>, customEntityActions?: EntityAction[] }) => EntityAction[];
57
+
58
+ /**
59
+ * Full path of the collection, used as context for action handlers.
60
+ */
61
+ path?: string;
62
+
63
+ /**
64
+ * How entities open when an action triggers navigation.
65
+ */
66
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
48
67
  };
49
68
 
50
69
  type ListColumnDef = {
@@ -58,19 +77,6 @@ type ListColumnDef = {
58
77
  width: string;
59
78
  };
60
79
 
61
- /**
62
- * Get the number of preview property lines to show based on size
63
- */
64
- function getPreviewCount(size: CollectionSize): number {
65
- switch (size) {
66
- case "xs": return 0;
67
- case "s": return 1;
68
- case "m": return 2;
69
- case "l": return 3;
70
- case "xl": return 4;
71
- default: return 2;
72
- }
73
- }
74
80
 
75
81
 
76
82
  /**
@@ -107,6 +113,9 @@ const OVERSCAN_COUNT = 8;
107
113
  /** Threshold in pixels from the bottom of the scroll area to trigger loading more. */
108
114
  const LOAD_MORE_THRESHOLD = 400;
109
115
 
116
+ /** Stable empty array for when no list-view actions are available. */
117
+ const EMPTY_LIST_VIEW_ACTIONS: EntityAction[] = [];
118
+
110
119
  /**
111
120
  * Walk up the DOM from `element` to find the nearest scrollable ancestor.
112
121
  */
@@ -262,11 +271,15 @@ export function EntityCollectionListView<M extends Record<string, unknown> = Rec
262
271
  emptyComponent,
263
272
 
264
273
  size = "m",
265
- selectedEntityId
274
+ selectedEntityId,
275
+ getActionsForEntity,
276
+ path,
277
+ openEntityMode
266
278
  }: EntityCollectionListViewProps<M>) {
267
279
  const authController = useAuthController();
268
280
  const customizationController = useCustomizationController();
269
281
  const analyticsController = useAnalyticsController();
282
+ const context = useCMSContext();
270
283
 
271
284
  const containerRef = useRef<HTMLDivElement>(null);
272
285
  const [containerWidth, setContainerWidth] = useState(1200);
@@ -475,6 +488,15 @@ export function EntityCollectionListView<M extends Record<string, unknown> = Rec
475
488
  return highlightedEntities?.some(e => e.id === entity.id && e.path === entity.path) ?? false;
476
489
  }, [highlightedEntities]);
477
490
 
491
+ // ── Compute list-view-visible actions per entity ──
492
+ const getListViewActions = useCallback((entity: Entity<M>): EntityAction[] => {
493
+ if (!getActionsForEntity) return EMPTY_LIST_VIEW_ACTIONS;
494
+ const customEntityActions = (collection.entityActions ?? [])
495
+ .map(action => resolveEntityAction(action, customizationController.entityActions))
496
+ .filter(Boolean) as EntityAction<M>[];
497
+ const allActions = getActionsForEntity({ entity, customEntityActions });
498
+ return allActions.filter(a => a.showActionsInListView);
499
+ }, [getActionsForEntity, collection.entityActions, customizationController.entityActions]);
478
500
 
479
501
  const rowClasses = getRowClasses(size);
480
502
 
@@ -615,6 +637,11 @@ export function EntityCollectionListView<M extends Record<string, unknown> = Rec
615
637
  size={size}
616
638
  isLast={isLast}
617
639
  isActive={selectedEntityId !== undefined && entity.id === selectedEntityId}
640
+ listViewActions={getListViewActions(entity)}
641
+ context={context}
642
+ path={path}
643
+ selectionController={selectionController}
644
+ openEntityMode={openEntityMode}
618
645
  />
619
646
  </div>
620
647
  );
@@ -668,7 +695,12 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
668
695
  showImage,
669
696
  size,
670
697
  isLast,
671
- isActive = false
698
+ isActive = false,
699
+ listViewActions = [],
700
+ context,
701
+ path,
702
+ selectionController,
703
+ openEntityMode
672
704
  }: {
673
705
  entity: Entity<M>;
674
706
  collection: EntityCollection<M>;
@@ -684,6 +716,11 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
684
716
  size: CollectionSize;
685
717
  isLast: boolean;
686
718
  isActive?: boolean;
719
+ listViewActions?: EntityAction[];
720
+ context?: ReturnType<typeof useCMSContext>;
721
+ path?: string;
722
+ selectionController?: SelectionController<M>;
723
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
687
724
  }) {
688
725
  // ── Resolve slots (pure function, no hooks) ──
689
726
  const slots = resolveEntitySlots(
@@ -720,11 +757,11 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
720
757
  "flex items-center gap-4 cursor-pointer group transition-colors duration-200 relative h-full",
721
758
  rowClasses,
722
759
  isActive
723
- ? "bg-surface-accent-100 dark:bg-surface-accent-950 hover:bg-surface-accent-200 dark:hover:bg-surface-accent-900"
760
+ ? "bg-surface-accent-100 dark:bg-surface-accent-950 hover:bg-surface-accent-200 dark:hover:bg-surface-accent-950"
724
761
  : selected
725
- ? "bg-surface-accent-50 dark:bg-surface-accent-950 hover:bg-surface-accent-100 dark:hover:bg-surface-accent-900"
762
+ ? "bg-surface-accent-50 dark:bg-surface-accent-900 hover:bg-surface-accent-100 dark:hover:bg-surface-accent-950"
726
763
  : highlighted
727
- ? "bg-surface-accent-50 dark:bg-surface-accent-950 hover:bg-surface-50 dark:hover:bg-surface-800/40"
764
+ ? "bg-surface-accent-50 dark:bg-surface-accent-900 hover:bg-surface-50 dark:hover:bg-surface-800/40"
728
765
  : "bg-white dark:bg-surface-900 hover:bg-surface-50 dark:hover:bg-surface-800/40"
729
766
  )}
730
767
  onClick={handleClick}
@@ -898,6 +935,33 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
898
935
  )}
899
936
  </div>
900
937
  )}
938
+
939
+ {/* LIST VIEW ACTIONS — always visible on each row */}
940
+ {listViewActions.length > 0 && (
941
+ <div className="flex items-center gap-0.5 flex-shrink-0 ml-auto" onClick={(e) => e.stopPropagation()}>
942
+ {listViewActions.map((action, index) => (
943
+ <Tooltip key={action.key ?? index} title={action.name} asChild>
944
+ <IconButton
945
+ size="small"
946
+ onClick={(e: React.MouseEvent) => {
947
+ e.stopPropagation();
948
+ action.onClick({
949
+ view: "collection",
950
+ entity,
951
+ path,
952
+ collection,
953
+ context: context!,
954
+ sideEntityController: context?.sideEntityController,
955
+ selectionController,
956
+ openEntityMode: openEntityMode ?? collection?.openEntityMode ?? "full_screen"
957
+ });
958
+ }}>
959
+ {action.icon}
960
+ </IconButton>
961
+ </Tooltip>
962
+ ))}
963
+ </div>
964
+ )}
901
965
  </div>
902
966
  );
903
967
  }) as <M extends Record<string, unknown>>(props: {
@@ -915,5 +979,10 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
915
979
  size: CollectionSize;
916
980
  isLast: boolean;
917
981
  isActive?: boolean;
982
+ listViewActions?: EntityAction[];
983
+ context?: ReturnType<typeof useCMSContext>;
984
+ path?: string;
985
+ selectionController?: SelectionController<M>;
986
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
918
987
  }) => React.ReactElement;
919
988
 
@@ -5,10 +5,11 @@ import React, { useCallback, useEffect, useMemo, useState } from "react";
5
5
 
6
6
  import { deepEqual as equal } from "fast-equals"
7
7
 
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- used as fallback for many array types
8
9
  const EMPTY_ARRAY: any[] = [];
9
10
  const DEFAULT_ENTITY_OPEN_MODE = "split";
10
11
 
11
- import { CollectionSize, Entity, EntityReference, EntityTableController, FilterValues, PartialEntityCollection, SaveEntityProps, ViewMode } from "@rebasepro/types";
12
+ import { CollectionSize, Entity, EntityReference, EntityTableController, FilterValues, PartialEntityCollection, ViewMode } from "@rebasepro/types";
12
13
  import {
13
14
  EntityCollectionRowActions,
14
15
  EntityCollectionTable
@@ -22,7 +23,6 @@ import { resolveEntityAction } from "../../util/resolutions";
22
23
  import { getPropertyInPath } from "../../util/property_utils";
23
24
  import { ReferencePreview } from "../../preview";
24
25
  import {
25
- saveEntityWithCallbacks,
26
26
  useAuthController,
27
27
  useCustomizationController,
28
28
  useData,
@@ -41,7 +41,7 @@ import { SplitListView } from "./SplitListView";
41
41
  import { EntityCollectionBoardView } from "./EntityCollectionBoardView";
42
42
  import { ViewModeToggle, KanbanPropertyOption } from "./ViewModeToggle";
43
43
  import { Button, cls, focusedDisabled, IconButton, Markdown, Popover, Skeleton, Tooltip, Typography, VirtualTableColumn , iconSize } from "@rebasepro/ui";
44
- import { PlusIcon, ArrowRightToLineIcon, SearchIcon } from "lucide-react";
44
+ import { ArrowRightToLineIcon, ErrorBoundary, PlusIcon, SearchIcon } from "@rebasepro/ui";
45
45
  import { setIn } from "@rebasepro/formex";
46
46
  import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
47
47
  import {
@@ -59,15 +59,14 @@ import { useSelectionController } from "./useSelectionController";
59
59
  import { EntityCollectionViewStartActions } from "./EntityCollectionViewStartActions";
60
60
  import { addRecentId, getRecentIds } from "./utils";
61
61
  import { useScrollRestoration } from "@rebasepro/core";
62
- import { ErrorBoundary } from "@rebasepro/ui";
63
62
  import { mergeDeep } from "@rebasepro/utils";
64
63
  import { useCollectionRegistryController, useUrlController, useSideEntityController, useCMSContext } from "../../index";
65
64
  import { useBreadcrumbsController } from "../../index";
66
65
 
67
66
  function getOpenEntityMode(
68
67
  viewMode: ViewMode,
69
- configuredMode?: "side_panel" | "full_screen" | "split"
70
- ): "side_panel" | "full_screen" | "split" {
68
+ configuredMode?: "side_panel" | "full_screen" | "split" | "dialog"
69
+ ): "side_panel" | "full_screen" | "split" | "dialog" {
71
70
  if (configuredMode) return configuredMode;
72
71
  if (viewMode === "kanban") return "side_panel";
73
72
  if (viewMode === "table" || viewMode === "cards") return "full_screen";
@@ -671,10 +670,14 @@ export const EntityCollectionView = React.memo(
671
670
  customEntityActions?: EntityAction[]
672
671
  }): EntityAction[] => {
673
672
  const deleteEnabled = entity ? canDelete(collection, path, entity) : true;
674
- const actions: EntityAction[] = [editEntityAction];
675
- if (createEnabled)
673
+ const disableActions = collection.disableDefaultActions ?? [];
674
+ const actions: EntityAction[] = [];
675
+ if (!disableActions.includes("edit")) {
676
+ actions.push(editEntityAction);
677
+ }
678
+ if (createEnabled && !disableActions.includes("copy"))
676
679
  actions.push(copyEntityAction);
677
- if (deleteEnabled)
680
+ if (deleteEnabled && !disableActions.includes("delete"))
678
681
  actions.push(deleteEntityAction);
679
682
  if (customEntityActions)
680
683
  return mergeEntityActions(actions, customEntityActions);
@@ -771,8 +774,8 @@ export const EntityCollectionView = React.memo(
771
774
  propertyKey,
772
775
  onHover,
773
776
  path,
774
- collection: collection as unknown as EntityCollection,
775
- tableController: tableController as unknown as EntityTableController,
777
+ collection: collection as EntityCollection,
778
+ tableController: tableController as EntityTableController,
776
779
  parentCollectionSlugs: parentCollectionSlugs ?? EMPTY_ARRAY, parentEntityIds: parentEntityIds ?? EMPTY_ARRAY
777
780
  };
778
781
  return <>{headerActionContributions.map((s, i) => (
@@ -953,6 +956,9 @@ export const EntityCollectionView = React.memo(
953
956
  highlightedEntities={highlightedEntity ? [highlightedEntity] : []}
954
957
  size={listSize}
955
958
  emptyComponent={emptyComponent}
959
+ getActionsForEntity={getActionsForEntity}
960
+ path={path}
961
+ openEntityMode={openEntityMode}
956
962
  />
957
963
  ) : (
958
964
  <EntityCollectionTable
@@ -1074,6 +1080,9 @@ export const EntityCollectionView = React.memo(
1074
1080
  size={listSize}
1075
1081
  emptyComponent={emptyComponent}
1076
1082
  selectedEntityId={selectedEntityIdProp}
1083
+ getActionsForEntity={getActionsForEntity}
1084
+ path={path}
1085
+ openEntityMode={openEntityMode}
1077
1086
  />
1078
1087
  </div>
1079
1088
  ) : (
@@ -5,11 +5,10 @@ import React, { lazy, Suspense } from "react";
5
5
  import { useLargeLayout, useTranslation, useSlot, resolveComponentRef } from "@rebasepro/core";
6
6
  import { CollectionActionsProps, EntityTableController, SelectionController } from "@rebasepro/types";
7
7
  import { Button, IconButton, Tooltip, Popover, iconSize } from "@rebasepro/ui";
8
- import { PlusIcon, Trash2Icon, MoreVerticalIcon } from "lucide-react";
9
- import { ErrorBoundary } from "@rebasepro/ui";
8
+ import { ErrorBoundary, MoreVerticalIcon, PlusIcon, Trash2Icon } from "@rebasepro/ui";
10
9
  import { usePermissions } from "@rebasepro/core";
11
10
  import { toArray } from "@rebasepro/utils";
12
- // Lazy-load import/export — pulls in xlsx (~800KB) only on demand
11
+ // Lazy-load import/export — pulls in exceljs only on demand
13
12
  const ImportCollectionAction = lazy(() => import("../../data_import/import").then(m => ({ default: m.ImportCollectionAction })));
14
13
  const ExportCollectionAction = lazy(() => import("../../data_export/export").then(m => ({ default: m.ExportCollectionAction })));
15
14
  import { EditorCollectionAction } from "../../collection_editor/ui/EditorCollectionAction";
@@ -135,7 +134,7 @@ export function EntityCollectionViewActions<M extends Record<string, unknown>>({
135
134
  );
136
135
  });
137
136
 
138
- const pluginActions = useSlot("collection.actions", actionProps as any);
137
+ const pluginActions = useSlot("collection.actions", actionProps as CollectionActionsProps);
139
138
 
140
139
  const secondaryActions = (
141
140
  <>
@@ -146,17 +145,17 @@ export function EntityCollectionViewActions<M extends Record<string, unknown>>({
146
145
  </ErrorBoundary>
147
146
  <ErrorBoundary>
148
147
  <Suspense fallback={null}>
149
- <ImportCollectionAction {...(actionProps as any)}/>
148
+ <ImportCollectionAction {...(actionProps as CollectionActionsProps)}/>
150
149
  </Suspense>
151
150
  </ErrorBoundary>
152
151
  <ErrorBoundary>
153
152
  <Suspense fallback={null}>
154
- <ExportCollectionAction {...(actionProps as any)}/>
153
+ <ExportCollectionAction {...(actionProps as CollectionActionsProps)}/>
155
154
  </Suspense>
156
155
  </ErrorBoundary>
157
156
  {hasCollectionEditor && (
158
157
  <ErrorBoundary>
159
- <EditorCollectionAction {...(actionProps as any)}/>
158
+ <EditorCollectionAction {...(actionProps as CollectionActionsProps)}/>
160
159
  </ErrorBoundary>
161
160
  )}
162
161
  </>
@@ -4,10 +4,10 @@ import React, { useState, useCallback } from "react";
4
4
  import { useAuthController, useLargeLayout, useTranslation, useSlot } from "@rebasepro/core";
5
5
  import { CollectionActionsProps, EntityTableController, SelectionController } from "@rebasepro/types";
6
6
  import { ErrorBoundary , iconSize } from "@rebasepro/ui";
7
- import { ArrowLeftIcon, FilterIcon } from "lucide-react";
7
+ import { ArrowLeftIcon, Badge, Button, cls, FilterIcon, IconButton, Tooltip } from "@rebasepro/ui";
8
8
  import { ClearFilterSortButton } from "../ClearFilterSortButton";
9
9
  import { FiltersDialog } from "./FiltersDialog";
10
- import { Badge, Button, cls, IconButton, Tooltip } from "@rebasepro/ui";
10
+ import { FilterPresetsButton } from "./FilterPresetsButton";
11
11
  import { toArray } from "@rebasepro/utils";
12
12
  import { useNavigate } from "react-router-dom";
13
13
  import { useUrlController, useCMSContext } from "../../index";
@@ -92,7 +92,6 @@ export function EntityCollectionViewStartActions<M extends Record<string, unknow
92
92
  </Tooltip>
93
93
  );
94
94
 
95
- // Filters button
96
95
  const filtersButton = resolvedProperties && tableController.setFilterValues && (
97
96
  <Tooltip title={t("filters")}
98
97
  key={"filters_tooltip"}>
@@ -108,7 +107,7 @@ export function EntityCollectionViewStartActions<M extends Record<string, unknow
108
107
  startIcon={<FilterIcon size={iconSize.small}/>}
109
108
  className={cls(activeFilterCount > 0 && "text-primary")}
110
109
  >
111
- {t("filters")}{activeFilterCount > 0 ? ` (${activeFilterCount})` : ""}
110
+ {activeFilterCount > 0 ? `(${activeFilterCount})` : t("filters")}
112
111
  </Button>
113
112
  ) : (
114
113
  <Button
@@ -124,13 +123,23 @@ export function EntityCollectionViewStartActions<M extends Record<string, unknow
124
123
  </Tooltip>
125
124
  );
126
125
 
126
+ const filterPresetsButton = collection.filterPresets?.length ? (
127
+ <FilterPresetsButton
128
+ key={"filter_presets"}
129
+ filterPresets={collection.filterPresets}
130
+ tableController={tableController}
131
+ compact={compact}
132
+ />
133
+ ) : null;
134
+
127
135
  const actions: React.ReactNode[] = [
128
136
  backButton,
129
137
  filtersButton,
130
138
  <ClearFilterSortButton
131
139
  key={"clear_filter"}
132
140
  tableController={tableController}
133
- enabled={!collection.fixedFilter}/>
141
+ enabled={!collection.fixedFilter}/>,
142
+ filterPresetsButton
134
143
  ];
135
144
 
136
145
  const pluginActionsStart = useSlot("collection.actions.start", actionProps);