@firecms/core 3.0.0-beta.11 → 3.0.0-beta.12

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 (173) hide show
  1. package/dist/components/ArrayContainer.d.ts +7 -3
  2. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
  3. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  4. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +15 -1
  5. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  6. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +4 -0
  7. package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
  8. package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
  9. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
  10. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  11. package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
  12. package/dist/components/common/default_entity_actions.d.ts +0 -2
  13. package/dist/components/common/index.d.ts +1 -1
  14. package/dist/components/common/useColumnsIds.d.ts +1 -0
  15. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
  16. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  17. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  18. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  19. package/dist/core/EntityEditView.d.ts +29 -21
  20. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  21. package/dist/core/FireCMSRouter.d.ts +4 -0
  22. package/dist/core/NavigationRoutes.d.ts +0 -1
  23. package/dist/core/SideDialogs.d.ts +4 -2
  24. package/dist/core/index.d.ts +2 -1
  25. package/dist/form/EntityForm.d.ts +45 -0
  26. package/dist/form/EntityFormActions.d.ts +17 -0
  27. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  28. package/dist/form/components/FormEntry.d.ts +6 -0
  29. package/dist/form/components/FormLayout.d.ts +5 -0
  30. package/dist/form/components/index.d.ts +2 -0
  31. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  32. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  33. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  34. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  35. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  36. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  37. package/dist/form/index.d.ts +16 -16
  38. package/dist/hooks/data/useEntityFetch.d.ts +2 -1
  39. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  40. package/dist/hooks/useBuildNavigationController.d.ts +4 -1
  41. package/dist/hooks/useModeController.d.ts +1 -2
  42. package/dist/index.es.js +18213 -16819
  43. package/dist/index.es.js.map +1 -1
  44. package/dist/index.umd.js +18164 -16771
  45. package/dist/index.umd.js.map +1 -1
  46. package/dist/internal/useBuildSideEntityController.d.ts +2 -2
  47. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  48. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  49. package/dist/routes/FireCMSRoute.d.ts +1 -0
  50. package/dist/routes/HomePageRoute.d.ts +3 -0
  51. package/dist/types/collections.d.ts +30 -10
  52. package/dist/types/datasource.d.ts +2 -2
  53. package/dist/types/dialogs_controller.d.ts +7 -3
  54. package/dist/types/entities.d.ts +1 -1
  55. package/dist/types/entity_actions.d.ts +10 -0
  56. package/dist/types/fields.d.ts +9 -2
  57. package/dist/types/navigation.d.ts +29 -12
  58. package/dist/types/plugins.d.ts +1 -0
  59. package/dist/types/properties.d.ts +18 -3
  60. package/dist/types/side_entity_controller.d.ts +6 -1
  61. package/dist/util/builders.d.ts +1 -1
  62. package/dist/util/entity_actions.d.ts +2 -0
  63. package/dist/util/entity_cache.d.ts +23 -0
  64. package/dist/util/index.d.ts +1 -0
  65. package/dist/util/navigation_from_path.d.ts +6 -1
  66. package/dist/util/navigation_utils.d.ts +12 -1
  67. package/dist/util/resolutions.d.ts +6 -1
  68. package/package.json +19 -21
  69. package/src/components/ArrayContainer.tsx +48 -29
  70. package/src/components/CircularProgressCenter.tsx +1 -1
  71. package/src/components/DeleteEntityDialog.tsx +1 -1
  72. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +40 -19
  73. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +10 -4
  74. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +18 -1
  75. package/src/components/EntityCollectionTable/index.tsx +1 -1
  76. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
  77. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +5 -11
  78. package/src/components/EntityCollectionView/EntityCollectionView.tsx +83 -41
  79. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  80. package/src/components/NotFoundPage.tsx +2 -2
  81. package/src/components/PropertyIdCopyTooltip.tsx +2 -3
  82. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +11 -6
  83. package/src/components/SelectableTable/SelectableTable.tsx +18 -3
  84. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +7 -7
  85. package/src/components/UnsavedChangesDialog.tsx +42 -0
  86. package/src/components/VirtualTable/VirtualTable.tsx +19 -2
  87. package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
  88. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
  89. package/src/components/common/default_entity_actions.tsx +26 -37
  90. package/src/components/common/index.ts +1 -1
  91. package/src/components/common/useColumnsIds.tsx +1 -1
  92. package/src/components/common/useDataSourceTableController.tsx +420 -0
  93. package/src/components/common/useDebouncedCallback.tsx +20 -0
  94. package/src/components/common/useScrollRestoration.tsx +68 -0
  95. package/src/contexts/BreacrumbsContext.tsx +38 -0
  96. package/src/contexts/DialogsProvider.tsx +3 -2
  97. package/src/contexts/ModeController.tsx +1 -3
  98. package/src/core/DefaultAppBar.tsx +44 -14
  99. package/src/core/DefaultDrawer.tsx +1 -1
  100. package/src/core/EntityEditView.tsx +278 -1000
  101. package/src/core/EntityEditViewFormActions.tsx +199 -0
  102. package/src/core/EntitySidePanel.tsx +85 -15
  103. package/src/core/FireCMS.tsx +7 -4
  104. package/src/core/FireCMSRouter.tsx +17 -0
  105. package/src/core/NavigationRoutes.tsx +23 -32
  106. package/src/core/SideDialogs.tsx +20 -11
  107. package/src/core/index.tsx +4 -2
  108. package/src/form/EntityForm.tsx +774 -0
  109. package/src/form/EntityFormActions.tsx +169 -0
  110. package/src/form/PropertyFieldBinding.tsx +13 -11
  111. package/src/form/components/FormEntry.tsx +22 -0
  112. package/src/form/components/FormLayout.tsx +16 -0
  113. package/src/form/components/LabelWithIcon.tsx +6 -3
  114. package/src/form/components/StorageUploadProgress.tsx +1 -1
  115. package/src/form/components/index.tsx +2 -0
  116. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +4 -4
  117. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +4 -2
  118. package/src/form/field_bindings/BlockFieldBinding.tsx +4 -2
  119. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -0
  120. package/src/form/field_bindings/MapFieldBinding.tsx +14 -16
  121. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +9 -6
  122. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -1
  123. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
  124. package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -1
  125. package/src/form/field_bindings/RepeatFieldBinding.tsx +5 -2
  126. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -1
  127. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +6 -4
  128. package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -0
  129. package/src/form/field_bindings/TextFieldBinding.tsx +1 -0
  130. package/src/form/index.tsx +16 -32
  131. package/src/form/validation.ts +12 -6
  132. package/src/hooks/data/save.ts +1 -1
  133. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  134. package/src/hooks/data/useEntityFetch.tsx +5 -1
  135. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  136. package/src/hooks/useBuildModeController.tsx +15 -28
  137. package/src/hooks/useBuildNavigationController.tsx +70 -24
  138. package/src/hooks/useLargeLayout.tsx +0 -35
  139. package/src/hooks/useModeController.tsx +1 -2
  140. package/src/hooks/useResolvedNavigationFrom.tsx +4 -6
  141. package/src/internal/useBuildSideDialogsController.tsx +3 -2
  142. package/src/internal/useBuildSideEntityController.tsx +124 -83
  143. package/src/internal/useUnsavedChangesDialog.tsx +126 -92
  144. package/src/preview/PropertyPreview.tsx +8 -8
  145. package/src/preview/components/UrlComponentPreview.tsx +17 -18
  146. package/src/preview/property_previews/MapPropertyPreview.tsx +3 -2
  147. package/src/routes/CustomCMSRoute.tsx +21 -0
  148. package/src/routes/FireCMSRoute.tsx +235 -0
  149. package/src/routes/HomePageRoute.tsx +17 -0
  150. package/src/types/collections.ts +38 -13
  151. package/src/types/datasource.ts +2 -1
  152. package/src/types/dialogs_controller.tsx +7 -3
  153. package/src/types/entities.ts +1 -1
  154. package/src/types/entity_actions.tsx +12 -0
  155. package/src/types/fields.tsx +13 -2
  156. package/src/types/navigation.ts +36 -16
  157. package/src/types/plugins.tsx +1 -0
  158. package/src/types/properties.ts +21 -3
  159. package/src/types/side_dialogs_controller.tsx +2 -0
  160. package/src/types/side_entity_controller.tsx +6 -1
  161. package/src/util/builders.ts +5 -3
  162. package/src/util/entity_actions.ts +28 -0
  163. package/src/util/entity_cache.ts +204 -0
  164. package/src/util/index.ts +1 -0
  165. package/src/util/join_collections.ts +3 -0
  166. package/src/util/navigation_from_path.ts +13 -6
  167. package/src/util/navigation_utils.ts +53 -1
  168. package/src/util/objects.ts +4 -1
  169. package/src/util/parent_references_from_path.ts +3 -3
  170. package/src/util/resolutions.ts +26 -5
  171. package/src/util/useStorageUploadController.tsx +39 -21
  172. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
  173. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -0,0 +1,169 @@
1
+ import React from "react";
2
+ import { Entity, EntityAction, FireCMSContext, ResolvedEntityCollection, SideEntityController } from "../types";
3
+ import { Button, cls, defaultBorderMixin, DialogActions, IconButton, LoadingButton, Typography } from "@firecms/ui";
4
+ import { FormexController } from "@firecms/formex";
5
+ import { useFireCMSContext, useSideEntityController } from "../hooks";
6
+
7
+ export interface EntityFormActionsProps {
8
+ collection: ResolvedEntityCollection;
9
+ path: string;
10
+ entity?: Entity;
11
+ layout: "bottom" | "side";
12
+ savingError?: Error;
13
+ formex: FormexController<any>;
14
+ disabled: boolean;
15
+ status: "new" | "existing" | "copy";
16
+ pluginActions: React.ReactNode[];
17
+ openEntityMode: "side_panel" | "full_screen";
18
+ showDefaultActions?: boolean;
19
+ }
20
+
21
+ export function EntityFormActions({
22
+ collection,
23
+ entity,
24
+ layout,
25
+ savingError,
26
+ formex,
27
+ disabled,
28
+ status,
29
+ pluginActions,
30
+ openEntityMode
31
+ }: EntityFormActionsProps) {
32
+
33
+ const context = useFireCMSContext();
34
+ const sideEntityController = useSideEntityController();
35
+
36
+ return layout === "bottom"
37
+ ? buildBottomActions({
38
+ savingError,
39
+ entity,
40
+ collection,
41
+ context,
42
+ sideEntityController,
43
+ isSubmitting: formex.isSubmitting,
44
+ disabled,
45
+ status,
46
+ pluginActions,
47
+ openEntityMode
48
+ })
49
+ : buildSideActions({
50
+ savingError,
51
+ entity,
52
+ collection,
53
+ context,
54
+ sideEntityController,
55
+ isSubmitting: formex.isSubmitting,
56
+ disabled,
57
+ status,
58
+ pluginActions,
59
+ openEntityMode
60
+ });
61
+ }
62
+
63
+ type ActionsViewProps<M extends object> = {
64
+ savingError: Error | undefined,
65
+ entity: Entity<M> | undefined,
66
+ formActions?: EntityAction[],
67
+ collection: ResolvedEntityCollection,
68
+ context: FireCMSContext,
69
+ sideEntityController: SideEntityController,
70
+ isSubmitting: boolean,
71
+ disabled: boolean,
72
+ status: "new" | "existing" | "copy",
73
+ pluginActions?: React.ReactNode[],
74
+ openEntityMode: "side_panel" | "full_screen";
75
+ };
76
+
77
+ function buildBottomActions<M extends object>({
78
+ savingError,
79
+ entity,
80
+ formActions,
81
+ collection,
82
+ context,
83
+ sideEntityController,
84
+ isSubmitting,
85
+ disabled,
86
+ status,
87
+ pluginActions,
88
+ openEntityMode
89
+ }: ActionsViewProps<M>) {
90
+
91
+ return <DialogActions position={"absolute"}>
92
+ {savingError &&
93
+ <div className="text-right">
94
+ <Typography color={"error"}>{savingError.message}</Typography>
95
+ </div>
96
+ }
97
+ {entity && (formActions ?? []).length > 0 && <div className="flex-grow flex overflow-auto no-scrollbar">
98
+ {(formActions ?? []).map(action => (
99
+ <IconButton
100
+ key={action.name}
101
+ color="primary"
102
+ onClick={(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
103
+ event.stopPropagation();
104
+ if (entity)
105
+ action.onClick({
106
+ entity,
107
+ fullPath: collection.path,
108
+ collection: collection,
109
+ context,
110
+ sideEntityController,
111
+ openEntityMode: openEntityMode
112
+ });
113
+ }}>
114
+ {action.icon}
115
+ </IconButton>
116
+ ))}
117
+ </div>}
118
+ {pluginActions}
119
+ <Button variant="text" disabled={disabled || isSubmitting} type="reset">
120
+ {status === "existing" ? "Discard" : "Clear"}
121
+ </Button>
122
+ <Button variant={"filled"} color="primary" type="submit"
123
+ disabled={disabled || isSubmitting}>
124
+ {status === "existing" && "Save"}
125
+ {status === "copy" && "Create copy"}
126
+ {status === "new" && "Create"}
127
+ </Button>
128
+
129
+ </DialogActions>;
130
+ }
131
+
132
+ function buildSideActions<M extends object>({
133
+ savingError,
134
+ entity,
135
+ formActions,
136
+ collection,
137
+ context,
138
+ sideEntityController,
139
+ isSubmitting,
140
+ disabled,
141
+ status,
142
+ pluginActions
143
+ }: ActionsViewProps<M>) {
144
+
145
+ return <div
146
+ className={cls("overflow-auto h-full flex flex-col gap-2 w-80 2xl:w-96 px-4 py-16 sticky top-0 border-l", defaultBorderMixin)}>
147
+ <LoadingButton fullWidth={true}
148
+ variant="filled"
149
+ color="primary"
150
+ type="submit"
151
+ size={"large"}
152
+ disabled={disabled || isSubmitting}>
153
+ {status === "existing" && "Save"}
154
+ {status === "copy" && "Create copy"}
155
+ {status === "new" && "Create"}
156
+ </LoadingButton>
157
+ <Button fullWidth={true} variant="text" disabled={disabled || isSubmitting} type="reset">
158
+ {status === "existing" ? "Discard" : "Clear"}
159
+ </Button>
160
+
161
+ {pluginActions}
162
+
163
+ {savingError &&
164
+ <div className="text-right">
165
+ <Typography color={"error"}>{savingError.message}</Typography>
166
+ </div>
167
+ }
168
+ </div>;
169
+ }
@@ -5,13 +5,13 @@ import { Field, FieldProps as FormexFieldProps, getIn } from "@firecms/formex";
5
5
 
6
6
  import {
7
7
  CMSType,
8
- EntityCollection,
9
8
  FieldProps,
10
9
  FireCMSPlugin,
11
10
  PluginFieldBuilderParams,
12
11
  Property,
13
12
  PropertyFieldBindingProps,
14
13
  PropertyOrBuilder,
14
+ ResolvedEntityCollection,
15
15
  ResolvedProperty
16
16
  } from "../types";
17
17
  import { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
@@ -74,7 +74,7 @@ export const PropertyFieldBinding = React.memo(PropertyFieldBindingInternal, (a:
74
74
  return false;
75
75
  }) as typeof PropertyFieldBindingInternal;
76
76
 
77
- function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Record<string, any> = Record<string, any>>
77
+ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Record<string, any> = any>
78
78
  ({
79
79
  propertyKey,
80
80
  property,
@@ -147,7 +147,9 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
147
147
  console.warn(`No field component found for property ${propertyKey}`);
148
148
  console.warn("Property:", property);
149
149
  return (
150
- <div>{`Currently the field ${resolvedProperty.dataType} is not supported`}</div>
150
+ <div className={"w-full"}>
151
+ {`Currently the field ${resolvedProperty.dataType} is not supported`}
152
+ </div>
151
153
  );
152
154
  }
153
155
 
@@ -175,7 +177,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
175
177
 
176
178
  }
177
179
 
178
- type ResolvedPropertyFieldBindingProps<T extends CMSType = CMSType, M extends Record<string, any> = Record<string, any>> =
180
+ type ResolvedPropertyFieldBindingProps<T extends CMSType = CMSType, M extends Record<string, any> = any> =
179
181
  Omit<PropertyFieldBindingProps<T, M>, "property">
180
182
  & {
181
183
  property: ResolvedProperty<T>
@@ -199,11 +201,11 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
199
201
  },
200
202
  formexFieldProps
201
203
  }:
202
- {
203
- Component: ComponentType<FieldProps<T, any, M>>,
204
- componentProps: ResolvedPropertyFieldBindingProps<T, M>,
205
- formexFieldProps: FormexFieldProps<T, any>
206
- }) {
204
+ {
205
+ Component: ComponentType<FieldProps<T, any, M>>,
206
+ componentProps: ResolvedPropertyFieldBindingProps<T, M>,
207
+ formexFieldProps: FormexFieldProps<T, any>
208
+ }) {
207
209
 
208
210
  const { plugins } = useCustomizationController();
209
211
 
@@ -296,7 +298,7 @@ const shouldPropertyReRender = (property: PropertyOrBuilder | ResolvedProperty,
296
298
 
297
299
  interface UseWrappedComponentParams<T extends CMSType = CMSType, M extends Record<string, any> = any> {
298
300
  path?: string,
299
- collection?: EntityCollection<M>,
301
+ collection?: ResolvedEntityCollection<M>,
300
302
  propertyKey: string,
301
303
  property: ResolvedProperty<T>,
302
304
  Component: ComponentType<FieldProps<T, any, M>>,
@@ -327,7 +329,7 @@ function useWrappedComponent<T extends CMSType = CMSType, M extends Record<strin
327
329
  Field: Component,
328
330
  plugin,
329
331
  path,
330
- collection
332
+ collection,
331
333
  };
332
334
  const enabled = plugin.form?.fieldBuilderEnabled?.(params);
333
335
  if (enabled === undefined || enabled)
@@ -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
+ }
@@ -1,4 +1,5 @@
1
1
  import React, { forwardRef } from "react";
2
+ import { cls } from "@firecms/ui";
2
3
 
3
4
  interface LabelWithIconProps {
4
5
  icon: React.ReactNode;
@@ -23,9 +24,11 @@ export const LabelWithIcon = forwardRef<HTMLDivElement, LabelWithIconProps>(
23
24
  return (
24
25
  <div
25
26
  ref={ref}
26
- className={`inline-flex items-center my-0.5 ${small ? "gap-1" : "gap-2"} ${className ?? ""}`}
27
+ className={cls("inline-flex items-center my-0.5",
28
+ small ? "gap-1" : "gap-2",
29
+ className)}
27
30
  >
28
- {icon}
31
+ {icon}
29
32
  <span
30
33
  className={`text-start font-medium text-${small ? "base" : "sm"} origin-top-left transform ${
31
34
  small ? "translate-x-2 scale-75" : ""
@@ -33,7 +36,7 @@ export const LabelWithIcon = forwardRef<HTMLDivElement, LabelWithIconProps>(
33
36
  >
34
37
  {(title ?? "") + (required ? " *" : "")}
35
38
  </span>
36
- </div>
39
+ </div>
37
40
  );
38
41
  }
39
42
  );
@@ -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}/>}
@@ -1,3 +1,5 @@
1
1
  export * from "./FieldHelperText";
2
2
  export * from "./LabelWithIcon";
3
3
  export * from "./LabelWithIconAndTooltip";
4
+ export * from "./FormEntry";
5
+ export * from "./FormLayout";
@@ -20,14 +20,15 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
20
20
  showError,
21
21
  isSubmitting,
22
22
  setValue,
23
- minimalistView,
23
+ minimalistView: minimalistViewProp,
24
24
  property,
25
25
  includeDescription,
26
- underlyingValueHasChanged,
27
26
  context,
28
27
  disabled
29
28
  }: FieldProps<T, any, any>) {
30
29
 
30
+ const minimalistView = minimalistViewProp || property.minimalistView;
31
+
31
32
  let resolvedProperties = "resolvedProperties" in property ? property.resolvedProperties : undefined;
32
33
  if (!resolvedProperties) {
33
34
  resolvedProperties = getArrayResolvedProperties({
@@ -52,7 +53,7 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
52
53
  icon={getIconForProperty(property, "small")}
53
54
  required={property.validation?.required}
54
55
  title={property.name}
55
- className={"flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
56
+ className={"h-8 flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
56
57
  {Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
57
58
  </>);
58
59
 
@@ -63,7 +64,6 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
63
64
  disabled: disabled || thisDisabled,
64
65
  property: childProperty,
65
66
  includeDescription,
66
- underlyingValueHasChanged,
67
67
  context,
68
68
  partOfArray: true,
69
69
  minimalistView: false,
@@ -25,13 +25,15 @@ export function ArrayOfReferencesFieldBinding({
25
25
  showError,
26
26
  disabled,
27
27
  isSubmitting,
28
- minimalistView,
28
+ minimalistView: minimalistViewProp,
29
29
  property,
30
30
  includeDescription,
31
31
  setValue,
32
32
  setFieldValue
33
33
  }: ArrayOfReferencesFieldProps) {
34
34
 
35
+ const minimalistView = minimalistViewProp || property.minimalistView;
36
+
35
37
  const ofProperty = property.of as ResolvedProperty;
36
38
  if (ofProperty.dataType !== "reference") {
37
39
  throw Error("ArrayOfReferencesField expected a property containing references");
@@ -104,7 +106,7 @@ export function ArrayOfReferencesFieldBinding({
104
106
  icon={getIconForProperty(property, "small")}
105
107
  required={property.validation?.required}
106
108
  title={property.name}
107
- className={"flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
109
+ className={"h-8 flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
108
110
  {Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
109
111
  </>);
110
112
 
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useState } from "react";
1
+ import React, { useEffect, useState } from "react";
2
2
 
3
3
  import { Field, useFormex } from "@firecms/formex";
4
4
 
@@ -28,7 +28,7 @@ export function BlockFieldBinding<T extends Array<any>>({
28
28
  isSubmitting,
29
29
  setValue,
30
30
  setFieldValue,
31
- minimalistView,
31
+ minimalistView: minimalistViewProp,
32
32
  property,
33
33
  includeDescription,
34
34
  underlyingValueHasChanged,
@@ -36,6 +36,8 @@ export function BlockFieldBinding<T extends Array<any>>({
36
36
  disabled
37
37
  }: FieldProps<T>) {
38
38
 
39
+ const minimalistView = minimalistViewProp || property.minimalistView;
40
+
39
41
  if (!property.oneOf)
40
42
  throw Error("ArrayOneOfField misconfiguration. Property `oneOf` not set");
41
43
 
@@ -51,6 +51,7 @@ export function DateTimeFieldBinding({
51
51
  clearable={property.clearable}
52
52
  locale={locale}
53
53
  error={showError}
54
+ disabled={disabled}
54
55
  label={<LabelWithIcon
55
56
  icon={getIconForProperty(property, "small")}
56
57
  required={property.validation?.required}
@@ -5,7 +5,7 @@ import { ErrorBoundary } from "../../components";
5
5
  import { getIconForProperty, isHidden, isReadOnly, pick } from "../../util";
6
6
  import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
7
7
  import { PropertyFieldBinding } from "../PropertyFieldBinding";
8
- import { ExpandablePanel, InputLabel, Select, SelectItem } from "@firecms/ui";
8
+ import { cls, ExpandablePanel, InputLabel, Select, SelectItem } from "@firecms/ui";
9
9
 
10
10
  /**
11
11
  * Field that renders the children property fields
@@ -21,9 +21,8 @@ export function MapFieldBinding({
21
21
  error,
22
22
  disabled,
23
23
  property,
24
- minimalistView,
24
+ minimalistView: minimalistViewProp,
25
25
  includeDescription,
26
- underlyingValueHasChanged,
27
26
  autoFocus,
28
27
  context,
29
28
  onPropertyChange
@@ -31,6 +30,7 @@ export function MapFieldBinding({
31
30
 
32
31
  const pickOnlySomeKeys = property.pickOnlySomeKeys || false;
33
32
  const expanded = property.expanded === undefined ? true : property.expanded;
33
+ const minimalistView = minimalistViewProp || property.minimalistView;
34
34
 
35
35
  if (!property.properties) {
36
36
  throw Error(`You need to specify a 'properties' prop (or specify a custom field) in your map property ${propertyKey}`);
@@ -51,7 +51,7 @@ export function MapFieldBinding({
51
51
  }
52
52
 
53
53
  const mapFormView = <>
54
- <div className="py-1 flex flex-col space-y-2">
54
+ <div className={cls("py-1 flex flex-col space-y-2", minimalistView && property.widthPercentage !== undefined ? "mt-8" : undefined)}>
55
55
  {Object.entries(mapProperties)
56
56
  .filter(([_, property]) => !isHidden(property))
57
57
  .map(([entryKey, childProperty], index) => {
@@ -61,7 +61,6 @@ export function MapFieldBinding({
61
61
  disabled: disabled || thisDisabled,
62
62
  property: childProperty,
63
63
  includeDescription,
64
- underlyingValueHasChanged,
65
64
  context,
66
65
  partOfArray: false,
67
66
  minimalistView: false,
@@ -76,7 +75,7 @@ export function MapFieldBinding({
76
75
  };
77
76
 
78
77
  return (
79
- <div key={`map-${propertyKey}-${index}`}>
78
+ <div key={`map-${propertyKey}-${index}`} className={"relative"}>
80
79
  <ErrorBoundary>
81
80
  <PropertyFieldBinding
82
81
  {...fieldBindingProps}/>
@@ -94,15 +93,6 @@ export function MapFieldBinding({
94
93
  </>
95
94
  ;
96
95
 
97
- const title = (
98
- <LabelWithIconAndTooltip
99
- propertyKey={propertyKey}
100
- icon={getIconForProperty(property, "small")}
101
- required={property.validation?.required}
102
- title={property.name}
103
- className={"text-text-secondary dark:text-text-secondary-dark"}/>
104
- );
105
-
106
96
  return (
107
97
  <ErrorBoundary>
108
98
 
@@ -112,8 +102,16 @@ export function MapFieldBinding({
112
102
  expanded
113
103
  });
114
104
  }}
105
+ className={property.widthPercentage !== undefined ? "mt-8" : undefined}
115
106
  innerClassName={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2 bg-white dark:bg-surface-900"}
116
- title={title}>{mapFormView}</ExpandablePanel>}
107
+ title={<LabelWithIconAndTooltip
108
+ propertyKey={propertyKey}
109
+ icon={getIconForProperty(property, "small")}
110
+ required={property.validation?.required}
111
+ title={property.name}
112
+ className={"text-text-secondary dark:text-text-secondary-dark"}/>}>
113
+ {mapFormView}
114
+ </ExpandablePanel>}
117
115
 
118
116
  {minimalistView && mapFormView}
119
117
 
@@ -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);
@@ -135,8 +137,9 @@ export function MarkdownEditorFieldBinding({
135
137
  icon={getIconForProperty(property, "small")}
136
138
  required={property.validation?.required}
137
139
  title={property.name}
138
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
139
- <div className={cls("rounded-md", fieldBackgroundMixin, fieldBackgroundHoverMixin)}>
140
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
141
+ <div
142
+ className={cls("rounded-md", fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin)}>
140
143
  {editor}
141
144
  </div>
142
145
  <FieldHelperText includeDescription={includeDescription}
@@ -92,7 +92,7 @@ export function MultiSelectFieldBinding({
92
92
  icon={getIconForProperty(property, "small")}
93
93
  required={property.validation?.required}
94
94
  title={property.name}
95
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
95
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
96
96
  onValueChange={(updatedValue: string[]) => {
97
97
  let newValue: EnumType[] | null;
98
98
  if (of && (of as ResolvedProperty)?.dataType === "number") {
@@ -39,11 +39,11 @@ export function ReadOnlyFieldBinding({
39
39
  icon={getIconForProperty(property, "small")}
40
40
  required={property.validation?.required}
41
41
  title={property.name}
42
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
42
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
43
43
  }
44
44
 
45
45
  <div
46
- className={cls(paperMixin, "min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
46
+ className={cls(paperMixin, "w-full min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
47
47
 
48
48
  <ErrorBoundary>
49
49
  <PropertyPreview propertyKey={propertyKey}
@@ -90,7 +90,7 @@ function ReferenceFieldBindingInternal({
90
90
  icon={getIconForProperty(property, "small")}
91
91
  required={property.validation?.required}
92
92
  title={property.name}
93
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
93
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
94
94
 
95
95
  {!collection && <ErrorView
96
96
  error={"The specified collection does not exist. Check console"}/>}
@@ -23,7 +23,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
23
23
  isSubmitting,
24
24
  setValue,
25
25
  setFieldValue,
26
- minimalistView,
26
+ minimalistView: minimalistViewProp,
27
27
  property,
28
28
  includeDescription,
29
29
  underlyingValueHasChanged,
@@ -31,6 +31,8 @@ export function RepeatFieldBinding<T extends Array<any>>({
31
31
  disabled
32
32
  }: FieldProps<T>) {
33
33
 
34
+ const minimalistView = minimalistViewProp || property.minimalistView;
35
+
34
36
  if (!property.of)
35
37
  throw Error("RepeatFieldBinding misconfiguration. Property `of` not set");
36
38
 
@@ -88,6 +90,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
88
90
  includeAddButton={!property.disabled}
89
91
  newDefaultEntry={getDefaultValueFor(property.of)}
90
92
  onValueChange={(value) => setFieldValue(propertyKey, value)}
93
+ className={property.widthPercentage !== undefined ? "mt-8" : undefined}
91
94
  />;
92
95
 
93
96
  const title = (<>
@@ -96,7 +99,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
96
99
  icon={getIconForProperty(property, "small")}
97
100
  required={property.validation?.required}
98
101
  title={property.name}
99
- className={"flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
102
+ className={"h-8 flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
100
103
  {Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
101
104
  </>);
102
105
 
@@ -62,7 +62,7 @@ export function SelectFieldBinding<T extends EnumType>({
62
62
  icon={getIconForProperty(property, "small")}
63
63
  required={property.validation?.required}
64
64
  title={property.name}
65
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}
65
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5 my-0"}
66
66
  />
67
67
  </PropertyIdCopyTooltip>}
68
68
  endAdornment={