@firecms/core 3.0.0-canary.5 → 3.0.0-canary.51

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 (218) 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/internal/CollectionTableToolbar.d.ts +1 -4
  9. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
  10. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -3
  11. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  12. package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
  13. package/dist/components/EntityPreview.d.ts +25 -7
  14. package/dist/components/EntityView.d.ts +11 -0
  15. package/dist/components/FieldCaption.d.ts +5 -0
  16. package/dist/components/FireCMSAppBar.d.ts +3 -2
  17. package/dist/components/HomePage/NavigationCard.d.ts +8 -0
  18. package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +2 -2
  19. package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
  20. package/dist/components/HomePage/index.d.ts +3 -1
  21. package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
  22. package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
  23. package/dist/components/common/types.d.ts +4 -6
  24. package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
  25. package/dist/components/index.d.ts +4 -2
  26. package/dist/contexts/AuthControllerContext.d.ts +1 -1
  27. package/dist/core/Drawer.d.ts +5 -12
  28. package/dist/core/DrawerNavigationItem.d.ts +9 -0
  29. package/dist/core/{EntityView.d.ts → EntityEditView.d.ts} +2 -2
  30. package/dist/core/NavigationRoutes.d.ts +1 -1
  31. package/dist/core/Scaffold.d.ts +7 -10
  32. package/dist/core/index.d.ts +3 -4
  33. package/dist/form/EntityForm.d.ts +1 -1
  34. package/dist/form/components/ErrorFocus.d.ts +1 -1
  35. package/dist/form/components/StorageItemPreview.d.ts +3 -2
  36. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  37. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  38. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  39. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +4 -3
  40. package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
  41. package/dist/form/validation.d.ts +1 -1
  42. package/dist/hooks/data/delete.d.ts +2 -2
  43. package/dist/hooks/data/save.d.ts +2 -3
  44. package/dist/hooks/data/useDataSource.d.ts +2 -2
  45. package/dist/hooks/data/useEntityFetch.d.ts +3 -3
  46. package/dist/hooks/index.d.ts +2 -0
  47. package/dist/hooks/useBuildNavigationController.d.ts +6 -4
  48. package/dist/hooks/useProjectLog.d.ts +6 -2
  49. package/dist/hooks/useStorageSource.d.ts +2 -2
  50. package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
  51. package/dist/index.es.js +9644 -9122
  52. package/dist/index.es.js.map +1 -1
  53. package/dist/index.umd.js +5 -5
  54. package/dist/index.umd.js.map +1 -1
  55. package/dist/internal/useBuildDataSource.d.ts +1 -12
  56. package/dist/preview/PropertyPreview.d.ts +1 -1
  57. package/dist/preview/PropertyPreviewProps.d.ts +1 -4
  58. package/dist/preview/components/BooleanPreview.d.ts +5 -1
  59. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  60. package/dist/preview/components/ReferencePreview.d.ts +1 -7
  61. package/dist/types/analytics.d.ts +1 -1
  62. package/dist/types/auth.d.ts +37 -1
  63. package/dist/types/collections.d.ts +29 -5
  64. package/dist/types/datasource.d.ts +3 -6
  65. package/dist/types/entities.d.ts +5 -1
  66. package/dist/types/entity_actions.d.ts +14 -0
  67. package/dist/types/entity_callbacks.d.ts +2 -2
  68. package/dist/types/entity_overrides.d.ts +6 -0
  69. package/dist/types/index.d.ts +2 -1
  70. package/dist/types/navigation.d.ts +14 -13
  71. package/dist/types/permissions.d.ts +5 -1
  72. package/dist/types/plugins.d.ts +20 -20
  73. package/dist/types/properties.d.ts +4 -4
  74. package/dist/types/property_config.d.ts +2 -2
  75. package/dist/types/roles.d.ts +31 -0
  76. package/dist/types/storage.d.ts +11 -3
  77. package/dist/types/user.d.ts +5 -0
  78. package/dist/util/collections.d.ts +9 -1
  79. package/dist/util/entities.d.ts +1 -1
  80. package/dist/util/icon_synonyms.d.ts +2 -4
  81. package/dist/util/icons.d.ts +8 -2
  82. package/dist/util/navigation_utils.d.ts +2 -2
  83. package/dist/util/permissions.d.ts +4 -4
  84. package/dist/util/references.d.ts +4 -2
  85. package/dist/util/resolutions.d.ts +9 -13
  86. package/dist/util/useTraceUpdate.d.ts +1 -0
  87. package/package.json +139 -119
  88. package/src/components/ClearFilterSortButton.tsx +41 -0
  89. package/src/components/DeleteEntityDialog.tsx +4 -4
  90. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +2 -2
  91. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +275 -278
  92. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
  93. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +44 -44
  94. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  95. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +9 -16
  96. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +3 -3
  97. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +27 -32
  98. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +11 -6
  99. package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +9 -5
  100. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
  101. package/src/components/EntityCollectionView/EntityCollectionView.tsx +560 -554
  102. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
  103. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  104. package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
  105. package/src/components/EntityPreview.tsx +207 -70
  106. package/src/components/EntityView.tsx +84 -0
  107. package/src/components/FieldCaption.tsx +14 -0
  108. package/src/components/FireCMSAppBar.tsx +33 -11
  109. package/src/components/HomePage/DefaultHomePage.tsx +15 -11
  110. package/src/components/HomePage/NavigationCard.tsx +69 -0
  111. package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
  112. package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
  113. package/src/components/HomePage/index.tsx +3 -1
  114. package/src/components/PropertyIdCopyTooltipContent.tsx +2 -3
  115. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
  116. package/src/components/ReferenceWidget.tsx +5 -5
  117. package/src/components/SearchIconsView.tsx +4 -4
  118. package/src/components/SelectableTable/SelectableTable.tsx +1 -1
  119. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  120. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +23 -8
  121. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +35 -24
  122. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
  123. package/src/components/VirtualTable/VirtualTable.tsx +28 -20
  124. package/src/components/VirtualTable/VirtualTableProps.tsx +1 -1
  125. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  126. package/src/components/common/types.tsx +4 -6
  127. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
  128. package/src/components/index.tsx +4 -2
  129. package/src/contexts/AuthControllerContext.tsx +1 -1
  130. package/src/core/Drawer.tsx +78 -103
  131. package/src/core/DrawerNavigationItem.tsx +62 -0
  132. package/src/core/{EntityView.tsx → EntityEditView.tsx} +21 -40
  133. package/src/core/EntitySidePanel.tsx +2 -2
  134. package/src/core/FireCMS.tsx +22 -7
  135. package/src/core/NavigationRoutes.tsx +11 -4
  136. package/src/core/Scaffold.tsx +76 -61
  137. package/src/core/field_configs.tsx +1 -2
  138. package/src/core/index.tsx +3 -4
  139. package/src/form/EntityForm.tsx +42 -22
  140. package/src/form/PropertyFieldBinding.tsx +0 -2
  141. package/src/form/components/StorageItemPreview.tsx +5 -3
  142. package/src/form/components/StorageUploadProgress.tsx +7 -6
  143. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +8 -12
  144. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  145. package/src/form/field_bindings/KeyValueFieldBinding.tsx +15 -15
  146. package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
  147. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +1 -1
  148. package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -0
  149. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +14 -5
  150. package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
  151. package/src/form/validation.ts +3 -4
  152. package/src/hooks/data/delete.ts +3 -3
  153. package/src/hooks/data/save.ts +2 -2
  154. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  155. package/src/hooks/data/useDataSource.tsx +8 -3
  156. package/src/hooks/data/useEntityFetch.tsx +4 -4
  157. package/src/hooks/index.tsx +3 -0
  158. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +9 -10
  159. package/src/hooks/useBuildModeController.tsx +11 -5
  160. package/src/hooks/useBuildNavigationController.tsx +199 -81
  161. package/src/hooks/useProjectLog.tsx +17 -7
  162. package/src/hooks/useReferenceDialog.tsx +2 -2
  163. package/src/hooks/useStorageSource.tsx +7 -2
  164. package/src/hooks/useValidateAuthenticator.tsx +115 -0
  165. package/src/internal/useBuildDataSource.ts +42 -44
  166. package/src/internal/useBuildSideEntityController.tsx +86 -20
  167. package/src/preview/PropertyPreview.tsx +3 -14
  168. package/src/preview/PropertyPreviewProps.tsx +1 -11
  169. package/src/preview/components/BooleanPreview.tsx +19 -4
  170. package/src/preview/components/EnumValuesChip.tsx +1 -1
  171. package/src/preview/components/ReferencePreview.tsx +55 -147
  172. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
  173. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -1
  174. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -1
  175. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
  176. package/src/preview/property_previews/ArrayOneOfPreview.tsx +0 -1
  177. package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -1
  178. package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
  179. package/src/types/analytics.ts +1 -0
  180. package/src/types/auth.tsx +50 -1
  181. package/src/types/collections.ts +33 -5
  182. package/src/types/datasource.ts +8 -5
  183. package/src/types/entities.ts +9 -1
  184. package/src/types/entity_actions.tsx +17 -0
  185. package/src/types/entity_callbacks.ts +2 -2
  186. package/src/types/entity_overrides.tsx +7 -0
  187. package/src/types/firecms.tsx +0 -1
  188. package/src/types/index.ts +2 -1
  189. package/src/types/navigation.ts +17 -16
  190. package/src/types/permissions.ts +6 -1
  191. package/src/types/plugins.tsx +26 -28
  192. package/src/types/properties.ts +8 -6
  193. package/src/types/property_config.tsx +2 -2
  194. package/src/types/roles.ts +41 -0
  195. package/src/types/side_entity_controller.tsx +1 -0
  196. package/src/types/storage.ts +12 -3
  197. package/src/types/user.ts +7 -0
  198. package/src/util/collections.ts +22 -0
  199. package/src/util/entities.ts +1 -1
  200. package/src/util/icon_list.ts +2 -2
  201. package/src/util/icon_synonyms.ts +4 -6
  202. package/src/util/icons.tsx +11 -3
  203. package/src/util/navigation_utils.ts +6 -6
  204. package/src/util/objects.ts +0 -14
  205. package/src/util/permissions.ts +11 -8
  206. package/src/util/references.ts +36 -5
  207. package/src/util/resolutions.ts +6 -24
  208. package/src/util/strings.ts +2 -2
  209. package/src/util/useTraceUpdate.tsx +2 -1
  210. package/dist/core/SideEntityView.d.ts +0 -7
  211. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  212. package/dist/internal/useLocaleConfig.d.ts +0 -1
  213. package/dist/types/appcheck.d.ts +0 -26
  214. package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
  215. package/src/core/SideEntityView.tsx +0 -38
  216. package/src/internal/useBuildCustomizationController.tsx +0 -5
  217. package/src/internal/useLocaleConfig.tsx +0 -18
  218. 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
@@ -134,12 +135,13 @@ export type EntityFormSaveParams<M extends Record<string, any>> = {
134
135
  * @constructor
135
136
  * @group Components
136
137
  */
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;
138
+ export const EntityForm = EntityFormInternal;
139
+ // export const EntityForm = React.memo<EntityFormProps<any>>(EntityFormInternal,
140
+ // (a: EntityFormProps<any>, b: EntityFormProps<any>) => {
141
+ // return a.status === b.status &&
142
+ // a.path === b.path &&
143
+ // equal(a.entity?.values, b.entity?.values);
144
+ // }) as typeof EntityFormInternal;
143
145
 
144
146
  function getDataSourceEntityValues<M extends object>(initialResolvedCollection: ResolvedEntityCollection,
145
147
  status: "new" | "existing" | "copy",
@@ -171,15 +173,16 @@ function EntityFormInternal<M extends Record<string, any>>({
171
173
  onFormContextChange,
172
174
  hideId,
173
175
  autoSave,
174
- onIdUpdateError
176
+ onIdUpdateError,
175
177
  }: EntityFormProps<M>) {
176
178
 
177
179
  const analyticsController = useAnalyticsController();
178
180
 
179
181
  const customizationController = useCustomizationController();
182
+ console.log("EntityFormInternal propertyConfigs", customizationController.propertyConfigs);
180
183
 
181
184
  const context = useFireCMSContext();
182
- const dataSource = useDataSource();
185
+ const dataSource = useDataSource(inputCollection);
183
186
  const plugins = customizationController.plugins;
184
187
 
185
188
  const initialResolvedCollection = useMemo(() => resolveCollection({
@@ -187,7 +190,7 @@ function EntityFormInternal<M extends Record<string, any>>({
187
190
  path,
188
191
  values: entity?.values,
189
192
  fields: customizationController.propertyConfigs
190
- }), [entity?.values, path]);
193
+ }), [entity?.values, path, customizationController.propertyConfigs]);
191
194
 
192
195
  const mustSetCustomId: boolean = (status === "new" || status === "copy") &&
193
196
  (Boolean(initialResolvedCollection.customId) && initialResolvedCollection.customId !== "optional");
@@ -344,6 +347,9 @@ function EntityFormInternal<M extends Record<string, any>>({
344
347
  fields: customizationController.propertyConfigs
345
348
  });
346
349
 
350
+ const titlePropertyKey = getEntityTitlePropertyKey(resolvedCollection, customizationController.propertyConfigs);
351
+ const title = internalValues && titlePropertyKey ? getValueInPath(internalValues, titlePropertyKey) : undefined;
352
+
347
353
  const onIdUpdate = inputCollection.callbacks?.onIdUpdate;
348
354
 
349
355
  const doOnIdUpdate = useCallback(async () => {
@@ -389,12 +395,15 @@ function EntityFormInternal<M extends Record<string, any>>({
389
395
 
390
396
  const authController = useAuthController();
391
397
 
392
- const getActionsForEntity = useCallback(({ entity, customEntityActions }: {
398
+ const getActionsForEntity = useCallback(({
399
+ entity,
400
+ customEntityActions
401
+ }: {
393
402
  entity?: Entity<M>,
394
403
  customEntityActions?: EntityAction[]
395
404
  }): EntityAction[] => {
396
- const createEnabled = canCreateEntity(inputCollection, authController, fullPathToCollectionSegments(path), null);
397
- const deleteEnabled = entity ? canDeleteEntity(inputCollection, authController, fullPathToCollectionSegments(path), entity) : true;
405
+ const createEnabled = canCreateEntity(inputCollection, authController, path, null);
406
+ const deleteEnabled = entity ? canDeleteEntity(inputCollection, authController, path, entity) : true;
398
407
  const actions: EntityAction[] = [];
399
408
  if (createEnabled)
400
409
  actions.push(copyEntityAction);
@@ -408,7 +417,8 @@ function EntityFormInternal<M extends Record<string, any>>({
408
417
  const pluginActions: React.ReactNode[] = [];
409
418
 
410
419
  const formContext: FormContext<M> = {
411
- setFieldValue: formex.setFieldValue,
420
+ // @ts-ignore
421
+ setFieldValue: useCallback(formex.setFieldValue, []),
412
422
  values: formex.values,
413
423
  collection: resolvedCollection,
414
424
  entityId,
@@ -416,12 +426,14 @@ function EntityFormInternal<M extends Record<string, any>>({
416
426
  save
417
427
  };
418
428
 
429
+ const submittedFormContext = useRef<FormContext<M> | null>(null);
419
430
  // eslint-disable-next-line react-hooks/rules-of-hooks
420
431
  useEffect(() => {
421
- if (onFormContextChange) {
432
+ if (onFormContextChange && !formContextsEqual(submittedFormContext.current ?? undefined, formContext)) {
422
433
  onFormContextChange(formContext);
434
+ submittedFormContext.current = formContext;
423
435
  }
424
- }, [onFormContextChange, formContext]);
436
+ }, [formContext, onFormContextChange]);
425
437
 
426
438
  if (plugins && inputCollection) {
427
439
  const actionProps: PluginFormActionProps = {
@@ -436,7 +448,7 @@ function EntityFormInternal<M extends Record<string, any>>({
436
448
  pluginActions.push(...plugins.map((plugin, i) => (
437
449
  plugin.form?.Actions
438
450
  ? <plugin.form.Actions
439
- key={`actions_${plugin.name}`} {...actionProps}/>
451
+ key={`actions_${plugin.key}`} {...actionProps}/>
440
452
  : null
441
453
  )).filter(Boolean));
442
454
  }
@@ -454,8 +466,8 @@ function EntityFormInternal<M extends Record<string, any>>({
454
466
  className={`w-full py-2 flex flex-col items-start mt-${4 + (pluginActions ? 8 : 0)} lg:mt-${8 + (pluginActions ? 8 : 0)} mb-8`}>
455
467
 
456
468
  <Typography
457
- className={"mt-4 flex-grow " + inputCollection.hideIdFromForm ? "mb-2" : "mb-0"}
458
- variant={"h4"}>{inputCollection.singularName ?? inputCollection.name}
469
+ className={"mt-4 flex-grow line-clamp-1 " + inputCollection.hideIdFromForm ? "mb-2" : "mb-0"}
470
+ variant={"h4"}>{title ?? inputCollection.singularName ?? inputCollection.name}
459
471
  </Typography>
460
472
  <Alert color={"base"} className={"w-full"} size={"small"}>
461
473
  <code className={"text-xs select-all"}>{path}/{entityId}</code>
@@ -508,7 +520,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
508
520
  savingError?: Error,
509
521
  closeAfterSaveRef: MutableRefObject<boolean>,
510
522
  autoSave?: boolean,
511
- entityActions: EntityAction[]
523
+ entityActions: EntityAction[],
512
524
  }) {
513
525
 
514
526
  const {
@@ -530,7 +542,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
530
542
  dirty,
531
543
  closeAfterSaveRef,
532
544
  autoSave,
533
- entityActions
545
+ entityActions,
534
546
  } = props;
535
547
 
536
548
  const context = useFireCMSContext();
@@ -598,6 +610,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
598
610
  <Tooltip title={<PropertyIdCopyTooltipContent propertyId={key}/>}
599
611
  delayDuration={800}
600
612
  side={"left"}
613
+ align={"start"}
601
614
  sideOffset={16}>
602
615
  <PropertyFieldBinding {...cmsFormFieldProps}/>
603
616
  </Tooltip>
@@ -655,7 +668,7 @@ function InnerForm<M extends Record<string, any>>(props: FormexController<M> & {
655
668
  fullPath: resolvedCollection.path,
656
669
  collection: resolvedCollection,
657
670
  context,
658
- sideEntityController
671
+ sideEntityController,
659
672
  });
660
673
  }}>
661
674
  {action.icon}
@@ -718,3 +731,10 @@ export function yupToFormErrors(yupError: ValidationError): Record<string, any>
718
731
  }
719
732
  return errors;
720
733
  }
734
+
735
+ function formContextsEqual(a: FormContext<any> | undefined, b: FormContext<any> | undefined): boolean {
736
+ return a?.path === b?.path &&
737
+ a?.entityId === b?.entityId &&
738
+ equal(a?.values, b?.values) &&
739
+ equal(a?.collection, b?.collection);
740
+ }
@@ -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,6 +1,6 @@
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
6
  import { cn, IconButton, paperMixin, RemoveIcon, Tooltip } from "@firecms/ui";
@@ -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,7 +24,8 @@ 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 (
@@ -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
  }
@@ -4,6 +4,7 @@ import { useSnackbarController, useStorageSource } from "../../hooks";
4
4
  import { StorageFieldItem } from "../../util/useStorageUploadController";
5
5
  import { ErrorView } from "../../components";
6
6
  import { cn, 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;
@@ -89,7 +90,7 @@ export function StorageUploadProgress({
89
90
 
90
91
  <div className={cn(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, cn, 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,17 @@ 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}
95
91
  />
96
- </div>
97
92
  );
98
- }, [ofProperty.path, ofProperty.previewProperties, onHover, value]);
93
+ }, [ofProperty.path, ofProperty.previewProperties, value]);
99
94
 
100
95
  const title = (
101
96
  <LabelWithIcon icon={getIconForProperty(property, "small")}
@@ -108,7 +103,7 @@ export function ArrayOfReferencesFieldBinding({
108
103
  {!collection && <ErrorView
109
104
  error={"The specified collection does not exist. Check console"}/>}
110
105
 
111
- {collection && <>
106
+ {collection && <div className={"group"}>
112
107
 
113
108
  <FormikArrayContainer value={value}
114
109
  addLabel={property.name ? "Add reference to " + property.name : "Add reference"}
@@ -126,7 +121,7 @@ export function ArrayOfReferencesFieldBinding({
126
121
  onClick={onEntryClick}>
127
122
  Edit {property.name}
128
123
  </Button>
129
- </>}
124
+ </div>}
130
125
  </>;
131
126
 
132
127
  return (
@@ -134,7 +129,8 @@ export function ArrayOfReferencesFieldBinding({
134
129
 
135
130
  {!tableMode &&
136
131
  <ExpandablePanel
137
- className={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2"}
132
+ titleClassName={fieldBackgroundMixin}
133
+ className={cn("px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2", fieldBackgroundMixin)}
138
134
  initiallyExpanded={expanded}
139
135
  title={title}>
140
136
  {body}
@@ -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}
@@ -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
 
@@ -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;
@@ -53,7 +53,7 @@ export function ReadOnlyFieldBinding({
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
 
@@ -95,6 +95,7 @@ function ReferenceFieldBindingInternal<M extends Record<string, any>>({
95
95
  {value && <ReferencePreview
96
96
  disabled={!property.path}
97
97
  previewProperties={property.previewProperties}
98
+ hover={!disabled}
98
99
  size={"medium"}
99
100
  onClick={disabled || isSubmitting ? undefined : onEntryClick}
100
101
  reference={value}
@@ -3,6 +3,7 @@ import React, { useCallback } from "react";
3
3
  import {
4
4
  ArrayProperty,
5
5
  Entity,
6
+ EntityCollection,
6
7
  FieldProps,
7
8
  ResolvedArrayProperty,
8
9
  ResolvedStringProperty,
@@ -10,10 +11,10 @@ import {
10
11
  } from "../../types";
11
12
  import { useDropzone } from "react-dropzone";
12
13
  import { PreviewSize } from "../../preview";
13
- import { FieldHelperText,LabelWithIcon } from "../components";
14
+ import { FieldHelperText, LabelWithIcon } from "../components";
14
15
 
15
16
  import { getIconForProperty, isReadOnly } from "../../util";
16
- import { useSnackbarController, useStorageSource } from "../../hooks";
17
+ import { useSnackbarController, useStorageSource } from "../../hooks";
17
18
  import { DragDropContext, Draggable, Droppable } from "@hello-pangea/dnd";
18
19
  import { StorageFieldItem, useStorageUploadController } from "../../util/useStorageUploadController";
19
20
  import { StorageUploadProgress } from "../components/StorageUploadProgress";
@@ -55,13 +56,13 @@ export function StorageUploadFieldBinding({
55
56
  property,
56
57
  includeDescription,
57
58
  context,
58
- isSubmitting
59
+ isSubmitting,
59
60
  }: StorageUploadFieldProps) {
60
61
 
61
62
  if (!context.entityId)
62
63
  throw new Error("StorageUploadFieldBinding: Entity id is null");
63
64
 
64
- const storageSource = useStorageSource();
65
+ const storageSource = useStorageSource(context.collection);
65
66
  const disabled = isReadOnly(property) || !!property.disabled || isSubmitting;
66
67
 
67
68
  const {
@@ -108,6 +109,7 @@ export function StorageUploadFieldBinding({
108
109
 
109
110
  <StorageUpload
110
111
  value={internalValue}
112
+ collection={context.collection}
111
113
  name={propertyKey}
112
114
  disabled={disabled}
113
115
  autoFocus={autoFocus}
@@ -133,6 +135,7 @@ export function StorageUploadFieldBinding({
133
135
 
134
136
  function FileDropComponent({
135
137
  storage,
138
+ collection,
136
139
  disabled,
137
140
  isDraggingOver,
138
141
  onFilesAdded,
@@ -151,6 +154,7 @@ function FileDropComponent({
151
154
  helpText
152
155
  }: {
153
156
  storage: StorageConfig,
157
+ collection: EntityCollection,
154
158
  disabled: boolean,
155
159
  isDraggingOver: boolean,
156
160
  droppableProvided: any,
@@ -231,6 +235,7 @@ function FileDropComponent({
231
235
  if (entry.storagePathOrDownloadUrl) {
232
236
  child = (
233
237
  <StorageItemPreview
238
+ collection={collection}
234
239
  name={`storage_preview_${entry.storagePathOrDownloadUrl}`}
235
240
  property={property}
236
241
  disabled={disabled}
@@ -294,6 +299,7 @@ function FileDropComponent({
294
299
 
295
300
  export interface StorageUploadProps {
296
301
  value: StorageFieldItem[];
302
+ collection: EntityCollection;
297
303
  setInternalValue: (v: StorageFieldItem[]) => void;
298
304
  name: string;
299
305
  property: ResolvedStringProperty | ResolvedArrayProperty<string[]>;
@@ -309,6 +315,7 @@ export interface StorageUploadProps {
309
315
  }
310
316
 
311
317
  export function StorageUpload({
318
+ collection,
312
319
  property,
313
320
  name,
314
321
  value,
@@ -321,7 +328,7 @@ export function StorageUpload({
321
328
  autoFocus,
322
329
  storage,
323
330
  entity,
324
- storagePathBuilder
331
+ storagePathBuilder,
325
332
  }: StorageUploadProps) {
326
333
 
327
334
  if (multipleFilesSupported) {
@@ -401,6 +408,7 @@ export function StorageUpload({
401
408
  className="rounded"
402
409
  >
403
410
  <StorageItemPreview
411
+ collection={collection}
404
412
  name={`storage_preview_${entry.storagePathOrDownloadUrl}`}
405
413
  property={renderProperty}
406
414
  disabled={true}
@@ -414,6 +422,7 @@ export function StorageUpload({
414
422
  >
415
423
  {(provided, snapshot) => {
416
424
  return <FileDropComponent storage={storage}
425
+ collection={collection}
417
426
  disabled={disabled}
418
427
  isDraggingOver={snapshot.isDraggingOver}
419
428
  droppableProvided={provided}
@@ -7,7 +7,7 @@ import { getIconForProperty } from "../../util";
7
7
  import { PropertyPreview } from "../../preview";
8
8
  import { useClearRestoreValue } from "../useClearRestoreValue";
9
9
 
10
- interface TextFieldProps<T extends string | number> extends FieldProps<T> {
10
+ interface TextFieldBindingProps<T extends string | number> extends FieldProps<T> {
11
11
  allowInfinity?: boolean
12
12
  }
13
13
 
@@ -18,6 +18,7 @@ interface TextFieldProps<T extends string | number> extends FieldProps<T> {
18
18
  * @group Form fields
19
19
  */
20
20
  export function TextFieldBinding<T extends string | number>({
21
+ context,
21
22
  propertyKey,
22
23
  value,
23
24
  setValue,
@@ -27,7 +28,7 @@ export function TextFieldBinding<T extends string | number>({
27
28
  autoFocus,
28
29
  property,
29
30
  includeDescription,
30
- }: TextFieldProps<T>) {
31
+ }: TextFieldBindingProps<T>) {
31
32
 
32
33
  let multiline: boolean | undefined;
33
34
  let url: boolean | PreviewType | undefined;
@@ -96,9 +97,10 @@ export function TextFieldBinding<T extends string | number>({
96
97
  {url && <Collapse
97
98
  className="mt-1 ml-1"
98
99
  in={Boolean(value)}>
99
- <PropertyPreview value={value}
100
- property={property}
101
- size={"medium"}/>
100
+ <PropertyPreview
101
+ value={value}
102
+ property={property}
103
+ size={"medium"}/>
102
104
  </Collapse>}
103
105
 
104
106
  </>
@@ -9,8 +9,7 @@ import {
9
9
  } from "../types";
10
10
  import * as yup from "yup";
11
11
  import { AnySchema, ArraySchema, BooleanSchema, DateSchema, NumberSchema, ObjectSchema, StringSchema } from "yup";
12
- import { enumToObjectEntries } from "../util/enums";
13
- import { getValueInPath, hydrateRegExp, isPropertyBuilder } from "../util";
12
+ import { enumToObjectEntries, getValueInPath, hydrateRegExp, isPropertyBuilder } from "../util";
14
13
 
15
14
  // Add custom unique function for array values
16
15
  declare module "yup" {
@@ -90,12 +89,12 @@ export function mapPropertyToYup<T extends CMSType>(propertyContext: PropertyCon
90
89
  throw Error("Unsupported data type in yup mapping");
91
90
  }
92
91
 
93
- export function getYupMapObjectSchema<M extends Record<string, any>>({
92
+ export function getYupMapObjectSchema({
94
93
  property,
95
94
  entityId,
96
95
  customFieldValidator,
97
96
  name
98
- }: PropertyContext<M>): ObjectSchema<any> {
97
+ }: PropertyContext<Record<string, any>>): ObjectSchema<any> {
99
98
  const objectSchema: any = {};
100
99
  const validation = property.validation;
101
100
  if (property.properties)