@firecms/core 3.0.0-beta.7 → 3.0.0-beta.8

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 (94) hide show
  1. package/dist/app/AppBar.d.ts +12 -0
  2. package/dist/app/Drawer.d.ts +17 -0
  3. package/dist/app/Scaffold.d.ts +30 -0
  4. package/dist/app/index.d.ts +4 -0
  5. package/dist/app/useApp.d.ts +16 -0
  6. package/dist/components/VirtualTable/VirtualTableProps.d.ts +4 -0
  7. package/dist/components/index.d.ts +1 -1
  8. package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +2 -7
  9. package/dist/core/DefaultDrawer.d.ts +19 -0
  10. package/dist/core/EntityEditView.d.ts +17 -3
  11. package/dist/core/NavigationRoutes.d.ts +1 -1
  12. package/dist/core/index.d.ts +2 -2
  13. package/dist/form/PropertiesForm.d.ts +8 -0
  14. package/dist/form/components/FieldHelperText.d.ts +3 -3
  15. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  16. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  17. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +2 -4
  18. package/dist/form/index.d.ts +0 -2
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.es.js +5595 -5574
  21. package/dist/index.es.js.map +1 -1
  22. package/dist/index.umd.js +5 -5
  23. package/dist/index.umd.js.map +1 -1
  24. package/dist/preview/PropertyPreviewProps.d.ts +5 -0
  25. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  26. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  27. package/dist/types/auth.d.ts +1 -1
  28. package/dist/types/collections.d.ts +14 -0
  29. package/dist/types/datasource.d.ts +18 -8
  30. package/dist/types/fields.d.ts +31 -30
  31. package/dist/types/plugins.d.ts +11 -3
  32. package/dist/types/properties.d.ts +7 -2
  33. package/dist/util/icons.d.ts +2 -2
  34. package/dist/util/storage.d.ts +23 -2
  35. package/dist/util/useStorageUploadController.d.ts +1 -1
  36. package/package.json +13 -22
  37. package/src/app/AppBar.tsx +18 -0
  38. package/src/app/Drawer.tsx +25 -0
  39. package/src/{core → app}/Scaffold.tsx +61 -107
  40. package/src/app/index.ts +4 -0
  41. package/src/app/useApp.tsx +32 -0
  42. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +7 -9
  43. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -1
  44. package/src/components/EntityCollectionView/EntityCollectionView.tsx +7 -4
  45. package/src/components/VirtualTable/VirtualTable.tsx +3 -1
  46. package/src/components/VirtualTable/VirtualTableProps.tsx +5 -0
  47. package/src/components/common/useTableSearchHelper.ts +52 -12
  48. package/src/components/index.tsx +1 -1
  49. package/src/contexts/DialogsProvider.tsx +2 -2
  50. package/src/{components/FireCMSAppBar.tsx → core/DefaultAppBar.tsx} +26 -28
  51. package/src/core/DefaultDrawer.tsx +177 -0
  52. package/src/core/EntityEditView.tsx +669 -129
  53. package/src/core/EntitySidePanel.tsx +0 -1
  54. package/src/core/NavigationRoutes.tsx +3 -3
  55. package/src/core/index.tsx +2 -2
  56. package/src/form/PropertiesForm.tsx +81 -0
  57. package/src/form/PropertyFieldBinding.tsx +29 -5
  58. package/src/form/components/FieldHelperText.tsx +3 -3
  59. package/src/form/components/StorageItemPreview.tsx +19 -10
  60. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +8 -5
  61. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -4
  62. package/src/form/field_bindings/KeyValueFieldBinding.tsx +40 -35
  63. package/src/form/field_bindings/MapFieldBinding.tsx +11 -3
  64. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +0 -7
  65. package/src/form/field_bindings/RepeatFieldBinding.tsx +10 -7
  66. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +6 -35
  67. package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -1
  68. package/src/form/index.tsx +4 -4
  69. package/src/form/validation.ts +1 -17
  70. package/src/index.ts +1 -0
  71. package/src/internal/useBuildDataSource.ts +12 -0
  72. package/src/preview/PropertyPreview.tsx +5 -2
  73. package/src/preview/PropertyPreviewProps.tsx +6 -0
  74. package/src/preview/components/ImagePreview.tsx +21 -33
  75. package/src/preview/components/ReferencePreview.tsx +2 -1
  76. package/src/preview/components/StorageThumbnail.tsx +5 -1
  77. package/src/preview/components/UrlComponentPreview.tsx +44 -11
  78. package/src/types/auth.tsx +1 -1
  79. package/src/types/collections.ts +14 -0
  80. package/src/types/customization_controller.tsx +0 -1
  81. package/src/types/datasource.ts +20 -16
  82. package/src/types/fields.tsx +33 -33
  83. package/src/types/plugins.tsx +12 -3
  84. package/src/types/properties.ts +7 -2
  85. package/src/util/entities.ts +4 -3
  86. package/src/util/objects.ts +17 -7
  87. package/src/util/permissions.ts +1 -0
  88. package/src/util/storage.ts +75 -21
  89. package/src/util/useStorageUploadController.tsx +21 -3
  90. package/dist/core/Drawer.d.ts +0 -16
  91. package/dist/core/Scaffold.d.ts +0 -51
  92. package/dist/form/EntityForm.d.ts +0 -77
  93. package/src/core/Drawer.tsx +0 -139
  94. package/src/form/EntityForm.tsx +0 -736
@@ -1,55 +1,16 @@
1
1
  import React, { PropsWithChildren, useCallback } from "react";
2
- import equal from "react-fast-compare"
3
- import { Link } from "react-router-dom";
4
-
5
- import { Drawer as DefaultDrawer, DrawerProps } from "./Drawer";
6
- import { useLargeLayout, useNavigationController } from "../hooks";
7
- import { ErrorBoundary, FireCMSAppBar as DefaultFireCMSAppBar, FireCMSAppBarProps, FireCMSLogo } from "../components";
8
2
  import { ChevronLeftIcon, cls, defaultBorderMixin, IconButton, MenuIcon, Sheet, Tooltip } from "@firecms/ui";
3
+ import equal from "react-fast-compare"
4
+ import { useLargeLayout } from "../hooks";
5
+ import { ErrorBoundary } from "../components";
6
+ import { AppContext } from "./useApp";
9
7
 
10
8
  export const DRAWER_WIDTH = 280;
11
9
 
12
- const DrawerContext = React.createContext<DrawerProps>({
13
- hovered: false,
14
- drawerOpen: false,
15
- openDrawer: () => {
16
- throw new Error("openDrawer not implemented");
17
- },
18
- closeDrawer: () => {
19
- throw new Error("closeDrawer not implemented");
20
- },
21
- autoOpenDrawer: false
22
- });
23
-
24
- export function useDrawer() {
25
- return React.useContext(DrawerContext);
26
- }
27
-
28
10
  /**
29
11
  * @group Core
30
12
  */
31
- export interface ScaffoldProps<ExtraAppbarProps = object> {
32
-
33
- /**
34
- * Name of the app, displayed as the main title and in the tab title
35
- */
36
- name?: React.ReactNode;
37
-
38
- /**
39
- * Logo to be displayed in the drawer of the CMS
40
- */
41
- logo?: string;
42
-
43
- /**
44
- * Whether to include the drawer in the scaffold
45
- */
46
- includeDrawer?: boolean;
47
-
48
- /**
49
- * You can define a custom drawer to be displayed in the scaffold.
50
- * Use the hook `useDrawer` to access the context values.
51
- */
52
- drawer?: React.ReactNode;
13
+ export interface ScaffoldProps {
53
14
 
54
15
  /**
55
16
  * Open the drawer on hover
@@ -57,15 +18,14 @@ export interface ScaffoldProps<ExtraAppbarProps = object> {
57
18
  autoOpenDrawer?: boolean;
58
19
 
59
20
  /**
60
- * The AppBar component to be used in the scaffold.
21
+ * Logo to be displayed in the top bar and drawer.
22
+ * Note that this has no effect if you are using a custom AppBar or Drawer.
61
23
  */
62
- FireCMSAppBar?: React.ComponentType<FireCMSAppBarProps<ExtraAppbarProps>>;
24
+ logo?: string;
63
25
 
64
- /**
65
- * Additional props passed to the custom AppBar
66
- */
67
- fireCMSAppBarProps?: Partial<FireCMSAppBarProps> & ExtraAppbarProps;
26
+ className?: string;
68
27
 
28
+ style?: React.CSSProperties;
69
29
  }
70
30
 
71
31
  /**
@@ -84,15 +44,23 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
84
44
 
85
45
  const {
86
46
  children,
87
- name,
88
- logo,
89
- includeDrawer = true,
90
47
  autoOpenDrawer,
91
- drawer = <DefaultDrawer/>,
92
- FireCMSAppBar = DefaultFireCMSAppBar,
93
- fireCMSAppBarProps,
48
+ logo,
49
+ className,
50
+ style
94
51
  } = props;
95
52
 
53
+ const drawerChildren = React.Children.toArray(children).filter((child: any) => child.type.componentType === "Drawer");
54
+ if (drawerChildren.length > 1) {
55
+ throw Error("Only one Drawer component is allowed in Scaffold");
56
+ }
57
+ const appBarChildren = React.Children.toArray(children).filter((child: any) => child.type.componentType === "AppBar");
58
+ if (appBarChildren.length > 1) {
59
+ throw Error("Only one AppBar component is allowed in Scaffold");
60
+ }
61
+ const otherChildren = React.Children.toArray(children)
62
+ .filter((child: any) => child.type.componentType !== "Drawer" && child.type.componentType !== "AppBar");
63
+ const includeDrawer = drawerChildren.length > 0;
96
64
  const largeLayout = useLargeLayout();
97
65
 
98
66
  const [drawerOpen, setDrawerOpen] = React.useState(false);
@@ -112,38 +80,37 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
112
80
  const computedDrawerOpen: boolean = drawerOpen || Boolean(largeLayout && autoOpenDrawer && onHover);
113
81
 
114
82
  return (
115
- <DrawerContext.Provider value={{
116
- hovered: onHover,
83
+ <AppContext.Provider value={{
84
+ logo,
85
+ hasDrawer: includeDrawer,
86
+ drawerHovered: onHover,
117
87
  drawerOpen: computedDrawerOpen,
118
88
  closeDrawer: handleDrawerClose,
119
89
  openDrawer: handleDrawerOpen,
120
90
  autoOpenDrawer
121
91
  }}>
122
92
  <div
123
- className="flex h-screen w-screen bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white overflow-hidden"
93
+ className={cls("flex h-screen w-screen bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white overflow-hidden", className)}
124
94
  style={{
125
95
  paddingTop: "env(safe-area-inset-top)",
126
96
  paddingLeft: "env(safe-area-inset-left)",
127
97
  paddingRight: "env(safe-area-inset-right)",
128
98
  paddingBottom: "env(safe-area-inset-bottom)",
129
- height: "100dvh"
99
+ height: "100dvh",
100
+ ...style
130
101
  }}>
131
102
 
132
- <FireCMSAppBar title={name}
133
- includeDrawer={includeDrawer}
134
- logo={logo}
135
- drawerOpen={computedDrawerOpen}
136
- {...fireCMSAppBarProps}/>
103
+ {appBarChildren}
104
+
137
105
  <DrawerWrapper
138
106
  displayed={includeDrawer}
139
107
  onMouseEnter={setOnHoverTrue}
140
108
  onMouseMove={setOnHoverTrue}
141
109
  onMouseLeave={setOnHoverFalse}
142
110
  open={computedDrawerOpen}
143
- logo={logo}
144
111
  hovered={onHover}
145
112
  setDrawerOpen={setDrawerOpen}>
146
- {includeDrawer && drawer}
113
+ {includeDrawer && drawerChildren}
147
114
  </DrawerWrapper>
148
115
 
149
116
  <main
@@ -153,13 +120,13 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
153
120
  className={cls(defaultBorderMixin, "flex-grow overflow-auto lg:m-0 lg:mx-4 lg:mb-4 lg:rounded-lg lg:border lg:border-solid m-0 mt-1")}>
154
121
 
155
122
  <ErrorBoundary>
156
- {children}
123
+ {otherChildren}
157
124
  </ErrorBoundary>
158
125
 
159
126
  </div>
160
127
  </main>
161
128
  </div>
162
- </DrawerContext.Provider>
129
+ </AppContext.Provider>
163
130
  );
164
131
  },
165
132
  equal
@@ -183,8 +150,6 @@ function DrawerWrapper(props: {
183
150
  onMouseLeave: () => void
184
151
  }) {
185
152
 
186
- const navigation = useNavigationController();
187
-
188
153
  const width = !props.displayed ? 0 : (props.open ? DRAWER_WIDTH : 72);
189
154
  const innerDrawer = <div
190
155
  className={"relative h-full no-scrollbar overflow-y-auto overflow-x-hidden"}
@@ -198,7 +163,7 @@ function DrawerWrapper(props: {
198
163
  <Tooltip title="Open menu"
199
164
  side="right"
200
165
  sideOffset={12}
201
- className="fixed top-2 left-3 !bg-gray-50 dark:!bg-gray-900 rounded-full w-fit"
166
+ className="fixed top-2 left-3 !bg-gray-50 dark:!bg-gray-900 rounded-full w-fit z-20"
202
167
  >
203
168
  <IconButton
204
169
  color="inherit"
@@ -212,30 +177,19 @@ function DrawerWrapper(props: {
212
177
  </Tooltip>
213
178
  )}
214
179
 
215
- <div className={"flex flex-col h-full"}>
216
- <div
217
- style={{
218
- transition: "padding 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms",
219
- padding: props.open ? "32px 144px 0px 24px" : "72px 16px 0px"
220
- }}
221
- className={cls("cursor-pointer")}>
222
-
223
- <Tooltip title={"Home"}
224
- sideOffset={20}
225
- side="right">
226
- <Link
227
- to={navigation.basePath}>
228
- {props.logo
229
- ? <img src={props.logo}
230
- alt="Logo"
231
- className={cls("max-w-full max-h-full",
232
- props.open ?? "w-[112px] h-[112px]")}/>
233
- : <FireCMSLogo/>}
234
-
235
- </Link>
236
- </Tooltip>
237
- </div>
180
+ <div
181
+ className={`z-20 absolute right-0 top-4 ${
182
+ props.open ? "opacity-100" : "opacity-0 invisible"
183
+ } transition-opacity duration-200 ease-in-out`}>
184
+ <IconButton
185
+ aria-label="Close drawer"
186
+ onClick={() => props.setDrawerOpen(false)}
187
+ >
188
+ <ChevronLeftIcon/>
189
+ </IconButton>
190
+ </div>
238
191
 
192
+ <div className={"flex flex-col h-full"}>
239
193
  {props.children}
240
194
  </div>
241
195
 
@@ -267,7 +221,7 @@ function DrawerWrapper(props: {
267
221
 
268
222
  return (
269
223
  <div
270
- className="relative"
224
+ className="z-20 relative"
271
225
  onMouseEnter={props.onMouseEnter}
272
226
  onMouseMove={props.onMouseMove}
273
227
  onMouseLeave={props.onMouseLeave}
@@ -278,17 +232,17 @@ function DrawerWrapper(props: {
278
232
 
279
233
  {innerDrawer}
280
234
 
281
- <div
282
- className={`absolute right-0 top-4 ${
283
- props.open ? "opacity-100" : "opacity-0 invisible"
284
- } transition-opacity duration-1000 ease-in-out`}>
285
- <IconButton
286
- aria-label="Close drawer"
287
- onClick={() => props.setDrawerOpen(false)}
288
- >
289
- <ChevronLeftIcon/>
290
- </IconButton>
291
- </div>
235
+ {/*<div*/}
236
+ {/* className={`z-20 absolute right-0 top-4 ${*/}
237
+ {/* props.open ? "opacity-100" : "opacity-0 invisible"*/}
238
+ {/* } transition-opacity duration-1000 ease-in-out`}>*/}
239
+ {/* <IconButton*/}
240
+ {/* aria-label="Close drawer"*/}
241
+ {/* onClick={() => props.setDrawerOpen(false)}*/}
242
+ {/* >*/}
243
+ {/* <ChevronLeftIcon/>*/}
244
+ {/* </IconButton>*/}
245
+ {/*</div>*/}
292
246
 
293
247
  </div>
294
248
  );
@@ -0,0 +1,4 @@
1
+ export * from "./Drawer";
2
+ export * from "./AppBar";
3
+ export * from "./Scaffold";
4
+ export * from "./useApp";
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+
3
+ /**
4
+ * This context represents the state of the app in terms of layout.
5
+ * @group Core
6
+ */
7
+ export type AppState = {
8
+ hasDrawer: boolean,
9
+ drawerHovered: boolean,
10
+ drawerOpen: boolean,
11
+ openDrawer: () => void,
12
+ closeDrawer: () => void,
13
+ autoOpenDrawer?: boolean,
14
+ logo?: string
15
+ }
16
+
17
+ export const AppContext = React.createContext<AppState>({
18
+ hasDrawer: false,
19
+ drawerHovered: false,
20
+ drawerOpen: false,
21
+ openDrawer: () => {
22
+ throw new Error("openDrawer not implemented");
23
+ },
24
+ closeDrawer: () => {
25
+ throw new Error("closeDrawer not implemented");
26
+ },
27
+ autoOpenDrawer: false
28
+ });
29
+
30
+ export function useApp() {
31
+ return React.useContext(AppContext);
32
+ }
@@ -1,7 +1,7 @@
1
1
  import React, { MouseEvent, useCallback } from "react";
2
2
 
3
3
  import { CollectionSize, Entity, EntityAction, EntityCollection, SelectionController } from "../../types";
4
- import { Checkbox, cls, IconButton, Menu, MenuItem, MoreVertIcon, Skeleton, Tooltip, Typography } from "@firecms/ui";
4
+ import { Checkbox, cls, IconButton, Menu, MenuItem, MoreVertIcon, Skeleton, Tooltip } from "@firecms/ui";
5
5
  import { useFireCMSContext, useLargeLayout } from "../../hooks";
6
6
 
7
7
  /**
@@ -149,16 +149,14 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
149
149
  </div>}
150
150
 
151
151
  {!hideId && size !== "xs" && (
152
- <div className="w-[138px] text-center overflow-hidden truncate">
152
+ <div
153
+ className="w-[138px] text-center overflow-hidden truncate font-mono text-xs text-text-secondary dark:text-text-secondary-dark max-w-full text-ellipsis px-2"
154
+ onClick={(event) => {
155
+ event.stopPropagation();
156
+ }}>
153
157
 
154
158
  {entity
155
- ? <Typography
156
- onClick={(event) => {
157
- event.stopPropagation();
158
- }}
159
- className={"font-mono select-all"}
160
- variant={"caption"}
161
- color={"secondary"}> {entity.id} </Typography>
159
+ ? entity.id
162
160
  : <Skeleton/>
163
161
  }
164
162
  </div>
@@ -264,7 +264,8 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
264
264
  values,
265
265
  path,
266
266
  setFieldValue,
267
- save: saveValue
267
+ save: saveValue,
268
+ formex
268
269
  };
269
270
 
270
271
  const property: ResolvedProperty<any> | undefined = propertyKey && getPropertyInPath(collection.properties, propertyKey as string);
@@ -7,7 +7,7 @@ import {
7
7
  CollectionSize,
8
8
  Entity,
9
9
  EntityAction,
10
- EntityCollection,
10
+ EntityCollection, EntityTableController,
11
11
  FilterValues,
12
12
  PartialEntityCollection,
13
13
  PropertyOrBuilder,
@@ -266,6 +266,7 @@ export const EntityCollectionView = React.memo(
266
266
  fullPath: string,
267
267
  parentCollectionIds: string[],
268
268
  collection: EntityCollection;
269
+ tableController: EntityTableController;
269
270
  }> | undefined
270
271
 
271
272
  // we are only using the first plugin that implements this
@@ -368,12 +369,12 @@ export const EntityCollectionView = React.memo(
368
369
  return resolveProperty({
369
370
  propertyKey,
370
371
  propertyOrBuilder,
371
- path: fullPath,
372
+ path: entity.path,
372
373
  values: entity.values,
373
374
  entityId: entity.id,
374
375
  fields: customizationController.propertyConfigs
375
376
  });
376
- }, [collection.properties, customizationController.propertyConfigs, fullPath, resolvedCollection.properties]);
377
+ }, [collection.properties, customizationController.propertyConfigs, resolvedCollection.properties]);
377
378
 
378
379
  const displayedColumnIds = useColumnIds(resolvedCollection, true);
379
380
 
@@ -564,6 +565,7 @@ export const EntityCollectionView = React.memo(
564
565
  property={property}
565
566
  fullPath={fullPath}
566
567
  collection={collection}
568
+ tableController={tableController}
567
569
  parentCollectionIds={parentCollectionIds ?? []}/>;
568
570
  })}
569
571
  </>;
@@ -574,7 +576,8 @@ export const EntityCollectionView = React.memo(
574
576
  if (typeof AddColumnComponent === "function")
575
577
  return <AddColumnComponent fullPath={fullPath}
576
578
  parentCollectionIds={parentCollectionIds ?? []}
577
- collection={collection}/>;
579
+ collection={collection}
580
+ tableController={tableController}/>;
578
581
  return null;
579
582
  }
580
583
  : undefined;
@@ -107,6 +107,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
107
107
  hoverRow,
108
108
  createFilterField,
109
109
  rowClassName,
110
+ style,
110
111
  className,
111
112
  endAdornment,
112
113
  AddColumnComponent
@@ -239,7 +240,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
239
240
  const empty = !loading && (data?.length ?? 0) === 0;
240
241
  const customView = error
241
242
  ? <CenteredView maxWidth={"2xl"}
242
- className="flex flex-col gap-2">
243
+ className="flex flex-col gap-2">
243
244
 
244
245
  <Typography variant={"h6"}>
245
246
  {"Error fetching data from the data source"}
@@ -275,6 +276,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
275
276
  return (
276
277
  <div
277
278
  ref={measureRef}
279
+ style={style}
278
280
  className={cls("h-full w-full", className)}>
279
281
  <VirtualListContext.Provider
280
282
  value={virtualListController}>
@@ -131,6 +131,11 @@ export interface VirtualTableProps<T extends Record<string, any>> {
131
131
  */
132
132
  className?: string;
133
133
 
134
+ /**
135
+ * Style applied to the table
136
+ */
137
+ style?: React.CSSProperties;
138
+
134
139
  /**
135
140
  * Component rendered at the end of the table, after scroll
136
141
  */
@@ -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,57 @@ 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
+ collection,
32
+ parentCollectionIds
33
+ };
34
+
35
+ const searchBlocked = customizationController.plugins?.find(p => {
36
+ return p.collectionView?.blockSearch?.(props);
37
+ });
38
+
39
+ const addTextSearchClickListener = Boolean(dataSource?.initTextSearch) || customizationController.plugins?.find(p => Boolean(p.collectionView?.onTextSearchClick));
40
+
41
+ if (addTextSearchClickListener) {
23
42
 
24
43
  onTextSearchClick = addTextSearchClickListener
25
44
  ? () => {
26
45
  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) => {
46
+ const promises: Promise<boolean>[] = [];
47
+ if (dataSource?.initTextSearch && !searchBlocked) {
48
+ promises.push(dataSource.initTextSearch(props));
49
+ }
50
+ if (searchBlocked) {
51
+ customizationController.plugins?.forEach(p => {
52
+ if (p.collectionView?.onTextSearchClick)
53
+ promises.push(p.collectionView.onTextSearchClick({
54
+ context,
55
+ path: fullPath,
56
+ collection,
57
+ parentCollectionIds
58
+ }));
59
+ })
60
+ }
61
+ return Promise.all(promises)
62
+ .then((res: boolean[]) => {
33
63
  if (res.every(Boolean)) setTextSearchInitialised(true);
34
64
  })
35
65
  .finally(() => setTextSearchLoading(false));
@@ -39,9 +69,19 @@ export function useTableSearchHelper<M extends Record<string, any>>({ collection
39
69
  customizationController.plugins?.forEach(p => {
40
70
  if (!textSearchEnabled)
41
71
  if (p.collectionView?.showTextSearchBar) {
42
- textSearchEnabled = p.collectionView.showTextSearchBar({ context, path: fullPath, collection, parentCollectionIds });
72
+ textSearchEnabled = p.collectionView.showTextSearchBar({
73
+ context,
74
+ path: fullPath,
75
+ collection,
76
+ parentCollectionIds
77
+ });
43
78
  }
44
79
  })
45
80
  }
46
- return { textSearchLoading, textSearchInitialised, onTextSearchClick, textSearchEnabled };
81
+ return {
82
+ textSearchLoading,
83
+ textSearchInitialised,
84
+ onTextSearchClick,
85
+ textSearchEnabled
86
+ };
47
87
  }
@@ -29,7 +29,7 @@ export * from "./DeleteConfirmationDialog";
29
29
 
30
30
  export * from "./FireCMSLogo";
31
31
 
32
- export * from "./FireCMSAppBar";
32
+ export * from "../core/DefaultAppBar";
33
33
 
34
34
  export * from "./ArrayContainer";
35
35
  export * from "./ReferenceWidget";
@@ -18,14 +18,14 @@ export const DialogsProvider: React.FC<PropsWithChildren<{}>> = ({ children }) =
18
18
  if (dialogEntries.length === 0)
19
19
  return;
20
20
 
21
- const updatedPanels = [...dialogEntries.slice(0, -1)];
21
+ const updatedPanels = [...dialogEntriesRef.current.slice(0, -1)];
22
22
  updateDialogEntries(updatedPanels);
23
23
 
24
24
  }, [dialogEntries]);
25
25
 
26
26
  const open = useCallback((dialogEntry: DialogControllerEntryProps) => {
27
27
 
28
- const updatedPanels = [...dialogEntries, dialogEntry];
28
+ const updatedPanels = [...dialogEntriesRef.current, dialogEntry];
29
29
  updateDialogEntries(updatedPanels);
30
30
 
31
31
  return {