@firecms/core 3.0.0-beta.10 → 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 (267) hide show
  1. package/dist/components/ArrayContainer.d.ts +22 -6
  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 +17 -3
  5. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  6. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +6 -3
  7. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +4 -0
  8. package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
  9. package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
  10. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
  11. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  12. package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
  13. package/dist/components/common/default_entity_actions.d.ts +0 -2
  14. package/dist/components/common/index.d.ts +1 -1
  15. package/dist/components/common/useColumnsIds.d.ts +1 -0
  16. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
  17. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  18. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  19. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  20. package/dist/core/EntityEditView.d.ts +30 -22
  21. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  22. package/dist/core/FireCMS.d.ts +1 -1
  23. package/dist/core/FireCMSRouter.d.ts +4 -0
  24. package/dist/core/NavigationRoutes.d.ts +0 -1
  25. package/dist/core/SideDialogs.d.ts +4 -2
  26. package/dist/core/index.d.ts +2 -1
  27. package/dist/form/EntityForm.d.ts +45 -0
  28. package/dist/form/EntityFormActions.d.ts +17 -0
  29. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  30. package/dist/form/components/FormEntry.d.ts +6 -0
  31. package/dist/form/components/FormLayout.d.ts +5 -0
  32. package/dist/form/components/index.d.ts +2 -1
  33. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  34. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  35. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  36. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  37. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  38. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  39. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  40. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  41. package/dist/form/index.d.ts +16 -16
  42. package/dist/hooks/data/delete.d.ts +4 -4
  43. package/dist/hooks/data/save.d.ts +3 -3
  44. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  45. package/dist/hooks/data/useEntityFetch.d.ts +4 -3
  46. package/dist/hooks/useAuthController.d.ts +1 -1
  47. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  48. package/dist/hooks/useBuildNavigationController.d.ts +7 -4
  49. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  50. package/dist/hooks/useModeController.d.ts +1 -2
  51. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  52. package/dist/hooks/useValidateAuthenticator.d.ts +3 -3
  53. package/dist/index.es.js +17032 -12909
  54. package/dist/index.es.js.map +1 -1
  55. package/dist/index.umd.js +17019 -12898
  56. package/dist/index.umd.js.map +1 -1
  57. package/dist/internal/useBuildSideEntityController.d.ts +2 -2
  58. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  59. package/dist/preview/PropertyPreviewProps.d.ts +1 -1
  60. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  61. package/dist/preview/util.d.ts +3 -3
  62. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  63. package/dist/routes/FireCMSRoute.d.ts +1 -0
  64. package/dist/routes/HomePageRoute.d.ts +3 -0
  65. package/dist/types/auth.d.ts +7 -9
  66. package/dist/types/collections.d.ts +44 -23
  67. package/dist/types/datasource.d.ts +2 -6
  68. package/dist/types/dialogs_controller.d.ts +7 -3
  69. package/dist/types/entities.d.ts +1 -1
  70. package/dist/types/entity_actions.d.ts +14 -4
  71. package/dist/types/entity_callbacks.d.ts +16 -16
  72. package/dist/types/export_import.d.ts +4 -4
  73. package/dist/types/fields.d.ts +27 -4
  74. package/dist/types/firecms.d.ts +2 -2
  75. package/dist/types/firecms_context.d.ts +1 -1
  76. package/dist/types/navigation.d.ts +29 -12
  77. package/dist/types/permissions.d.ts +4 -4
  78. package/dist/types/plugins.d.ts +9 -8
  79. package/dist/types/properties.d.ts +18 -3
  80. package/dist/types/property_config.d.ts +0 -2
  81. package/dist/types/side_entity_controller.d.ts +6 -1
  82. package/dist/types/user.d.ts +1 -0
  83. package/dist/util/builders.d.ts +3 -3
  84. package/dist/util/entities.d.ts +1 -1
  85. package/dist/util/entity_actions.d.ts +2 -0
  86. package/dist/util/entity_cache.d.ts +23 -0
  87. package/dist/util/icon_synonyms.d.ts +0 -1
  88. package/dist/util/icons.d.ts +3 -1
  89. package/dist/util/index.d.ts +1 -0
  90. package/dist/util/navigation_from_path.d.ts +6 -1
  91. package/dist/util/navigation_utils.d.ts +12 -1
  92. package/dist/util/objects.d.ts +1 -0
  93. package/dist/util/permissions.d.ts +4 -4
  94. package/dist/util/property_utils.d.ts +2 -2
  95. package/dist/util/resolutions.d.ts +12 -7
  96. package/package.json +129 -125
  97. package/src/app/Scaffold.tsx +4 -4
  98. package/src/components/ArrayContainer.tsx +115 -34
  99. package/src/components/CircularProgressCenter.tsx +1 -1
  100. package/src/components/ConfirmationDialog.tsx +2 -2
  101. package/src/components/DeleteEntityDialog.tsx +10 -19
  102. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +44 -20
  103. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +23 -17
  104. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +20 -3
  105. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +6 -4
  106. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +8 -9
  107. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -11
  108. package/src/components/EntityCollectionTable/index.tsx +1 -1
  109. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
  110. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +5 -5
  111. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +2 -2
  112. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +77 -73
  113. package/src/components/EntityCollectionView/EntityCollectionView.tsx +90 -49
  114. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  115. package/src/components/EntityCollectionView/useSelectionController.tsx +5 -4
  116. package/src/components/EntityPreview.tsx +39 -30
  117. package/src/components/EntityView.tsx +5 -5
  118. package/src/components/ErrorView.tsx +3 -3
  119. package/src/components/HomePage/DefaultHomePage.tsx +1 -0
  120. package/src/components/HomePage/FavouritesView.tsx +6 -11
  121. package/src/components/HomePage/NavigationCard.tsx +1 -1
  122. package/src/components/HomePage/NavigationCardBinding.tsx +4 -9
  123. package/src/components/HomePage/NavigationGroup.tsx +1 -1
  124. package/src/components/NotFoundPage.tsx +2 -2
  125. package/src/components/PropertyConfigBadge.tsx +1 -1
  126. package/src/components/PropertyIdCopyTooltip.tsx +3 -4
  127. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +13 -8
  128. package/src/components/SelectableTable/SelectableTable.tsx +20 -5
  129. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +4 -2
  130. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +10 -8
  131. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +7 -5
  132. package/src/components/UnsavedChangesDialog.tsx +42 -0
  133. package/src/components/VirtualTable/VirtualTable.tsx +19 -2
  134. package/src/components/VirtualTable/VirtualTableHeader.tsx +8 -8
  135. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +1 -1
  136. package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
  137. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  138. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  139. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
  140. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +2 -0
  141. package/src/components/common/default_entity_actions.tsx +26 -37
  142. package/src/components/common/index.ts +1 -1
  143. package/src/components/common/useColumnsIds.tsx +1 -1
  144. package/src/components/common/useDataSourceTableController.tsx +420 -0
  145. package/src/components/common/useDebouncedCallback.tsx +20 -0
  146. package/src/components/common/useScrollRestoration.tsx +68 -0
  147. package/src/contexts/BreacrumbsContext.tsx +38 -0
  148. package/src/contexts/DialogsProvider.tsx +3 -2
  149. package/src/contexts/ModeController.tsx +1 -3
  150. package/src/contexts/SnackbarProvider.tsx +2 -0
  151. package/src/core/DefaultAppBar.tsx +56 -25
  152. package/src/core/DefaultDrawer.tsx +11 -9
  153. package/src/core/DrawerNavigationItem.tsx +4 -4
  154. package/src/core/EntityEditView.tsx +282 -1006
  155. package/src/core/EntityEditViewFormActions.tsx +199 -0
  156. package/src/core/EntitySidePanel.tsx +85 -15
  157. package/src/core/FireCMS.tsx +12 -9
  158. package/src/core/FireCMSRouter.tsx +17 -0
  159. package/src/core/NavigationRoutes.tsx +23 -32
  160. package/src/core/SideDialogs.tsx +21 -12
  161. package/src/core/field_configs.tsx +4 -4
  162. package/src/core/index.tsx +4 -2
  163. package/src/form/EntityForm.tsx +774 -0
  164. package/src/form/EntityFormActions.tsx +169 -0
  165. package/src/form/PropertyFieldBinding.tsx +39 -30
  166. package/src/form/components/CustomIdField.tsx +2 -0
  167. package/src/form/components/FormEntry.tsx +22 -0
  168. package/src/form/components/FormLayout.tsx +16 -0
  169. package/src/form/components/LabelWithIcon.tsx +6 -3
  170. package/src/form/components/StorageItemPreview.tsx +3 -3
  171. package/src/form/components/StorageUploadProgress.tsx +1 -1
  172. package/src/form/components/index.tsx +2 -1
  173. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +7 -6
  174. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +20 -12
  175. package/src/form/field_bindings/BlockFieldBinding.tsx +45 -25
  176. package/src/form/field_bindings/DateTimeFieldBinding.tsx +2 -1
  177. package/src/form/field_bindings/KeyValueFieldBinding.tsx +10 -7
  178. package/src/form/field_bindings/MapFieldBinding.tsx +69 -52
  179. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +9 -6
  180. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -1
  181. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
  182. package/src/form/field_bindings/ReferenceFieldBinding.tsx +5 -5
  183. package/src/form/field_bindings/RepeatFieldBinding.tsx +30 -22
  184. package/src/form/field_bindings/SelectFieldBinding.tsx +6 -5
  185. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +7 -5
  186. package/src/form/field_bindings/SwitchFieldBinding.tsx +26 -25
  187. package/src/form/field_bindings/TextFieldBinding.tsx +4 -3
  188. package/src/form/index.tsx +16 -32
  189. package/src/form/validation.ts +12 -6
  190. package/src/hooks/data/delete.ts +4 -4
  191. package/src/hooks/data/save.ts +8 -9
  192. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  193. package/src/hooks/data/useEntityFetch.tsx +10 -6
  194. package/src/hooks/useAuthController.tsx +1 -1
  195. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  196. package/src/hooks/useBuildModeController.tsx +15 -28
  197. package/src/hooks/useBuildNavigationController.tsx +74 -29
  198. package/src/hooks/useFireCMSContext.tsx +5 -5
  199. package/src/hooks/useLargeLayout.tsx +0 -35
  200. package/src/hooks/useModeController.tsx +1 -2
  201. package/src/hooks/useResolvedNavigationFrom.tsx +9 -11
  202. package/src/hooks/useValidateAuthenticator.tsx +3 -3
  203. package/src/internal/useBuildDataSource.ts +1 -1
  204. package/src/internal/useBuildSideDialogsController.tsx +3 -2
  205. package/src/internal/useBuildSideEntityController.tsx +124 -83
  206. package/src/internal/useUnsavedChangesDialog.tsx +127 -93
  207. package/src/preview/PropertyPreview.tsx +11 -11
  208. package/src/preview/PropertyPreviewProps.tsx +1 -1
  209. package/src/preview/components/BooleanPreview.tsx +1 -1
  210. package/src/preview/components/EmptyValue.tsx +1 -1
  211. package/src/preview/components/EnumValuesChip.tsx +1 -1
  212. package/src/preview/components/ImagePreview.tsx +5 -6
  213. package/src/preview/components/UrlComponentPreview.tsx +20 -21
  214. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +1 -1
  215. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +2 -2
  216. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -2
  217. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -1
  218. package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -2
  219. package/src/preview/property_previews/ArrayPropertyPreview.tsx +2 -2
  220. package/src/preview/property_previews/MapPropertyPreview.tsx +7 -6
  221. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
  222. package/src/preview/property_previews/StringPropertyPreview.tsx +2 -2
  223. package/src/preview/util.ts +10 -10
  224. package/src/routes/CustomCMSRoute.tsx +21 -0
  225. package/src/routes/FireCMSRoute.tsx +235 -0
  226. package/src/routes/HomePageRoute.tsx +17 -0
  227. package/src/types/auth.tsx +8 -12
  228. package/src/types/collections.ts +52 -26
  229. package/src/types/datasource.ts +2 -6
  230. package/src/types/dialogs_controller.tsx +7 -3
  231. package/src/types/entities.ts +1 -1
  232. package/src/types/entity_actions.tsx +16 -4
  233. package/src/types/entity_callbacks.ts +18 -18
  234. package/src/types/export_import.ts +4 -4
  235. package/src/types/fields.tsx +33 -4
  236. package/src/types/firecms.tsx +2 -2
  237. package/src/types/firecms_context.tsx +1 -1
  238. package/src/types/navigation.ts +36 -16
  239. package/src/types/permissions.ts +5 -5
  240. package/src/types/plugins.tsx +9 -8
  241. package/src/types/properties.ts +21 -3
  242. package/src/types/property_config.tsx +0 -2
  243. package/src/types/side_dialogs_controller.tsx +2 -0
  244. package/src/types/side_entity_controller.tsx +6 -1
  245. package/src/types/user.ts +2 -0
  246. package/src/util/builders.ts +10 -8
  247. package/src/util/entities.ts +3 -1
  248. package/src/util/entity_actions.ts +28 -0
  249. package/src/util/entity_cache.ts +204 -0
  250. package/src/util/icon_list.ts +1 -0
  251. package/src/util/icon_synonyms.ts +0 -1
  252. package/src/util/icons.tsx +12 -8
  253. package/src/util/index.ts +1 -0
  254. package/src/util/join_collections.ts +3 -0
  255. package/src/util/navigation_from_path.ts +13 -6
  256. package/src/util/navigation_utils.ts +53 -1
  257. package/src/util/objects.ts +24 -1
  258. package/src/util/parent_references_from_path.ts +3 -3
  259. package/src/util/permissions.ts +8 -8
  260. package/src/util/property_utils.tsx +10 -3
  261. package/src/util/references.ts +8 -2
  262. package/src/util/resolutions.ts +34 -13
  263. package/src/util/useStorageUploadController.tsx +40 -22
  264. package/dist/form/components/FormikArrayContainer.d.ts +0 -19
  265. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
  266. package/src/form/components/FormikArrayContainer.tsx +0 -47
  267. /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,19 +74,20 @@ 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,
81
81
  context,
82
82
  includeDescription,
83
83
  underlyingValueHasChanged,
84
- disabled,
84
+ disabled: disabledProp,
85
85
  partOfArray,
86
86
  minimalistView,
87
87
  autoFocus,
88
88
  index,
89
- size
89
+ size,
90
+ onPropertyChange
90
91
  }: PropertyFieldBindingProps<T, M>): ReactElement<PropertyFieldBindingProps<T, M>> {
91
92
 
92
93
  const customizationController = useCustomizationController();
@@ -105,10 +106,12 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
105
106
  values: fieldProps.form.values,
106
107
  path: context.path,
107
108
  entityId: context.entityId,
108
- fields: customizationController.propertyConfigs,
109
+ propertyConfigs: customizationController.propertyConfigs,
109
110
  index
110
111
  });
111
112
 
113
+ const disabled = disabledProp || isReadOnly(resolvedProperty) || Boolean(resolvedProperty?.disabled);
114
+
112
115
  if (resolvedProperty === null || isHidden(resolvedProperty)) {
113
116
  return <></>;
114
117
  } else if (isReadOnly(resolvedProperty)) {
@@ -122,6 +125,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
122
125
  if (!propertyConfig) {
123
126
  console.log("INTERNAL: Could not find field config for property", {
124
127
  propertyKey,
128
+ property,
125
129
  resolvedProperty,
126
130
  fields: customizationController.propertyConfigs,
127
131
  propertyConfig
@@ -134,7 +138,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
134
138
  values: fieldProps.form.values,
135
139
  path: context.path,
136
140
  entityId: context.entityId,
137
- fields: customizationController.propertyConfigs,
141
+ propertyConfigs: customizationController.propertyConfigs,
138
142
  index
139
143
  });
140
144
  Component = configProperty.Field as ComponentType<FieldProps<T>>;
@@ -143,7 +147,9 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
143
147
  console.warn(`No field component found for property ${propertyKey}`);
144
148
  console.warn("Property:", property);
145
149
  return (
146
- <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>
147
153
  );
148
154
  }
149
155
 
@@ -157,20 +163,21 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
157
163
  partOfArray,
158
164
  minimalistView,
159
165
  autoFocus,
160
- size
166
+ size,
167
+ onPropertyChange
161
168
  };
162
169
 
163
170
  return <FieldInternal
164
171
  Component={Component as ComponentType<FieldProps>}
165
172
  componentProps={componentProps}
166
- fieldProps={fieldProps}/>;
173
+ formexFieldProps={fieldProps}/>;
167
174
  }}
168
175
  </Field>
169
176
  );
170
177
 
171
178
  }
172
179
 
173
- 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> =
174
181
  Omit<PropertyFieldBindingProps<T, M>, "property">
175
182
  & {
176
183
  property: ResolvedProperty<T>
@@ -189,26 +196,27 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
189
196
  autoFocus,
190
197
  context,
191
198
  disabled,
192
- size
199
+ size,
200
+ onPropertyChange
193
201
  },
194
- fieldProps
202
+ formexFieldProps
195
203
  }:
196
- {
197
- Component: ComponentType<FieldProps<T, any, M>>,
198
- componentProps: ResolvedPropertyFieldBindingProps<T, M>,
199
- fieldProps: FormexFieldProps<T, any>
200
- }) {
204
+ {
205
+ Component: ComponentType<FieldProps<T, any, M>>,
206
+ componentProps: ResolvedPropertyFieldBindingProps<T, M>,
207
+ formexFieldProps: FormexFieldProps<T, any>
208
+ }) {
201
209
 
202
210
  const { plugins } = useCustomizationController();
203
211
 
204
212
  const customFieldProps: any = property.customProps;
205
- const value = fieldProps.field.value;
206
- // const initialValue = fieldProps.meta.initialValue;
207
- const error = getIn(fieldProps.form.errors, propertyKey);
208
- const touched = getIn(fieldProps.form.touched, propertyKey);
213
+ const value = formexFieldProps.field.value;
214
+ // const initialValue = formexFieldProps.meta.initialValue;
215
+ const error = getIn(formexFieldProps.form.errors, propertyKey);
216
+ const touched = getIn(formexFieldProps.form.touched, propertyKey);
209
217
 
210
218
  const showError: boolean = error &&
211
- (fieldProps.form.submitCount > 0 || property.validation?.unique) &&
219
+ (formexFieldProps.form.submitCount > 0 || property.validation?.unique) &&
212
220
  (!Array.isArray(error) || !!error.filter((e: any) => !!e).length);
213
221
 
214
222
  const WrappedComponent: ComponentType<FieldProps<T, any, M>> | null = useWrappedComponent({
@@ -221,16 +229,16 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
221
229
  });
222
230
  const UsedComponent: ComponentType<FieldProps<T>> = WrappedComponent ?? Component;
223
231
 
224
- const isSubmitting = fieldProps.form.isSubmitting;
232
+ const isSubmitting = formexFieldProps.form.isSubmitting;
225
233
 
226
234
  const setValue = useCallback((value: T | null, shouldValidate?: boolean) => {
227
- fieldProps.form.setFieldTouched(propertyKey, true, false);
228
- fieldProps.form.setFieldValue(propertyKey, value, shouldValidate);
235
+ formexFieldProps.form.setFieldTouched(propertyKey, true, false);
236
+ formexFieldProps.form.setFieldValue(propertyKey, value, shouldValidate);
229
237
  }, []);
230
238
 
231
239
  const setFieldValue = useCallback((otherPropertyKey: string, value: CMSType | null, shouldValidate?: boolean) => {
232
- fieldProps.form.setFieldTouched(propertyKey, true, false);
233
- fieldProps.form.setFieldValue(otherPropertyKey, value, shouldValidate);
240
+ formexFieldProps.form.setFieldTouched(propertyKey, true, false);
241
+ formexFieldProps.form.setFieldValue(otherPropertyKey, value, shouldValidate);
234
242
  }, []);
235
243
 
236
244
  const cmsFieldProps: FieldProps<T, CustomProps, M> = {
@@ -251,7 +259,8 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
251
259
  autoFocus: autoFocus ?? false,
252
260
  customProps: customFieldProps,
253
261
  context,
254
- size
262
+ size,
263
+ onPropertyChange
255
264
  };
256
265
 
257
266
  return (
@@ -289,7 +298,7 @@ const shouldPropertyReRender = (property: PropertyOrBuilder | ResolvedProperty,
289
298
 
290
299
  interface UseWrappedComponentParams<T extends CMSType = CMSType, M extends Record<string, any> = any> {
291
300
  path?: string,
292
- collection?: EntityCollection<M>,
301
+ collection?: ResolvedEntityCollection<M>,
293
302
  propertyKey: string,
294
303
  property: ResolvedProperty<T>,
295
304
  Component: ComponentType<FieldProps<T, any, M>>,
@@ -320,7 +329,7 @@ function useWrappedComponent<T extends CMSType = CMSType, M extends Record<strin
320
329
  Field: Component,
321
330
  plugin,
322
331
  path,
323
- collection
332
+ collection,
324
333
  };
325
334
  const enabled = plugin.form?.fieldBuilderEnabled?.(params);
326
335
  if (enabled === undefined || enabled)
@@ -100,7 +100,9 @@ export function CustomIdField<M extends Record<string, any>>({
100
100
 
101
101
  {enumValues &&
102
102
  <Select
103
+ size={"large"}
103
104
  error={error}
105
+ fullWidth={true}
104
106
  onValueChange={(v) => onChange(v as string)}
105
107
  {...fieldProps}
106
108
  renderValue={(option) => {
@@ -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
  );
@@ -31,12 +31,12 @@ 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 &&
38
38
  <div
39
- className="absolute rounded-full -top-2 -right-2 z-10 bg-white dark:bg-gray-900">
39
+ className="absolute rounded-full -top-2 -right-2 z-10 bg-white dark:bg-surface-900">
40
40
 
41
41
  <Tooltip
42
42
  asChild={true}
@@ -67,7 +67,7 @@ export function StorageItemPreview({
67
67
  <div
68
68
  onClick={(e) => e.stopPropagation()}
69
69
  className="flex flex-col items-center justify-center w-full h-full">
70
- <DescriptionIcon className="text-gray-700 dark:text-gray-300"/>
70
+ <DescriptionIcon className="text-surface-700 dark:text-surface-300"/>
71
71
  </div>
72
72
  }
73
73
 
@@ -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,4 +1,5 @@
1
- export * from "./FormikArrayContainer";
2
1
  export * from "./FieldHelperText";
3
2
  export * from "./LabelWithIcon";
4
3
  export * from "./LabelWithIconAndTooltip";
4
+ export * from "./FormEntry";
5
+ export * from "./FormLayout";
@@ -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 { getArrayResolvedProperties, getIconForProperty } from "../../util";
6
+ import { getArrayResolvedProperties, getIconForProperty, isReadOnly } from "../../util";
7
7
  import { useClearRestoreValue } from "../useClearRestoreValue";
8
8
 
9
9
  /**
@@ -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,17 +53,17 @@ 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
 
59
60
  const body = resolvedProperties.map((childProperty, index) => {
61
+ const thisDisabled = isReadOnly(childProperty) || Boolean(childProperty.disabled);
60
62
  const fieldProps = {
61
63
  propertyKey: `${propertyKey}[${index}]`,
62
- disabled,
64
+ disabled: disabled || thisDisabled,
63
65
  property: childProperty,
64
66
  includeDescription,
65
- underlyingValueHasChanged,
66
67
  context,
67
68
  partOfArray: true,
68
69
  minimalistView: false,
@@ -1,8 +1,8 @@
1
1
  import React, { useCallback, useMemo } from "react";
2
2
  import { Entity, EntityCollection, EntityReference, FieldProps, ResolvedProperty } from "../../types";
3
3
  import { ReferencePreview } from "../../preview";
4
- import { FieldHelperText, FormikArrayContainer, LabelWithIconAndTooltip } from "../components";
5
- import { ErrorView } from "../../components";
4
+ import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
5
+ import { ArrayContainer, ArrayEntryParams, ErrorView } from "../../components";
6
6
  import { getIconForProperty, getReferenceFrom } from "../../util";
7
7
 
8
8
  import { useNavigationController, useReferenceDialog } from "../../hooks";
@@ -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");
@@ -74,7 +76,12 @@ export function ArrayOfReferencesFieldBinding({
74
76
  referenceDialogController.open();
75
77
  };
76
78
 
77
- const buildEntry = useCallback((index: number, internalId: number) => {
79
+ const buildEntry = useCallback(({
80
+ index,
81
+ internalId,
82
+ storedProps,
83
+ storeProps
84
+ }: ArrayEntryParams) => {
78
85
  const entryValue = value && value.length > index ? value[index] : undefined;
79
86
  if (!entryValue)
80
87
  return <div>Internal ERROR</div>;
@@ -99,7 +106,7 @@ export function ArrayOfReferencesFieldBinding({
99
106
  icon={getIconForProperty(property, "small")}
100
107
  required={property.validation?.required}
101
108
  title={property.name}
102
- 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"}/>
103
110
  {Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
104
111
  </>);
105
112
 
@@ -109,13 +116,14 @@ export function ArrayOfReferencesFieldBinding({
109
116
 
110
117
  {collection && <div className={"group"}>
111
118
 
112
- <FormikArrayContainer value={value}
113
- addLabel={property.name ? "Add reference to " + property.name : "Add reference"}
114
- name={propertyKey}
115
- buildEntry={buildEntry}
116
- disabled={isSubmitting}
117
- setFieldValue={setFieldValue}
118
- newDefaultEntry={property.of.defaultValue}/>
119
+ <ArrayContainer droppableId={propertyKey}
120
+ value={value}
121
+ disabled={isSubmitting}
122
+ buildEntry={buildEntry}
123
+ addLabel={property.name ? "Add reference to " + property.name : "Add reference"}
124
+ newDefaultEntry={property.of.defaultValue}
125
+ onValueChange={(value) => setFieldValue(propertyKey, value)}
126
+ />
119
127
 
120
128
  <Button
121
129
  className="my-4 justify-center text-left"