@firecms/core 3.0.0-canary.119 → 3.0.0-canary.120

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.
@@ -1,4 +1,4 @@
1
- import { CMSType, PropertyOrBuilder } from "./properties";
1
+ import { CMSType, Property, PropertyOrBuilder } from "./properties";
2
2
  import { ResolvedEntityCollection, ResolvedProperty } from "./resolved_entities";
3
3
  import { FormexController } from "@firecms/formex";
4
4
  /**
@@ -52,7 +52,7 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
52
52
  /**
53
53
  * Property related to this field
54
54
  */
55
- property: ResolvedProperty<T>;
55
+ property: Property<T> | ResolvedProperty<T>;
56
56
  /**
57
57
  * Should this field include a description
58
58
  */
@@ -8,7 +8,7 @@ import { ChipColorKey, ChipColorScheme } from "@firecms/ui";
8
8
  /**
9
9
  * @group Entity properties
10
10
  */
11
- export type DataType<T extends CMSType = CMSType> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : T extends Date ? "date" : T extends GeoPoint ? "geopoint" : T extends Vector ? "vector" : T extends EntityReference ? "reference" : T extends Array<CMSType> ? "array" : T extends Record<string, CMSType> ? "map" : never;
11
+ export type DataType<T extends CMSType = CMSType> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : T extends Date ? "date" : T extends GeoPoint ? "geopoint" : T extends Vector ? "vector" : T extends EntityReference ? "reference" : T extends Array<any> ? "array" : T extends Record<string, any> ? "map" : never;
12
12
  /**
13
13
  * @group Entity properties
14
14
  */
@@ -20,7 +20,7 @@ export type AnyProperty = StringProperty | NumberProperty | BooleanProperty | Da
20
20
  /**
21
21
  * @group Entity properties
22
22
  */
23
- export type Property<T extends CMSType = CMSType> = T extends string ? StringProperty : T extends number ? NumberProperty : T extends boolean ? BooleanProperty : T extends Date ? DateProperty : T extends GeoPoint ? GeopointProperty : T extends EntityReference ? ReferenceProperty : T extends Array<CMSType> ? ArrayProperty<T> : T extends Record<string, any> ? MapProperty<T> : AnyProperty;
23
+ export type Property<T extends CMSType = any> = T extends string ? StringProperty : T extends number ? NumberProperty : T extends boolean ? BooleanProperty : T extends Date ? DateProperty : T extends GeoPoint ? GeopointProperty : T extends EntityReference ? ReferenceProperty : T extends Array<CMSType> ? ArrayProperty<T> : T extends Record<string, any> ? MapProperty<T> : AnyProperty;
24
24
  /**
25
25
  * Interface including all common properties of a CMS property
26
26
  * @group Entity properties
@@ -306,7 +306,7 @@ export interface StringProperty extends BaseProperty<string> {
306
306
  /**
307
307
  * @group Entity properties
308
308
  */
309
- export interface ArrayProperty<T extends ArrayT[] = any[], ArrayT extends CMSType = CMSType> extends BaseProperty<T> {
309
+ export interface ArrayProperty<T extends ArrayT[] = any[], ArrayT extends CMSType = any> extends BaseProperty<T> {
310
310
  dataType: "array";
311
311
  /**
312
312
  * The property of this array.
@@ -1,5 +1,5 @@
1
1
  import { CMSType, DataType, Entity, EntityReference, EntityStatus, EntityValues, PropertiesOrBuilders, Property, PropertyBuilder, PropertyOrBuilder, ResolvedProperties, ResolvedProperty } from "../types";
2
- export declare function isReadOnly(property: Property | ResolvedProperty): boolean;
2
+ export declare function isReadOnly(property: Property<any> | ResolvedProperty<any>): boolean;
3
3
  export declare function isHidden(property: Property | ResolvedProperty): boolean;
4
4
  export declare function isPropertyBuilder<T extends CMSType, M extends Record<string, any>>(propertyOrBuilder?: PropertyOrBuilder<T, M> | Property<T> | ResolvedProperty<T>): propertyOrBuilder is PropertyBuilder<T, M>;
5
5
  export declare function getDefaultValuesFor<M extends Record<string, any>>(properties: PropertiesOrBuilders<M> | ResolvedProperties<M>): Partial<EntityValues<M>>;
@@ -3,7 +3,7 @@ import { EntityCollection, PropertiesOrBuilders, PropertyConfig, PropertyOrBuild
3
3
  export declare function isReferenceProperty(propertyOrBuilder: PropertyOrBuilder, fields: Record<string, PropertyConfig>): boolean | null;
4
4
  export declare function getIdIcon(size: "small" | "medium" | "large"): React.ReactNode;
5
5
  export declare function getIconForWidget(widget: PropertyConfig | undefined, size: "small" | "medium" | "large"): import("react/jsx-runtime").JSX.Element;
6
- export declare function getIconForProperty(property: PropertyOrBuilder | ResolvedProperty, size?: "small" | "medium" | "large", fields?: Record<string, PropertyConfig>): React.ReactNode;
6
+ export declare function getIconForProperty(property: PropertyOrBuilder<any> | ResolvedProperty<any>, size?: "small" | "medium" | "large", fields?: Record<string, PropertyConfig>): React.ReactNode;
7
7
  export declare function getColorForProperty(property: PropertyOrBuilder, fields: Record<string, PropertyConfig>): string;
8
8
  /**
9
9
  * Get a property in a property tree from a path like
@@ -1,4 +1,4 @@
1
- import { EntityValues, ResolvedArrayProperty, ResolvedStringProperty, StorageConfig, StorageSource } from "../types";
1
+ import { ArrayProperty, EntityValues, ResolvedArrayProperty, ResolvedStringProperty, StorageConfig, StorageSource, StringProperty } from "../types";
2
2
  import { PreviewSize } from "../preview";
3
3
  /**
4
4
  * Internal representation of an item in the storage
@@ -20,7 +20,7 @@ export declare function useStorageUploadController<M extends object>({ entityId,
20
20
  value: string | string[] | null;
21
21
  path?: string;
22
22
  propertyKey: string;
23
- property: ResolvedStringProperty | ResolvedArrayProperty<string[]>;
23
+ property: StringProperty | ArrayProperty<string[]> | ResolvedStringProperty | ResolvedArrayProperty<string[]>;
24
24
  storageSource: StorageSource;
25
25
  disabled: boolean;
26
26
  onChange: (value: string | string[] | null) => void;
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.119",
4
+ "version": "3.0.0-canary.120",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -46,9 +46,9 @@
46
46
  "./package.json": "./package.json"
47
47
  },
48
48
  "dependencies": {
49
- "@firecms/editor": "^3.0.0-canary.119",
50
- "@firecms/formex": "^3.0.0-canary.119",
51
- "@firecms/ui": "^3.0.0-canary.119",
49
+ "@firecms/editor": "^3.0.0-canary.120",
50
+ "@firecms/formex": "^3.0.0-canary.120",
51
+ "@firecms/ui": "^3.0.0-canary.120",
52
52
  "@hello-pangea/dnd": "^16.6.0",
53
53
  "@radix-ui/react-portal": "^1.1.1",
54
54
  "clsx": "^2.1.1",
@@ -100,7 +100,7 @@
100
100
  "dist",
101
101
  "src"
102
102
  ],
103
- "gitHead": "22e1ffb78b12816a576df70e3aa7df1ee29e26ad",
103
+ "gitHead": "aa817730cb582b5724774a50ac8a512bf0643ef3",
104
104
  "publishConfig": {
105
105
  "access": "public"
106
106
  },
@@ -3,7 +3,7 @@ import { FieldProps } from "../../types";
3
3
  import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
4
4
  import { PropertyFieldBinding } from "../PropertyFieldBinding";
5
5
  import { ExpandablePanel, Typography } from "@firecms/ui";
6
- import { getIconForProperty } from "../../util";
6
+ import { getArrayResolvedProperties, getIconForProperty } from "../../util";
7
7
  import { useClearRestoreValue } from "../useClearRestoreValue";
8
8
 
9
9
  /**
@@ -28,8 +28,15 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
28
28
  disabled
29
29
  }: FieldProps<T, any, any>) {
30
30
 
31
- if (!Array.isArray(property.resolvedProperties))
32
- throw Error("ArrayCustomShapedFieldBinding misconfiguration. Property `of` not set");
31
+ let resolvedProperties = "resolvedProperties" in property ? property.resolvedProperties : undefined;
32
+ if (!resolvedProperties) {
33
+ resolvedProperties = getArrayResolvedProperties({
34
+ propertyValue: value,
35
+ propertyKey,
36
+ property,
37
+ ignoreMissingFields: false
38
+ })
39
+ }
33
40
 
34
41
  const expanded = property.expanded === undefined ? true : property.expanded;
35
42
 
@@ -49,7 +56,7 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
49
56
  {Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
50
57
  </>);
51
58
 
52
- const body = property.resolvedProperties.map((childProperty, index) => {
59
+ const body = resolvedProperties.map((childProperty, index) => {
53
60
  const fieldProps = {
54
61
  propertyKey: `${propertyKey}[${index}]`,
55
62
  disabled,
@@ -3,13 +3,15 @@ import {
3
3
  FieldHelperText,
4
4
  FieldProps,
5
5
  getIconForProperty,
6
- LabelWithIconAndTooltip,
6
+ LabelWithIconAndTooltip, PropertyOrBuilder,
7
7
  randomString,
8
+ ResolvedArrayProperty,
9
+ ResolvedStringProperty,
8
10
  useStorageSource
9
11
  } from "../../index";
10
12
  import { cls, fieldBackgroundHoverMixin, fieldBackgroundMixin } from "@firecms/ui";
11
13
  import { FireCMSEditor, FireCMSEditorProps } from "@firecms/editor";
12
- import { resolveStorageFilenameString, resolveStoragePathString } from "../../util";
14
+ import { resolveProperty, resolveStorageFilenameString, resolveStoragePathString } from "../../util";
13
15
 
14
16
  interface MarkdownEditorFieldProps {
15
17
  highlight?: { from: number, to: number };
@@ -56,6 +58,12 @@ export function MarkdownEditorFieldBinding({
56
58
  }
57
59
  }, [value]);
58
60
 
61
+
62
+ const resolvedProperty = resolveProperty({
63
+ propertyOrBuilder: property as PropertyOrBuilder,
64
+ values: entityValues
65
+ }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
66
+
59
67
  const fileNameBuilder = useCallback(async (file: File) => {
60
68
  if (storage?.fileName) {
61
69
  const fileName = await resolveStorageFilenameString({
@@ -64,7 +72,7 @@ export function MarkdownEditorFieldBinding({
64
72
  values: entityValues,
65
73
  entityId,
66
74
  path,
67
- property,
75
+ property: resolvedProperty,
68
76
  file,
69
77
  propertyKey
70
78
  });
@@ -74,17 +82,21 @@ export function MarkdownEditorFieldBinding({
74
82
  return fileName;
75
83
  }
76
84
  return randomString() + "_" + file.name;
77
- }, [entityId, entityValues, path, property, propertyKey, storage]);
85
+ }, [entityId, entityValues, path, resolvedProperty, propertyKey, storage]);
78
86
 
79
87
  const storagePathBuilder = useCallback((file: File) => {
80
88
  if (!storage) return "/";
89
+ const resolvedProperty = resolveProperty({
90
+ propertyOrBuilder: property,
91
+ values: entityValues
92
+ }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
81
93
  return resolveStoragePathString({
82
94
  input: storage.storagePath,
83
95
  storage,
84
96
  values: entityValues,
85
97
  entityId,
86
98
  path,
87
- property,
99
+ property: resolvedProperty,
88
100
  file,
89
101
  propertyKey
90
102
  }) ?? "/";
@@ -111,7 +123,7 @@ export function MarkdownEditorFieldBinding({
111
123
  return url;
112
124
  }}
113
125
  {...editorProps}
114
- />;
126
+ />;
115
127
 
116
128
  if (minimalistView)
117
129
  return editor;
@@ -34,7 +34,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
34
34
  if (!property.of)
35
35
  throw Error("RepeatFieldBinding misconfiguration. Property `of` not set");
36
36
 
37
- let resolvedProperties = property.resolvedProperties;
37
+ let resolvedProperties = "resolvedProperties" in property ? property.resolvedProperties : undefined;
38
38
  if (!resolvedProperties) {
39
39
  resolvedProperties = getArrayResolvedProperties({
40
40
  propertyValue: value,
@@ -3,7 +3,7 @@ import React, { useCallback } from "react";
3
3
  import { EnumType, FieldProps } from "../../types";
4
4
  import { FieldHelperText, LabelWithIcon } from "../components";
5
5
  import { EnumValuesChip } from "../../preview";
6
- import { getIconForProperty } from "../../util";
6
+ import { getIconForProperty, resolveEnumValues } from "../../util";
7
7
  import { ClearIcon, cls, IconButton, Select, SelectItem } from "@firecms/ui";
8
8
  import { useClearRestoreValue } from "../useClearRestoreValue";
9
9
  import { PropertyIdCopyTooltip } from "../../components";
@@ -32,7 +32,7 @@ export function SelectFieldBinding<T extends EnumType>({
32
32
  size = "medium"
33
33
  }: SelectProps<T>) {
34
34
 
35
- const enumValues = property.enumValues;
35
+ const enumValues = resolveEnumValues(property.enumValues ?? []);
36
36
 
37
37
  useClearRestoreValue({
38
38
  property,
@@ -1,11 +1,18 @@
1
1
  import React, { useCallback } from "react";
2
2
 
3
- import { ArrayProperty, FieldProps, ResolvedArrayProperty, ResolvedStringProperty, StorageConfig } from "../../types";
3
+ import {
4
+ ArrayProperty,
5
+ FieldProps,
6
+ PropertyOrBuilder,
7
+ ResolvedArrayProperty,
8
+ ResolvedStringProperty,
9
+ StorageConfig
10
+ } from "../../types";
4
11
  import { useDropzone } from "react-dropzone";
5
12
  import { PreviewSize } from "../../preview";
6
13
  import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
7
14
 
8
- import { getIconForProperty, isReadOnly } from "../../util";
15
+ import { getIconForProperty, isReadOnly, resolveProperty } from "../../util";
9
16
  import { useSnackbarController, useStorageSource } from "../../hooks";
10
17
  import { DragDropContext, Draggable, Droppable } from "@hello-pangea/dnd";
11
18
  import { StorageFieldItem, useStorageUploadController } from "../../util/useStorageUploadController";
@@ -82,6 +89,10 @@ export function StorageUploadFieldBinding({
82
89
  setValue
83
90
  });
84
91
 
92
+ const resolvedProperty = resolveProperty({
93
+ propertyOrBuilder: property as PropertyOrBuilder,
94
+ }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
95
+
85
96
  return (
86
97
 
87
98
  <>
@@ -99,7 +110,7 @@ export function StorageUploadFieldBinding({
99
110
  name={propertyKey}
100
111
  disabled={disabled ?? false}
101
112
  autoFocus={autoFocus ?? false}
102
- property={property}
113
+ property={resolvedProperty}
103
114
  onChange={setValue}
104
115
  setInternalValue={setInternalValue}
105
116
  onFilesAdded={onFilesAdded}
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef } from "react";
2
- import { CMSType, ResolvedProperty } from "../types";
2
+ import { CMSType, Property, ResolvedProperty } from "../types";
3
3
 
4
4
  /**
5
5
  * Hook we use to restore a value after it has been cleared
@@ -14,7 +14,7 @@ export function useClearRestoreValue<T extends CMSType>({
14
14
  setValue
15
15
  }:
16
16
  {
17
- property: ResolvedProperty<T>,
17
+ property: Property<T> | ResolvedProperty<T>,
18
18
  value: T,
19
19
  setValue: (value: T | null, shouldValidate?: boolean) => void
20
20
  }) {
@@ -1,4 +1,4 @@
1
- import { CMSType, PropertyOrBuilder } from "./properties";
1
+ import { CMSType, Property, PropertyOrBuilder } from "./properties";
2
2
  import { ResolvedEntityCollection, ResolvedProperty } from "./resolved_entities";
3
3
  import { FormexController } from "@firecms/formex";
4
4
 
@@ -62,7 +62,7 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
62
62
  /**
63
63
  * Property related to this field
64
64
  */
65
- property: ResolvedProperty<T>;
65
+ property: Property<T> | ResolvedProperty<T>;
66
66
 
67
67
  /**
68
68
  * Should this field include a description
@@ -17,8 +17,8 @@ export type DataType<T extends CMSType = CMSType> =
17
17
  T extends GeoPoint ? "geopoint" :
18
18
  T extends Vector ? "vector" :
19
19
  T extends EntityReference ? "reference" :
20
- T extends Array<CMSType> ? "array" :
21
- T extends Record<string, CMSType> ? "map" : never;
20
+ T extends Array<any> ? "array" :
21
+ T extends Record<string, any> ? "map" : never;
22
22
 
23
23
  /**
24
24
  * @group Entity properties
@@ -49,7 +49,7 @@ export type AnyProperty =
49
49
  /**
50
50
  * @group Entity properties
51
51
  */
52
- export type Property<T extends CMSType = CMSType> =
52
+ export type Property<T extends CMSType = any> =
53
53
  T extends string ? StringProperty :
54
54
  T extends number ? NumberProperty :
55
55
  T extends boolean ? BooleanProperty :
@@ -405,7 +405,7 @@ export interface StringProperty extends BaseProperty<string> {
405
405
  /**
406
406
  * @group Entity properties
407
407
  */
408
- export interface ArrayProperty<T extends ArrayT[] = any[], ArrayT extends CMSType = CMSType> extends BaseProperty<T> {
408
+ export interface ArrayProperty<T extends ArrayT[] = any[], ArrayT extends CMSType = any> extends BaseProperty<T> {
409
409
 
410
410
  dataType: "array";
411
411
 
@@ -15,7 +15,7 @@ import {
15
15
  } from "../types";
16
16
  import { DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE } from "./common";
17
17
 
18
- export function isReadOnly(property: Property | ResolvedProperty): boolean {
18
+ export function isReadOnly(property: Property<any> | ResolvedProperty<any>): boolean {
19
19
  if (property.readOnly)
20
20
  return true;
21
21
  if (property.dataType === "date") {
@@ -35,7 +35,7 @@ export function getIconForWidget(widget: PropertyConfig | undefined,
35
35
  }
36
36
 
37
37
  export function getIconForProperty(
38
- property: PropertyOrBuilder | ResolvedProperty,
38
+ property: PropertyOrBuilder<any> | ResolvedProperty<any>,
39
39
  size: "small" | "medium" | "large" = "small",
40
40
  fields: Record<string, PropertyConfig> = {}
41
41
  ): React.ReactNode {
@@ -1,8 +1,11 @@
1
1
  import {
2
+ ArrayProperty,
2
3
  EntityValues,
4
+ PropertyOrBuilder,
3
5
  ResolvedArrayProperty,
4
6
  ResolvedStringProperty,
5
7
  StorageConfig,
8
+ StringProperty,
6
9
  UploadedFileContext
7
10
  } from "../types";
8
11
  import { randomString } from "./strings";
@@ -13,7 +16,7 @@ interface ResolveFilenameStringParams<M extends object> {
13
16
  values: EntityValues<M>;
14
17
  entityId: string;
15
18
  path?: string;
16
- property: ResolvedStringProperty | ResolvedArrayProperty<string[]>;
19
+ property: ResolvedStringProperty | ResolvedArrayProperty<string[]>,
17
20
  file: File;
18
21
  propertyKey: string;
19
22
  }
@@ -30,6 +33,7 @@ export async function resolveStorageFilenameString<M extends object>(
30
33
  propertyKey
31
34
  }: ResolveFilenameStringParams<M>): Promise<string> {
32
35
  let result;
36
+
33
37
  if (typeof input === "function") {
34
38
  result = await input({
35
39
  path,
@@ -2,9 +2,11 @@ import Resizer from "react-image-file-resizer";
2
2
  import equal from "react-fast-compare";
3
3
 
4
4
  import {
5
+ ArrayProperty,
5
6
  EntityValues,
6
7
  ImageCompression,
7
8
  Property,
9
+ PropertyOrBuilder,
8
10
  ResolvedArrayProperty,
9
11
  ResolvedStringProperty,
10
12
  StorageConfig,
@@ -15,6 +17,7 @@ import { useCallback, useEffect, useState } from "react";
15
17
  import { PreviewSize } from "../preview";
16
18
  import { randomString } from "./strings";
17
19
  import { resolveStorageFilenameString, resolveStoragePathString } from "./storage";
20
+ import { resolveProperty } from "./resolutions";
18
21
 
19
22
  /**
20
23
  * Internal representation of an item in the storage
@@ -48,7 +51,7 @@ export function useStorageUploadController<M extends object>({
48
51
  value: string | string[] | null;
49
52
  path?: string,
50
53
  propertyKey: string,
51
- property: ResolvedStringProperty | ResolvedArrayProperty<string[]>,
54
+ property: StringProperty | ArrayProperty<string[]> | ResolvedStringProperty | ResolvedArrayProperty<string[]>,
52
55
  storageSource: StorageSource,
53
56
  disabled: boolean,
54
57
  onChange: (value: string | string[] | null) => void
@@ -93,6 +96,11 @@ export function useStorageUploadController<M extends object>({
93
96
  }
94
97
  }, [internalInitialValue, value, initialValue]);
95
98
 
99
+ const resolvedProperty = resolveProperty({
100
+ propertyOrBuilder: property as PropertyOrBuilder,
101
+ values: entityValues
102
+ }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
103
+
96
104
  const fileNameBuilder = useCallback(async (file: File) => {
97
105
  if (storage.fileName) {
98
106
  const fileName = await resolveStorageFilenameString({
@@ -101,7 +109,7 @@ export function useStorageUploadController<M extends object>({
101
109
  values: entityValues,
102
110
  entityId,
103
111
  path,
104
- property,
112
+ property: resolvedProperty,
105
113
  file,
106
114
  propertyKey
107
115
  });
@@ -111,7 +119,7 @@ export function useStorageUploadController<M extends object>({
111
119
  return fileName;
112
120
  }
113
121
  return randomString() + "_" + file.name;
114
- }, [entityId, entityValues, path, property, propertyKey, storage]);
122
+ }, [entityId, entityValues, path, resolvedProperty, propertyKey, storage]);
115
123
 
116
124
  const storagePathBuilder = useCallback((file: File) => {
117
125
  return resolveStoragePathString({
@@ -120,11 +128,11 @@ export function useStorageUploadController<M extends object>({
120
128
  values: entityValues,
121
129
  entityId,
122
130
  path,
123
- property,
131
+ property: resolvedProperty,
124
132
  file,
125
133
  propertyKey
126
134
  }) ?? "/";
127
- }, [entityId, entityValues, path, property, propertyKey, storage]);
135
+ }, [entityId, entityValues, path, resolvedProperty, propertyKey, storage]);
128
136
 
129
137
  const onFileUploadComplete = useCallback(async (uploadedPath: string,
130
138
  entry: StorageFieldItem,