@firecms/core 3.0.0-canary.186 → 3.0.0-canary.188
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/dist/core/EntityEditView.d.ts +4 -15
- package/dist/core/EntityForm.d.ts +43 -0
- package/dist/form/components/FormEntry.d.ts +6 -0
- package/dist/form/components/FormLayout.d.ts +5 -0
- package/dist/form/components/index.d.ts +2 -0
- package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
- package/dist/index.es.js +12124 -11823
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +12100 -11799
- package/dist/index.umd.js.map +1 -1
- package/dist/types/fields.d.ts +11 -0
- package/dist/types/navigation.d.ts +1 -0
- package/dist/types/plugins.d.ts +1 -1
- package/dist/types/properties.d.ts +1 -1
- package/package.json +5 -5
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +4 -2
- package/src/core/EntityEditView.tsx +210 -1049
- package/src/core/EntityForm.tsx +956 -0
- package/src/core/NavigationRoutes.tsx +16 -12
- package/src/form/components/FormEntry.tsx +22 -0
- package/src/form/components/FormLayout.tsx +16 -0
- package/src/form/components/StorageUploadProgress.tsx +1 -1
- package/src/form/components/index.tsx +2 -0
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +0 -2
- package/src/form/field_bindings/MapFieldBinding.tsx +0 -2
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +8 -5
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +5 -3
- package/src/preview/components/UrlComponentPreview.tsx +17 -18
- package/src/routes/FireCMSRoute.tsx +7 -2
- package/src/types/fields.tsx +16 -0
- package/src/types/navigation.ts +1 -0
- package/src/types/plugins.tsx +1 -1
- package/src/types/properties.ts +1 -1
- package/src/util/entity_cache.ts +9 -1
- package/src/util/useStorageUploadController.tsx +39 -21
|
@@ -68,24 +68,28 @@ export const NavigationRoutes = React.memo<NavigationRoutesProps>(
|
|
|
68
68
|
});
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
const
|
|
72
|
-
const collectionRoute =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
const collectionUrlPath = navigation.buildUrlCollectionPath("");
|
|
72
|
+
const collectionRoute = (
|
|
73
|
+
<Route path={collectionUrlPath + "/*"}
|
|
74
|
+
key={`navigation_entity`}
|
|
75
|
+
element={
|
|
76
|
+
<ErrorBoundary>
|
|
77
|
+
<FireCMSRoute/>
|
|
78
|
+
</ErrorBoundary>
|
|
79
|
+
}/>
|
|
80
|
+
);
|
|
79
81
|
|
|
80
82
|
const homeRoute = (
|
|
81
83
|
<Route path={"/"}
|
|
82
84
|
element={<HomePageRoute>{homePage}</HomePageRoute>}/>
|
|
83
85
|
);
|
|
84
86
|
|
|
85
|
-
const notFoundRoute =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
const notFoundRoute = (
|
|
88
|
+
<Route path={"*"}
|
|
89
|
+
element={
|
|
90
|
+
<NotFoundPage/>
|
|
91
|
+
}/>
|
|
92
|
+
);
|
|
89
93
|
|
|
90
94
|
return (
|
|
91
95
|
<Routes location={baseLocation}>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ErrorBoundary } from "../../components";
|
|
3
|
+
|
|
4
|
+
export function FormEntry({
|
|
5
|
+
propertyKey,
|
|
6
|
+
widthPercentage = 100,
|
|
7
|
+
children
|
|
8
|
+
}: {
|
|
9
|
+
propertyKey: string;
|
|
10
|
+
widthPercentage?: number;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}) {
|
|
13
|
+
return (
|
|
14
|
+
<div id={`form_field_${propertyKey}`}
|
|
15
|
+
className={"relative"}
|
|
16
|
+
style={{ width: widthPercentage === 100 ? "100%" : `calc(${widthPercentage}% - 8px)` }}>
|
|
17
|
+
<ErrorBoundary>
|
|
18
|
+
{children}
|
|
19
|
+
</ErrorBoundary>
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cls } from "@firecms/ui";
|
|
3
|
+
|
|
4
|
+
export function FormLayout({
|
|
5
|
+
children,
|
|
6
|
+
className
|
|
7
|
+
}: {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
}) {
|
|
11
|
+
return (
|
|
12
|
+
<div className={cls("flex flex-wrap gap-x-4 w-full space-y-8", className)}>
|
|
13
|
+
{children}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -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}/>}
|
|
@@ -23,7 +23,6 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
|
|
|
23
23
|
minimalistView: minimalistViewProp,
|
|
24
24
|
property,
|
|
25
25
|
includeDescription,
|
|
26
|
-
underlyingValueHasChanged,
|
|
27
26
|
context,
|
|
28
27
|
disabled
|
|
29
28
|
}: FieldProps<T, any, any>) {
|
|
@@ -65,7 +64,6 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
|
|
|
65
64
|
disabled: disabled || thisDisabled,
|
|
66
65
|
property: childProperty,
|
|
67
66
|
includeDescription,
|
|
68
|
-
underlyingValueHasChanged,
|
|
69
67
|
context,
|
|
70
68
|
partOfArray: true,
|
|
71
69
|
minimalistView: false,
|
|
@@ -23,7 +23,6 @@ export function MapFieldBinding({
|
|
|
23
23
|
property,
|
|
24
24
|
minimalistView: minimalistViewProp,
|
|
25
25
|
includeDescription,
|
|
26
|
-
underlyingValueHasChanged,
|
|
27
26
|
autoFocus,
|
|
28
27
|
context,
|
|
29
28
|
onPropertyChange
|
|
@@ -62,7 +61,6 @@ export function MapFieldBinding({
|
|
|
62
61
|
disabled: disabled || thisDisabled,
|
|
63
62
|
property: childProperty,
|
|
64
63
|
includeDescription,
|
|
65
|
-
underlyingValueHasChanged,
|
|
66
64
|
context,
|
|
67
65
|
partOfArray: false,
|
|
68
66
|
minimalistView: false,
|
|
@@ -3,13 +3,14 @@ import {
|
|
|
3
3
|
FieldHelperText,
|
|
4
4
|
FieldProps,
|
|
5
5
|
getIconForProperty,
|
|
6
|
-
LabelWithIconAndTooltip,
|
|
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
|
|
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 =
|
|
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 === "
|
|
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
|
-
<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
}
|
|
@@ -190,10 +190,15 @@ function EntityFullScreenRoute({
|
|
|
190
190
|
onValuesModified={(modified) => blocked.current = modified}
|
|
191
191
|
onSaved={(params) => {
|
|
192
192
|
console.log("Entity saved", params);
|
|
193
|
-
|
|
193
|
+
const newSelectedTab = params.selectedTab;
|
|
194
|
+
const newEntityId = params.entityId;
|
|
195
|
+
if (newSelectedTab) {
|
|
196
|
+
navigate(`${basePath}/${newEntityId}/${newSelectedTab}`, { replace: true });
|
|
197
|
+
} else {
|
|
198
|
+
navigate(`${basePath}/${newEntityId}`, { replace: true });
|
|
199
|
+
}
|
|
194
200
|
}}
|
|
195
201
|
onTabChange={(params) => {
|
|
196
|
-
// updateUrl(params.entityId, params.selectedTab, !isNew, params.path, isNew);
|
|
197
202
|
setSelectedTab(params.selectedTab);
|
|
198
203
|
if (isNew) {
|
|
199
204
|
return;
|
package/src/types/fields.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CMSType, Property, PropertyOrBuilder } from "./properties";
|
|
2
2
|
import { ResolvedEntityCollection, ResolvedProperty } from "./resolved_entities";
|
|
3
3
|
import { FormexController } from "@firecms/formex";
|
|
4
|
+
import { Entity } from "./entities";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* When building a custom field you need to create a React component that takes
|
|
@@ -161,6 +162,21 @@ export interface FormContext<M extends Record<string, any> = any> {
|
|
|
161
162
|
*/
|
|
162
163
|
path?: string;
|
|
163
164
|
|
|
165
|
+
status: "new" | "existing" | "copy";
|
|
166
|
+
|
|
167
|
+
entity?: Entity<M>;
|
|
168
|
+
|
|
169
|
+
savingError?: Error;
|
|
170
|
+
|
|
171
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* If pending close is set to true, the form will close when the user
|
|
175
|
+
* saves the entity
|
|
176
|
+
* @param pendingClose
|
|
177
|
+
*/
|
|
178
|
+
setPendingClose?: (pendingClose: boolean) => void;
|
|
179
|
+
|
|
164
180
|
/**
|
|
165
181
|
* This is the underlying formex controller that powers the form
|
|
166
182
|
*/
|
package/src/types/navigation.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { EntityReference } from "./entities";
|
|
|
5
5
|
/**
|
|
6
6
|
* Controller that includes the resolved navigation and utility methods and
|
|
7
7
|
* attributes.
|
|
8
|
+
* This controller holds the state of the navigation including the collections.
|
|
8
9
|
* @group Models
|
|
9
10
|
*/
|
|
10
11
|
export type NavigationController<EC extends EntityCollection = EntityCollection<any>> = {
|
package/src/types/plugins.tsx
CHANGED
|
@@ -195,7 +195,7 @@ export interface PluginFormActionProps<USER extends User = User, EC extends Enti
|
|
|
195
195
|
formContext?: FormContext<any>;
|
|
196
196
|
context: FireCMSContext<USER>;
|
|
197
197
|
currentEntityId?: string;
|
|
198
|
-
|
|
198
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
export type PluginFieldBuilderParams<T extends CMSType = CMSType, M extends Record<string, any> = any, EC extends EntityCollection<M> = EntityCollection<M>> = {
|
package/src/types/properties.ts
CHANGED
|
@@ -377,7 +377,7 @@ export interface StringProperty extends BaseProperty<string> {
|
|
|
377
377
|
|
|
378
378
|
/**
|
|
379
379
|
* You can specify a `Storage` configuration. It is used to
|
|
380
|
-
* indicate that this string refers to a path in
|
|
380
|
+
* indicate that this string refers to a path in your storage provider.
|
|
381
381
|
*/
|
|
382
382
|
storage?: StorageConfig;
|
|
383
383
|
|
package/src/util/entity_cache.ts
CHANGED
|
@@ -10,23 +10,31 @@ const entityCache: Map<string, object> = new Map();
|
|
|
10
10
|
const isLocalStorageAvailable = typeof localStorage !== "undefined";
|
|
11
11
|
|
|
12
12
|
// Define custom replacer for JSON.stringify
|
|
13
|
-
function customReplacer(key: string
|
|
13
|
+
function customReplacer(key: string): any {
|
|
14
|
+
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
const value = this[key];
|
|
17
|
+
|
|
14
18
|
// Handle Date objects
|
|
19
|
+
// @ts-ignore
|
|
15
20
|
if (value instanceof Date) {
|
|
16
21
|
return { __type: "Date", value: value.toISOString() };
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
// Handle EntityReference
|
|
25
|
+
// @ts-ignore
|
|
20
26
|
if (value instanceof EntityReference) {
|
|
21
27
|
return { __type: "EntityReference", id: value.id, path: value.path };
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
// Handle GeoPoint
|
|
31
|
+
// @ts-ignore
|
|
25
32
|
if (value instanceof GeoPoint) {
|
|
26
33
|
return { __type: "GeoPoint", latitude: value.latitude, longitude: value.longitude };
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
// Handle Vector
|
|
37
|
+
// @ts-ignore
|
|
30
38
|
if (value instanceof Vector) {
|
|
31
39
|
return { __type: "Vector", value: value.value };
|
|
32
40
|
}
|
|
@@ -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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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) => {
|