@firecms/core 3.1.0-canary.24c8270 → 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 (224) 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/VirtualTable/VirtualTableHeader.d.ts +1 -0
  7. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  8. package/dist/components/VirtualTable/VirtualTableProps.d.ts +6 -1
  9. package/dist/components/VirtualTable/types.d.ts +1 -0
  10. package/dist/components/index.d.ts +1 -0
  11. package/dist/core/DrawerNavigationGroup.d.ts +2 -2
  12. package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
  13. package/dist/editor/components/editor-bubble-item.d.ts +8 -0
  14. package/dist/editor/components/editor-bubble.d.ts +8 -0
  15. package/dist/editor/components/image-bubble.d.ts +5 -0
  16. package/dist/editor/components/index.d.ts +16 -0
  17. package/dist/editor/components/table-bubble.d.ts +5 -0
  18. package/dist/editor/editor.d.ts +30 -0
  19. package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
  20. package/dist/editor/extensions/Image/index.d.ts +6 -0
  21. package/dist/editor/extensions/Image.d.ts +6 -0
  22. package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
  23. package/dist/editor/extensions/clipboard.d.ts +7 -0
  24. package/dist/editor/extensions/custom-keymap.d.ts +1 -0
  25. package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
  26. package/dist/editor/hooks/useProseMirror.d.ts +13 -0
  27. package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
  28. package/dist/editor/index.d.ts +2 -0
  29. package/dist/editor/markdown.d.ts +5 -0
  30. package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
  31. package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
  32. package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
  33. package/dist/editor/nodeViews/index.d.ts +6 -0
  34. package/dist/editor/plugins/index.d.ts +2 -0
  35. package/dist/editor/plugins/inputrules.d.ts +6 -0
  36. package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
  37. package/dist/editor/plugins/slashCommandPlugin.d.ts +12 -0
  38. package/dist/editor/schema.d.ts +2 -0
  39. package/dist/editor/selectors/ai-selector.d.ts +0 -0
  40. package/dist/editor/selectors/color-selector.d.ts +10 -0
  41. package/dist/editor/selectors/link-selector.d.ts +8 -0
  42. package/dist/editor/selectors/node-selector.d.ts +15 -0
  43. package/dist/editor/selectors/text-buttons.d.ts +1 -0
  44. package/dist/editor/types.d.ts +5 -0
  45. package/dist/editor/useProseMirror.d.ts +16 -0
  46. package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
  47. package/dist/editor/utils/remove_classes.d.ts +1 -0
  48. package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
  49. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  50. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  51. package/dist/hooks/index.d.ts +1 -0
  52. package/dist/hooks/useBuildNavigationController.d.ts +0 -1
  53. package/dist/hooks/useCollapsedGroups.d.ts +3 -3
  54. package/dist/hooks/useTranslation.d.ts +17 -0
  55. package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
  56. package/dist/index.d.ts +5 -0
  57. package/dist/index.es.js +29889 -18645
  58. package/dist/index.es.js.map +1 -1
  59. package/dist/index.umd.js +29883 -18659
  60. package/dist/index.umd.js.map +1 -1
  61. package/dist/locales/de.d.ts +2 -0
  62. package/dist/locales/en.d.ts +10 -0
  63. package/dist/locales/es.d.ts +10 -0
  64. package/dist/locales/fr.d.ts +2 -0
  65. package/dist/locales/hi.d.ts +2 -0
  66. package/dist/locales/it.d.ts +2 -0
  67. package/dist/locales/pt.d.ts +7 -0
  68. package/dist/types/collections.d.ts +38 -0
  69. package/dist/types/customization_controller.d.ts +2 -1
  70. package/dist/types/firecms.d.ts +2 -1
  71. package/dist/types/index.d.ts +1 -0
  72. package/dist/types/navigation.d.ts +2 -2
  73. package/dist/types/plugins.d.ts +7 -0
  74. package/dist/types/properties.d.ts +9 -8
  75. package/dist/types/storage.d.ts +1 -0
  76. package/dist/types/translations.d.ts +669 -0
  77. package/dist/util/index.d.ts +1 -0
  78. package/dist/util/lazy_eager.d.ts +7 -0
  79. package/dist/util/objects.d.ts +1 -0
  80. package/dist/util/useStorageUploadController.d.ts +10 -1
  81. package/package.json +45 -9
  82. package/src/app/Scaffold.tsx +7 -5
  83. package/src/components/AIIcon.tsx +3 -1
  84. package/src/components/ArrayContainer.tsx +6 -4
  85. package/src/components/ClearFilterSortButton.tsx +6 -3
  86. package/src/components/ConfirmationDialog.tsx +4 -2
  87. package/src/components/DeleteEntityDialog.tsx +10 -7
  88. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +9 -3
  89. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
  90. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -1
  91. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
  92. package/src/components/EntityCollectionView/BoardSortableList.tsx +3 -1
  93. package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
  94. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +16 -43
  95. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +17 -25
  96. package/src/components/EntityCollectionView/EntityCollectionView.tsx +24 -18
  97. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -3
  98. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +4 -2
  99. package/src/components/EntityCollectionView/FiltersDialog.tsx +8 -5
  100. package/src/components/EntityCollectionView/ViewModeToggle.tsx +11 -8
  101. package/src/components/EntityJsonPreview.tsx +2 -1
  102. package/src/components/EntityView.tsx +3 -2
  103. package/src/components/ErrorBoundary.tsx +27 -15
  104. package/src/components/HomePage/DefaultHomePage.tsx +19 -13
  105. package/src/components/HomePage/HomePageDnD.tsx +3 -1
  106. package/src/components/HomePage/NavigationGroup.tsx +3 -1
  107. package/src/components/HomePage/RenameGroupDialog.tsx +15 -13
  108. package/src/components/LanguageToggle.tsx +66 -0
  109. package/src/components/NotFoundPage.tsx +5 -3
  110. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +9 -7
  111. package/src/components/ReferenceWidget.tsx +3 -2
  112. package/src/components/SearchIconsView.tsx +3 -1
  113. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +11 -0
  114. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +15 -2
  115. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +11 -0
  116. package/src/components/UnsavedChangesDialog.tsx +6 -4
  117. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +1 -0
  118. package/src/components/VirtualTable/VirtualTable.tsx +5 -3
  119. package/src/components/VirtualTable/VirtualTableHeader.tsx +21 -18
  120. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +8 -3
  121. package/src/components/VirtualTable/VirtualTableProps.tsx +7 -1
  122. package/src/components/VirtualTable/types.tsx +1 -0
  123. package/src/components/common/default_entity_actions.tsx +4 -0
  124. package/src/components/common/useDataSourceTableController.tsx +5 -14
  125. package/src/components/index.tsx +1 -0
  126. package/src/core/DefaultAppBar.tsx +14 -10
  127. package/src/core/DefaultDrawer.tsx +8 -2
  128. package/src/core/DrawerNavigationGroup.tsx +5 -3
  129. package/src/core/EntityEditView.tsx +53 -7
  130. package/src/core/EntityEditViewFormActions.tsx +24 -17
  131. package/src/core/EntitySidePanel.tsx +6 -4
  132. package/src/core/FireCMS.tsx +33 -6
  133. package/src/core/field_configs.tsx +4 -2
  134. package/src/editor/components/SlashCommandMenu.tsx +516 -0
  135. package/src/editor/components/editor-bubble-item.tsx +32 -0
  136. package/src/editor/components/editor-bubble.tsx +118 -0
  137. package/src/editor/components/image-bubble.tsx +156 -0
  138. package/src/editor/components/index.ts +14 -0
  139. package/src/editor/components/table-bubble.tsx +165 -0
  140. package/src/editor/editor.tsx +455 -0
  141. package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
  142. package/src/editor/extensions/Image/index.ts +133 -0
  143. package/src/editor/extensions/Image.ts +159 -0
  144. package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
  145. package/src/editor/extensions/clipboard.ts +72 -0
  146. package/src/editor/extensions/custom-keymap.ts +24 -0
  147. package/src/editor/extensions/drag-and-drop.tsx +480 -0
  148. package/src/editor/hooks/useProseMirror.ts +124 -0
  149. package/src/editor/hooks/useProseMirrorContext.ts +15 -0
  150. package/src/editor/index.ts +2 -0
  151. package/src/editor/markdown.ts +172 -0
  152. package/src/editor/nodeViews/ImageComponent.tsx +20 -0
  153. package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
  154. package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
  155. package/src/editor/nodeViews/index.ts +35 -0
  156. package/src/editor/plugins/index.ts +58 -0
  157. package/src/editor/plugins/inputrules.ts +82 -0
  158. package/src/editor/plugins/placeholderPlugin.ts +55 -0
  159. package/src/editor/plugins/slashCommandPlugin.ts +61 -0
  160. package/src/editor/schema.ts +240 -0
  161. package/src/editor/selectors/ai-selector.tsx +111 -0
  162. package/src/editor/selectors/color-selector.tsx +200 -0
  163. package/src/editor/selectors/link-selector.tsx +118 -0
  164. package/src/editor/selectors/node-selector.tsx +157 -0
  165. package/src/editor/selectors/text-buttons.tsx +86 -0
  166. package/src/editor/types.ts +6 -0
  167. package/src/editor/useProseMirror.ts +126 -0
  168. package/src/editor/utils/prosemirror-utils.ts +108 -0
  169. package/src/editor/utils/remove_classes.ts +17 -0
  170. package/src/editor/utils/useDebouncedCallback.ts +25 -0
  171. package/src/form/EntityForm.tsx +80 -7
  172. package/src/form/EntityFormActions.tsx +19 -12
  173. package/src/form/PropertyFieldBinding.tsx +7 -5
  174. package/src/form/components/LocalChangesMenu.tsx +13 -13
  175. package/src/form/components/StorageItemPreview.tsx +3 -2
  176. package/src/form/components/StorageUploadProgress.tsx +18 -3
  177. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +18 -5
  178. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +22 -9
  179. package/src/form/field_bindings/BlockFieldBinding.tsx +26 -9
  180. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  181. package/src/form/field_bindings/KeyValueFieldBinding.tsx +46 -24
  182. package/src/form/field_bindings/MapFieldBinding.tsx +27 -11
  183. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +73 -36
  184. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +15 -1
  185. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +25 -11
  186. package/src/form/field_bindings/ReferenceFieldBinding.tsx +25 -11
  187. package/src/form/field_bindings/RepeatFieldBinding.tsx +21 -6
  188. package/src/form/field_bindings/SelectFieldBinding.tsx +7 -5
  189. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +28 -10
  190. package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -14
  191. package/src/form/field_bindings/TextFieldBinding.tsx +10 -7
  192. package/src/form/field_bindings/UserSelectFieldBinding.tsx +7 -5
  193. package/src/hooks/index.tsx +1 -0
  194. package/src/hooks/useBuildNavigationController.tsx +20 -13
  195. package/src/hooks/useCollapsedGroups.ts +7 -6
  196. package/src/hooks/useTranslation.ts +31 -0
  197. package/src/i18n/FireCMSi18nProvider.tsx +160 -0
  198. package/src/index.ts +5 -0
  199. package/src/locales/de.ts +718 -0
  200. package/src/locales/en.ts +730 -0
  201. package/src/locales/es.ts +730 -0
  202. package/src/locales/fr.ts +718 -0
  203. package/src/locales/hi.ts +718 -0
  204. package/src/locales/it.ts +718 -0
  205. package/src/locales/pt.ts +727 -0
  206. package/src/preview/PropertyPreview.tsx +3 -2
  207. package/src/preview/components/ReferencePreview.tsx +2 -1
  208. package/src/preview/components/UrlComponentPreview.tsx +4 -2
  209. package/src/preview/components/UserPreview.tsx +3 -1
  210. package/src/preview/property_previews/MapPropertyPreview.tsx +49 -27
  211. package/src/routes/FireCMSRoute.tsx +63 -54
  212. package/src/types/collections.ts +40 -0
  213. package/src/types/customization_controller.tsx +2 -1
  214. package/src/types/firecms.tsx +2 -1
  215. package/src/types/index.ts +1 -0
  216. package/src/types/navigation.ts +2 -2
  217. package/src/types/plugins.tsx +8 -0
  218. package/src/types/properties.ts +12 -10
  219. package/src/types/storage.ts +2 -1
  220. package/src/types/translations.ts +752 -0
  221. package/src/util/index.ts +1 -0
  222. package/src/util/lazy_eager.tsx +33 -0
  223. package/src/util/objects.ts +15 -0
  224. package/src/util/useStorageUploadController.tsx +23 -29
@@ -19,6 +19,7 @@ import {
19
19
  } from "@firecms/ui";
20
20
  import { FormexController } from "@firecms/formex";
21
21
  import { useFireCMSContext, useSideEntityController } from "../hooks";
22
+ import { useTranslation } from "../hooks/useTranslation";
22
23
 
23
24
  export interface EntityFormActionsProps {
24
25
  fullPath: string;
@@ -56,6 +57,7 @@ export function EntityFormActions({
56
57
 
57
58
  const context = useFireCMSContext();
58
59
  const sideEntityController = useSideEntityController();
60
+ const { t } = useTranslation();
59
61
 
60
62
  return layout === "bottom"
61
63
  ? buildBottomActions({
@@ -72,7 +74,8 @@ export function EntityFormActions({
72
74
  openEntityMode,
73
75
  navigateBack,
74
76
  formContext,
75
- formex
77
+ formex,
78
+ t
76
79
  })
77
80
  : buildSideActions({
78
81
  fullPath,
@@ -88,7 +91,8 @@ export function EntityFormActions({
88
91
  openEntityMode,
89
92
  navigateBack,
90
93
  formContext,
91
- formex
94
+ formex,
95
+ t
92
96
  });
93
97
  }
94
98
 
@@ -108,6 +112,7 @@ type ActionsViewProps<M extends object> = {
108
112
  navigateBack: () => void;
109
113
  formContext: FormContext,
110
114
  formex: FormexController<any>;
115
+ t: (key: any, vars?: Record<string, string>) => string;
111
116
  };
112
117
 
113
118
  function buildBottomActions<M extends object>({
@@ -125,7 +130,8 @@ function buildBottomActions<M extends object>({
125
130
  openEntityMode,
126
131
  navigateBack,
127
132
  formContext,
128
- formex
133
+ formex,
134
+ t
129
135
  }: ActionsViewProps<M>) {
130
136
 
131
137
  const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
@@ -165,16 +171,16 @@ function buildBottomActions<M extends object>({
165
171
  <Button variant="text" disabled={disabled || formex.isSubmitting}
166
172
  color={"primary"}
167
173
  type="reset">
168
- {status === "existing" ? "Discard" : "Clear"}
174
+ {status === "existing" ? t("discard") : t("clear")}
169
175
  </Button>
170
176
  <Button variant={"filled"}
171
177
  color="primary"
172
178
  type="submit"
173
179
  disabled={disabled || formex.isSubmitting}
174
180
  startIcon={hasErrors ? <ErrorIcon/> : undefined}>
175
- {status === "existing" && "Save"}
176
- {status === "copy" && "Create copy"}
177
- {status === "new" && "Create"}
181
+ {status === "existing" && t("save")}
182
+ {status === "copy" && t("create_copy")}
183
+ {status === "new" && t("create")}
178
184
  </Button>
179
185
 
180
186
  </DialogActions>;
@@ -193,7 +199,8 @@ function buildSideActions<M extends object>({
193
199
  disabled,
194
200
  status,
195
201
  pluginActions,
196
- formex
202
+ formex,
203
+ t
197
204
  }: ActionsViewProps<M>) {
198
205
 
199
206
  const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
@@ -207,12 +214,12 @@ function buildSideActions<M extends object>({
207
214
  size={"large"}
208
215
  startIcon={hasErrors ? <ErrorIcon/> : undefined}
209
216
  disabled={disabled || formex.isSubmitting}>
210
- {status === "existing" && "Save"}
211
- {status === "copy" && "Create copy"}
212
- {status === "new" && "Create"}
217
+ {status === "existing" && t("save")}
218
+ {status === "copy" && t("create_copy")}
219
+ {status === "new" && t("create")}
213
220
  </LoadingButton>
214
221
  <Button fullWidth={true} variant="text" disabled={disabled || formex.isSubmitting} type="reset">
215
- {status === "existing" ? "Discard" : "Clear"}
222
+ {status === "existing" ? t("discard") : t("clear")}
216
223
  </Button>
217
224
 
218
225
  {pluginActions}
@@ -17,10 +17,10 @@ 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
- import { ErrorBoundary } from "../components";
23
+ import { ErrorBoundary, CircularProgressCenter } from "../components";
24
24
 
25
25
  /**
26
26
  * This component renders a form field creating the corresponding configuration
@@ -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;
@@ -286,12 +287,13 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
286
287
 
287
288
  return (
288
289
  <ErrorBoundary>
289
-
290
- <UsedComponent {...cmsFieldProps} />
290
+ <React.Suspense fallback={<CircularProgressCenter />}>
291
+ <UsedComponent {...cmsFieldProps} />
292
+ </React.Suspense>
291
293
 
292
294
  {underlyingValueHasChanged && !isSubmitting &&
293
295
  <Typography variant={"caption"} className={"ml-3.5"}>
294
- This value has been updated elsewhere
296
+ {t("value_updated_elsewhere")}
295
297
  </Typography>}
296
298
 
297
299
  </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
 
@@ -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}