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

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 (201) hide show
  1. package/dist/app/Scaffold.d.ts +4 -0
  2. package/dist/components/ArrayContainer.d.ts +14 -3
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +15 -1
  6. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  7. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +8 -0
  8. package/dist/components/EntityJsonPreview.d.ts +3 -0
  9. package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
  10. package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
  11. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
  12. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  13. package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
  14. package/dist/components/common/default_entity_actions.d.ts +0 -2
  15. package/dist/components/common/index.d.ts +1 -1
  16. package/dist/components/common/useColumnsIds.d.ts +1 -0
  17. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
  18. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  19. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  20. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  21. package/dist/core/DefaultAppBar.d.ts +8 -2
  22. package/dist/core/EntityEditView.d.ts +36 -21
  23. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  24. package/dist/core/FireCMS.d.ts +2 -2
  25. package/dist/core/FireCMSRouter.d.ts +4 -0
  26. package/dist/core/NavigationRoutes.d.ts +0 -1
  27. package/dist/core/SideDialogs.d.ts +4 -2
  28. package/dist/core/index.d.ts +2 -1
  29. package/dist/form/EntityForm.d.ts +49 -0
  30. package/dist/form/EntityFormActions.d.ts +17 -0
  31. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  32. package/dist/form/components/FormEntry.d.ts +6 -0
  33. package/dist/form/components/FormLayout.d.ts +5 -0
  34. package/dist/form/components/index.d.ts +2 -0
  35. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  36. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  37. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  38. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  39. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  40. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  41. package/dist/form/index.d.ts +16 -16
  42. package/dist/hooks/data/save.d.ts +1 -1
  43. package/dist/hooks/data/useEntityFetch.d.ts +2 -1
  44. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  45. package/dist/hooks/useBuildNavigationController.d.ts +4 -1
  46. package/dist/hooks/useModeController.d.ts +1 -2
  47. package/dist/index.es.js +15842 -14396
  48. package/dist/index.es.js.map +1 -1
  49. package/dist/index.umd.js +15833 -14389
  50. package/dist/index.umd.js.map +1 -1
  51. package/dist/internal/useBuildDataSource.d.ts +3 -2
  52. package/dist/internal/useBuildSideEntityController.d.ts +3 -3
  53. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  54. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  55. package/dist/routes/FireCMSRoute.d.ts +1 -0
  56. package/dist/routes/HomePageRoute.d.ts +3 -0
  57. package/dist/types/collections.d.ts +36 -10
  58. package/dist/types/datasource.d.ts +2 -2
  59. package/dist/types/dialogs_controller.d.ts +7 -3
  60. package/dist/types/entities.d.ts +1 -1
  61. package/dist/types/entity_actions.d.ts +10 -0
  62. package/dist/types/fields.d.ts +13 -3
  63. package/dist/types/firecms.d.ts +1 -1
  64. package/dist/types/navigation.d.ts +33 -12
  65. package/dist/types/plugins.d.ts +2 -0
  66. package/dist/types/properties.d.ts +40 -4
  67. package/dist/types/side_entity_controller.d.ts +6 -1
  68. package/dist/util/builders.d.ts +1 -1
  69. package/dist/util/createFormexStub.d.ts +2 -0
  70. package/dist/util/entity_actions.d.ts +2 -0
  71. package/dist/util/entity_cache.d.ts +23 -0
  72. package/dist/util/index.d.ts +1 -0
  73. package/dist/util/navigation_from_path.d.ts +6 -1
  74. package/dist/util/navigation_utils.d.ts +13 -1
  75. package/dist/util/objects.d.ts +1 -1
  76. package/dist/util/property_utils.d.ts +2 -2
  77. package/dist/util/references.d.ts +2 -2
  78. package/dist/util/resolutions.d.ts +12 -2
  79. package/package.json +20 -21
  80. package/src/app/Scaffold.tsx +13 -3
  81. package/src/components/ArrayContainer.tsx +60 -24
  82. package/src/components/CircularProgressCenter.tsx +1 -1
  83. package/src/components/DeleteEntityDialog.tsx +5 -3
  84. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +46 -23
  85. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +10 -4
  86. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +18 -1
  87. package/src/components/EntityCollectionTable/index.tsx +1 -1
  88. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
  89. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +10 -13
  90. package/src/components/EntityCollectionView/EntityCollectionView.tsx +105 -47
  91. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  92. package/src/components/EntityJsonPreview.tsx +66 -0
  93. package/src/components/EntityPreview.tsx +10 -3
  94. package/src/components/EntityView.tsx +4 -1
  95. package/src/components/NotFoundPage.tsx +2 -2
  96. package/src/components/PropertyIdCopyTooltip.tsx +2 -3
  97. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +14 -7
  98. package/src/components/SelectableTable/SelectableTable.tsx +18 -3
  99. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +7 -7
  100. package/src/components/UnsavedChangesDialog.tsx +42 -0
  101. package/src/components/VirtualTable/VirtualTable.tsx +48 -3
  102. package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
  103. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
  104. package/src/components/common/default_entity_actions.tsx +37 -37
  105. package/src/components/common/index.ts +1 -1
  106. package/src/components/common/useColumnsIds.tsx +1 -1
  107. package/src/components/common/useDataSourceTableController.tsx +420 -0
  108. package/src/components/common/useDebouncedCallback.tsx +20 -0
  109. package/src/components/common/useScrollRestoration.tsx +68 -0
  110. package/src/contexts/BreacrumbsContext.tsx +38 -0
  111. package/src/contexts/DialogsProvider.tsx +3 -2
  112. package/src/contexts/ModeController.tsx +1 -3
  113. package/src/core/DefaultAppBar.tsx +59 -17
  114. package/src/core/DefaultDrawer.tsx +1 -1
  115. package/src/core/EntityEditView.tsx +354 -1000
  116. package/src/core/EntityEditViewFormActions.tsx +199 -0
  117. package/src/core/EntitySidePanel.tsx +85 -15
  118. package/src/core/FireCMS.tsx +20 -16
  119. package/src/core/FireCMSRouter.tsx +17 -0
  120. package/src/core/NavigationRoutes.tsx +23 -32
  121. package/src/core/SideDialogs.tsx +20 -11
  122. package/src/core/index.tsx +4 -2
  123. package/src/form/EntityForm.tsx +782 -0
  124. package/src/form/EntityFormActions.tsx +169 -0
  125. package/src/form/PropertyFieldBinding.tsx +21 -16
  126. package/src/form/components/FormEntry.tsx +22 -0
  127. package/src/form/components/FormLayout.tsx +16 -0
  128. package/src/form/components/LabelWithIcon.tsx +6 -3
  129. package/src/form/components/StorageUploadProgress.tsx +1 -1
  130. package/src/form/components/index.tsx +2 -0
  131. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +8 -5
  132. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -2
  133. package/src/form/field_bindings/BlockFieldBinding.tsx +5 -3
  134. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -0
  135. package/src/form/field_bindings/KeyValueFieldBinding.tsx +1 -1
  136. package/src/form/field_bindings/MapFieldBinding.tsx +14 -16
  137. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +15 -8
  138. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +3 -3
  139. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
  140. package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -1
  141. package/src/form/field_bindings/RepeatFieldBinding.tsx +13 -4
  142. package/src/form/field_bindings/SelectFieldBinding.tsx +2 -2
  143. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +11 -6
  144. package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -0
  145. package/src/form/field_bindings/TextFieldBinding.tsx +1 -0
  146. package/src/form/index.tsx +16 -32
  147. package/src/form/validation.ts +12 -6
  148. package/src/hooks/data/save.ts +25 -30
  149. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  150. package/src/hooks/data/useEntityFetch.tsx +5 -1
  151. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  152. package/src/hooks/useBuildModeController.tsx +15 -28
  153. package/src/hooks/useBuildNavigationController.tsx +81 -24
  154. package/src/hooks/useFireCMSContext.tsx +0 -30
  155. package/src/hooks/useLargeLayout.tsx +0 -35
  156. package/src/hooks/useModeController.tsx +1 -2
  157. package/src/hooks/useResolvedNavigationFrom.tsx +4 -6
  158. package/src/internal/useBuildDataSource.ts +9 -5
  159. package/src/internal/useBuildSideDialogsController.tsx +3 -2
  160. package/src/internal/useBuildSideEntityController.tsx +135 -88
  161. package/src/internal/useUnsavedChangesDialog.tsx +126 -92
  162. package/src/preview/PropertyPreview.tsx +12 -10
  163. package/src/preview/components/UrlComponentPreview.tsx +17 -18
  164. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +4 -3
  165. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  166. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +4 -2
  167. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -3
  168. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -2
  169. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -2
  170. package/src/preview/property_previews/MapPropertyPreview.tsx +3 -2
  171. package/src/routes/CustomCMSRoute.tsx +21 -0
  172. package/src/routes/FireCMSRoute.tsx +246 -0
  173. package/src/routes/HomePageRoute.tsx +17 -0
  174. package/src/types/collections.ts +45 -13
  175. package/src/types/datasource.ts +2 -1
  176. package/src/types/dialogs_controller.tsx +7 -3
  177. package/src/types/entities.ts +1 -1
  178. package/src/types/entity_actions.tsx +12 -0
  179. package/src/types/fields.tsx +18 -3
  180. package/src/types/firecms.tsx +1 -1
  181. package/src/types/navigation.ts +41 -16
  182. package/src/types/plugins.tsx +2 -0
  183. package/src/types/properties.ts +48 -4
  184. package/src/types/side_dialogs_controller.tsx +2 -0
  185. package/src/types/side_entity_controller.tsx +11 -1
  186. package/src/util/builders.ts +5 -3
  187. package/src/util/createFormexStub.tsx +62 -0
  188. package/src/util/entity_actions.ts +28 -0
  189. package/src/util/entity_cache.ts +204 -0
  190. package/src/util/index.ts +1 -0
  191. package/src/util/join_collections.ts +6 -1
  192. package/src/util/navigation_from_path.ts +18 -7
  193. package/src/util/navigation_utils.ts +115 -14
  194. package/src/util/objects.ts +9 -2
  195. package/src/util/parent_references_from_path.ts +3 -3
  196. package/src/util/property_utils.tsx +7 -3
  197. package/src/util/references.ts +8 -6
  198. package/src/util/resolutions.ts +41 -12
  199. package/src/util/useStorageUploadController.tsx +60 -23
  200. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
  201. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -3,13 +3,15 @@ import {
3
3
  FieldHelperText,
4
4
  FieldProps,
5
5
  getIconForProperty,
6
- LabelWithIconAndTooltip, PropertyOrBuilder,
6
+ LabelWithIconAndTooltip,
7
+ PropertyOrBuilder,
7
8
  randomString,
8
9
  ResolvedArrayProperty,
9
10
  ResolvedStringProperty,
11
+ useAuthController,
10
12
  useStorageSource
11
13
  } from "../../index";
12
- import { cls, fieldBackgroundHoverMixin, fieldBackgroundMixin } from "@firecms/ui";
14
+ import { cls, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundMixin } from "@firecms/ui";
13
15
  import { FireCMSEditor, FireCMSEditorProps } from "@firecms/editor";
14
16
  import { resolveProperty, resolveStorageFilenameString, resolveStoragePathString } from "../../util";
15
17
 
@@ -27,11 +29,14 @@ export function MarkdownEditorFieldBinding({
27
29
  showError,
28
30
  error,
29
31
  minimalistView,
32
+ disabled: disabledProp,
30
33
  isSubmitting,
31
34
  context,
32
35
  customProps,
33
36
  }: FieldProps<string, MarkdownEditorFieldProps>) {
34
37
 
38
+ const authController = useAuthController();
39
+ const disabled = disabledProp || isSubmitting;
35
40
  const highlight = customProps?.highlight;
36
41
  const editorProps = customProps?.editorProps;
37
42
  const storageSource = useStorageSource();
@@ -54,14 +59,13 @@ export function MarkdownEditorFieldBinding({
54
59
  if (internalValue.current !== value) {
55
60
  internalValue.current = value;
56
61
  setFieldVersion(fieldVersion + 1);
57
- // fieldVersion.current = fieldVersion.current + 1;
58
62
  }
59
63
  }, [value]);
60
64
 
61
-
62
65
  const resolvedProperty = resolveProperty({
63
66
  propertyOrBuilder: property as PropertyOrBuilder,
64
- values: entityValues
67
+ values: entityValues,
68
+ authController
65
69
  }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
66
70
 
67
71
  const fileNameBuilder = useCallback(async (file: File) => {
@@ -88,7 +92,8 @@ export function MarkdownEditorFieldBinding({
88
92
  if (!storage) return "/";
89
93
  const resolvedProperty = resolveProperty({
90
94
  propertyOrBuilder: property,
91
- values: entityValues
95
+ values: entityValues,
96
+ authController
92
97
  }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
93
98
  return resolveStoragePathString({
94
99
  input: storage.storagePath,
@@ -107,6 +112,7 @@ export function MarkdownEditorFieldBinding({
107
112
  onMarkdownContentChange={onContentChange}
108
113
  version={context.formex.version + fieldVersion}
109
114
  highlight={highlight}
115
+ disabled={disabled}
110
116
  handleImageUpload={async (file: File) => {
111
117
  const storagePath = storagePathBuilder(file);
112
118
  const fileName = await fileNameBuilder(file);
@@ -135,8 +141,9 @@ export function MarkdownEditorFieldBinding({
135
141
  icon={getIconForProperty(property, "small")}
136
142
  required={property.validation?.required}
137
143
  title={property.name}
138
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
139
- <div className={cls("rounded-md", fieldBackgroundMixin, fieldBackgroundHoverMixin)}>
144
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
145
+ <div
146
+ className={cls("rounded-md", fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin)}>
140
147
  {editor}
141
148
  </div>
142
149
  <FieldHelperText includeDescription={includeDescription}
@@ -23,7 +23,7 @@ export function MultiSelectFieldBinding({
23
23
  disabled,
24
24
  property,
25
25
  includeDescription,
26
- size = "medium",
26
+ size = "large",
27
27
  autoFocus
28
28
  }: FieldProps<EnumType[], any, any>) {
29
29
 
@@ -83,7 +83,7 @@ export function MultiSelectFieldBinding({
83
83
  <>
84
84
  <MultiSelect
85
85
  className={"w-full mt-2"}
86
- size={size === "medium" ? "medium" : "small"}
86
+ size={size}
87
87
  value={validValue ? value.map((v) => v.toString()) : []}
88
88
  disabled={disabled}
89
89
  modalPopover={true}
@@ -92,7 +92,7 @@ export function MultiSelectFieldBinding({
92
92
  icon={getIconForProperty(property, "small")}
93
93
  required={property.validation?.required}
94
94
  title={property.name}
95
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
95
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
96
96
  onValueChange={(updatedValue: string[]) => {
97
97
  let newValue: EnumType[] | null;
98
98
  if (of && (of as ResolvedProperty)?.dataType === "number") {
@@ -39,11 +39,11 @@ export function ReadOnlyFieldBinding({
39
39
  icon={getIconForProperty(property, "small")}
40
40
  required={property.validation?.required}
41
41
  title={property.name}
42
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
42
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
43
43
  }
44
44
 
45
45
  <div
46
- className={cls(paperMixin, "min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
46
+ className={cls(paperMixin, "w-full min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
47
47
 
48
48
  <ErrorBoundary>
49
49
  <PropertyPreview propertyKey={propertyKey}
@@ -90,7 +90,7 @@ function ReferenceFieldBindingInternal({
90
90
  icon={getIconForProperty(property, "small")}
91
91
  required={property.validation?.required}
92
92
  title={property.name}
93
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
93
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
94
94
 
95
95
  {!collection && <ErrorView
96
96
  error={"The specified collection does not exist. Check console"}/>}
@@ -6,6 +6,7 @@ import { getArrayResolvedProperties, getDefaultValueFor, getIconForProperty, mer
6
6
  import { PropertyFieldBinding } from "../PropertyFieldBinding";
7
7
  import { ExpandablePanel, Typography } from "@firecms/ui";
8
8
  import { useClearRestoreValue } from "../useClearRestoreValue";
9
+ import { useAuthController } from "../../hooks";
9
10
 
10
11
  /**
11
12
  * Generic array field that allows reordering and renders the child property
@@ -23,7 +24,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
23
24
  isSubmitting,
24
25
  setValue,
25
26
  setFieldValue,
26
- minimalistView,
27
+ minimalistView: minimalistViewProp,
27
28
  property,
28
29
  includeDescription,
29
30
  underlyingValueHasChanged,
@@ -31,6 +32,9 @@ export function RepeatFieldBinding<T extends Array<any>>({
31
32
  disabled
32
33
  }: FieldProps<T>) {
33
34
 
35
+ const authController = useAuthController();
36
+ const minimalistView = minimalistViewProp || property.minimalistView;
37
+
34
38
  if (!property.of)
35
39
  throw Error("RepeatFieldBinding misconfiguration. Property `of` not set");
36
40
 
@@ -40,7 +44,8 @@ export function RepeatFieldBinding<T extends Array<any>>({
40
44
  propertyValue: value,
41
45
  propertyKey,
42
46
  property,
43
- ignoreMissingFields: false
47
+ ignoreMissingFields: false,
48
+ authController
44
49
  })
45
50
  }
46
51
 
@@ -79,15 +84,19 @@ export function RepeatFieldBinding<T extends Array<any>>({
79
84
  </ErrorBoundary>;
80
85
  };
81
86
 
87
+ const canAddElements = !property.disabled && !isSubmitting && !disabled && (property.canAddElements || property.canAddElements === undefined);
88
+ const sortable = property.sortable === undefined ? true : property.sortable;
82
89
  const arrayContainer = <ArrayContainer droppableId={propertyKey}
83
90
  addLabel={property.name ? "Add entry to " + property.name : "Add entry"}
84
91
  value={value}
85
92
  buildEntry={buildEntry}
86
93
  onInternalIdAdded={setLastAddedId}
87
94
  disabled={isSubmitting || Boolean(property.disabled)}
88
- includeAddButton={!property.disabled}
95
+ canAddElements={canAddElements}
96
+ sortable={sortable}
89
97
  newDefaultEntry={getDefaultValueFor(property.of)}
90
98
  onValueChange={(value) => setFieldValue(propertyKey, value)}
99
+ className={property.widthPercentage !== undefined ? "mt-8" : undefined}
91
100
  />;
92
101
 
93
102
  const title = (<>
@@ -96,7 +105,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
96
105
  icon={getIconForProperty(property, "small")}
97
106
  required={property.validation?.required}
98
107
  title={property.name}
99
- className={"flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
108
+ className={"h-8 flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
100
109
  {Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
101
110
  </>);
102
111
 
@@ -62,11 +62,11 @@ export function SelectFieldBinding<T extends EnumType>({
62
62
  icon={getIconForProperty(property, "small")}
63
63
  required={property.validation?.required}
64
64
  title={property.name}
65
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}
65
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5 my-0"}
66
66
  />
67
67
  </PropertyIdCopyTooltip>}
68
68
  endAdornment={
69
- property.clearable && <IconButton
69
+ property.clearable && !disabled && <IconButton
70
70
  onClick={handleClearClick}>
71
71
  <CloseIcon/>
72
72
  </IconButton>
@@ -13,7 +13,7 @@ import { PreviewSize } from "../../preview";
13
13
  import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
14
14
 
15
15
  import { getIconForProperty, isReadOnly, resolveProperty } from "../../util";
16
- import { useSnackbarController, useStorageSource } from "../../hooks";
16
+ import { useAuthController, useSnackbarController, useStorageSource } from "../../hooks";
17
17
  import { DragDropContext, Draggable, Droppable } from "@hello-pangea/dnd";
18
18
  import { StorageFieldItem, useStorageUploadController } from "../../util/useStorageUploadController";
19
19
  import { StorageUploadProgress } from "../components/StorageUploadProgress";
@@ -28,7 +28,7 @@ import {
28
28
  import { useClearRestoreValue } from "../useClearRestoreValue";
29
29
 
30
30
  const dropZoneClasses = "box-border relative pt-[2px] items-center border border-transparent min-h-[254px] outline-none rounded-md duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid";
31
- const disabledClasses = "border-dotted-gray"
31
+ const disabledClasses = fieldBackgroundDisabledMixin;
32
32
  const nonActiveDropClasses = fieldBackgroundHoverMixin
33
33
  const activeDropClasses = "pt-0 border-2 border-solid"
34
34
  const acceptDropClasses = "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-2 border-solid border-green-500"
@@ -57,11 +57,13 @@ export function StorageUploadFieldBinding({
57
57
  isSubmitting,
58
58
  }: StorageUploadFieldProps) {
59
59
 
60
+ const authController = useAuthController();
61
+
60
62
  if (!context.entityId)
61
63
  throw new Error("StorageUploadFieldBinding: Entity id is null");
62
64
 
63
65
  const storageSource = useStorageSource(context.collection);
64
- const disabled = isReadOnly(property) || !!property.disabled || isSubmitting;
66
+ const disabled = isReadOnly(property) || !!property.disabled || isSubmitting || context.disabled;
65
67
 
66
68
  const {
67
69
  internalValue,
@@ -91,6 +93,7 @@ export function StorageUploadFieldBinding({
91
93
 
92
94
  const resolvedProperty = resolveProperty({
93
95
  propertyOrBuilder: property as PropertyOrBuilder,
96
+ authController
94
97
  }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
95
98
 
96
99
  return (
@@ -103,7 +106,7 @@ export function StorageUploadFieldBinding({
103
106
  icon={getIconForProperty(property, "small")}
104
107
  required={property.validation?.required}
105
108
  title={property.name}
106
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
109
+ className={"h-8text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
107
110
 
108
111
  <StorageUpload
109
112
  value={internalValue}
@@ -206,6 +209,7 @@ function FileDropComponent({
206
209
  className={cls(
207
210
  fieldBackgroundMixin,
208
211
  disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
212
+ disabled ? "text-surface-accent-600 dark:text-surface-accent-500" : "",
209
213
  dropZoneClasses,
210
214
  multipleFilesSupported && internalValue.length ? "" : "flex",
211
215
  {
@@ -248,7 +252,7 @@ function FileDropComponent({
248
252
  metadata={metadata}
249
253
  storagePath={storagePathBuilder(entry.file)}
250
254
  onFileUploadComplete={onFileUploadComplete}
251
- imageSize={size === "medium" ? 220 : 118}
255
+ imageSize={size === "large" ? 220 : 118}
252
256
  simple={false}
253
257
  />
254
258
  );
@@ -285,7 +289,8 @@ function FileDropComponent({
285
289
  <div
286
290
  className="flex-grow min-h-[38px] box-border m-2 text-center">
287
291
  <Typography align={"center"}
288
- variant={"label"}>
292
+ variant={"label"}
293
+ className={disabled ? "text-surface-accent-600 dark:text-surface-accent-500" : ""}>
289
294
  {helpText}
290
295
  </Typography>
291
296
  </div>
@@ -43,6 +43,7 @@ export const SwitchFieldBinding = function SwitchFieldBinding({
43
43
  value={value}
44
44
  onValueChange={(v) => setValue(v)}
45
45
  error={showError}
46
+ className={property.widthPercentage !== undefined ? "mt-8" : undefined}
46
47
  label={<LabelWithIcon
47
48
  icon={getIconForProperty(property, "small")}
48
49
  required={property.validation?.required}
@@ -75,6 +75,7 @@ export function TextFieldBinding<T extends string | number>({
75
75
  value={value}
76
76
  onChange={onChange}
77
77
  autoFocus={autoFocus}
78
+ className={property.widthPercentage !== undefined ? "mt-8" : undefined}
78
79
  label={<LabelWithIcon
79
80
  icon={getIconForProperty(property, "small")}
80
81
  required={property.validation?.required}
@@ -1,36 +1,20 @@
1
- import { SelectFieldBinding } from "./field_bindings/SelectFieldBinding";
2
- import { MultiSelectFieldBinding } from "./field_bindings/MultiSelectFieldBinding";
3
- import { ArrayOfReferencesFieldBinding } from "./field_bindings/ArrayOfReferencesFieldBinding";
4
- import { StorageUploadFieldBinding } from "./field_bindings/StorageUploadFieldBinding";
5
- import { TextFieldBinding } from "./field_bindings/TextFieldBinding";
6
- import { SwitchFieldBinding } from "./field_bindings/SwitchFieldBinding";
7
- import { DateTimeFieldBinding } from "./field_bindings/DateTimeFieldBinding";
8
- import { ReferenceFieldBinding } from "./field_bindings/ReferenceFieldBinding";
9
- import { MapFieldBinding } from "./field_bindings/MapFieldBinding";
10
- import { KeyValueFieldBinding } from "./field_bindings/KeyValueFieldBinding";
11
- import { RepeatFieldBinding } from "./field_bindings/RepeatFieldBinding";
12
- import { BlockFieldBinding } from "./field_bindings/BlockFieldBinding";
13
- import { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
14
- import { MarkdownEditorFieldBinding } from "./field_bindings/MarkdownEditorFieldBinding";
15
- import { ArrayCustomShapedFieldBinding } from "./field_bindings/ArrayCustomShapedFieldBinding";
1
+ export * from "./EntityForm";
16
2
 
17
- export {
18
- ArrayCustomShapedFieldBinding,
19
- RepeatFieldBinding,
20
- MultiSelectFieldBinding,
21
- ArrayOfReferencesFieldBinding,
22
- BlockFieldBinding,
23
- DateTimeFieldBinding,
24
- ReadOnlyFieldBinding,
25
- MapFieldBinding,
26
- KeyValueFieldBinding,
27
- ReferenceFieldBinding,
28
- SelectFieldBinding,
29
- StorageUploadFieldBinding,
30
- SwitchFieldBinding,
31
- MarkdownEditorFieldBinding,
32
- TextFieldBinding
33
- };
3
+ export { SelectFieldBinding } from "./field_bindings/SelectFieldBinding";
4
+ export { MultiSelectFieldBinding } from "./field_bindings/MultiSelectFieldBinding";
5
+ export { ArrayOfReferencesFieldBinding } from "./field_bindings/ArrayOfReferencesFieldBinding";
6
+ export { StorageUploadFieldBinding } from "./field_bindings/StorageUploadFieldBinding";
7
+ export { TextFieldBinding } from "./field_bindings/TextFieldBinding";
8
+ export { SwitchFieldBinding } from "./field_bindings/SwitchFieldBinding";
9
+ export { DateTimeFieldBinding } from "./field_bindings/DateTimeFieldBinding";
10
+ export { ReferenceFieldBinding } from "./field_bindings/ReferenceFieldBinding";
11
+ export { MapFieldBinding } from "./field_bindings/MapFieldBinding";
12
+ export { KeyValueFieldBinding } from "./field_bindings/KeyValueFieldBinding";
13
+ export { RepeatFieldBinding } from "./field_bindings/RepeatFieldBinding";
14
+ export { BlockFieldBinding } from "./field_bindings/BlockFieldBinding";
15
+ export { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
16
+ export { MarkdownEditorFieldBinding } from "./field_bindings/MarkdownEditorFieldBinding";
17
+ export { ArrayCustomShapedFieldBinding } from "./field_bindings/ArrayCustomShapedFieldBinding";
34
18
 
35
19
  export * from "./components";
36
20
 
@@ -90,11 +90,11 @@ export function mapPropertyToYup<T extends CMSType>(propertyContext: PropertyCon
90
90
  }
91
91
 
92
92
  export function getYupMapObjectSchema({
93
- property,
94
- entityId,
95
- customFieldValidator,
96
- name
97
- }: PropertyContext<Record<string, any>>): ObjectSchema<any> {
93
+ property,
94
+ entityId,
95
+ customFieldValidator,
96
+ name
97
+ }: PropertyContext<Record<string, any>>): ObjectSchema<any> {
98
98
  const objectSchema: any = {};
99
99
  const validation = property.validation;
100
100
  if (property.properties)
@@ -159,7 +159,13 @@ function getYupStringSchema({
159
159
  if (validation.lowercase) collection = collection.lowercase();
160
160
  if (validation.uppercase) collection = collection.uppercase();
161
161
  if (property.email) collection = collection.email(`${property.name} must be an email`);
162
- if (property.url) collection = collection.url(`${property.name} must be a url`);
162
+ if (property.url) {
163
+ if (!property.storage || property.storage?.storeUrl) {
164
+ collection = collection.url(`${property.name} must be a url`);
165
+ } else {
166
+ console.warn(`Property ${property.name} has a url validation but its storage configuration is not set to store urls`);
167
+ }
168
+ }
163
169
  } else {
164
170
  collection = collection.notRequired().nullable(true);
165
171
  }
@@ -1,12 +1,4 @@
1
- import {
2
- DataSource,
3
- Entity,
4
- EntityCollection,
5
- EntityValues,
6
- FireCMSContext,
7
- SaveEntityProps,
8
- User
9
- } from "../../types";
1
+ import { DataSource, Entity, EntityCollection, EntityValues, FireCMSContext, SaveEntityProps, User } from "../../types";
10
2
  import { useDataSource } from "./useDataSource";
11
3
  import { resolveCollection } from "../../util";
12
4
 
@@ -49,23 +41,23 @@ export type SaveEntityWithCallbacksProps<M extends Record<string, any>> =
49
41
  * @group Hooks and utilities
50
42
  */
51
43
  export async function saveEntityWithCallbacks<M extends Record<string, any>, USER extends User>({
52
- collection,
53
- path,
54
- entityId,
55
- values,
56
- previousValues,
57
- status,
58
- dataSource,
59
- context,
60
- onSaveSuccess,
61
- onSaveFailure,
62
- onPreSaveHookError,
63
- onSaveSuccessHookError
64
- }: SaveEntityWithCallbacksProps<M> & {
65
- collection: EntityCollection<M, USER>,
66
- dataSource: DataSource,
67
- context: FireCMSContext<USER>,
68
- }
44
+ collection,
45
+ path,
46
+ entityId,
47
+ values,
48
+ previousValues,
49
+ status,
50
+ dataSource,
51
+ context,
52
+ onSaveSuccess,
53
+ onSaveFailure,
54
+ onPreSaveHookError,
55
+ onSaveSuccessHookError
56
+ }: SaveEntityWithCallbacksProps<M> & {
57
+ collection: EntityCollection<M, USER>,
58
+ dataSource: DataSource,
59
+ context: FireCMSContext,
60
+ }
69
61
  ): Promise<void> {
70
62
 
71
63
  if (status !== "new" && !entityId) {
@@ -75,7 +67,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, USE
75
67
 
76
68
  const customizationController = context.customizationController;
77
69
 
78
- const resolvedPath = context.navigation.resolveAliasesFrom(path);
70
+ const resolvedPath = context.navigation.resolveIdsFrom(path);
79
71
 
80
72
  const callbacks = collection.callbacks;
81
73
  if (callbacks?.onPreSave) {
@@ -85,7 +77,8 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, USE
85
77
  path,
86
78
  values: previousValues as EntityValues<M>,
87
79
  entityId,
88
- propertyConfigs: customizationController.propertyConfigs
80
+ propertyConfigs: customizationController.propertyConfigs,
81
+ authController: context.authController
89
82
  });
90
83
  updatedValues = await callbacks.onPreSave({
91
84
  collection: resolvedCollection,
@@ -127,7 +120,8 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, USE
127
120
  path,
128
121
  values: updatedValues as EntityValues<M>,
129
122
  entityId,
130
- propertyConfigs: customizationController.propertyConfigs
123
+ propertyConfigs: customizationController.propertyConfigs,
124
+ authController: context.authController
131
125
  });
132
126
  callbacks.onSaveSuccess({
133
127
  collection: resolvedCollection,
@@ -156,7 +150,8 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, USE
156
150
  path,
157
151
  values: updatedValues as EntityValues<M>,
158
152
  entityId,
159
- propertyConfigs: customizationController.propertyConfigs
153
+ propertyConfigs: customizationController.propertyConfigs,
154
+ authController: context.authController
160
155
  });
161
156
  callbacks.onSaveFailure({
162
157
  collection: resolvedCollection,
@@ -73,7 +73,7 @@ export function useCollectionFetch<M extends Record<string, any>, USER extends U
73
73
  const dataSource = useDataSource(collection);
74
74
  const navigationController = useNavigationController();
75
75
 
76
- const path = navigationController.resolveAliasesFrom(inputPath);
76
+ const path = navigationController.resolveIdsFrom(inputPath);
77
77
 
78
78
  const sortByProperty = sortBy ? sortBy[0] : undefined;
79
79
  const currentSort = sortBy ? sortBy[1] : undefined;
@@ -10,6 +10,7 @@ import { useFireCMSContext } from "../useFireCMSContext";
10
10
  export interface EntityFetchProps<M extends Record<string, any>, USER extends User = User> {
11
11
  path: string;
12
12
  entityId?: string;
13
+ databaseId?: string;
13
14
  collection: EntityCollection<M, USER>;
14
15
  useCache?: boolean;
15
16
  }
@@ -40,13 +41,14 @@ export function useEntityFetch<M extends Record<string, any>, USER extends User>
40
41
  path: inputPath,
41
42
  entityId,
42
43
  collection,
44
+ databaseId,
43
45
  useCache = false
44
46
  }: EntityFetchProps<M, USER>): EntityFetchResult<M> {
45
47
 
46
48
  const dataSource = useDataSource(collection);
47
49
  const navigationController = useNavigationController();
48
50
 
49
- const path = navigationController.resolveAliasesFrom(inputPath);
51
+ const path = navigationController.resolveIdsFrom(inputPath);
50
52
 
51
53
  const context: FireCMSContext<USER> = useFireCMSContext();
52
54
 
@@ -96,6 +98,7 @@ export function useEntityFetch<M extends Record<string, any>, USER extends User>
96
98
  return dataSource.listenEntity<M>({
97
99
  path,
98
100
  entityId,
101
+ databaseId,
99
102
  collection,
100
103
  onUpdate: onEntityUpdate,
101
104
  onError
@@ -104,6 +107,7 @@ export function useEntityFetch<M extends Record<string, any>, USER extends User>
104
107
  dataSource.fetchEntity<M>({
105
108
  path,
106
109
  entityId,
110
+ databaseId,
107
111
  collection
108
112
  })
109
113
  .then(onEntityUpdate)
@@ -0,0 +1,31 @@
1
+ import { useContext } from "react";
2
+ import { BreadcrumbContext } from "../contexts/BreacrumbsContext";
3
+
4
+ /**
5
+ * @group Hooks and utilities
6
+ */
7
+ export interface BreadcrumbsController {
8
+ breadcrumbs: BreadcrumbEntry[];
9
+ set: (props: {
10
+ breadcrumbs: BreadcrumbEntry[];
11
+ }) => void;
12
+ }
13
+
14
+ /**
15
+ * @group Hooks and utilities
16
+ */
17
+ export interface BreadcrumbEntry {
18
+ title: string;
19
+ url: string;
20
+ }
21
+
22
+ /**
23
+ * Hook to retrieve the BreadcrumbsController.
24
+ *
25
+ * Consider that in order to use this hook you need to have a parent
26
+ * `FireCMS`
27
+ *
28
+ * @see BreadcrumbsController
29
+ * @group Hooks and utilities
30
+ */
31
+ export const useBreadcrumbsController = (): BreadcrumbsController => useContext(BreadcrumbContext);
@@ -16,7 +16,7 @@ export function useBuildModeController(): ModeController {
16
16
  }, []);
17
17
 
18
18
  const prefersDarkModeStorage: boolean | null = localStorage.getItem("prefers-dark-mode") != null ? localStorage.getItem("prefers-dark-mode") === "true" : null;
19
- const prefersDarkMode = prefersDarkModeStorage ?? prefersDarkModeQuery;
19
+ const prefersDarkMode = prefersDarkModeStorage ?? prefersDarkModeQuery();
20
20
  const [mode, setMode] = useState<"light" | "dark">(prefersDarkMode ? "dark" : "light");
21
21
 
22
22
  useEffect(() => {
@@ -24,43 +24,30 @@ export function useBuildModeController(): ModeController {
24
24
  setDocumentMode(prefersDarkMode ? "dark" : "light");
25
25
  }, [prefersDarkMode]);
26
26
 
27
- // color-scheme: dark;
28
- const setDarkMode = useCallback(() => {
29
- setMode("dark");
30
- setDocumentMode("dark");
31
- }, []);
32
-
33
- const setLightMode = useCallback(() => {
34
- setMode("light");
35
- setDocumentMode("light");
36
- }, []);
37
-
38
27
  const setDocumentMode = (mode: "light" | "dark") => {
39
28
  document.body.style.setProperty("color-scheme", mode);
40
29
  document.documentElement.dataset.theme = mode;
41
30
  };
42
31
 
43
- const toggleMode = useCallback(() => {
44
-
45
- const prefersDarkModeQueryResult = prefersDarkModeQuery();
32
+ const setModeInternal = useCallback((mode: "light" | "dark" | "system") => {
46
33
  if (mode === "light") {
47
- if (!prefersDarkModeQueryResult)
48
- localStorage.setItem("prefers-dark-mode", "true");
49
- else
50
- localStorage.removeItem("prefers-dark-mode");
51
- setDarkMode();
34
+ setDocumentMode("light");
35
+ localStorage.setItem("prefers-dark-mode", "false");
36
+ setMode("light");
37
+ } else if (mode === "dark") {
38
+ setDocumentMode("dark");
39
+ localStorage.setItem("prefers-dark-mode", "true");
40
+ setMode("dark");
52
41
  } else {
53
- if (prefersDarkModeQueryResult)
54
- localStorage.setItem("prefers-dark-mode", "false");
55
- else
56
- localStorage.removeItem("prefers-dark-mode");
57
- setLightMode();
42
+ const preferredMode = prefersDarkModeQuery() ? "dark" : "light";
43
+ setDocumentMode(preferredMode);
44
+ localStorage.removeItem("prefers-dark-mode");
45
+ setMode(preferredMode);
58
46
  }
59
- }, [mode, prefersDarkModeQuery]);
47
+ }, [prefersDarkModeQuery]);
60
48
 
61
49
  return {
62
50
  mode,
63
- setMode,
64
- toggleMode
51
+ setMode: setModeInternal
65
52
  };
66
53
  }