@firecms/core 3.1.0 → 3.2.0-canary.44dc65b

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 (191) hide show
  1. package/dist/components/EntityCollectionView/CollectionDataErrorBanner.d.ts +4 -0
  2. package/dist/components/ErrorBoundary.d.ts +3 -1
  3. package/dist/components/HomePage/DefaultHomePage.d.ts +0 -1
  4. package/dist/components/LanguageToggle.d.ts +1 -0
  5. package/dist/components/UnsavedChangesDialog.d.ts +1 -0
  6. package/dist/components/index.d.ts +1 -0
  7. package/dist/core/DrawerNavigationGroup.d.ts +2 -2
  8. package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
  9. package/dist/editor/components/editor-bubble-item.d.ts +8 -0
  10. package/dist/editor/components/editor-bubble.d.ts +8 -0
  11. package/dist/editor/components/image-bubble.d.ts +5 -0
  12. package/dist/editor/components/index.d.ts +16 -0
  13. package/dist/editor/components/table-bubble.d.ts +5 -0
  14. package/dist/editor/editor.d.ts +30 -0
  15. package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
  16. package/dist/editor/extensions/Image/index.d.ts +6 -0
  17. package/dist/editor/extensions/Image.d.ts +6 -0
  18. package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
  19. package/dist/editor/extensions/clipboard.d.ts +7 -0
  20. package/dist/editor/extensions/custom-keymap.d.ts +1 -0
  21. package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
  22. package/dist/editor/hooks/useProseMirror.d.ts +13 -0
  23. package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
  24. package/dist/editor/index.d.ts +2 -0
  25. package/dist/editor/markdown.d.ts +5 -0
  26. package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
  27. package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
  28. package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
  29. package/dist/editor/nodeViews/index.d.ts +6 -0
  30. package/dist/editor/plugins/index.d.ts +2 -0
  31. package/dist/editor/plugins/inputrules.d.ts +6 -0
  32. package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
  33. package/dist/editor/plugins/slashCommandPlugin.d.ts +12 -0
  34. package/dist/editor/schema.d.ts +2 -0
  35. package/dist/editor/selectors/ai-selector.d.ts +0 -0
  36. package/dist/editor/selectors/color-selector.d.ts +10 -0
  37. package/dist/editor/selectors/link-selector.d.ts +8 -0
  38. package/dist/editor/selectors/node-selector.d.ts +15 -0
  39. package/dist/editor/selectors/text-buttons.d.ts +1 -0
  40. package/dist/editor/types.d.ts +5 -0
  41. package/dist/editor/useProseMirror.d.ts +16 -0
  42. package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
  43. package/dist/editor/utils/remove_classes.d.ts +1 -0
  44. package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
  45. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  46. package/dist/hooks/index.d.ts +1 -0
  47. package/dist/hooks/useBuildNavigationController.d.ts +0 -1
  48. package/dist/hooks/useCollapsedGroups.d.ts +3 -3
  49. package/dist/hooks/useTranslation.d.ts +17 -0
  50. package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.es.js +12898 -2265
  53. package/dist/index.es.js.map +1 -1
  54. package/dist/index.umd.js +12877 -2264
  55. package/dist/index.umd.js.map +1 -1
  56. package/dist/locales/de.d.ts +2 -0
  57. package/dist/locales/en.d.ts +10 -0
  58. package/dist/locales/es.d.ts +10 -0
  59. package/dist/locales/fr.d.ts +2 -0
  60. package/dist/locales/hi.d.ts +2 -0
  61. package/dist/locales/it.d.ts +2 -0
  62. package/dist/locales/pt.d.ts +7 -0
  63. package/dist/types/customization_controller.d.ts +2 -1
  64. package/dist/types/firecms.d.ts +2 -1
  65. package/dist/types/index.d.ts +1 -0
  66. package/dist/types/navigation.d.ts +2 -2
  67. package/dist/types/plugins.d.ts +7 -0
  68. package/dist/types/storage.d.ts +1 -0
  69. package/dist/types/translations.d.ts +646 -0
  70. package/dist/util/useStorageUploadController.d.ts +10 -1
  71. package/package.json +45 -9
  72. package/src/app/Scaffold.tsx +7 -5
  73. package/src/components/AIIcon.tsx +3 -1
  74. package/src/components/ArrayContainer.tsx +6 -4
  75. package/src/components/ClearFilterSortButton.tsx +6 -3
  76. package/src/components/ConfirmationDialog.tsx +4 -2
  77. package/src/components/DeleteEntityDialog.tsx +10 -7
  78. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
  79. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -1
  80. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
  81. package/src/components/EntityCollectionView/BoardSortableList.tsx +3 -1
  82. package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
  83. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +16 -43
  84. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +17 -25
  85. package/src/components/EntityCollectionView/EntityCollectionView.tsx +26 -18
  86. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -3
  87. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +4 -2
  88. package/src/components/EntityCollectionView/FiltersDialog.tsx +8 -5
  89. package/src/components/EntityCollectionView/ViewModeToggle.tsx +11 -8
  90. package/src/components/EntityView.tsx +3 -2
  91. package/src/components/ErrorBoundary.tsx +27 -15
  92. package/src/components/HomePage/DefaultHomePage.tsx +19 -13
  93. package/src/components/HomePage/HomePageDnD.tsx +3 -1
  94. package/src/components/HomePage/NavigationGroup.tsx +3 -1
  95. package/src/components/HomePage/RenameGroupDialog.tsx +15 -13
  96. package/src/components/LanguageToggle.tsx +66 -0
  97. package/src/components/NotFoundPage.tsx +5 -3
  98. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +9 -7
  99. package/src/components/ReferenceWidget.tsx +3 -2
  100. package/src/components/SearchIconsView.tsx +3 -1
  101. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +11 -0
  102. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +15 -2
  103. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +11 -0
  104. package/src/components/UnsavedChangesDialog.tsx +6 -4
  105. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +1 -0
  106. package/src/components/VirtualTable/VirtualTableHeader.tsx +12 -10
  107. package/src/components/common/default_entity_actions.tsx +4 -0
  108. package/src/components/common/useDataSourceTableController.tsx +12 -4
  109. package/src/components/index.tsx +1 -0
  110. package/src/core/DefaultAppBar.tsx +14 -10
  111. package/src/core/DefaultDrawer.tsx +8 -2
  112. package/src/core/DrawerNavigationGroup.tsx +5 -3
  113. package/src/core/EntityEditView.tsx +4 -3
  114. package/src/core/EntityEditViewFormActions.tsx +24 -17
  115. package/src/core/EntitySidePanel.tsx +6 -5
  116. package/src/core/FireCMS.tsx +33 -6
  117. package/src/editor/components/SlashCommandMenu.tsx +516 -0
  118. package/src/editor/components/editor-bubble-item.tsx +32 -0
  119. package/src/editor/components/editor-bubble.tsx +118 -0
  120. package/src/editor/components/image-bubble.tsx +156 -0
  121. package/src/editor/components/index.ts +14 -0
  122. package/src/editor/components/table-bubble.tsx +165 -0
  123. package/src/editor/editor.tsx +455 -0
  124. package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
  125. package/src/editor/extensions/Image/index.ts +133 -0
  126. package/src/editor/extensions/Image.ts +159 -0
  127. package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
  128. package/src/editor/extensions/clipboard.ts +72 -0
  129. package/src/editor/extensions/custom-keymap.ts +24 -0
  130. package/src/editor/extensions/drag-and-drop.tsx +480 -0
  131. package/src/editor/hooks/useProseMirror.ts +124 -0
  132. package/src/editor/hooks/useProseMirrorContext.ts +15 -0
  133. package/src/editor/index.ts +2 -0
  134. package/src/editor/markdown.ts +172 -0
  135. package/src/editor/nodeViews/ImageComponent.tsx +20 -0
  136. package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
  137. package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
  138. package/src/editor/nodeViews/index.ts +35 -0
  139. package/src/editor/plugins/index.ts +58 -0
  140. package/src/editor/plugins/inputrules.ts +82 -0
  141. package/src/editor/plugins/placeholderPlugin.ts +55 -0
  142. package/src/editor/plugins/slashCommandPlugin.ts +61 -0
  143. package/src/editor/schema.ts +240 -0
  144. package/src/editor/selectors/ai-selector.tsx +111 -0
  145. package/src/editor/selectors/color-selector.tsx +200 -0
  146. package/src/editor/selectors/link-selector.tsx +118 -0
  147. package/src/editor/selectors/node-selector.tsx +157 -0
  148. package/src/editor/selectors/text-buttons.tsx +86 -0
  149. package/src/editor/types.ts +6 -0
  150. package/src/editor/useProseMirror.ts +126 -0
  151. package/src/editor/utils/prosemirror-utils.ts +108 -0
  152. package/src/editor/utils/remove_classes.ts +17 -0
  153. package/src/editor/utils/useDebouncedCallback.ts +25 -0
  154. package/src/form/EntityForm.tsx +16 -3
  155. package/src/form/EntityFormActions.tsx +19 -12
  156. package/src/form/PropertyFieldBinding.tsx +3 -2
  157. package/src/form/components/LocalChangesMenu.tsx +13 -13
  158. package/src/form/components/StorageItemPreview.tsx +3 -2
  159. package/src/form/components/StorageUploadProgress.tsx +18 -3
  160. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +4 -4
  161. package/src/form/field_bindings/BlockFieldBinding.tsx +5 -2
  162. package/src/form/field_bindings/KeyValueFieldBinding.tsx +23 -18
  163. package/src/form/field_bindings/MapFieldBinding.tsx +4 -3
  164. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +33 -19
  165. package/src/form/field_bindings/RepeatFieldBinding.tsx +3 -1
  166. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +4 -3
  167. package/src/hooks/index.tsx +1 -0
  168. package/src/hooks/useBuildNavigationController.tsx +45 -18
  169. package/src/hooks/useCollapsedGroups.ts +7 -6
  170. package/src/hooks/useTranslation.ts +31 -0
  171. package/src/i18n/FireCMSi18nProvider.tsx +160 -0
  172. package/src/index.ts +4 -0
  173. package/src/internal/useBuildSideEntityController.tsx +22 -20
  174. package/src/locales/de.ts +691 -0
  175. package/src/locales/en.ts +703 -0
  176. package/src/locales/es.ts +703 -0
  177. package/src/locales/fr.ts +691 -0
  178. package/src/locales/hi.ts +691 -0
  179. package/src/locales/it.ts +691 -0
  180. package/src/locales/pt.ts +700 -0
  181. package/src/preview/components/UrlComponentPreview.tsx +4 -2
  182. package/src/preview/components/UserPreview.tsx +3 -1
  183. package/src/types/customization_controller.tsx +2 -1
  184. package/src/types/firecms.tsx +2 -1
  185. package/src/types/index.ts +1 -0
  186. package/src/types/navigation.ts +2 -2
  187. package/src/types/plugins.tsx +8 -0
  188. package/src/types/properties.ts +1 -0
  189. package/src/types/storage.ts +2 -1
  190. package/src/types/translations.ts +725 -0
  191. package/src/util/useStorageUploadController.tsx +23 -29
@@ -17,7 +17,7 @@ import {
17
17
  import { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
18
18
 
19
19
  import { isHidden, isPropertyBuilder, isReadOnly, resolveProperty } from "../util";
20
- import { useAuthController, useCustomizationController } from "../hooks";
20
+ import { useAuthController, useCustomizationController, useTranslation } from "../hooks";
21
21
  import { Typography } from "@firecms/ui";
22
22
  import { getFieldConfig, getFieldId } from "../core";
23
23
  import { ErrorBoundary } from "../components";
@@ -213,6 +213,7 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
213
213
  formexFieldProps: FormexFieldProps<T, any>
214
214
  }) {
215
215
 
216
+ const { t } = useTranslation();
216
217
  const { plugins } = useCustomizationController();
217
218
 
218
219
  const customFieldProps: any = property.customProps;
@@ -291,7 +292,7 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
291
292
 
292
293
  {underlyingValueHasChanged && !isSubmitting &&
293
294
  <Typography variant={"caption"} className={"ml-3.5"}>
294
- This value has been updated elsewhere
295
+ {t("value_updated_elsewhere")}
295
296
  </Typography>}
296
297
 
297
298
  </ErrorBoundary>);
@@ -16,7 +16,7 @@ import {
16
16
  WarningIcon
17
17
  } from "@firecms/ui";
18
18
  import { FormexController } from "@firecms/formex";
19
- import { useSnackbarController } from "../../hooks";
19
+ import { useSnackbarController, useTranslation } from "../../hooks";
20
20
  import { mergeDeep } from "../../util";
21
21
  import { flattenKeys, removeEntityFromCache } from "../../util/entity_cache";
22
22
  import { ResolvedProperties } from "../../types";
@@ -39,6 +39,7 @@ export function LocalChangesMenu<M extends object>({
39
39
  }: LocalChangesMenuProps<M>) {
40
40
 
41
41
  const snackbarController = useSnackbarController();
42
+ const { t } = useTranslation();
42
43
  const [previewDialogOpen, setPreviewDialogOpen] = useState(false);
43
44
  const [open, setOpen] = useState(false);
44
45
 
@@ -62,7 +63,7 @@ export function LocalChangesMenu<M extends object>({
62
63
  formex.setValues(mergedValues);
63
64
  snackbarController.open({
64
65
  type: "info",
65
- message: "Local changes applied to the form"
66
+ message: t("local_changes_applied")
66
67
  });
67
68
  handleCloseMenu();
68
69
  onClearLocalChanges?.();
@@ -72,7 +73,7 @@ export function LocalChangesMenu<M extends object>({
72
73
  removeEntityFromCache(cacheKey);
73
74
  snackbarController.open({
74
75
  type: "info",
75
- message: "Local changes discarded"
76
+ message: t("local_changes_discarded")
76
77
  });
77
78
  handleCloseMenu();
78
79
  onClearLocalChanges?.();
@@ -90,7 +91,7 @@ export function LocalChangesMenu<M extends object>({
90
91
  onClick={handleOpenMenu}
91
92
  >
92
93
  <WarningIcon size={"smallest"} className={"mr-1 text-yellow-600 dark:text-yellow-400"}/>
93
- Unsaved Local changes
94
+ {t("unsaved_local_changes")}
94
95
  <KeyboardArrowDownIcon size={"smallest"}/>
95
96
  </Button>
96
97
  }
@@ -98,12 +99,11 @@ export function LocalChangesMenu<M extends object>({
98
99
  onOpenChange={setOpen}
99
100
  >
100
101
  <div className={"max-w-xs px-4 py-4 text-sm text-gray-700 dark:text-gray-300"}>
101
- This document was edited locally and has unsaved changes. These local changes will be lost if you
102
- don't apply them.
102
+ {t("unsaved_local_changes_description")}
103
103
  </div>
104
- <MenuItem dense onClick={handlePreview}><VisibilityIcon size={"small"}/>Preview Changes</MenuItem>
105
- <MenuItem dense onClick={handleApply}><CheckIcon size={"small"}/>Apply Changes</MenuItem>
106
- <MenuItem dense onClick={handleDiscard}><CancelIcon size={"small"}/>Discard Local Changes</MenuItem>
104
+ <MenuItem dense onClick={handlePreview}><VisibilityIcon size={"small"}/>{t("preview_changes")}</MenuItem>
105
+ <MenuItem dense onClick={handleApply}><CheckIcon size={"small"}/>{t("apply_changes")}</MenuItem>
106
+ <MenuItem dense onClick={handleDiscard}><CancelIcon size={"small"}/>{t("discard_local_changes")}</MenuItem>
107
107
  </Menu>
108
108
 
109
109
  <Dialog
@@ -111,10 +111,10 @@ export function LocalChangesMenu<M extends object>({
111
111
  onOpenChange={setPreviewDialogOpen}
112
112
  maxWidth={"4xl"}
113
113
  >
114
- <DialogTitle variant={"h6"}>Preview Local Changes</DialogTitle>
114
+ <DialogTitle variant={"h6"}>{t("preview_local_changes")}</DialogTitle>
115
115
  <DialogContent className={"my-4"}>
116
116
  <Typography variant={"body2"} className={"mb-4"}>
117
- These are the local changes that will be applied to the form.
117
+ {t("preview_local_changes_description")}
118
118
  </Typography>
119
119
  <div className={`border rounded-lg ${defaultBorderMixin}`} style={{
120
120
  maxHeight: 520,
@@ -127,7 +127,7 @@ export function LocalChangesMenu<M extends object>({
127
127
  </div>
128
128
  </DialogContent>
129
129
  <DialogActions>
130
- <Button onClick={() => setPreviewDialogOpen(false)}>Close</Button>
130
+ <Button onClick={() => setPreviewDialogOpen(false)}>{t("close")}</Button>
131
131
  <Button
132
132
  variant={"filled"}
133
133
  onClick={() => {
@@ -135,7 +135,7 @@ export function LocalChangesMenu<M extends object>({
135
135
  setPreviewDialogOpen(false);
136
136
  }}
137
137
  >
138
- Apply changes
138
+ {t("apply_changes")}
139
139
  </Button>
140
140
  </DialogActions>
141
141
  </Dialog>
@@ -5,6 +5,7 @@ import { PreviewSize, PropertyPreview } from "../../preview";
5
5
 
6
6
  import { cls, DescriptionIcon, IconButton, paperMixin, RemoveIcon, Tooltip } from "@firecms/ui";
7
7
  import { ErrorBoundary } from "../../components";
8
+ import { useTranslation } from "../../hooks/useTranslation";
8
9
 
9
10
  interface StorageItemPreviewProps {
10
11
  name: string;
@@ -27,7 +28,7 @@ export function StorageItemPreview({
27
28
  placeholder,
28
29
  className
29
30
  }: StorageItemPreviewProps) {
30
-
31
+ const { t } = useTranslation();
31
32
  return (
32
33
  <div className={cls(
33
34
  "relative border-box flex items-center justify-center",
@@ -41,7 +42,7 @@ export function StorageItemPreview({
41
42
 
42
43
  <Tooltip
43
44
  asChild={true}
44
- title="Remove">
45
+ title={t("remove")}>
45
46
  <IconButton
46
47
  size={"small"}
47
48
  onClick={(event) => {
@@ -32,6 +32,7 @@ export function StorageUploadProgress({
32
32
 
33
33
  const [error, setError] = React.useState<Error | undefined>();
34
34
  const [loading, setLoading] = React.useState<boolean>(false);
35
+ const [progress, setProgress] = React.useState<number>(0);
35
36
  const mounted = React.useRef(false);
36
37
  const uploading = React.useRef(false);
37
38
 
@@ -46,7 +47,10 @@ export function StorageUploadProgress({
46
47
  file,
47
48
  fileName,
48
49
  path: storagePath,
49
- metadata
50
+ metadata,
51
+ onProgress: (p) => {
52
+ if (mounted.current) setProgress(p);
53
+ }
50
54
  })
51
55
  .then(async ({ path, storageUrl }) => {
52
56
  console.debug("Upload successful", path);
@@ -79,22 +83,33 @@ export function StorageUploadProgress({
79
83
  };
80
84
  }, [entry.file, entry.fileName, upload]);
81
85
 
86
+ const isLargeFile = entry.file && entry.file.size > 500 * 1024;
87
+ const renderProgressBar = loading && isLargeFile && progress > 0;
88
+ const progressBar = renderProgressBar && (
89
+ <div className="absolute bottom-0 left-0 h-1 bg-primary w-full origin-left transition-transform duration-200"
90
+ style={{ transform: `scaleX(${progress / 100})` }} />
91
+ );
92
+
82
93
  if (simple) {
83
- return <div className={`w-${imageSize} h-${imageSize}`}>
94
+ return <div className={`relative overflow-hidden w-${imageSize} h-${imageSize}`}>
84
95
 
85
96
  {loading && <Skeleton className={`w-${imageSize} h-${imageSize}`}/>}
86
97
 
98
+ {progressBar}
99
+
87
100
  </div>
88
101
  }
89
102
  return (
90
103
 
91
104
  <div className={cls(paperMixin,
92
- "p-4 relative border-box flex items-center justify-center",
105
+ "p-4 relative overflow-hidden border-box flex items-center justify-center",
93
106
  `min-w-[${imageSize}px] min-h-[${imageSize}px]`)}>
94
107
 
95
108
  {loading &&
96
109
  <Skeleton className="w-full h-full"/>}
97
110
 
111
+ {progressBar}
112
+
98
113
  {error && <ErrorView title={"Error uploading file"}
99
114
  error={error}/>}
100
115
 
@@ -4,8 +4,7 @@ import { ReferencePreview } from "../../preview";
4
4
  import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
5
5
  import { ArrayContainer, ArrayEntryParams, ErrorView } from "../../components";
6
6
  import { getIconForProperty, getReferenceFrom } from "../../util";
7
-
8
- import { useNavigationController, useReferenceDialog } from "../../hooks";
7
+ import { useNavigationController, useReferenceDialog, useTranslation } from "../../hooks";
9
8
  import { Button, cls, EditIcon, ExpandablePanel, fieldBackgroundMixin, Typography } from "@firecms/ui";
10
9
  import { useClearRestoreValue } from "../useClearRestoreValue";
11
10
 
@@ -48,6 +47,7 @@ export function ArrayOfReferencesFieldBinding({
48
47
  setValue
49
48
  });
50
49
 
50
+ const { t } = useTranslation();
51
51
  const navigationController = useNavigationController();
52
52
  const collection: EntityCollection | undefined = useMemo(() => {
53
53
  return ofProperty.path ? navigationController.getCollection(ofProperty.path) : undefined;
@@ -84,7 +84,7 @@ export function ArrayOfReferencesFieldBinding({
84
84
  }: ArrayEntryParams) => {
85
85
  const entryValue = value && value.length > index ? value[index] : undefined;
86
86
  if (!entryValue)
87
- return <div>Internal ERROR</div>;
87
+ return <div>{t("internal_error")}</div>;
88
88
  return (
89
89
  <ReferencePreview
90
90
  key={internalId}
@@ -132,7 +132,7 @@ export function ArrayOfReferencesFieldBinding({
132
132
  disabled={isSubmitting}
133
133
  onClick={onEntryClick}>
134
134
  <EditIcon size={"small"}/>
135
- Edit {property.name}
135
+ {t("edit_name", { name: property.name ?? "" })}
136
136
  </Button>
137
137
  </div>}
138
138
  </>;
@@ -11,6 +11,7 @@ import { DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE } from "../../util/common";
11
11
  import { cls, ExpandablePanel, paperMixin, Select, SelectItem, Typography } from "@firecms/ui";
12
12
  import { useClearRestoreValue } from "../useClearRestoreValue";
13
13
  import { ArrayContainer, ArrayEntryParams } from "../../components";
14
+ import { useTranslation } from "../../hooks/useTranslation";
14
15
 
15
16
  /**
16
17
  * If the `oneOf` property is specified, this fields render each array entry as
@@ -37,6 +38,7 @@ export function BlockFieldBinding<T extends Array<any>>({
37
38
  }: FieldProps<T>) {
38
39
 
39
40
  const minimalistView = minimalistViewProp || property.minimalistView;
41
+ const { t } = useTranslation();
40
42
 
41
43
  if (!property.oneOf)
42
44
  throw Error("ArrayOneOfField misconfiguration. Property `oneOf` not set");
@@ -84,7 +86,7 @@ export function BlockFieldBinding<T extends Array<any>>({
84
86
  const body = <ArrayContainer value={value}
85
87
  className={"flex flex-col gap-3"}
86
88
  droppableId={propertyKey}
87
- addLabel={property.name ? "Add entry to " + property.name : "Add entry"}
89
+ addLabel={property.name ? t("add_to_field", { fieldName: property.name }) : t("add_entry")}
88
90
  buildEntry={buildEntry}
89
91
  onInternalIdAdded={setLastAddedId}
90
92
  disabled={isSubmitting || Boolean(property.disabled)}
@@ -167,6 +169,7 @@ function BlockEntry({
167
169
  const [typeInternal, setTypeInternal] = useState<string | undefined>(type ?? undefined);
168
170
 
169
171
  const formex = useFormex();
172
+ const { t } = useTranslation();
170
173
 
171
174
  useEffect(() => {
172
175
  if (!type) {
@@ -227,7 +230,7 @@ function BlockEntry({
227
230
  <Select
228
231
  className="mb-2"
229
232
  placeholder={<Typography variant={"caption"}
230
- className={"px-4 py-2 font-medium"}>Type</Typography>}
233
+ className={"px-4 py-2 font-medium"}>{t("type")}</Typography>}
231
234
  size={"medium"}
232
235
  fullWidth={true}
233
236
  position={"item-aligned"}
@@ -22,6 +22,7 @@ import {
22
22
  import { getDefaultValueForDataType, getIconForProperty } from "../../util";
23
23
  import { useCustomizationController } from "../../hooks";
24
24
  import { getIn } from "@firecms/formex";
25
+ import { useTranslation } from "../../hooks/useTranslation";
25
26
 
26
27
  type MapEditViewRowState = [number, {
27
28
  key: string,
@@ -54,6 +55,7 @@ export function KeyValueFieldBinding({
54
55
  throw Error(`Your property ${propertyKey} needs to have the 'keyValue' prop in order to use this field binding`);
55
56
  }
56
57
 
58
+ const { t } = useTranslation();
57
59
  const initialValues = getIn(context.formex.initialValues, propertyKey);
58
60
 
59
61
  const mapFormView = <MapEditView value={value}
@@ -103,6 +105,7 @@ function MapEditView<T extends Record<string, any>>({
103
105
  fieldName,
104
106
  disabled
105
107
  }: MapEditViewParams<T>) {
108
+ const { t } = useTranslation();
106
109
  const [internalState, setInternalState] = React.useState<MapEditViewRowState[]>(
107
110
  Object.keys(initialValue ?? {}).map((key) => [getRandomId(), {
108
111
  key,
@@ -230,7 +233,7 @@ function MapEditView<T extends Record<string, any>>({
230
233
  }]]);
231
234
  }
232
235
  }>
233
- {fieldName ? `Add to ${fieldName}` : "Add"}
236
+ {fieldName ? t("add_to_field", { fieldName }) : t("add_entry")}
234
237
  </Button>
235
238
 
236
239
  </div>;
@@ -261,12 +264,13 @@ function MapKeyValueRow<T extends Record<string, any>>({
261
264
  }) {
262
265
 
263
266
  const { locale } = useCustomizationController();
267
+ const { t } = useTranslation();
264
268
 
265
269
  function buildInput(entryValue: any, fieldKey: string, dataType: DataType) {
266
270
  if (dataType === "string" || dataType === "number") {
267
271
  return <TextField
268
272
  key={dataType}
269
- placeholder={"value"}
273
+ placeholder={t("value")}
270
274
  value={entryValue}
271
275
  type={dataType === "number" ? "number" : "text"}
272
276
  size={"medium"}
@@ -325,7 +329,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
325
329
  <ArrayContainer value={entryValue}
326
330
  newDefaultEntry={""}
327
331
  droppableId={rowId.toString()}
328
- addLabel={fieldKey ? `Add to ${fieldKey}` : "Add"}
332
+ addLabel={fieldKey ? t("add_to_field", { fieldName: fieldKey }) : t("add_entry")}
329
333
  size={"small"}
330
334
  disabled={disabled || !fieldKey}
331
335
  canAddElements={true}
@@ -370,7 +374,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
370
374
  } else {
371
375
  return <Typography
372
376
  variant={"caption"}>
373
- {`Data type ${dataType} not supported yet`}
377
+ {t("data_type_not_supported", { dataType })}
374
378
  </Typography>;
375
379
  }
376
380
  }
@@ -386,7 +390,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
386
390
  <div className="w-[300px] max-w-[30%]">
387
391
  <TextField
388
392
  value={fieldKey}
389
- placeholder={"key"}
393
+ placeholder={t("key")}
390
394
  disabled={disabled || (entryValue !== undefined && entryValue !== null && entryValue !== "")}
391
395
  size={"medium"}
392
396
  onChange={(event) => {
@@ -404,17 +408,17 @@ function MapKeyValueRow<T extends Record<string, any>>({
404
408
  </IconButton>}
405
409
  >
406
410
  <MenuItem dense
407
- onClick={() => doUpdateDataType("string")}>string</MenuItem>
411
+ onClick={() => doUpdateDataType("string")}>{t("string")}</MenuItem>
408
412
  <MenuItem dense
409
- onClick={() => doUpdateDataType("number")}>number</MenuItem>
413
+ onClick={() => doUpdateDataType("number")}>{t("number")}</MenuItem>
410
414
  <MenuItem dense
411
- onClick={() => doUpdateDataType("boolean")}>boolean</MenuItem>
415
+ onClick={() => doUpdateDataType("boolean")}>{t("boolean")}</MenuItem>
412
416
  <MenuItem dense
413
- onClick={() => doUpdateDataType("date")}>date</MenuItem>
417
+ onClick={() => doUpdateDataType("date")}>{t("date")}</MenuItem>
414
418
  <MenuItem dense
415
- onClick={() => doUpdateDataType("map")}>map</MenuItem>
419
+ onClick={() => doUpdateDataType("map")}>{t("map")}</MenuItem>
416
420
  <MenuItem dense
417
- onClick={() => doUpdateDataType("array")}>array</MenuItem>
421
+ onClick={() => doUpdateDataType("array")}>{t("array")}</MenuItem>
418
422
  </Menu>
419
423
 
420
424
  <IconButton aria-label="delete"
@@ -446,6 +450,7 @@ function ArrayKeyValueRow<T>({
446
450
  }) {
447
451
 
448
452
  const { locale } = useCustomizationController();
453
+ const { t } = useTranslation();
449
454
  const [selectedDataType, setSelectedDataType] = useState<DataType>(getDataType(value) ?? "string");
450
455
 
451
456
  function doUpdateDataType(dataType: DataType) {
@@ -487,7 +492,7 @@ function ArrayKeyValueRow<T>({
487
492
  }}/>;
488
493
  } else if (dataType === "array") {
489
494
  return <Typography variant={"caption"}>
490
- Arrays of arrays are not supported.
495
+ {t("arrays_of_arrays_not_supported")}
491
496
  </Typography>;
492
497
  } else if (dataType === "map") {
493
498
  return <div className={cls(defaultBorderMixin, "ml-2 pl-2 border-l border-solid")}>
@@ -499,7 +504,7 @@ function ArrayKeyValueRow<T>({
499
504
  } else {
500
505
  return <Typography
501
506
  variant={"caption"}>
502
- {`Data type ${dataType} not supported yet`}
507
+ {t("data_type_not_supported", { dataType })}
503
508
  </Typography>;
504
509
  }
505
510
  }
@@ -519,15 +524,15 @@ function ArrayKeyValueRow<T>({
519
524
  <ArrowDropDownIcon/>
520
525
  </IconButton>}>
521
526
  <MenuItem dense
522
- onClick={() => doUpdateDataType("string")}>string</MenuItem>
527
+ onClick={() => doUpdateDataType("string")}>{t("string")}</MenuItem>
523
528
  <MenuItem dense
524
- onClick={() => doUpdateDataType("number")}>number</MenuItem>
529
+ onClick={() => doUpdateDataType("number")}>{t("number")}</MenuItem>
525
530
  <MenuItem dense
526
- onClick={() => doUpdateDataType("boolean")}>boolean</MenuItem>
531
+ onClick={() => doUpdateDataType("boolean")}>{t("boolean")}</MenuItem>
527
532
  <MenuItem dense
528
- onClick={() => doUpdateDataType("map")}>map</MenuItem>
533
+ onClick={() => doUpdateDataType("map")}>{t("map")}</MenuItem>
529
534
  <MenuItem dense
530
- onClick={() => doUpdateDataType("date")}>date</MenuItem>
535
+ onClick={() => doUpdateDataType("date")}>{t("date")}</MenuItem>
531
536
  </Menu>
532
537
 
533
538
  </Typography>
@@ -7,6 +7,7 @@ import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
7
7
  import { FormEntry } from "../components/FormEntry";
8
8
  import { PropertyFieldBinding } from "../PropertyFieldBinding";
9
9
  import { cls, ExpandablePanel, InputLabel, Select, SelectItem } from "@firecms/ui";
10
+ import { useTranslation } from "../../hooks";
10
11
 
11
12
  /**
12
13
  * Field that renders the children property fields
@@ -91,7 +92,7 @@ export function MapFieldBinding({
91
92
  }
92
93
  </div>
93
94
 
94
- {/*{pickOnlySomeKeys && buildPickKeysSelect(disabled, property.properties, setValue, value)}*/}
95
+ {/*{pickOnlySomeKeys && buildPickKeysSelect(disabled, property.properties, setValue, value, t)}*/}
95
96
 
96
97
  </>
97
98
  ;
@@ -128,7 +129,7 @@ export function MapFieldBinding({
128
129
  );
129
130
  }
130
131
 
131
- const buildPickKeysSelect = (disabled: boolean, properties: Properties, setValue: (value: any) => void, value: any) => {
132
+ const buildPickKeysSelect = (disabled: boolean, properties: Properties, setValue: (value: any) => void, value: any, t: any) => {
132
133
 
133
134
  const keys = Object.keys(properties)
134
135
  .filter((key) => !value || !(key in value));
@@ -143,7 +144,7 @@ const buildPickKeysSelect = (disabled: boolean, properties: Properties, setValue
143
144
  if (!keys.length) return <></>;
144
145
 
145
146
  return <div className={"m-4"}>
146
- <InputLabel>Add property</InputLabel>
147
+ <InputLabel>{t("add_property")}</InputLabel>
147
148
  <Select
148
149
  value={""}
149
150
  size={"large"}
@@ -12,8 +12,9 @@ import {
12
12
  useStorageSource
13
13
  } from "../../index";
14
14
  import { cls, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundMixin } from "@firecms/ui";
15
- import { FireCMSEditor, FireCMSEditorProps } from "@firecms/editor";
15
+ import { FireCMSEditor, FireCMSEditorProps } from "../../editor";
16
16
  import { resolveProperty, resolveStorageFilenameString, resolveStoragePathString } from "../../util";
17
+ import { isImageFile, resizeImage } from "../../util/useStorageUploadController";
17
18
 
18
19
  interface MarkdownEditorFieldProps {
19
20
  highlight?: { from: number, to: number };
@@ -55,12 +56,12 @@ export function MarkdownEditorFieldBinding({
55
56
  }
56
57
  internalValue.current = content;
57
58
  setValue(content);
58
- }, [setValue]);
59
+ }, [setValue, value]);
59
60
 
60
61
  useEffect(() => {
61
62
  if (internalValue.current !== value) {
62
63
  internalValue.current = value;
63
- setFieldVersion(fieldVersion + 1);
64
+ setFieldVersion(v => v + 1);
64
65
  }
65
66
  }, [value]);
66
67
 
@@ -112,33 +113,46 @@ export function MarkdownEditorFieldBinding({
112
113
  // Extract markdown config from property - can be boolean or object
113
114
  const markdownConfig = typeof property.markdown === 'object' ? property.markdown : undefined;
114
115
 
116
+ const handleImageUpload = async (file: File) => {
117
+ const imageResize = storage?.imageResize;
118
+ const legacyCompression = storage?.imageCompression;
119
+ if ((imageResize || legacyCompression) && isImageFile(file)) {
120
+ file = await resizeImage(file, imageResize, legacyCompression);
121
+ }
122
+
123
+ const storagePath = storagePathBuilder(file);
124
+ const fileName = await fileNameBuilder(file);
125
+ const result = await storageSource.uploadFile({
126
+ file,
127
+ fileName,
128
+ path: storagePath,
129
+ });
130
+ const downloadConfig = await storageSource.getDownloadURL(result.path);
131
+ const url = downloadConfig.url;
132
+ if (!url) {
133
+ throw new Error("Error uploading image");
134
+ }
135
+ return url;
136
+ };
137
+
115
138
  const editor = <FireCMSEditor
139
+ key={context.formex.version + fieldVersion}
116
140
  content={value}
117
141
  onMarkdownContentChange={onContentChange}
118
142
  version={context.formex.version + fieldVersion}
119
143
  highlight={highlight}
120
144
  disabled={disabled}
121
145
  markdownConfig={markdownConfig}
122
- handleImageUpload={async (file: File) => {
123
- const storagePath = storagePathBuilder(file);
124
- const fileName = await fileNameBuilder(file);
125
- const result = await storageSource.uploadFile({
126
- file,
127
- fileName,
128
- path: storagePath,
129
- });
130
- const downloadConfig = await storageSource.getDownloadURL(result.path);
131
- const url = downloadConfig.url;
132
- if (!url) {
133
- throw new Error("Error uploading image");
134
- }
135
- return url;
136
- }}
146
+ handleImageUpload={handleImageUpload}
137
147
  {...editorProps}
138
148
  />;
139
149
 
140
150
  if (minimalistView)
141
- return editor;
151
+ return (
152
+ <>
153
+ {editor}
154
+ </>
155
+ );
142
156
 
143
157
  return (
144
158
  <>
@@ -7,6 +7,7 @@ import { PropertyFieldBinding } from "../PropertyFieldBinding";
7
7
  import { ExpandablePanel, Typography } from "@firecms/ui";
8
8
  import { useClearRestoreValue } from "../useClearRestoreValue";
9
9
  import { useAuthController } from "../../hooks";
10
+ import { useTranslation } from "../../hooks/useTranslation";
10
11
 
11
12
  /**
12
13
  * Generic array field that allows reordering and renders the child property
@@ -34,6 +35,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
34
35
 
35
36
  const authController = useAuthController();
36
37
  const minimalistView = minimalistViewProp || property.minimalistView;
38
+ const { t } = useTranslation();
37
39
 
38
40
  if (!property.of)
39
41
  throw Error("RepeatFieldBinding misconfiguration. Property `of` not set");
@@ -87,7 +89,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
87
89
  const canAddElements = !property.disabled && !isSubmitting && !disabled && (property.canAddElements || property.canAddElements === undefined);
88
90
  const sortable = property.sortable === undefined ? true : property.sortable;
89
91
  const arrayContainer = <ArrayContainer droppableId={propertyKey}
90
- addLabel={property.name ? "Add entry to " + property.name : "Add entry"}
92
+ addLabel={property.name ? t("add_to_field", { fieldName: property.name }) : t("add_entry")}
91
93
  value={value}
92
94
  buildEntry={buildEntry}
93
95
  onInternalIdAdded={setLastAddedId}
@@ -41,6 +41,7 @@ import {
41
41
  Typography
42
42
  } from "@firecms/ui";
43
43
  import { useClearRestoreValue } from "../useClearRestoreValue";
44
+ import { useTranslation } from "../../hooks/useTranslation";
44
45
 
45
46
  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";
46
47
  const disabledClasses = fieldBackgroundDisabledMixin;
@@ -135,7 +136,6 @@ export function StorageUploadFieldBinding({
135
136
  error={error}
136
137
  disabled={disabled}
137
138
  property={property} />
138
-
139
139
  </>
140
140
  );
141
141
  }
@@ -387,6 +387,7 @@ export function StorageUpload({
387
387
  storage,
388
388
  storagePathBuilder,
389
389
  }: StorageUploadProps) {
390
+ const { t } = useTranslation();
390
391
 
391
392
  if (multipleFilesSupported) {
392
393
  const arrayProperty = property as ResolvedArrayProperty<string[]>;
@@ -461,8 +462,8 @@ export function StorageUpload({
461
462
  }, [value, multipleFilesSupported, onChange, setInternalValue]);
462
463
 
463
464
  const helpText = multipleFilesSupported
464
- ? "Drag 'n' drop some files here, or click to select files. Drag to reorder."
465
- : "Drag 'n' drop a file here, or click to select one";
465
+ ? t("drag_drop_multiple")
466
+ : t("drag_drop_single");
466
467
 
467
468
  const renderProperty: ResolvedStringProperty = multipleFilesSupported
468
469
  ? (property as ResolvedArrayProperty<string[]>).of as ResolvedStringProperty
@@ -31,3 +31,4 @@ export * from "./useBuildLocalConfigurationPersistence";
31
31
  export * from "./useBuildModeController";
32
32
 
33
33
  export * from "./useValidateAuthenticator";
34
+ export * from "./useTranslation";