@firecms/core 3.0.0-canary.6 → 3.0.0-canary.60

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 (242) hide show
  1. package/README.md +2 -2
  2. package/dist/components/ClearFilterSortButton.d.ts +5 -0
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +11 -11
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +5 -3
  6. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +3 -2
  7. package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
  8. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +2 -0
  9. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
  10. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  11. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
  12. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -3
  13. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  14. package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
  15. package/dist/components/EntityPreview.d.ts +26 -7
  16. package/dist/components/EntityView.d.ts +11 -0
  17. package/dist/components/FieldCaption.d.ts +5 -0
  18. package/dist/components/FireCMSAppBar.d.ts +4 -2
  19. package/dist/components/HomePage/NavigationCard.d.ts +8 -0
  20. package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +2 -2
  21. package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
  22. package/dist/components/HomePage/index.d.ts +3 -1
  23. package/dist/components/ReferenceWidget.d.ts +3 -1
  24. package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
  25. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  26. package/dist/components/VirtualTable/VirtualTableProps.d.ts +6 -7
  27. package/dist/components/VirtualTable/types.d.ts +3 -3
  28. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
  29. package/dist/components/common/index.d.ts +1 -0
  30. package/dist/components/common/table_height.d.ts +5 -0
  31. package/dist/components/common/types.d.ts +4 -6
  32. package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
  33. package/dist/components/index.d.ts +5 -2
  34. package/dist/contexts/AuthControllerContext.d.ts +1 -1
  35. package/dist/core/Drawer.d.ts +5 -12
  36. package/dist/core/DrawerNavigationItem.d.ts +9 -0
  37. package/dist/core/{EntityView.d.ts → EntityEditView.d.ts} +2 -2
  38. package/dist/core/NavigationRoutes.d.ts +1 -1
  39. package/dist/core/Scaffold.d.ts +8 -12
  40. package/dist/core/index.d.ts +3 -4
  41. package/dist/form/EntityForm.d.ts +1 -1
  42. package/dist/form/components/ErrorFocus.d.ts +1 -1
  43. package/dist/form/components/StorageItemPreview.d.ts +3 -2
  44. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  45. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  46. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  47. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +4 -3
  48. package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
  49. package/dist/form/validation.d.ts +1 -1
  50. package/dist/hooks/data/delete.d.ts +2 -2
  51. package/dist/hooks/data/save.d.ts +2 -3
  52. package/dist/hooks/data/useDataSource.d.ts +2 -2
  53. package/dist/hooks/data/useEntityFetch.d.ts +3 -3
  54. package/dist/hooks/index.d.ts +2 -0
  55. package/dist/hooks/useBuildNavigationController.d.ts +6 -4
  56. package/dist/hooks/useProjectLog.d.ts +6 -2
  57. package/dist/hooks/useStorageSource.d.ts +2 -2
  58. package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
  59. package/dist/index.es.js +10496 -9945
  60. package/dist/index.es.js.map +1 -1
  61. package/dist/index.umd.js +5 -5
  62. package/dist/index.umd.js.map +1 -1
  63. package/dist/internal/useBuildDataSource.d.ts +1 -16
  64. package/dist/preview/PropertyPreview.d.ts +1 -1
  65. package/dist/preview/PropertyPreviewProps.d.ts +1 -4
  66. package/dist/preview/components/BooleanPreview.d.ts +5 -1
  67. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  68. package/dist/preview/components/ReferencePreview.d.ts +3 -8
  69. package/dist/types/analytics.d.ts +1 -1
  70. package/dist/types/auth.d.ts +37 -1
  71. package/dist/types/collections.d.ts +30 -6
  72. package/dist/types/datasource.d.ts +21 -14
  73. package/dist/types/entities.d.ts +5 -1
  74. package/dist/types/entity_actions.d.ts +14 -0
  75. package/dist/types/entity_callbacks.d.ts +2 -2
  76. package/dist/types/entity_overrides.d.ts +6 -0
  77. package/dist/types/index.d.ts +2 -1
  78. package/dist/types/navigation.d.ts +15 -14
  79. package/dist/types/permissions.d.ts +5 -1
  80. package/dist/types/plugins.d.ts +20 -20
  81. package/dist/types/properties.d.ts +12 -4
  82. package/dist/types/property_config.d.ts +2 -2
  83. package/dist/types/roles.d.ts +31 -0
  84. package/dist/types/storage.d.ts +11 -3
  85. package/dist/types/user.d.ts +5 -0
  86. package/dist/util/collections.d.ts +9 -1
  87. package/dist/util/entities.d.ts +1 -1
  88. package/dist/util/icon_synonyms.d.ts +1 -97
  89. package/dist/util/icons.d.ts +8 -2
  90. package/dist/util/navigation_utils.d.ts +2 -2
  91. package/dist/util/objects.d.ts +1 -1
  92. package/dist/util/permissions.d.ts +4 -4
  93. package/dist/util/references.d.ts +4 -2
  94. package/dist/util/resolutions.d.ts +14 -14
  95. package/dist/util/useTraceUpdate.d.ts +1 -0
  96. package/package.json +139 -119
  97. package/src/components/ClearFilterSortButton.tsx +41 -0
  98. package/src/components/DeleteEntityDialog.tsx +4 -4
  99. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +4 -4
  100. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +276 -279
  101. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
  102. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +48 -45
  103. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  104. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +18 -17
  105. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -5
  106. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +29 -34
  107. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +16 -12
  108. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
  109. package/src/components/EntityCollectionView/EntityCollectionView.tsx +73 -72
  110. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
  111. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  112. package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
  113. package/src/components/EntityPreview.tsx +209 -70
  114. package/src/components/EntityView.tsx +84 -0
  115. package/src/components/FieldCaption.tsx +14 -0
  116. package/src/components/FireCMSAppBar.tsx +40 -15
  117. package/src/components/HomePage/DefaultHomePage.tsx +15 -11
  118. package/src/components/HomePage/NavigationCard.tsx +69 -0
  119. package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
  120. package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
  121. package/src/components/HomePage/index.tsx +3 -1
  122. package/src/components/PropertyIdCopyTooltipContent.tsx +2 -3
  123. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
  124. package/src/components/ReferenceWidget.tsx +22 -12
  125. package/src/components/SearchIconsView.tsx +5 -5
  126. package/src/components/SelectableTable/SelectableTable.tsx +5 -3
  127. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  128. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +23 -8
  129. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +38 -24
  130. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
  131. package/src/components/VirtualTable/VirtualTable.tsx +38 -29
  132. package/src/components/VirtualTable/VirtualTableHeader.tsx +4 -4
  133. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  134. package/src/components/VirtualTable/VirtualTableProps.tsx +7 -7
  135. package/src/components/VirtualTable/VirtualTableRow.tsx +4 -5
  136. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  137. package/src/components/VirtualTable/types.tsx +2 -3
  138. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +11 -7
  139. package/src/components/common/index.ts +1 -0
  140. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  141. package/src/components/common/types.tsx +4 -6
  142. package/src/components/common/useColumnsIds.tsx +10 -2
  143. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
  144. package/src/components/common/useTableSearchHelper.ts +39 -9
  145. package/src/components/index.tsx +5 -2
  146. package/src/contexts/AuthControllerContext.tsx +1 -1
  147. package/src/core/Drawer.tsx +78 -103
  148. package/src/core/DrawerNavigationItem.tsx +62 -0
  149. package/src/core/{EntityView.tsx → EntityEditView.tsx} +27 -45
  150. package/src/core/EntitySidePanel.tsx +3 -3
  151. package/src/core/FireCMS.tsx +54 -43
  152. package/src/core/NavigationRoutes.tsx +11 -4
  153. package/src/core/Scaffold.tsx +80 -66
  154. package/src/core/field_configs.tsx +2 -3
  155. package/src/core/index.tsx +3 -4
  156. package/src/form/EntityForm.tsx +49 -33
  157. package/src/form/PropertyFieldBinding.tsx +0 -2
  158. package/src/form/components/StorageItemPreview.tsx +7 -5
  159. package/src/form/components/StorageUploadProgress.tsx +9 -8
  160. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +10 -12
  161. package/src/form/field_bindings/BlockFieldBinding.tsx +2 -2
  162. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  163. package/src/form/field_bindings/KeyValueFieldBinding.tsx +19 -19
  164. package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
  165. package/src/form/field_bindings/MarkdownFieldBinding.tsx +2 -2
  166. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +3 -3
  167. package/src/form/field_bindings/ReferenceFieldBinding.tsx +16 -13
  168. package/src/form/field_bindings/SelectFieldBinding.tsx +3 -3
  169. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +18 -9
  170. package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
  171. package/src/form/validation.ts +3 -4
  172. package/src/hooks/data/delete.ts +3 -3
  173. package/src/hooks/data/save.ts +4 -2
  174. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  175. package/src/hooks/data/useDataSource.tsx +8 -3
  176. package/src/hooks/data/useEntityFetch.tsx +4 -4
  177. package/src/hooks/index.tsx +3 -0
  178. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  179. package/src/hooks/useBuildModeController.tsx +11 -5
  180. package/src/hooks/useBuildNavigationController.tsx +200 -83
  181. package/src/hooks/useProjectLog.tsx +17 -7
  182. package/src/hooks/useReferenceDialog.tsx +2 -2
  183. package/src/hooks/useResolvedNavigationFrom.tsx +1 -1
  184. package/src/hooks/useStorageSource.tsx +7 -2
  185. package/src/hooks/useValidateAuthenticator.tsx +115 -0
  186. package/src/internal/useBuildDataSource.ts +54 -47
  187. package/src/internal/useBuildSideEntityController.tsx +88 -21
  188. package/src/preview/PropertyPreview.tsx +5 -15
  189. package/src/preview/PropertyPreviewProps.tsx +1 -11
  190. package/src/preview/components/BooleanPreview.tsx +19 -4
  191. package/src/preview/components/EnumValuesChip.tsx +2 -2
  192. package/src/preview/components/ReferencePreview.tsx +72 -165
  193. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
  194. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +2 -1
  195. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -1
  196. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
  197. package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -3
  198. package/src/preview/property_previews/ArrayPropertyPreview.tsx +2 -3
  199. package/src/preview/property_previews/MapPropertyPreview.tsx +5 -5
  200. package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
  201. package/src/types/analytics.ts +1 -0
  202. package/src/types/auth.tsx +50 -1
  203. package/src/types/collections.ts +37 -6
  204. package/src/types/datasource.ts +24 -17
  205. package/src/types/entities.ts +9 -1
  206. package/src/types/entity_actions.tsx +17 -0
  207. package/src/types/entity_callbacks.ts +2 -2
  208. package/src/types/entity_overrides.tsx +7 -0
  209. package/src/types/firecms.tsx +0 -1
  210. package/src/types/index.ts +2 -1
  211. package/src/types/navigation.ts +17 -17
  212. package/src/types/permissions.ts +6 -1
  213. package/src/types/plugins.tsx +26 -28
  214. package/src/types/properties.ts +18 -6
  215. package/src/types/property_config.tsx +2 -2
  216. package/src/types/roles.ts +41 -0
  217. package/src/types/side_entity_controller.tsx +1 -0
  218. package/src/types/storage.ts +12 -3
  219. package/src/types/user.ts +7 -0
  220. package/src/util/collections.ts +22 -0
  221. package/src/util/entities.ts +1 -1
  222. package/src/util/enums.ts +1 -1
  223. package/src/util/icon_list.ts +2 -2
  224. package/src/util/icon_synonyms.ts +3 -99
  225. package/src/util/icons.tsx +11 -3
  226. package/src/util/navigation_utils.ts +6 -6
  227. package/src/util/objects.ts +8 -21
  228. package/src/util/permissions.ts +11 -8
  229. package/src/util/references.ts +36 -5
  230. package/src/util/resolutions.ts +32 -31
  231. package/src/util/strings.ts +2 -2
  232. package/src/util/useTraceUpdate.tsx +2 -1
  233. package/dist/components/VirtualTable/common.d.ts +0 -2
  234. package/dist/core/SideEntityView.d.ts +0 -7
  235. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  236. package/dist/internal/useLocaleConfig.d.ts +0 -1
  237. package/dist/types/appcheck.d.ts +0 -26
  238. package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
  239. package/src/core/SideEntityView.tsx +0 -38
  240. package/src/internal/useBuildCustomizationController.tsx +0 -5
  241. package/src/internal/useLocaleConfig.tsx +0 -18
  242. package/src/types/appcheck.ts +0 -29
@@ -19,8 +19,9 @@ import equal from "react-fast-compare"
19
19
  import {
20
20
  canCreateEntity,
21
21
  canDeleteEntity,
22
- fullPathToCollectionSegments,
23
22
  getDefaultValuesFor,
23
+ getEntityTitlePropertyKey,
24
+ getValueInPath,
24
25
  isHidden,
25
26
  isReadOnly,
26
27
  resolveCollection
@@ -34,12 +35,9 @@ import {
34
35
  } from "../hooks";
35
36
  import { ErrorFocus } from "./components/ErrorFocus";
36
37
  import { CustomIdField } from "./components/CustomIdField";
37
- import { Alert, Button, cn, DialogActions, IconButton, Tooltip, Typography } from "@firecms/ui";
38
- import { ErrorBoundary } from "../components";
39
- import {
40
- copyEntityAction,
41
- deleteEntityAction
42
- } from "../components/EntityCollectionTable/internal/default_entity_actions";
38
+ import { Alert, Button, CircularProgress, cls, DialogActions, IconButton, Tooltip, Typography } from "@firecms/ui";
39
+ import { CircularProgressCenter, ErrorBoundary } from "../components";
40
+ import { copyEntityAction, deleteEntityAction } from "../components/common/default_entity_actions";
43
41
  import { useAnalyticsController } from "../hooks/useAnalyticsController";
44
42
  import { ValidationError } from "yup";
45
43
  import { PropertyIdCopyTooltipContent } from "../components/PropertyIdCopyTooltipContent";
@@ -134,12 +132,13 @@ export type EntityFormSaveParams<M extends Record<string, any>> = {
134
132
  * @constructor
135
133
  * @group Components
136
134
  */
137
- export const EntityForm = React.memo<EntityFormProps<any>>(EntityFormInternal,
138
- (a: EntityFormProps<any>, b: EntityFormProps<any>) => {
139
- return a.status === b.status &&
140
- a.path === b.path &&
141
- equal(a.entity?.values, b.entity?.values);
142
- }) as typeof EntityFormInternal;
135
+ export const EntityForm = EntityFormInternal;
136
+ // export const EntityForm = React.memo<EntityFormProps<any>>(EntityFormInternal,
137
+ // (a: EntityFormProps<any>, b: EntityFormProps<any>) => {
138
+ // return a.status === b.status &&
139
+ // a.path === b.path &&
140
+ // equal(a.entity?.values, b.entity?.values);
141
+ // }) as typeof EntityFormInternal;
143
142
 
144
143
  function getDataSourceEntityValues<M extends object>(initialResolvedCollection: ResolvedEntityCollection,
145
144
  status: "new" | "existing" | "copy",
@@ -171,7 +170,7 @@ function EntityFormInternal<M extends Record<string, any>>({
171
170
  onFormContextChange,
172
171
  hideId,
173
172
  autoSave,
174
- onIdUpdateError
173
+ onIdUpdateError,
175
174
  }: EntityFormProps<M>) {
176
175
 
177
176
  const analyticsController = useAnalyticsController();
@@ -179,7 +178,7 @@ function EntityFormInternal<M extends Record<string, any>>({
179
178
  const customizationController = useCustomizationController();
180
179
 
181
180
  const context = useFireCMSContext();
182
- const dataSource = useDataSource();
181
+ const dataSource = useDataSource(inputCollection);
183
182
  const plugins = customizationController.plugins;
184
183
 
185
184
  const initialResolvedCollection = useMemo(() => resolveCollection({
@@ -187,7 +186,7 @@ function EntityFormInternal<M extends Record<string, any>>({
187
186
  path,
188
187
  values: entity?.values,
189
188
  fields: customizationController.propertyConfigs
190
- }), [entity?.values, path]);
189
+ }), [entity?.values, path, customizationController.propertyConfigs]);
191
190
 
192
191
  const mustSetCustomId: boolean = (status === "new" || status === "copy") &&
193
192
  (Boolean(initialResolvedCollection.customId) && initialResolvedCollection.customId !== "optional");
@@ -344,6 +343,9 @@ function EntityFormInternal<M extends Record<string, any>>({
344
343
  fields: customizationController.propertyConfigs
345
344
  });
346
345
 
346
+ const titlePropertyKey = getEntityTitlePropertyKey(resolvedCollection, customizationController.propertyConfigs);
347
+ const title = internalValues && titlePropertyKey ? getValueInPath(internalValues, titlePropertyKey) : undefined;
348
+
347
349
  const onIdUpdate = inputCollection.callbacks?.onIdUpdate;
348
350
 
349
351
  const doOnIdUpdate = useCallback(async () => {
@@ -389,12 +391,15 @@ function EntityFormInternal<M extends Record<string, any>>({
389
391
 
390
392
  const authController = useAuthController();
391
393
 
392
- const getActionsForEntity = useCallback(({ entity, customEntityActions }: {
394
+ const getActionsForEntity = useCallback(({
395
+ entity,
396
+ customEntityActions
397
+ }: {
393
398
  entity?: Entity<M>,
394
399
  customEntityActions?: EntityAction[]
395
400
  }): EntityAction[] => {
396
- const createEnabled = canCreateEntity(inputCollection, authController, fullPathToCollectionSegments(path), null);
397
- const deleteEnabled = entity ? canDeleteEntity(inputCollection, authController, fullPathToCollectionSegments(path), entity) : true;
401
+ const createEnabled = canCreateEntity(inputCollection, authController, path, null);
402
+ const deleteEnabled = entity ? canDeleteEntity(inputCollection, authController, path, entity) : true;
398
403
  const actions: EntityAction[] = [];
399
404
  if (createEnabled)
400
405
  actions.push(copyEntityAction);
@@ -408,7 +413,8 @@ function EntityFormInternal<M extends Record<string, any>>({
408
413
  const pluginActions: React.ReactNode[] = [];
409
414
 
410
415
  const formContext: FormContext<M> = {
411
- setFieldValue: formex.setFieldValue,
416
+ // @ts-ignore
417
+ setFieldValue: useCallback(formex.setFieldValue, []),
412
418
  values: formex.values,
413
419
  collection: resolvedCollection,
414
420
  entityId,
@@ -416,12 +422,14 @@ function EntityFormInternal<M extends Record<string, any>>({
416
422
  save
417
423
  };
418
424
 
425
+ const submittedFormContext = useRef<FormContext<M> | null>(null);
419
426
  // eslint-disable-next-line react-hooks/rules-of-hooks
420
427
  useEffect(() => {
421
- if (onFormContextChange) {
428
+ if (onFormContextChange && !formContextsEqual(submittedFormContext.current ?? undefined, formContext)) {
422
429
  onFormContextChange(formContext);
430
+ submittedFormContext.current = formContext;
423
431
  }
424
- }, [onFormContextChange, formContext]);
432
+ }, [formContext, onFormContextChange]);
425
433
 
426
434
  if (plugins && inputCollection) {
427
435
  const actionProps: PluginFormActionProps = {
@@ -436,7 +444,7 @@ function EntityFormInternal<M extends Record<string, any>>({
436
444
  pluginActions.push(...plugins.map((plugin, i) => (
437
445
  plugin.form?.Actions
438
446
  ? <plugin.form.Actions
439
- key={`actions_${plugin.name}`} {...actionProps}/>
447
+ key={`actions_${plugin.key}`} {...actionProps}/>
440
448
  : null
441
449
  )).filter(Boolean));
442
450
  }
@@ -445,7 +453,7 @@ function EntityFormInternal<M extends Record<string, any>>({
445
453
  <div className="h-full overflow-auto">
446
454
 
447
455
  {pluginActions.length > 0 && <div
448
- className={cn("w-full flex justify-end items-center sticky top-0 right-0 left-0 z-10 bg-opacity-60 bg-slate-200 dark:bg-opacity-60 dark:bg-slate-800 backdrop-blur-md")}>
456
+ className={cls("w-full flex justify-end items-center sticky top-0 right-0 left-0 z-10 bg-opacity-60 bg-slate-200 dark:bg-opacity-60 dark:bg-slate-800 backdrop-blur-md")}>
449
457
  {pluginActions}
450
458
  </div>}
451
459
 
@@ -454,8 +462,8 @@ function EntityFormInternal<M extends Record<string, any>>({
454
462
  className={`w-full py-2 flex flex-col items-start mt-${4 + (pluginActions ? 8 : 0)} lg:mt-${8 + (pluginActions ? 8 : 0)} mb-8`}>
455
463
 
456
464
  <Typography
457
- className={"mt-4 flex-grow " + inputCollection.hideIdFromForm ? "mb-2" : "mb-0"}
458
- variant={"h4"}>{inputCollection.singularName ?? inputCollection.name}
465
+ className={"mt-4 flex-grow line-clamp-1 " + inputCollection.hideIdFromForm ? "mb-2" : "mb-0"}
466
+ variant={"h4"}>{title ?? inputCollection.singularName ?? inputCollection.name}
459
467
  </Typography>
460
468
  <Alert color={"base"} className={"w-full"} size={"small"}>
461
469
  <code className={"text-xs select-all"}>{path}/{entityId}</code>
@@ -508,7 +516,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
508
516
  savingError?: Error,
509
517
  closeAfterSaveRef: MutableRefObject<boolean>,
510
518
  autoSave?: boolean,
511
- entityActions: EntityAction[]
519
+ entityActions: EntityAction[],
512
520
  }) {
513
521
 
514
522
  const {
@@ -530,7 +538,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
530
538
  dirty,
531
539
  closeAfterSaveRef,
532
540
  autoSave,
533
- entityActions
541
+ entityActions,
534
542
  } = props;
535
543
 
536
544
  const context = useFireCMSContext();
@@ -598,6 +606,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
598
606
  <Tooltip title={<PropertyIdCopyTooltipContent propertyId={key}/>}
599
607
  delayDuration={800}
600
608
  side={"left"}
609
+ align={"start"}
601
610
  sideOffset={16}>
602
611
  <PropertyFieldBinding {...cmsFormFieldProps}/>
603
612
  </Tooltip>
@@ -655,17 +664,17 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
655
664
  fullPath: resolvedCollection.path,
656
665
  collection: resolvedCollection,
657
666
  context,
658
- sideEntityController
667
+ sideEntityController,
659
668
  });
660
669
  }}>
661
670
  {action.icon}
662
671
  </IconButton>
663
672
  ))}
664
673
  </div>}
665
-
674
+ {isSubmitting && <CircularProgress size={"small"}/>}
666
675
  <Button
667
676
  variant="text"
668
- disabled={disabled}
677
+ disabled={disabled || isSubmitting}
669
678
  type="reset"
670
679
  >
671
680
  {status === "existing" ? "Discard" : "Clear"}
@@ -675,7 +684,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
675
684
  variant="text"
676
685
  color="primary"
677
686
  type="submit"
678
- disabled={disabled}
687
+ disabled={disabled || isSubmitting}
679
688
  onClick={() => {
680
689
  closeAfterSaveRef.current = false;
681
690
  }}
@@ -689,7 +698,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
689
698
  variant="filled"
690
699
  color="primary"
691
700
  type="submit"
692
- disabled={disabled}
701
+ disabled={disabled || isSubmitting}
693
702
  onClick={() => {
694
703
  closeAfterSaveRef.current = true;
695
704
  }}
@@ -718,3 +727,10 @@ export function yupToFormErrors(yupError: ValidationError): Record<string, any>
718
727
  }
719
728
  return errors;
720
729
  }
730
+
731
+ function formContextsEqual(a: FormContext<any> | undefined, b: FormContext<any> | undefined): boolean {
732
+ return a?.path === b?.path &&
733
+ a?.entityId === b?.entityId &&
734
+ equal(a?.values, b?.values) &&
735
+ equal(a?.collection, b?.collection);
736
+ }
@@ -92,7 +92,6 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
92
92
  let Component: ComponentType<FieldProps<T>> | undefined;
93
93
  const resolvedProperty: ResolvedProperty<T> | null = resolveProperty({
94
94
  propertyKey,
95
- propertyValue: fieldProps.field.value,
96
95
  propertyOrBuilder: property,
97
96
  values: fieldProps.form.values,
98
97
  path: context.path,
@@ -116,7 +115,6 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
116
115
  }
117
116
  const configProperty = resolveProperty({
118
117
  propertyOrBuilder: propertyConfig.property,
119
- propertyValue: fieldProps.field.value,
120
118
  values: fieldProps.form.values,
121
119
  path: context.path,
122
120
  entityId: context.entityId,
@@ -1,9 +1,9 @@
1
1
  import React from "react";
2
2
 
3
- import { Entity, ResolvedStringProperty } from "../../types";
3
+ import { Entity, EntityCollection, ResolvedStringProperty } from "../../types";
4
4
  import { PreviewSize, PropertyPreview } from "../../preview";
5
5
 
6
- import { cn, IconButton, paperMixin, RemoveIcon, Tooltip } from "@firecms/ui";
6
+ import { cls, IconButton, paperMixin, RemoveIcon, Tooltip } from "@firecms/ui";
7
7
  import { ErrorBoundary } from "../../components";
8
8
 
9
9
  interface StorageItemPreviewProps {
@@ -14,6 +14,7 @@ interface StorageItemPreviewProps {
14
14
  onRemove: (value: string) => void;
15
15
  size: PreviewSize;
16
16
  disabled: boolean;
17
+ collection: EntityCollection;
17
18
  }
18
19
 
19
20
  export function StorageItemPreview({
@@ -23,11 +24,12 @@ export function StorageItemPreview({
23
24
  entity,
24
25
  onRemove,
25
26
  disabled,
26
- size
27
+ size,
28
+ collection
27
29
  }: StorageItemPreviewProps) {
28
30
 
29
31
  return (
30
- <div className={cn(paperMixin,
32
+ <div className={cls(paperMixin,
31
33
  "relative m-4 border-box flex items-center justify-center",
32
34
  size === "medium" ? "min-w-[220px] min-h-[220px] max-w-[220px]" : "min-w-[118px] min-h-[118px] max-w-[118px]")}>
33
35
 
@@ -54,7 +56,7 @@ export function StorageItemPreview({
54
56
  <PropertyPreview propertyKey={name}
55
57
  value={value}
56
58
  property={property}
57
- // entity={entity}
59
+ // entity={entity}
58
60
  size={size}/>
59
61
  </ErrorBoundary>
60
62
  }
@@ -3,7 +3,8 @@ import React, { useCallback } from "react";
3
3
  import { useSnackbarController, useStorageSource } from "../../hooks";
4
4
  import { StorageFieldItem } from "../../util/useStorageUploadController";
5
5
  import { ErrorView } from "../../components";
6
- import { cn, paperMixin, Skeleton } from "@firecms/ui";
6
+ import { cls, paperMixin, Skeleton } from "@firecms/ui";
7
+ import { EntityCollection, StorageSource } from "../../types";
7
8
 
8
9
  export interface StorageUploadItemProps {
9
10
  storagePath: string;
@@ -22,10 +23,10 @@ export function StorageUploadProgress({
22
23
  metadata,
23
24
  onFileUploadComplete,
24
25
  imageSize,
25
- simple
26
+ simple,
26
27
  }: StorageUploadItemProps) {
27
28
 
28
- const storage = useStorageSource();
29
+ const storageSource = useStorageSource();
29
30
 
30
31
  const snackbarController = useSnackbarController();
31
32
 
@@ -41,14 +42,14 @@ export function StorageUploadProgress({
41
42
  setError(undefined);
42
43
  setLoading(true);
43
44
 
44
- storage.uploadFile({
45
+ storageSource.uploadFile({
45
46
  file,
46
47
  fileName,
47
48
  path: storagePath,
48
49
  metadata
49
50
  })
50
51
  .then(async ({ path }) => {
51
- console.debug("Upload successful");
52
+ console.debug("Upload successful", path);
52
53
  await onFileUploadComplete(path, entry, metadata);
53
54
  if (mounted.current)
54
55
  setLoading(false);
@@ -67,7 +68,7 @@ export function StorageUploadProgress({
67
68
  .finally(() => {
68
69
  uploading.current = false;
69
70
  });
70
- }, [entry, metadata, onFileUploadComplete, storage, storagePath]);
71
+ }, [entry, metadata, onFileUploadComplete, storageSource, storagePath]);
71
72
 
72
73
  React.useEffect(() => {
73
74
  mounted.current = true;
@@ -87,9 +88,9 @@ export function StorageUploadProgress({
87
88
  }
88
89
  return (
89
90
 
90
- <div className={cn(paperMixin,
91
+ <div className={cls(paperMixin,
91
92
  "relative m-4 border-box flex items-center justify-center",
92
- `min-w-[${imageSize}px] min-h-[${imageSize}px]`)}>
93
+ `min-w-[${imageSize}px] min-h-[${imageSize}px]`)}>
93
94
 
94
95
  {loading &&
95
96
  <Skeleton className="w-full h-full"/>}
@@ -6,7 +6,7 @@ import { ErrorView } from "../../components";
6
6
  import { getIconForProperty, getReferenceFrom } from "../../util";
7
7
 
8
8
  import { useNavigationController, useReferenceDialog } from "../../hooks";
9
- import { Button, ExpandablePanel } from "@firecms/ui";
9
+ import { Button, cls, ExpandablePanel, fieldBackgroundMixin } from "@firecms/ui";
10
10
  import { useClearRestoreValue } from "../useClearRestoreValue";
11
11
 
12
12
  type ArrayOfReferencesFieldProps = FieldProps<EntityReference[]>;
@@ -38,7 +38,6 @@ export function ArrayOfReferencesFieldBinding({
38
38
  }
39
39
 
40
40
  const expanded = property.expanded === undefined ? true : property.expanded;
41
- const [onHover, setOnHover] = React.useState(false);
42
41
  const selectedEntityIds = value && Array.isArray(value) ? value.map((ref) => ref.id) : [];
43
42
 
44
43
  useClearRestoreValue({
@@ -81,21 +80,19 @@ export function ArrayOfReferencesFieldBinding({
81
80
  if (!entryValue)
82
81
  return <div>Internal ERROR</div>;
83
82
  return (
84
- <div
85
- onMouseEnter={() => setOnHover(true)}
86
- onMouseMove={() => setOnHover(true)}
87
- onMouseLeave={() => setOnHover(false)}>
88
83
  <ReferencePreview
84
+ key={internalId}
89
85
  disabled={!ofProperty.path}
90
86
  previewProperties={ofProperty.previewProperties}
91
87
  size={"medium"}
92
88
  onClick={onEntryClick}
89
+ hover={!disabled}
93
90
  reference={entryValue}
94
- onHover={onHover}
91
+ includeId={ofProperty.includeId}
92
+ includeEntityLink={ofProperty.includeEntityLink}
95
93
  />
96
- </div>
97
94
  );
98
- }, [ofProperty.path, ofProperty.previewProperties, onHover, value]);
95
+ }, [ofProperty.path, ofProperty.previewProperties, value]);
99
96
 
100
97
  const title = (
101
98
  <LabelWithIcon icon={getIconForProperty(property, "small")}
@@ -108,7 +105,7 @@ export function ArrayOfReferencesFieldBinding({
108
105
  {!collection && <ErrorView
109
106
  error={"The specified collection does not exist. Check console"}/>}
110
107
 
111
- {collection && <>
108
+ {collection && <div className={"group"}>
112
109
 
113
110
  <FormikArrayContainer value={value}
114
111
  addLabel={property.name ? "Add reference to " + property.name : "Add reference"}
@@ -126,7 +123,7 @@ export function ArrayOfReferencesFieldBinding({
126
123
  onClick={onEntryClick}>
127
124
  Edit {property.name}
128
125
  </Button>
129
- </>}
126
+ </div>}
130
127
  </>;
131
128
 
132
129
  return (
@@ -134,7 +131,8 @@ export function ArrayOfReferencesFieldBinding({
134
131
 
135
132
  {!tableMode &&
136
133
  <ExpandablePanel
137
- className={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2"}
134
+ titleClassName={fieldBackgroundMixin}
135
+ className={cls("px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2", fieldBackgroundMixin)}
138
136
  initiallyExpanded={expanded}
139
137
  title={title}>
140
138
  {body}
@@ -8,7 +8,7 @@ import { EnumValuesChip } from "../../preview";
8
8
  import { FieldProps, FormContext, PropertyFieldBindingProps, PropertyOrBuilder } from "../../types";
9
9
  import { getDefaultValueFor, getIconForProperty, } from "../../util";
10
10
  import { DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE } from "../../util/common";
11
- import { cn, ExpandablePanel, paperMixin, Select, SelectItem, Typography } from "@firecms/ui";
11
+ import { cls, ExpandablePanel, paperMixin, Select, SelectItem, Typography } from "@firecms/ui";
12
12
  import { useClearRestoreValue } from "../useClearRestoreValue";
13
13
 
14
14
  /**
@@ -193,7 +193,7 @@ function BlockEntry({
193
193
  };
194
194
 
195
195
  return (
196
- <div className={cn(paperMixin, "bg-transparent p-4 my-4 py-8")}>
196
+ <div className={cls(paperMixin, "bg-transparent p-4 my-4 py-8")}>
197
197
 
198
198
  <Field
199
199
  name={typeFieldName}
@@ -43,7 +43,7 @@ export function DateTimeFieldBinding({
43
43
  <>
44
44
  <DateTimeField
45
45
  value={internalValue}
46
- onChange={(dateValue) => setValue(dateValue)}
46
+ onChange={(dateValue) => setValue(dateValue ?? null)}
47
47
  size={"medium"}
48
48
  mode={property.mode}
49
49
  clearable={property.clearable}
@@ -8,7 +8,7 @@ import {
8
8
  ArrowDropDownIcon,
9
9
  BooleanSwitchWithLabel,
10
10
  Button,
11
- cn,
11
+ cls,
12
12
  DateTimeField,
13
13
  defaultBorderMixin,
14
14
  ExpandablePanel,
@@ -32,20 +32,20 @@ type MapEditViewRowState = [number, {
32
32
  *
33
33
  * @group Form fields
34
34
  */
35
- export function KeyValueFieldBinding<T extends Record<string, any>>({
36
- propertyKey,
37
- value,
38
- showError,
39
- error,
40
- disabled,
41
- property,
42
- setValue,
43
- tableMode,
44
- includeDescription,
45
- underlyingValueHasChanged,
46
- autoFocus,
47
- context
48
- }: FieldProps<T>) {
35
+ export function KeyValueFieldBinding({
36
+ propertyKey,
37
+ value,
38
+ showError,
39
+ error,
40
+ disabled,
41
+ property,
42
+ setValue,
43
+ tableMode,
44
+ includeDescription,
45
+ underlyingValueHasChanged,
46
+ autoFocus,
47
+ context
48
+ }: FieldProps<Record<string, any>>) {
49
49
 
50
50
  const expanded = (property.expanded === undefined ? true : property.expanded) || autoFocus;
51
51
 
@@ -316,7 +316,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
316
316
  }}/>;
317
317
  } else if (dataType === "array") {
318
318
  return <div
319
- className={cn(defaultBorderMixin, "ml-2 pl-2 border-l border-solid")}>
319
+ className={cls(defaultBorderMixin, "ml-2 pl-2 border-l border-solid")}>
320
320
  <ArrayContainer value={entryValue}
321
321
  newDefaultEntry={""}
322
322
  droppableId={rowId.toString()}
@@ -349,7 +349,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
349
349
  </div>;
350
350
  } else if (dataType === "map") {
351
351
  return <div
352
- className={cn(defaultBorderMixin, "ml-2 pl-2 border-l border-solid")}>
352
+ className={cls(defaultBorderMixin, "ml-2 pl-2 border-l border-solid")}>
353
353
  <MapEditView value={entryValue}
354
354
  fieldName={fieldKey}
355
355
  setValue={(updatedValue) => {
@@ -482,7 +482,7 @@ function ArrayKeyValueRow<T>({
482
482
  Arrays of arrays are not supported.
483
483
  </Typography>;
484
484
  } else if (dataType === "map") {
485
- return <div className={cn(defaultBorderMixin, "ml-2 pl-2 border-l border-solid")}>
485
+ return <div className={cls(defaultBorderMixin, "ml-2 pl-2 border-l border-solid")}>
486
486
  <MapEditView value={entryValue}
487
487
  setValue={(updatedValue) => {
488
488
  setValue(updatedValue);
@@ -546,7 +546,7 @@ function getDataType(value: any): DataType | undefined {
546
546
  return "array";
547
547
  } else if (value instanceof Date) {
548
548
  return "date";
549
- } else if (value.isEntityReference && value.isEntityReference()) {
549
+ } else if (value?.isEntityReference && value?.isEntityReference()) {
550
550
  return "reference";
551
551
  } else if (value instanceof GeoPoint) {
552
552
  return "geopoint";
@@ -14,21 +14,21 @@ import { ExpandablePanel, InputLabel, Select, SelectItem } from "@firecms/ui";
14
14
  * and tables to the specified properties.
15
15
  * @group Form fields
16
16
  */
17
- export function MapFieldBinding<T extends Record<string, any>>({
18
- propertyKey,
19
- value,
20
- showError,
21
- error,
22
- disabled,
23
- property,
24
- setValue,
25
- partOfBlock,
26
- tableMode,
27
- includeDescription,
28
- underlyingValueHasChanged,
29
- autoFocus,
30
- context
31
- }: FieldProps<T>) {
17
+ export function MapFieldBinding({
18
+ propertyKey,
19
+ value,
20
+ showError,
21
+ error,
22
+ disabled,
23
+ property,
24
+ setValue,
25
+ partOfBlock,
26
+ tableMode,
27
+ includeDescription,
28
+ underlyingValueHasChanged,
29
+ autoFocus,
30
+ context
31
+ }: FieldProps<Record<string, any>>) {
32
32
 
33
33
  const pickOnlySomeKeys = property.pickOnlySomeKeys || false;
34
34
  const expanded = (property.expanded === undefined ? true : property.expanded) || autoFocus;
@@ -8,7 +8,7 @@ import { FieldHelperText, LabelWithIcon } from "../components";
8
8
  import { FieldProps } from "../../types";
9
9
  import { getIconForProperty } from "../../util";
10
10
  import {
11
- cn,
11
+ cls,
12
12
  fieldBackgroundDisabledMixin,
13
13
  fieldBackgroundHoverMixin,
14
14
  fieldBackgroundMixin,
@@ -81,7 +81,7 @@ export function MarkdownFieldBinding({
81
81
  </Typography>}
82
82
 
83
83
  <MdEditor value={internalValue ?? ""}
84
- className={cn(fieldBackgroundMixin,
84
+ className={cls(fieldBackgroundMixin,
85
85
  disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
86
86
  "text-base")}
87
87
  readOnly={disabled}
@@ -6,7 +6,7 @@ import { PropertyPreview } from "../../preview";
6
6
  import { FieldHelperText, LabelWithIcon } from "../components";
7
7
  import { ErrorBoundary } from "../../components";
8
8
  import { getIconForProperty } from "../../util";
9
- import { cn, paperMixin } from "@firecms/ui";
9
+ import { cls, paperMixin } from "@firecms/ui";
10
10
 
11
11
  /**
12
12
  *
@@ -47,13 +47,13 @@ export function ReadOnlyFieldBinding({
47
47
  }
48
48
 
49
49
  <div
50
- className={cn(paperMixin, "min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
50
+ className={cls(paperMixin, "min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
51
51
 
52
52
  <ErrorBoundary>
53
53
  <PropertyPreview propertyKey={propertyKey}
54
54
  value={value}
55
55
  property={property}
56
- // entity={entity}
56
+ // entity={entity}
57
57
  size={"medium"}/>
58
58
  </ErrorBoundary>
59
59