@firecms/core 3.1.0-canary.1df3b2c → 3.1.0-canary.501d471

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 (246) hide show
  1. package/dist/components/EntityCollectionTable/internal/popup_field/useDraggable.d.ts +2 -2
  2. package/dist/components/EntityCollectionView/CollectionDataErrorBanner.d.ts +4 -0
  3. package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +5 -10
  4. package/dist/components/ErrorBoundary.d.ts +4 -2
  5. package/dist/components/HomePage/DefaultHomePage.d.ts +0 -1
  6. package/dist/components/LanguageToggle.d.ts +1 -0
  7. package/dist/components/UnsavedChangesDialog.d.ts +1 -0
  8. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +2 -1
  9. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  10. package/dist/components/VirtualTable/VirtualTableProps.d.ts +6 -1
  11. package/dist/components/VirtualTable/types.d.ts +1 -0
  12. package/dist/components/index.d.ts +1 -0
  13. package/dist/core/DrawerNavigationGroup.d.ts +2 -2
  14. package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
  15. package/dist/editor/components/editor-bubble-item.d.ts +8 -0
  16. package/dist/editor/components/editor-bubble.d.ts +8 -0
  17. package/dist/editor/components/image-bubble.d.ts +5 -0
  18. package/dist/editor/components/index.d.ts +16 -0
  19. package/dist/editor/components/table-bubble.d.ts +5 -0
  20. package/dist/editor/editor.d.ts +30 -0
  21. package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
  22. package/dist/editor/extensions/Image/index.d.ts +6 -0
  23. package/dist/editor/extensions/Image.d.ts +6 -0
  24. package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
  25. package/dist/editor/extensions/clipboard.d.ts +7 -0
  26. package/dist/editor/extensions/custom-keymap.d.ts +1 -0
  27. package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
  28. package/dist/editor/hooks/useProseMirror.d.ts +13 -0
  29. package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
  30. package/dist/editor/index.d.ts +2 -0
  31. package/dist/editor/markdown.d.ts +5 -0
  32. package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
  33. package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
  34. package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
  35. package/dist/editor/nodeViews/index.d.ts +6 -0
  36. package/dist/editor/plugins/index.d.ts +2 -0
  37. package/dist/editor/plugins/inputrules.d.ts +6 -0
  38. package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
  39. package/dist/editor/plugins/slashCommandPlugin.d.ts +12 -0
  40. package/dist/editor/schema.d.ts +2 -0
  41. package/dist/editor/selectors/ai-selector.d.ts +0 -0
  42. package/dist/editor/selectors/color-selector.d.ts +10 -0
  43. package/dist/editor/selectors/link-selector.d.ts +8 -0
  44. package/dist/editor/selectors/node-selector.d.ts +15 -0
  45. package/dist/editor/selectors/text-buttons.d.ts +1 -0
  46. package/dist/editor/types.d.ts +5 -0
  47. package/dist/editor/useProseMirror.d.ts +16 -0
  48. package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
  49. package/dist/editor/utils/remove_classes.d.ts +1 -0
  50. package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
  51. package/dist/form/components/ErrorFocus.d.ts +1 -1
  52. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  53. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  54. package/dist/hooks/index.d.ts +1 -0
  55. package/dist/hooks/useBuildNavigationController.d.ts +0 -1
  56. package/dist/hooks/useCollapsedGroups.d.ts +3 -3
  57. package/dist/hooks/useTranslation.d.ts +17 -0
  58. package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
  59. package/dist/index.d.ts +5 -0
  60. package/dist/index.es.js +29682 -18363
  61. package/dist/index.es.js.map +1 -1
  62. package/dist/index.umd.js +29681 -18382
  63. package/dist/index.umd.js.map +1 -1
  64. package/dist/internal/useRestoreScroll.d.ts +1 -1
  65. package/dist/locales/de.d.ts +2 -0
  66. package/dist/locales/en.d.ts +10 -0
  67. package/dist/locales/es.d.ts +10 -0
  68. package/dist/locales/fr.d.ts +2 -0
  69. package/dist/locales/hi.d.ts +2 -0
  70. package/dist/locales/it.d.ts +2 -0
  71. package/dist/locales/pt.d.ts +7 -0
  72. package/dist/types/analytics.d.ts +1 -1
  73. package/dist/types/collections.d.ts +46 -0
  74. package/dist/types/customization_controller.d.ts +2 -1
  75. package/dist/types/firecms.d.ts +2 -1
  76. package/dist/types/index.d.ts +1 -0
  77. package/dist/types/navigation.d.ts +2 -2
  78. package/dist/types/plugins.d.ts +23 -0
  79. package/dist/types/properties.d.ts +9 -8
  80. package/dist/types/storage.d.ts +1 -0
  81. package/dist/types/translations.d.ts +669 -0
  82. package/dist/util/entities.d.ts +1 -1
  83. package/dist/util/index.d.ts +1 -0
  84. package/dist/util/lazy_eager.d.ts +7 -0
  85. package/dist/util/objects.d.ts +1 -0
  86. package/dist/util/resolutions.d.ts +2 -2
  87. package/dist/util/useStorageUploadController.d.ts +10 -1
  88. package/package.json +49 -13
  89. package/src/app/Scaffold.tsx +7 -5
  90. package/src/components/AIIcon.tsx +3 -1
  91. package/src/components/ArrayContainer.tsx +6 -4
  92. package/src/components/ClearFilterSortButton.tsx +6 -3
  93. package/src/components/ConfirmationDialog.tsx +4 -2
  94. package/src/components/DeleteEntityDialog.tsx +10 -7
  95. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +9 -3
  96. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
  97. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -1
  98. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
  99. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
  100. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
  101. package/src/components/EntityCollectionView/BoardSortableList.tsx +3 -1
  102. package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
  103. package/src/components/EntityCollectionView/EntityBoardCard.tsx +1 -1
  104. package/src/components/EntityCollectionView/EntityCard.tsx +4 -0
  105. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +39 -46
  106. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +17 -25
  107. package/src/components/EntityCollectionView/EntityCollectionView.tsx +71 -31
  108. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -3
  109. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +4 -2
  110. package/src/components/EntityCollectionView/FiltersDialog.tsx +8 -5
  111. package/src/components/EntityCollectionView/ViewModeToggle.tsx +37 -37
  112. package/src/components/EntityJsonPreview.tsx +2 -1
  113. package/src/components/EntityView.tsx +3 -2
  114. package/src/components/ErrorBoundary.tsx +27 -15
  115. package/src/components/HomePage/DefaultHomePage.tsx +19 -13
  116. package/src/components/HomePage/HomePageDnD.tsx +3 -1
  117. package/src/components/HomePage/NavigationGroup.tsx +3 -1
  118. package/src/components/HomePage/RenameGroupDialog.tsx +15 -13
  119. package/src/components/LanguageToggle.tsx +66 -0
  120. package/src/components/NotFoundPage.tsx +5 -3
  121. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +9 -7
  122. package/src/components/ReferenceWidget.tsx +3 -2
  123. package/src/components/SearchIconsView.tsx +3 -1
  124. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +11 -0
  125. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +15 -2
  126. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +11 -0
  127. package/src/components/UnsavedChangesDialog.tsx +6 -4
  128. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +1 -0
  129. package/src/components/VirtualTable/VirtualTable.tsx +121 -116
  130. package/src/components/VirtualTable/VirtualTableHeader.tsx +59 -56
  131. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +9 -4
  132. package/src/components/VirtualTable/VirtualTableProps.tsx +7 -1
  133. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +3 -3
  134. package/src/components/VirtualTable/types.tsx +1 -0
  135. package/src/components/common/default_entity_actions.tsx +4 -0
  136. package/src/components/common/useDataSourceTableController.tsx +12 -4
  137. package/src/components/index.tsx +1 -0
  138. package/src/core/DefaultAppBar.tsx +15 -11
  139. package/src/core/DefaultDrawer.tsx +8 -2
  140. package/src/core/DrawerNavigationGroup.tsx +5 -3
  141. package/src/core/EntityEditView.tsx +54 -8
  142. package/src/core/EntityEditViewFormActions.tsx +24 -17
  143. package/src/core/EntitySidePanel.tsx +34 -30
  144. package/src/core/FireCMS.tsx +33 -6
  145. package/src/core/field_configs.tsx +18 -11
  146. package/src/editor/components/SlashCommandMenu.tsx +516 -0
  147. package/src/editor/components/editor-bubble-item.tsx +32 -0
  148. package/src/editor/components/editor-bubble.tsx +118 -0
  149. package/src/editor/components/image-bubble.tsx +156 -0
  150. package/src/editor/components/index.ts +14 -0
  151. package/src/editor/components/table-bubble.tsx +165 -0
  152. package/src/editor/editor.tsx +455 -0
  153. package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
  154. package/src/editor/extensions/Image/index.ts +133 -0
  155. package/src/editor/extensions/Image.ts +159 -0
  156. package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
  157. package/src/editor/extensions/clipboard.ts +72 -0
  158. package/src/editor/extensions/custom-keymap.ts +24 -0
  159. package/src/editor/extensions/drag-and-drop.tsx +480 -0
  160. package/src/editor/hooks/useProseMirror.ts +124 -0
  161. package/src/editor/hooks/useProseMirrorContext.ts +15 -0
  162. package/src/editor/index.ts +2 -0
  163. package/src/editor/markdown.ts +172 -0
  164. package/src/editor/nodeViews/ImageComponent.tsx +20 -0
  165. package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
  166. package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
  167. package/src/editor/nodeViews/index.ts +35 -0
  168. package/src/editor/plugins/index.ts +58 -0
  169. package/src/editor/plugins/inputrules.ts +82 -0
  170. package/src/editor/plugins/placeholderPlugin.ts +55 -0
  171. package/src/editor/plugins/slashCommandPlugin.ts +61 -0
  172. package/src/editor/schema.ts +240 -0
  173. package/src/editor/selectors/ai-selector.tsx +111 -0
  174. package/src/editor/selectors/color-selector.tsx +200 -0
  175. package/src/editor/selectors/link-selector.tsx +118 -0
  176. package/src/editor/selectors/node-selector.tsx +157 -0
  177. package/src/editor/selectors/text-buttons.tsx +86 -0
  178. package/src/editor/types.ts +6 -0
  179. package/src/editor/useProseMirror.ts +126 -0
  180. package/src/editor/utils/prosemirror-utils.ts +108 -0
  181. package/src/editor/utils/remove_classes.ts +17 -0
  182. package/src/editor/utils/useDebouncedCallback.ts +25 -0
  183. package/src/form/EntityForm.tsx +149 -67
  184. package/src/form/EntityFormActions.tsx +19 -12
  185. package/src/form/PropertyFieldBinding.tsx +10 -8
  186. package/src/form/components/ErrorFocus.tsx +3 -3
  187. package/src/form/components/LocalChangesMenu.tsx +13 -13
  188. package/src/form/components/StorageItemPreview.tsx +3 -2
  189. package/src/form/components/StorageUploadProgress.tsx +18 -3
  190. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +18 -5
  191. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +22 -9
  192. package/src/form/field_bindings/BlockFieldBinding.tsx +26 -9
  193. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  194. package/src/form/field_bindings/KeyValueFieldBinding.tsx +46 -24
  195. package/src/form/field_bindings/MapFieldBinding.tsx +27 -11
  196. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +74 -37
  197. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +15 -1
  198. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +25 -11
  199. package/src/form/field_bindings/ReferenceFieldBinding.tsx +25 -11
  200. package/src/form/field_bindings/RepeatFieldBinding.tsx +21 -6
  201. package/src/form/field_bindings/SelectFieldBinding.tsx +7 -5
  202. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +110 -92
  203. package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -14
  204. package/src/form/field_bindings/TextFieldBinding.tsx +10 -7
  205. package/src/form/field_bindings/UserSelectFieldBinding.tsx +7 -5
  206. package/src/hooks/index.tsx +1 -0
  207. package/src/hooks/useBuildNavigationController.tsx +49 -22
  208. package/src/hooks/useCollapsedGroups.ts +7 -6
  209. package/src/hooks/useTranslation.ts +31 -0
  210. package/src/hooks/useValidateAuthenticator.tsx +1 -1
  211. package/src/i18n/FireCMSi18nProvider.tsx +160 -0
  212. package/src/index.ts +5 -0
  213. package/src/internal/useBuildDataSource.ts +1 -2
  214. package/src/internal/useBuildSideEntityController.tsx +22 -20
  215. package/src/locales/de.ts +718 -0
  216. package/src/locales/en.ts +730 -0
  217. package/src/locales/es.ts +730 -0
  218. package/src/locales/fr.ts +718 -0
  219. package/src/locales/hi.ts +718 -0
  220. package/src/locales/it.ts +718 -0
  221. package/src/locales/pt.ts +727 -0
  222. package/src/preview/PropertyPreview.tsx +4 -2
  223. package/src/preview/components/ReferencePreview.tsx +2 -1
  224. package/src/preview/components/UrlComponentPreview.tsx +4 -2
  225. package/src/preview/components/UserPreview.tsx +3 -1
  226. package/src/preview/property_previews/MapPropertyPreview.tsx +49 -27
  227. package/src/routes/FireCMSRoute.tsx +63 -54
  228. package/src/types/analytics.ts +10 -0
  229. package/src/types/collections.ts +49 -0
  230. package/src/types/customization_controller.tsx +2 -1
  231. package/src/types/firecms.tsx +2 -1
  232. package/src/types/index.ts +1 -0
  233. package/src/types/navigation.ts +2 -2
  234. package/src/types/plugins.tsx +26 -0
  235. package/src/types/properties.ts +12 -10
  236. package/src/types/storage.ts +2 -1
  237. package/src/types/translations.ts +752 -0
  238. package/src/util/entities.ts +1 -1
  239. package/src/util/index.ts +1 -0
  240. package/src/util/join_collections.ts +10 -8
  241. package/src/util/lazy_eager.tsx +33 -0
  242. package/src/util/objects.ts +15 -0
  243. package/src/util/previews.ts +2 -2
  244. package/src/util/property_utils.tsx +1 -1
  245. package/src/util/resolutions.ts +5 -3
  246. package/src/util/useStorageUploadController.tsx +23 -29
@@ -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
 
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { FieldProps } from "../../types";
3
3
  import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
4
4
  import { PropertyFieldBinding } from "../PropertyFieldBinding";
5
- import { ExpandablePanel, Typography } from "@firecms/ui";
5
+ import { ExpandablePanel, IconButton, CloseIcon } from "@firecms/ui";
6
6
  import { getArrayResolvedProperties, getIconForProperty, isReadOnly } from "../../util";
7
7
  import { useClearRestoreValue } from "../useClearRestoreValue";
8
8
  import { useAuthController } from "../../hooks";
@@ -50,15 +50,28 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
50
50
  setValue
51
51
  });
52
52
 
53
- const title = (<>
53
+ const title = (<div className="flex items-center w-full">
54
54
  <LabelWithIconAndTooltip
55
55
  propertyKey={propertyKey}
56
56
  icon={getIconForProperty(property, "small")}
57
57
  required={property.validation?.required}
58
58
  title={property.name}
59
- className={"h-8 flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
60
- {Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
61
- </>);
59
+ className={"text-text-secondary dark:text-text-secondary-dark"}/>
60
+ {Array.isArray(value) && <span className={"text-sm text-text-secondary dark:text-text-secondary-dark ml-1"}>({value.length})</span>}
61
+ <div className="flex-grow"/>
62
+ {(property.nullable || property.clearable) && !disabled && (
63
+ <IconButton
64
+ size="small"
65
+ onClick={(e) => {
66
+ e.stopPropagation();
67
+ e.preventDefault();
68
+ setValue(null);
69
+ }}
70
+ >
71
+ <CloseIcon size={"small"}/>
72
+ </IconButton>
73
+ )}
74
+ </div>);
62
75
 
63
76
  const body = resolvedProperties.map((childProperty, index) => {
64
77
  const thisDisabled = isReadOnly(childProperty) || Boolean(childProperty.disabled);
@@ -4,9 +4,8 @@ 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";
9
- import { Button, cls, EditIcon, ExpandablePanel, fieldBackgroundMixin, Typography } from "@firecms/ui";
7
+ import { useNavigationController, useReferenceDialog, useTranslation } from "../../hooks";
8
+ import { Button, cls, EditIcon, ExpandablePanel, fieldBackgroundMixin, Typography, IconButton, CloseIcon } from "@firecms/ui";
10
9
  import { useClearRestoreValue } from "../useClearRestoreValue";
11
10
 
12
11
  type ArrayOfReferencesFieldProps = FieldProps<EntityReference[]>;
@@ -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}
@@ -100,15 +100,28 @@ export function ArrayOfReferencesFieldBinding({
100
100
  );
101
101
  }, [ofProperty.path, ofProperty.previewProperties, value]);
102
102
 
103
- const title = (<>
103
+ const title = (<div className="flex items-center w-full">
104
104
  <LabelWithIconAndTooltip
105
105
  propertyKey={propertyKey}
106
106
  icon={getIconForProperty(property, "small")}
107
107
  required={property.validation?.required}
108
108
  title={property.name}
109
- className={"h-8 flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
110
- {Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
111
- </>);
109
+ className={"text-text-secondary dark:text-text-secondary-dark"}/>
110
+ {Array.isArray(value) && <span className={"text-sm text-text-secondary dark:text-text-secondary-dark ml-1"}>({value.length})</span>}
111
+ <div className="flex-grow"/>
112
+ {(property.nullable || property.clearable) && !disabled && (
113
+ <IconButton
114
+ size="small"
115
+ onClick={(e) => {
116
+ e.stopPropagation();
117
+ e.preventDefault();
118
+ setValue(null);
119
+ }}
120
+ >
121
+ <CloseIcon size={"small"}/>
122
+ </IconButton>
123
+ )}
124
+ </div>);
112
125
 
113
126
  const body = <>
114
127
  {!collection && <ErrorView
@@ -132,7 +145,7 @@ export function ArrayOfReferencesFieldBinding({
132
145
  disabled={isSubmitting}
133
146
  onClick={onEntryClick}>
134
147
  <EditIcon size={"small"}/>
135
- Edit {property.name}
148
+ {t("edit_name", { name: property.name ?? "" })}
136
149
  </Button>
137
150
  </div>}
138
151
  </>;
@@ -8,9 +8,10 @@ import { EnumValuesChip } from "../../preview";
8
8
  import { FieldProps, FormContext, PropertyFieldBindingProps, PropertyOrBuilder } from "../../types";
9
9
  import { getDefaultValueFor, getIconForProperty, mergeDeep, } from "../../util";
10
10
  import { DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE } from "../../util/common";
11
- import { cls, ExpandablePanel, paperMixin, Select, SelectItem, Typography } from "@firecms/ui";
11
+ import { cls, ExpandablePanel, paperMixin, Select, SelectItem, Typography, IconButton, CloseIcon } 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");
@@ -72,19 +74,33 @@ export function BlockFieldBinding<T extends Array<any>>({
72
74
  };
73
75
 
74
76
  const title = (
75
- <LabelWithIconAndTooltip
76
- propertyKey={propertyKey}
77
- icon={getIconForProperty(property, "small")}
78
- required={property.validation?.required}
79
- title={property.name}
80
- className={"text-text-secondary dark:text-text-secondary-dark"}/>
77
+ <div className="flex items-center w-full">
78
+ <LabelWithIconAndTooltip
79
+ propertyKey={propertyKey}
80
+ icon={getIconForProperty(property, "small")}
81
+ required={property.validation?.required}
82
+ title={property.name}
83
+ className={"text-text-secondary dark:text-text-secondary-dark flex-grow"}/>
84
+ {(property.nullable || property.clearable) && !disabled && (
85
+ <IconButton
86
+ size="small"
87
+ onClick={(e) => {
88
+ e.stopPropagation();
89
+ e.preventDefault();
90
+ setValue(null);
91
+ }}
92
+ >
93
+ <CloseIcon size={"small"}/>
94
+ </IconButton>
95
+ )}
96
+ </div>
81
97
  );
82
98
 
83
99
  const firstOneOfKey = Object.keys(property.oneOf.properties)[0];
84
100
  const body = <ArrayContainer value={value}
85
101
  className={"flex flex-col gap-3"}
86
102
  droppableId={propertyKey}
87
- addLabel={property.name ? "Add entry to " + property.name : "Add entry"}
103
+ addLabel={property.name ? t("add_to_field", { fieldName: property.name }) : t("add_entry")}
88
104
  buildEntry={buildEntry}
89
105
  onInternalIdAdded={setLastAddedId}
90
106
  disabled={isSubmitting || Boolean(property.disabled)}
@@ -167,6 +183,7 @@ function BlockEntry({
167
183
  const [typeInternal, setTypeInternal] = useState<string | undefined>(type ?? undefined);
168
184
 
169
185
  const formex = useFormex();
186
+ const { t } = useTranslation();
170
187
 
171
188
  useEffect(() => {
172
189
  if (!type) {
@@ -227,7 +244,7 @@ function BlockEntry({
227
244
  <Select
228
245
  className="mb-2"
229
246
  placeholder={<Typography variant={"caption"}
230
- className={"px-4 py-2 font-medium"}>Type</Typography>}
247
+ className={"px-4 py-2 font-medium"}>{t("type")}</Typography>}
231
248
  size={"medium"}
232
249
  fullWidth={true}
233
250
  position={"item-aligned"}
@@ -48,7 +48,7 @@ export function DateTimeFieldBinding({
48
48
  onChange={(dateValue) => setValue(dateValue)}
49
49
  size={"large"}
50
50
  mode={property.mode}
51
- clearable={property.clearable}
51
+ clearable={property.nullable || property.clearable}
52
52
  locale={locale}
53
53
  timezone={property.timezone}
54
54
  error={showError}
@@ -13,6 +13,7 @@ import {
13
13
  defaultBorderMixin,
14
14
  ExpandablePanel,
15
15
  IconButton,
16
+ CloseIcon,
16
17
  Menu,
17
18
  MenuItem,
18
19
  RemoveIcon,
@@ -22,6 +23,7 @@ import {
22
23
  import { getDefaultValueForDataType, getIconForProperty } from "../../util";
23
24
  import { useCustomizationController } from "../../hooks";
24
25
  import { getIn } from "@firecms/formex";
26
+ import { useTranslation } from "../../hooks/useTranslation";
25
27
 
26
28
  type MapEditViewRowState = [number, {
27
29
  key: string,
@@ -54,6 +56,7 @@ export function KeyValueFieldBinding({
54
56
  throw Error(`Your property ${propertyKey} needs to have the 'keyValue' prop in order to use this field binding`);
55
57
  }
56
58
 
59
+ const { t } = useTranslation();
57
60
  const initialValues = getIn(context.formex.initialValues, propertyKey);
58
61
 
59
62
  const mapFormView = <MapEditView value={value}
@@ -62,12 +65,28 @@ export function KeyValueFieldBinding({
62
65
  initialValue={initialValues}
63
66
  fieldName={property.name ?? propertyKey}/>;
64
67
 
65
- const title = <LabelWithIconAndTooltip
66
- propertyKey={propertyKey}
67
- icon={getIconForProperty(property, "small")}
68
- required={property.validation?.required}
69
- title={property.name}
70
- className={"text-text-secondary dark:text-text-secondary-dark"}/>;
68
+ const title = (
69
+ <div className="flex items-center w-full">
70
+ <LabelWithIconAndTooltip
71
+ propertyKey={propertyKey}
72
+ icon={getIconForProperty(property, "small")}
73
+ required={property.validation?.required}
74
+ title={property.name}
75
+ className={"text-text-secondary dark:text-text-secondary-dark flex-grow"}/>
76
+ {(property.nullable || property.clearable) && !disabled && (
77
+ <IconButton
78
+ size="small"
79
+ onClick={(e) => {
80
+ e.stopPropagation();
81
+ e.preventDefault();
82
+ setValue(null);
83
+ }}
84
+ >
85
+ <CloseIcon size={"small"}/>
86
+ </IconButton>
87
+ )}
88
+ </div>
89
+ );
71
90
 
72
91
  return (
73
92
  <>
@@ -103,6 +122,7 @@ function MapEditView<T extends Record<string, any>>({
103
122
  fieldName,
104
123
  disabled
105
124
  }: MapEditViewParams<T>) {
125
+ const { t } = useTranslation();
106
126
  const [internalState, setInternalState] = React.useState<MapEditViewRowState[]>(
107
127
  Object.keys(initialValue ?? {}).map((key) => [getRandomId(), {
108
128
  key,
@@ -230,7 +250,7 @@ function MapEditView<T extends Record<string, any>>({
230
250
  }]]);
231
251
  }
232
252
  }>
233
- {fieldName ? `Add to ${fieldName}` : "Add"}
253
+ {fieldName ? t("add_to_field", { fieldName }) : t("add_entry")}
234
254
  </Button>
235
255
 
236
256
  </div>;
@@ -261,12 +281,13 @@ function MapKeyValueRow<T extends Record<string, any>>({
261
281
  }) {
262
282
 
263
283
  const { locale } = useCustomizationController();
284
+ const { t } = useTranslation();
264
285
 
265
286
  function buildInput(entryValue: any, fieldKey: string, dataType: DataType) {
266
287
  if (dataType === "string" || dataType === "number") {
267
288
  return <TextField
268
289
  key={dataType}
269
- placeholder={"value"}
290
+ placeholder={t("value")}
270
291
  value={entryValue}
271
292
  type={dataType === "number" ? "number" : "text"}
272
293
  size={"medium"}
@@ -325,7 +346,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
325
346
  <ArrayContainer value={entryValue}
326
347
  newDefaultEntry={""}
327
348
  droppableId={rowId.toString()}
328
- addLabel={fieldKey ? `Add to ${fieldKey}` : "Add"}
349
+ addLabel={fieldKey ? t("add_to_field", { fieldName: fieldKey }) : t("add_entry")}
329
350
  size={"small"}
330
351
  disabled={disabled || !fieldKey}
331
352
  canAddElements={true}
@@ -370,7 +391,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
370
391
  } else {
371
392
  return <Typography
372
393
  variant={"caption"}>
373
- {`Data type ${dataType} not supported yet`}
394
+ {t("data_type_not_supported", { dataType })}
374
395
  </Typography>;
375
396
  }
376
397
  }
@@ -386,7 +407,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
386
407
  <div className="w-[300px] max-w-[30%]">
387
408
  <TextField
388
409
  value={fieldKey}
389
- placeholder={"key"}
410
+ placeholder={t("key")}
390
411
  disabled={disabled || (entryValue !== undefined && entryValue !== null && entryValue !== "")}
391
412
  size={"medium"}
392
413
  onChange={(event) => {
@@ -404,17 +425,17 @@ function MapKeyValueRow<T extends Record<string, any>>({
404
425
  </IconButton>}
405
426
  >
406
427
  <MenuItem dense
407
- onClick={() => doUpdateDataType("string")}>string</MenuItem>
428
+ onClick={() => doUpdateDataType("string")}>{t("string")}</MenuItem>
408
429
  <MenuItem dense
409
- onClick={() => doUpdateDataType("number")}>number</MenuItem>
430
+ onClick={() => doUpdateDataType("number")}>{t("number")}</MenuItem>
410
431
  <MenuItem dense
411
- onClick={() => doUpdateDataType("boolean")}>boolean</MenuItem>
432
+ onClick={() => doUpdateDataType("boolean")}>{t("boolean")}</MenuItem>
412
433
  <MenuItem dense
413
- onClick={() => doUpdateDataType("date")}>date</MenuItem>
434
+ onClick={() => doUpdateDataType("date")}>{t("date")}</MenuItem>
414
435
  <MenuItem dense
415
- onClick={() => doUpdateDataType("map")}>map</MenuItem>
436
+ onClick={() => doUpdateDataType("map")}>{t("map")}</MenuItem>
416
437
  <MenuItem dense
417
- onClick={() => doUpdateDataType("array")}>array</MenuItem>
438
+ onClick={() => doUpdateDataType("array")}>{t("array")}</MenuItem>
418
439
  </Menu>
419
440
 
420
441
  <IconButton aria-label="delete"
@@ -446,6 +467,7 @@ function ArrayKeyValueRow<T>({
446
467
  }) {
447
468
 
448
469
  const { locale } = useCustomizationController();
470
+ const { t } = useTranslation();
449
471
  const [selectedDataType, setSelectedDataType] = useState<DataType>(getDataType(value) ?? "string");
450
472
 
451
473
  function doUpdateDataType(dataType: DataType) {
@@ -487,7 +509,7 @@ function ArrayKeyValueRow<T>({
487
509
  }}/>;
488
510
  } else if (dataType === "array") {
489
511
  return <Typography variant={"caption"}>
490
- Arrays of arrays are not supported.
512
+ {t("arrays_of_arrays_not_supported")}
491
513
  </Typography>;
492
514
  } else if (dataType === "map") {
493
515
  return <div className={cls(defaultBorderMixin, "ml-2 pl-2 border-l border-solid")}>
@@ -499,7 +521,7 @@ function ArrayKeyValueRow<T>({
499
521
  } else {
500
522
  return <Typography
501
523
  variant={"caption"}>
502
- {`Data type ${dataType} not supported yet`}
524
+ {t("data_type_not_supported", { dataType })}
503
525
  </Typography>;
504
526
  }
505
527
  }
@@ -519,15 +541,15 @@ function ArrayKeyValueRow<T>({
519
541
  <ArrowDropDownIcon/>
520
542
  </IconButton>}>
521
543
  <MenuItem dense
522
- onClick={() => doUpdateDataType("string")}>string</MenuItem>
544
+ onClick={() => doUpdateDataType("string")}>{t("string")}</MenuItem>
523
545
  <MenuItem dense
524
- onClick={() => doUpdateDataType("number")}>number</MenuItem>
546
+ onClick={() => doUpdateDataType("number")}>{t("number")}</MenuItem>
525
547
  <MenuItem dense
526
- onClick={() => doUpdateDataType("boolean")}>boolean</MenuItem>
548
+ onClick={() => doUpdateDataType("boolean")}>{t("boolean")}</MenuItem>
527
549
  <MenuItem dense
528
- onClick={() => doUpdateDataType("map")}>map</MenuItem>
550
+ onClick={() => doUpdateDataType("map")}>{t("map")}</MenuItem>
529
551
  <MenuItem dense
530
- onClick={() => doUpdateDataType("date")}>date</MenuItem>
552
+ onClick={() => doUpdateDataType("date")}>{t("date")}</MenuItem>
531
553
  </Menu>
532
554
 
533
555
  </Typography>
@@ -6,7 +6,8 @@ import { getIconForProperty, isHidden, isReadOnly, pick } from "../../util";
6
6
  import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
7
7
  import { FormEntry } from "../components/FormEntry";
8
8
  import { PropertyFieldBinding } from "../PropertyFieldBinding";
9
- import { cls, ExpandablePanel, InputLabel, Select, SelectItem } from "@firecms/ui";
9
+ import { cls, ExpandablePanel, InputLabel, Select, SelectItem, IconButton, CloseIcon } from "@firecms/ui";
10
+ import { useTranslation } from "../../hooks";
10
11
 
11
12
  /**
12
13
  * Field that renders the children property fields
@@ -27,7 +28,8 @@ export function MapFieldBinding({
27
28
  includeDescription,
28
29
  autoFocus,
29
30
  context,
30
- onPropertyChange
31
+ onPropertyChange,
32
+ setValue
31
33
  }: FieldProps<Record<string, any>>) {
32
34
 
33
35
  const pickOnlySomeKeys = property.pickOnlySomeKeys || false;
@@ -91,7 +93,7 @@ export function MapFieldBinding({
91
93
  }
92
94
  </div>
93
95
 
94
- {/*{pickOnlySomeKeys && buildPickKeysSelect(disabled, property.properties, setValue, value)}*/}
96
+ {/*{pickOnlySomeKeys && buildPickKeysSelect(disabled, property.properties, setValue, value, t)}*/}
95
97
 
96
98
  </>
97
99
  ;
@@ -107,12 +109,26 @@ export function MapFieldBinding({
107
109
  }}
108
110
  className={property.widthPercentage !== undefined ? "mt-8" : undefined}
109
111
  innerClassName={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2 bg-white dark:bg-surface-900"}
110
- title={<LabelWithIconAndTooltip
111
- propertyKey={propertyKey}
112
- icon={getIconForProperty(property, "small")}
113
- required={property.validation?.required}
114
- title={property.name}
115
- className={"text-text-secondary dark:text-text-secondary-dark"} />}>
112
+ title={<div className="flex items-center w-full">
113
+ <LabelWithIconAndTooltip
114
+ propertyKey={propertyKey}
115
+ icon={getIconForProperty(property, "small")}
116
+ required={property.validation?.required}
117
+ title={property.name}
118
+ className={"text-text-secondary dark:text-text-secondary-dark flex-grow"} />
119
+ {(property.nullable || property.clearable) && !disabled && (
120
+ <IconButton
121
+ size="small"
122
+ onClick={(e) => {
123
+ e.stopPropagation();
124
+ e.preventDefault();
125
+ setValue(null);
126
+ }}
127
+ >
128
+ <CloseIcon size={"small"}/>
129
+ </IconButton>
130
+ )}
131
+ </div>}>
116
132
  {mapFormView}
117
133
  </ExpandablePanel>}
118
134
 
@@ -128,7 +144,7 @@ export function MapFieldBinding({
128
144
  );
129
145
  }
130
146
 
131
- const buildPickKeysSelect = (disabled: boolean, properties: Properties, setValue: (value: any) => void, value: any) => {
147
+ const buildPickKeysSelect = (disabled: boolean, properties: Properties, setValue: (value: any) => void, value: any, t: any) => {
132
148
 
133
149
  const keys = Object.keys(properties)
134
150
  .filter((key) => !value || !(key in value));
@@ -143,7 +159,7 @@ const buildPickKeysSelect = (disabled: boolean, properties: Properties, setValue
143
159
  if (!keys.length) return <></>;
144
160
 
145
161
  return <div className={"m-4"}>
146
- <InputLabel>Add property</InputLabel>
162
+ <InputLabel>{t("add_property")}</InputLabel>
147
163
  <Select
148
164
  value={""}
149
165
  size={"large"}