@firecms/core 3.0.0-canary.187 → 3.0.0-canary.189

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.
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.187",
4
+ "version": "3.0.0-canary.189",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -50,9 +50,9 @@
50
50
  "./package.json": "./package.json"
51
51
  },
52
52
  "dependencies": {
53
- "@firecms/editor": "^3.0.0-canary.187",
54
- "@firecms/formex": "^3.0.0-canary.187",
55
- "@firecms/ui": "^3.0.0-canary.187",
53
+ "@firecms/editor": "^3.0.0-canary.189",
54
+ "@firecms/formex": "^3.0.0-canary.189",
55
+ "@firecms/ui": "^3.0.0-canary.189",
56
56
  "@hello-pangea/dnd": "^17.0.0",
57
57
  "@radix-ui/react-portal": "^1.1.3",
58
58
  "clsx": "^2.1.1",
@@ -104,7 +104,7 @@
104
104
  "dist",
105
105
  "src"
106
106
  ],
107
- "gitHead": "57a64af52d840cb893f7790ef5857a8f8a4249b4",
107
+ "gitHead": "67a42d377d53ad171b9acdde6fb81ac1468b5f5d",
108
108
  "publishConfig": {
109
109
  "access": "public"
110
110
  },
@@ -891,10 +891,14 @@ function buildBottomActions<M extends object>({
891
891
  {status === "copy" && "Create copy"}
892
892
  {status === "new" && "Create"}
893
893
  </Button>
894
- {canClose && <LoadingButton variant="filled" color="primary" type="submit" loading={isSubmitting}
895
- disabled={disabled} onClick={() => {
896
- setPendingClose?.(true);
897
- }}>
894
+ {canClose && <LoadingButton variant="filled"
895
+ color="primary"
896
+ type="submit"
897
+ loading={isSubmitting}
898
+ disabled={disabled}
899
+ onClick={() => {
900
+ setPendingClose?.(true);
901
+ }}>
898
902
  {status === "existing" && "Save and close"}
899
903
  {status === "copy" && "Create copy and close"}
900
904
  {status === "new" && "Create and close"}
@@ -92,7 +92,7 @@ export function StorageUploadProgress({
92
92
  `min-w-[${imageSize}px] min-h-[${imageSize}px]`)}>
93
93
 
94
94
  {loading &&
95
- <Skeleton className="w-full h-full"/>}
95
+ <Skeleton className="m-4 w-full h-full"/>}
96
96
 
97
97
  {error && <ErrorView title={"Error uploading file"}
98
98
  error={error}/>}
@@ -3,13 +3,14 @@ import {
3
3
  FieldHelperText,
4
4
  FieldProps,
5
5
  getIconForProperty,
6
- LabelWithIconAndTooltip, PropertyOrBuilder,
6
+ LabelWithIconAndTooltip,
7
+ PropertyOrBuilder,
7
8
  randomString,
8
9
  ResolvedArrayProperty,
9
10
  ResolvedStringProperty,
10
11
  useStorageSource
11
12
  } from "../../index";
12
- import { cls, fieldBackgroundHoverMixin, fieldBackgroundMixin } from "@firecms/ui";
13
+ import { cls, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundMixin } from "@firecms/ui";
13
14
  import { FireCMSEditor, FireCMSEditorProps } from "@firecms/editor";
14
15
  import { resolveProperty, resolveStorageFilenameString, resolveStoragePathString } from "../../util";
15
16
 
@@ -27,11 +28,13 @@ export function MarkdownEditorFieldBinding({
27
28
  showError,
28
29
  error,
29
30
  minimalistView,
31
+ disabled: disabledProp,
30
32
  isSubmitting,
31
33
  context,
32
34
  customProps,
33
35
  }: FieldProps<string, MarkdownEditorFieldProps>) {
34
36
 
37
+ const disabled = disabledProp || isSubmitting;
35
38
  const highlight = customProps?.highlight;
36
39
  const editorProps = customProps?.editorProps;
37
40
  const storageSource = useStorageSource();
@@ -54,11 +57,9 @@ export function MarkdownEditorFieldBinding({
54
57
  if (internalValue.current !== value) {
55
58
  internalValue.current = value;
56
59
  setFieldVersion(fieldVersion + 1);
57
- // fieldVersion.current = fieldVersion.current + 1;
58
60
  }
59
61
  }, [value]);
60
62
 
61
-
62
63
  const resolvedProperty = resolveProperty({
63
64
  propertyOrBuilder: property as PropertyOrBuilder,
64
65
  values: entityValues
@@ -107,6 +108,7 @@ export function MarkdownEditorFieldBinding({
107
108
  onMarkdownContentChange={onContentChange}
108
109
  version={context.formex.version + fieldVersion}
109
110
  highlight={highlight}
111
+ disabled={disabled}
110
112
  handleImageUpload={async (file: File) => {
111
113
  const storagePath = storagePathBuilder(file);
112
114
  const fileName = await fileNameBuilder(file);
@@ -136,7 +138,8 @@ export function MarkdownEditorFieldBinding({
136
138
  required={property.validation?.required}
137
139
  title={property.name}
138
140
  className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
139
- <div className={cls("rounded-md", fieldBackgroundMixin, fieldBackgroundHoverMixin)}>
141
+ <div
142
+ className={cls("rounded-md", fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin)}>
140
143
  {editor}
141
144
  </div>
142
145
  <FieldHelperText includeDescription={includeDescription}
@@ -28,7 +28,7 @@ import {
28
28
  import { useClearRestoreValue } from "../useClearRestoreValue";
29
29
 
30
30
  const dropZoneClasses = "box-border relative pt-[2px] items-center border border-transparent min-h-[254px] outline-none rounded-md duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid";
31
- const disabledClasses = "border-dotted-gray"
31
+ const disabledClasses = fieldBackgroundDisabledMixin;
32
32
  const nonActiveDropClasses = fieldBackgroundHoverMixin
33
33
  const activeDropClasses = "pt-0 border-2 border-solid"
34
34
  const acceptDropClasses = "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-2 border-solid border-green-500"
@@ -206,6 +206,7 @@ function FileDropComponent({
206
206
  className={cls(
207
207
  fieldBackgroundMixin,
208
208
  disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
209
+ disabled ? "text-surface-accent-600 dark:text-surface-accent-500" : "",
209
210
  dropZoneClasses,
210
211
  multipleFilesSupported && internalValue.length ? "" : "flex",
211
212
  {
@@ -248,7 +249,7 @@ function FileDropComponent({
248
249
  metadata={metadata}
249
250
  storagePath={storagePathBuilder(entry.file)}
250
251
  onFileUploadComplete={onFileUploadComplete}
251
- imageSize={size === "medium" ? 220 : 118}
252
+ imageSize={size === "large" ? 220 : 118}
252
253
  simple={false}
253
254
  />
254
255
  );
@@ -285,7 +286,8 @@ function FileDropComponent({
285
286
  <div
286
287
  className="flex-grow min-h-[38px] box-border m-2 text-center">
287
288
  <Typography align={"center"}
288
- variant={"label"}>
289
+ variant={"label"}
290
+ className={disabled ? "text-surface-accent-600 dark:text-surface-accent-500" : ""}>
289
291
  {helpText}
290
292
  </Typography>
291
293
  </div>
@@ -55,24 +55,23 @@ export function UrlComponentPreview({
55
55
  return <VideoPreview size={size} src={url} interactive={interactive}/>;
56
56
  } else {
57
57
  return (
58
- <a
59
- href={url}
60
- rel="noopener noreferrer"
61
- target="_blank"
62
- onClick={(e) => e.stopPropagation()}
63
- className="flex flex-col items-center justify-center"
64
- style={{
65
- width: getThumbnailMeasure(size),
66
- height: getThumbnailMeasure(size)
67
- }}>
68
- <DescriptionIcon className="text-surface-700 dark:text-surface-300"/>
69
- {hint &&
70
- <Tooltip title={hint}>
71
- <Typography
72
- className="max-w-full truncate rtl text-left"
73
- variant={"caption"}>{hint}</Typography>
74
- </Tooltip>}
75
- </a>
58
+ <Tooltip title={hint}>
59
+ <a
60
+ href={url}
61
+ rel="noopener noreferrer"
62
+ target="_blank"
63
+ onClick={(e) => e.stopPropagation()}
64
+ className="flex flex-col items-center justify-center"
65
+ style={{
66
+ width: getThumbnailMeasure(size),
67
+ height: getThumbnailMeasure(size)
68
+ }}>
69
+ <DescriptionIcon className="text-surface-700 dark:text-surface-300"/>
70
+ {hint && <Typography
71
+ className="max-w-full truncate rtl text-left"
72
+ variant={"caption"}>{hint}</Typography>}
73
+ </a>
74
+ </Tooltip>
76
75
  );
77
76
  }
78
77
  }
@@ -101,7 +101,6 @@ export function saveEntityToCache(path: string, data: object): void {
101
101
  if (isLocalStorageAvailable) {
102
102
  try {
103
103
  const key = LOCAL_STORAGE_PREFIX + path;
104
- console.log("Saving entity to cache", key, data);
105
104
  const entityString = JSON.stringify(data, customReplacer);
106
105
  localStorage.setItem(key, entityString);
107
106
  } catch (error) {
@@ -34,6 +34,7 @@ export interface StorageFieldItem {
34
34
  size: PreviewSize
35
35
  }
36
36
 
37
+
37
38
  export function useStorageUploadController<M extends object>({
38
39
  entityId,
39
40
  entityValues,
@@ -45,17 +46,17 @@ export function useStorageUploadController<M extends object>({
45
46
  disabled,
46
47
  onChange
47
48
  }:
48
- {
49
- entityId: string,
50
- entityValues: EntityValues<M>,
51
- value: string | string[] | null;
52
- path?: string,
53
- propertyKey: string,
54
- property: StringProperty | ArrayProperty<string[]> | ResolvedStringProperty | ResolvedArrayProperty<string[]>,
55
- storageSource: StorageSource,
56
- disabled: boolean,
57
- onChange: (value: string | string[] | null) => void
58
- }) {
49
+ {
50
+ entityId: string,
51
+ entityValues: EntityValues<M>,
52
+ value: string | string[] | null;
53
+ path?: string,
54
+ propertyKey: string,
55
+ property: StringProperty | ArrayProperty<string[]> | ResolvedStringProperty | ResolvedArrayProperty<string[]>,
56
+ storageSource: StorageSource,
57
+ disabled: boolean,
58
+ onChange: (value: string | string[] | null) => void
59
+ }) {
59
60
 
60
61
  const storage: StorageConfig | undefined = property.dataType === "string"
61
62
  ? property.storage
@@ -75,16 +76,7 @@ export function useStorageUploadController<M extends object>({
75
76
  const compression: ImageCompression | undefined = storage?.imageCompression;
76
77
 
77
78
  const internalInitialValue: StorageFieldItem[] =
78
- (multipleFilesSupported
79
- ? (value ?? []) as string[]
80
- : value ? [value as string] : []).map(entry => (
81
- {
82
- id: getRandomId(),
83
- storagePathOrDownloadUrl: entry,
84
- metadata,
85
- size
86
- }
87
- ));
79
+ getInternalInitialValue(multipleFilesSupported, value, metadata, size);
88
80
 
89
81
  const [initialValue, setInitialValue] = useState<string | string[] | null>(value);
90
82
  const [internalValue, setInternalValue] = useState<StorageFieldItem[]>(internalInitialValue);
@@ -226,6 +218,32 @@ export function useStorageUploadController<M extends object>({
226
218
  }
227
219
  }
228
220
 
221
+ function getInternalInitialValue(multipleFilesSupported: boolean,
222
+ value: string | string[] | null,
223
+ metadata: Record<string, any> | undefined,
224
+ size: PreviewSize): StorageFieldItem[] {
225
+ let strings: string[] = [];
226
+ if (multipleFilesSupported) {
227
+ if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
228
+ strings = (value ?? []) as string[];
229
+ }
230
+ } else {
231
+ if (typeof value === "string") {
232
+ strings = value ? [value as string] : [];
233
+ }
234
+ }
235
+
236
+ return strings
237
+ .map(entry => (
238
+ {
239
+ id: getRandomId(),
240
+ storagePathOrDownloadUrl: entry,
241
+ metadata,
242
+ size
243
+ }
244
+ ));
245
+ }
246
+
229
247
  function removeDuplicates(items: StorageFieldItem[]) {
230
248
  return items.filter(
231
249
  (item, i) => {