@firecms/core 3.0.0-canary.154 → 3.0.0-canary.156

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 (27) hide show
  1. package/dist/index.es.js +13729 -11121
  2. package/dist/index.es.js.map +1 -1
  3. package/dist/index.umd.js +13720 -11113
  4. package/dist/index.umd.js.map +1 -1
  5. package/dist/preview/PropertyPreviewProps.d.ts +1 -1
  6. package/package.json +15 -13
  7. package/src/components/ConfirmationDialog.tsx +2 -2
  8. package/src/components/DeleteEntityDialog.tsx +8 -17
  9. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +7 -5
  10. package/src/components/ErrorView.tsx +1 -1
  11. package/src/components/HomePage/DefaultHomePage.tsx +1 -0
  12. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +1 -0
  13. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +1 -0
  14. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +2 -0
  15. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +1 -0
  16. package/src/core/EntityEditView.tsx +9 -7
  17. package/src/core/field_configs.tsx +1 -1
  18. package/src/form/components/CustomIdField.tsx +1 -0
  19. package/src/form/components/StorageItemPreview.tsx +1 -1
  20. package/src/form/field_bindings/BlockFieldBinding.tsx +1 -0
  21. package/src/form/field_bindings/MapFieldBinding.tsx +1 -0
  22. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -0
  23. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +1 -1
  24. package/src/internal/useUnsavedChangesDialog.tsx +2 -2
  25. package/src/preview/PropertyPreviewProps.tsx +1 -1
  26. package/src/preview/property_previews/MapPropertyPreview.tsx +3 -3
  27. package/src/util/useStorageUploadController.tsx +1 -1
@@ -2,7 +2,7 @@ import { CMSType, Property, ResolvedProperty } from "../types";
2
2
  /**
3
3
  * @group Preview components
4
4
  */
5
- export type PreviewSize = "large" | "medium" | "small";
5
+ export type PreviewSize = "small" | "medium" | "large";
6
6
  /**
7
7
  * @group Preview components
8
8
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@firecms/core",
3
3
  "type": "module",
4
- "version": "3.0.0-canary.154",
4
+ "version": "3.0.0-canary.156",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -10,7 +10,7 @@
10
10
  "license": "MIT",
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "git+https://github.com/firecmsco/firecms.git",
13
+ "url": "https://github.com/firecmsco/firecms.git",
14
14
  "directory": "packages/firecms_core"
15
15
  },
16
16
  "main": "./dist/index.umd.js",
@@ -50,9 +50,9 @@
50
50
  "./package.json": "./package.json"
51
51
  },
52
52
  "dependencies": {
53
- "@firecms/editor": "^3.0.0-canary.154",
54
- "@firecms/formex": "^3.0.0-canary.154",
55
- "@firecms/ui": "^3.0.0-canary.154",
53
+ "@firecms/editor": "^3.0.0-canary.156",
54
+ "@firecms/formex": "^3.0.0-canary.156",
55
+ "@firecms/ui": "^3.0.0-canary.156",
56
56
  "@hello-pangea/dnd": "^17.0.0",
57
57
  "@radix-ui/react-portal": "^1.1.2",
58
58
  "clsx": "^2.1.1",
@@ -62,7 +62,7 @@
62
62
  "markdown-it": "^14.1.0",
63
63
  "notistack": "^3.0.1",
64
64
  "object-hash": "^3.0.0",
65
- "react-dropzone": "^14.2.10",
65
+ "react-dropzone": "^14.3.5",
66
66
  "react-fast-compare": "^3.2.2",
67
67
  "react-image-file-resizer": "^0.4.8",
68
68
  "react-transition-group": "^4.4.5",
@@ -82,29 +82,31 @@
82
82
  "@testing-library/react": "^16.0.1",
83
83
  "@testing-library/user-event": "^14.5.2",
84
84
  "@types/jest": "^29.5.14",
85
- "@types/node": "^20.16.11",
85
+ "@types/node": "^20.17.9",
86
86
  "@types/object-hash": "^3.0.6",
87
87
  "@types/react": "^18.3.12",
88
88
  "@types/react-dom": "^18.3.1",
89
89
  "@types/react-measure": "^2.0.12",
90
- "@vitejs/plugin-react": "^4.3.3",
90
+ "@vitejs/plugin-react": "^4.3.4",
91
+ "babel-plugin-react-compiler": "beta",
91
92
  "cross-env": "^7.0.3",
93
+ "eslint-plugin-react-compiler": "beta",
92
94
  "firebase": "^10.14.1",
93
95
  "jest": "^29.7.0",
94
96
  "npm-run-all": "^4.1.5",
95
- "react-router": "^6.27.0",
96
- "react-router-dom": "^6.27.0",
97
+ "react-router": "^6.28.0",
98
+ "react-router-dom": "^6.28.0",
97
99
  "ts-jest": "^29.2.5",
98
100
  "ts-node": "^10.9.2",
99
101
  "tsd": "^0.31.2",
100
- "typescript": "^5.6.3",
101
- "vite": "^5.4.10"
102
+ "typescript": "^5.7.2",
103
+ "vite": "^5.4.11"
102
104
  },
103
105
  "files": [
104
106
  "dist",
105
107
  "src"
106
108
  ],
107
- "gitHead": "52858cb15cdbbbb9c1b6ed8368e133304321cf49",
109
+ "gitHead": "78b61328121fb331b164ca96030419b9607971a1",
108
110
  "publishConfig": {
109
111
  "access": "public"
110
112
  },
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
 
3
- import { Button, Dialog, DialogActions, DialogContent, LoadingButton, Typography } from "@firecms/ui";
3
+ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, LoadingButton, Typography } from "@firecms/ui";
4
4
 
5
5
  export function ConfirmationDialog({
6
6
  open,
@@ -22,8 +22,8 @@ export function ConfirmationDialog({
22
22
  open={open}
23
23
  onOpenChange={(open) => !open ? onCancel() : undefined}
24
24
  >
25
+ <DialogTitle variant={"h6"} className={"mb-2"}>{title}</DialogTitle>
25
26
  <DialogContent>
26
- <Typography variant={"h6"} className={"mb-2"}>{title}</Typography>
27
27
  {body}
28
28
  </DialogContent>
29
29
 
@@ -1,6 +1,6 @@
1
1
  import { Entity, EntityCallbacks, EntityCollection } from "../types";
2
2
  import React, { useCallback, useMemo, useState } from "react";
3
- import { Button, CircularProgress, Dialog, DialogActions, DialogContent, Typography } from "@firecms/ui";
3
+ import { Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogTitle } from "@firecms/ui";
4
4
  import {
5
5
  deleteEntityWithCallbacks,
6
6
  useCustomizationController,
@@ -40,20 +40,12 @@ export function DeleteEntityDialog<M extends Record<string, any>>({
40
40
  const snackbarController = useSnackbarController();
41
41
  const [loading, setLoading] = useState(false);
42
42
 
43
- const [entityOrEntities, setUsedEntityOrEntities] = React.useState<Entity<M> | Entity<M>[]>();
44
-
45
- const [multipleEntities, setMultipleEntities] = React.useState<boolean>();
46
43
  const context = useFireCMSContext();
44
+ const entityOrEntities = Array.isArray(entityOrEntitiesToDelete) && entityOrEntitiesToDelete.length === 1
45
+ ? entityOrEntitiesToDelete[0]
46
+ : entityOrEntitiesToDelete;
47
47
 
48
- React.useEffect(() => {
49
- if (entityOrEntitiesToDelete) {
50
- const revisedEntityOrEntities = Array.isArray(entityOrEntitiesToDelete) && entityOrEntitiesToDelete.length === 1
51
- ? entityOrEntitiesToDelete[0]
52
- : entityOrEntitiesToDelete;
53
- setUsedEntityOrEntities(revisedEntityOrEntities);
54
- setMultipleEntities(Array.isArray(revisedEntityOrEntities));
55
- }
56
- }, [entityOrEntitiesToDelete]);
48
+ const multipleEntities = Array.isArray(entityOrEntities);
57
49
 
58
50
  const resolvedCollection = useMemo(() => resolveCollection<M>({
59
51
  collection,
@@ -181,11 +173,10 @@ export function DeleteEntityDialog<M extends Record<string, any>>({
181
173
  open={open}
182
174
  onOpenChange={(open) => !open ? onClose() : undefined}
183
175
  >
176
+ <DialogTitle id="delete-dialog-title">
177
+ {dialogTitle}
178
+ </DialogTitle>
184
179
  <DialogContent fullHeight={true}>
185
- <Typography variant={"subtitle2"} className={"p-4"}>
186
- {dialogTitle}
187
- </Typography>
188
-
189
180
  {!multipleEntities && <div className={"p-4"}>{content}</div>}
190
181
  </DialogContent>
191
182
  <DialogActions>
@@ -176,12 +176,14 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
176
176
  throw new Error("When using additional fields you need to provide a Builder or a value");
177
177
  }
178
178
 
179
- const child = Builder
179
+ const child: React.ReactNode = Builder
180
180
  ? <Builder entity={entity} context={context}/>
181
- : <>{additionalField.value?.({
182
- entity,
183
- context
184
- })}</>;
181
+ : <>
182
+ {additionalField.value?.({
183
+ entity,
184
+ context
185
+ })?.toString()}
186
+ </>;
185
187
 
186
188
  return (
187
189
  <EntityTableCell
@@ -26,7 +26,7 @@ export function ErrorView({
26
26
  tooltip
27
27
  }: ErrorViewProps): React.ReactElement {
28
28
  const component = error instanceof Error ? error.message : error;
29
- console.error("ErrorView", error)
29
+ console.warn("ErrorView", error)
30
30
 
31
31
  const body = (
32
32
  <div
@@ -140,6 +140,7 @@ export function DefaultHomePage({
140
140
  <SearchBar onTextSearch={updateSearchResults}
141
141
  placeholder={"Search collections"}
142
142
  large={false}
143
+ autoFocus={true}
143
144
  innerClassName={"w-full"}
144
145
  className={"w-full flex-grow"}/>
145
146
  {additionalActions}
@@ -77,6 +77,7 @@ export function DateTimeFilterField({
77
77
  <div className="w-[80px]">
78
78
  <Select value={operation}
79
79
  size={"large"}
80
+ fullWidth={true}
80
81
  onValueChange={(value) => {
81
82
  updateFilter(value as VirtualTableWhereFilterOp, internalValue);
82
83
  }}
@@ -148,6 +148,7 @@ export function ReferenceFilterField({
148
148
  <div className="w-[140px]">
149
149
  <Select value={operation}
150
150
  size={"large"}
151
+ fullWidth={true}
151
152
  onValueChange={(value) => {
152
153
  updateFilter(value as VirtualTableWhereFilterOp, internalValue);
153
154
  }}
@@ -98,6 +98,7 @@ export function StringNumberFilterField({
98
98
  <div className="flex w-[440px]">
99
99
  <div className={"w-[80px]"}>
100
100
  <Select value={operation}
101
+ fullWidth={true}
101
102
  position={"item-aligned"}
102
103
  onValueChange={(value) => {
103
104
  updateFilter(value as VirtualTableWhereFilterOp, internalValue);
@@ -131,6 +132,7 @@ export function StringNumberFilterField({
131
132
  {enumValues && !multiple &&
132
133
  <Select
133
134
  position={"item-aligned"}
135
+ fullWidth={true}
134
136
  value={typeof internalValue === "string" ? internalValue : ""}
135
137
  onValueChange={(value) => {
136
138
  if (value !== "")
@@ -92,6 +92,7 @@ export function VirtualTableSelect(props: {
92
92
  : <Select
93
93
  inputRef={ref}
94
94
  size={"large"}
95
+ fullWidth={true}
95
96
  className="w-full h-full p-0 bg-transparent"
96
97
  position={"item-aligned"}
97
98
  disabled={disabled}
@@ -96,9 +96,9 @@ export interface EntityEditViewProps<M extends Record<string, any>> {
96
96
  * side panel.
97
97
  */
98
98
  export function EntityEditView<M extends Record<string, any>, USER extends User>({
99
- entityId,
100
- ...props
101
- }: EntityEditViewProps<M>) {
99
+ entityId,
100
+ ...props
101
+ }: EntityEditViewProps<M>) {
102
102
  const {
103
103
  entity,
104
104
  dataLoading,
@@ -778,10 +778,12 @@ export function EntityEditViewInner<M extends Record<string, any>>({
778
778
 
779
779
  const child = Builder
780
780
  ? <Builder entity={entity} context={context}/>
781
- : <>{additionalField.value?.({
782
- entity,
783
- context
784
- })}</>;
781
+ : <>
782
+ {additionalField.value?.({
783
+ entity,
784
+ context
785
+ })?.toString()}
786
+ </>;
785
787
  return (
786
788
  <div>
787
789
  <LabelWithIconAndTooltip
@@ -300,7 +300,7 @@ export const DEFAULT_FIELD_CONFIGS: Record<string, PropertyConfig<any>> = {
300
300
  block: {
301
301
  key: "block",
302
302
  name: "Block",
303
- description: "A complex field that allows the user to compose different fields together, with a key->value format",
303
+ description: "A complex field that allows the user to compose different fields together, with a key/value format",
304
304
  Icon: ViewStreamIcon,
305
305
  color: "#ff9408",
306
306
  property: {
@@ -102,6 +102,7 @@ export function CustomIdField<M extends Record<string, any>>({
102
102
  <Select
103
103
  size={"large"}
104
104
  error={error}
105
+ fullWidth={true}
105
106
  onValueChange={(v) => onChange(v as string)}
106
107
  {...fieldProps}
107
108
  renderValue={(option) => {
@@ -31,7 +31,7 @@ export function StorageItemPreview({
31
31
  return (
32
32
  <div className={cls(paperMixin,
33
33
  "relative m-4 border-box flex items-center justify-center",
34
- size === "medium" ? "min-w-[220px] min-h-[220px] max-w-[220px]" : "min-w-[118px] min-h-[118px] max-w-[118px]",
34
+ size === "large" ? "min-w-[220px] min-h-[220px] max-w-[220px]" : "min-w-[118px] min-h-[118px] max-w-[118px]",
35
35
  className)}>
36
36
 
37
37
  {!placeholder && !disabled &&
@@ -226,6 +226,7 @@ function BlockEntry({
226
226
  placeholder={<Typography variant={"caption"}
227
227
  className={"px-4 py-2 font-medium"}>Type</Typography>}
228
228
  size={"medium"}
229
+ fullWidth={true}
229
230
  position={"item-aligned"}
230
231
  value={value1}
231
232
  renderValue={(enumKey: any) =>
@@ -146,6 +146,7 @@ const buildPickKeysSelect = (disabled: boolean, properties: Properties, setValue
146
146
  <Select
147
147
  value={""}
148
148
  size={"large"}
149
+ fullWidth={true}
149
150
  disabled={disabled}
150
151
  onValueChange={handleAddProperty}
151
152
  renderValue={(key) => (properties as Properties)[key].name || key}>
@@ -53,6 +53,7 @@ export function SelectFieldBinding<T extends EnumType>({
53
53
  value={value !== undefined && value != null ? value.toString() : ""}
54
54
  disabled={disabled}
55
55
  size={size}
56
+ fullWidth={true}
56
57
  position="item-aligned"
57
58
  inputClassName={cls("w-full")}
58
59
  label={
@@ -339,7 +339,7 @@ export function StorageUpload({
339
339
  }
340
340
 
341
341
  const metadata: Record<string, unknown> | undefined = storage?.metadata;
342
- const size = multipleFilesSupported ? "small" : "medium";
342
+ const size = multipleFilesSupported ? "medium" : "large";
343
343
 
344
344
  const moveItem = useCallback((fromIndex: number, toIndex: number) => {
345
345
  if (!multipleFilesSupported) return;
@@ -1,7 +1,7 @@
1
1
  import React, { useCallback } from "react";
2
2
  import { Blocker, Transition } from "history";
3
3
  import { UNSAFE_NavigationContext, useNavigate } from "react-router-dom";
4
- import { Button, Dialog, DialogActions, DialogContent, Typography } from "@firecms/ui";
4
+ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@firecms/ui";
5
5
 
6
6
  export function useNavigationUnsavedChangesDialog(when: boolean, onSuccess: () => void):
7
7
  {
@@ -89,8 +89,8 @@ export function UnsavedChangesDialog({
89
89
  }}
90
90
  open={open}
91
91
  >
92
+ <DialogTitle variant={"h6"}>{title}</DialogTitle>
92
93
  <DialogContent>
93
- <Typography variant={"h6"}>{title}</Typography>
94
94
 
95
95
  {body}
96
96
 
@@ -3,7 +3,7 @@ import { CMSType, Property, ResolvedProperty } from "../types";
3
3
  /**
4
4
  * @group Preview components
5
5
  */
6
- export type PreviewSize = "large" | "medium" | "small";
6
+ export type PreviewSize = "small" | "medium" | "large";
7
7
 
8
8
  /**
9
9
  * @group Preview components
@@ -110,7 +110,7 @@ export function KeyValuePreview({ value }: { value: any }) {
110
110
  return <div
111
111
  className="flex flex-col gap-1 w-full">
112
112
  {
113
- Object.entries(value).map(([key, childValue]) => (
113
+ Object.entries(value).map(([key, childValue]: [string, any]) => (
114
114
  <div
115
115
  key={`map_preview_table_${key}}`}
116
116
  className={cls(defaultBorderMixin, "last:border-b-0 border-b")}>
@@ -127,9 +127,9 @@ export function KeyValuePreview({ value }: { value: any }) {
127
127
  </div>
128
128
  <div
129
129
  className="flex-grow max-w-[75%]">
130
- {typeof childValue !== "object" && <Typography>
130
+ {childValue && ("toString" in childValue) && <Typography>
131
131
  <ErrorBoundary>
132
- {childValue && childValue.toString()}
132
+ {childValue.toString()}
133
133
  </ErrorBoundary>
134
134
  </Typography>}
135
135
  </div>
@@ -70,7 +70,7 @@ export function useStorageUploadController<M extends object>({
70
70
  throw Error("Storage meta must be specified");
71
71
 
72
72
  const metadata: Record<string, any> | undefined = storage?.metadata;
73
- const size = multipleFilesSupported ? "small" : "medium";
73
+ const size = multipleFilesSupported ? "medium" : "large";
74
74
 
75
75
  const compression: ImageCompression | undefined = storage?.imageCompression;
76
76