@firecms/core 3.0.0 → 3.1.0-canary.02232f4

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 (340) hide show
  1. package/README.md +1 -1
  2. package/dist/components/AIIcon.d.ts +16 -0
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +7 -1
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +14 -0
  6. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +6 -0
  7. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -4
  8. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +6 -0
  9. package/dist/components/EntityCollectionTable/internal/popup_field/useDraggable.d.ts +2 -2
  10. package/dist/components/EntityCollectionView/Board.d.ts +2 -0
  11. package/dist/components/EntityCollectionView/BoardColumn.d.ts +42 -0
  12. package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +9 -0
  13. package/dist/components/EntityCollectionView/BoardSortableList.d.ts +14 -0
  14. package/dist/components/EntityCollectionView/CollectionDataErrorBanner.d.ts +4 -0
  15. package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +26 -0
  16. package/dist/components/EntityCollectionView/EntityCard.d.ts +19 -0
  17. package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +20 -0
  18. package/dist/components/EntityCollectionView/EntityCollectionCardView.d.ts +31 -0
  19. package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
  20. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +7 -3
  21. package/dist/components/EntityCollectionView/FiltersDialog.d.ts +14 -0
  22. package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +44 -0
  23. package/dist/components/EntityCollectionView/board_types.d.ts +105 -0
  24. package/dist/components/EntityCollectionView/useBoardDataController.d.ts +60 -0
  25. package/dist/components/ErrorBoundary.d.ts +4 -2
  26. package/dist/components/HomePage/DefaultHomePage.d.ts +0 -1
  27. package/dist/components/LanguageToggle.d.ts +1 -0
  28. package/dist/components/SelectableTable/SelectableTable.d.ts +5 -1
  29. package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -1
  30. package/dist/components/UnsavedChangesDialog.d.ts +1 -0
  31. package/dist/components/VirtualTable/VirtualTable.performance.test.d.ts +1 -0
  32. package/dist/components/VirtualTable/VirtualTableCell.d.ts +6 -0
  33. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +4 -1
  34. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  35. package/dist/components/VirtualTable/VirtualTableProps.d.ts +17 -1
  36. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
  37. package/dist/components/VirtualTable/types.d.ts +3 -0
  38. package/dist/components/index.d.ts +4 -0
  39. package/dist/contexts/index.d.ts +10 -0
  40. package/dist/core/DrawerNavigationGroup.d.ts +45 -0
  41. package/dist/core/index.d.ts +1 -0
  42. package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
  43. package/dist/editor/components/editor-bubble-item.d.ts +8 -0
  44. package/dist/editor/components/editor-bubble.d.ts +8 -0
  45. package/dist/editor/components/image-bubble.d.ts +5 -0
  46. package/dist/editor/components/index.d.ts +16 -0
  47. package/dist/editor/components/table-bubble.d.ts +5 -0
  48. package/dist/editor/editor.d.ts +30 -0
  49. package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
  50. package/dist/editor/extensions/Image/index.d.ts +6 -0
  51. package/dist/editor/extensions/Image.d.ts +6 -0
  52. package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
  53. package/dist/editor/extensions/clipboard.d.ts +7 -0
  54. package/dist/editor/extensions/custom-keymap.d.ts +1 -0
  55. package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
  56. package/dist/editor/hooks/useProseMirror.d.ts +13 -0
  57. package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
  58. package/dist/editor/index.d.ts +2 -0
  59. package/dist/editor/markdown.d.ts +5 -0
  60. package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
  61. package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
  62. package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
  63. package/dist/editor/nodeViews/index.d.ts +6 -0
  64. package/dist/editor/plugins/index.d.ts +2 -0
  65. package/dist/editor/plugins/inputrules.d.ts +6 -0
  66. package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
  67. package/dist/editor/plugins/slashCommandPlugin.d.ts +12 -0
  68. package/dist/editor/schema.d.ts +2 -0
  69. package/dist/editor/selectors/ai-selector.d.ts +0 -0
  70. package/dist/editor/selectors/color-selector.d.ts +10 -0
  71. package/dist/editor/selectors/link-selector.d.ts +8 -0
  72. package/dist/editor/selectors/node-selector.d.ts +15 -0
  73. package/dist/editor/selectors/text-buttons.d.ts +1 -0
  74. package/dist/editor/types.d.ts +5 -0
  75. package/dist/editor/useProseMirror.d.ts +16 -0
  76. package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
  77. package/dist/editor/utils/remove_classes.d.ts +1 -0
  78. package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
  79. package/dist/form/components/ErrorFocus.d.ts +1 -1
  80. package/dist/form/components/LocalChangesMenu.d.ts +2 -2
  81. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  82. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  83. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  84. package/dist/form/validation.d.ts +3 -2
  85. package/dist/hooks/index.d.ts +1 -0
  86. package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
  87. package/dist/hooks/useBuildNavigationController.d.ts +0 -1
  88. package/dist/hooks/useCollapsedGroups.d.ts +6 -3
  89. package/dist/hooks/useTranslation.d.ts +17 -0
  90. package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
  91. package/dist/index.d.ts +5 -0
  92. package/dist/index.es.js +31028 -16080
  93. package/dist/index.es.js.map +1 -1
  94. package/dist/index.umd.js +29955 -15028
  95. package/dist/index.umd.js.map +1 -1
  96. package/dist/internal/useRestoreScroll.d.ts +1 -1
  97. package/dist/locales/de.d.ts +2 -0
  98. package/dist/locales/en.d.ts +10 -0
  99. package/dist/locales/es.d.ts +10 -0
  100. package/dist/locales/fr.d.ts +2 -0
  101. package/dist/locales/hi.d.ts +2 -0
  102. package/dist/locales/it.d.ts +2 -0
  103. package/dist/locales/pt.d.ts +7 -0
  104. package/dist/preview/PropertyPreviewProps.d.ts +5 -0
  105. package/dist/preview/components/DatePreview.d.ts +13 -3
  106. package/dist/preview/components/ImagePreview.d.ts +5 -1
  107. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  108. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  109. package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
  110. package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
  111. package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
  112. package/dist/types/analytics.d.ts +1 -1
  113. package/dist/types/collections.d.ts +88 -2
  114. package/dist/types/customization_controller.d.ts +2 -1
  115. package/dist/types/datasource.d.ts +0 -1
  116. package/dist/types/entities.d.ts +1 -0
  117. package/dist/types/firecms.d.ts +2 -1
  118. package/dist/types/index.d.ts +1 -0
  119. package/dist/types/navigation.d.ts +2 -2
  120. package/dist/types/plugins.d.ts +69 -1
  121. package/dist/types/properties.d.ts +277 -12
  122. package/dist/types/storage.d.ts +9 -0
  123. package/dist/types/translations.d.ts +669 -0
  124. package/dist/util/__tests__/conditions.test.d.ts +1 -0
  125. package/dist/util/__tests__/objects.test.d.ts +1 -0
  126. package/dist/util/conditions.d.ts +26 -0
  127. package/dist/util/entities.d.ts +2 -3
  128. package/dist/util/index.d.ts +3 -1
  129. package/dist/util/lazy_eager.d.ts +7 -0
  130. package/dist/util/objects.d.ts +1 -0
  131. package/dist/util/property_utils.d.ts +2 -1
  132. package/dist/util/resolutions.d.ts +3 -3
  133. package/dist/util/useStorageUploadController.d.ts +11 -2
  134. package/package.json +52 -12
  135. package/src/app/Scaffold.tsx +20 -19
  136. package/src/components/AIIcon.tsx +41 -0
  137. package/src/components/ArrayContainer.tsx +7 -8
  138. package/src/components/ClearFilterSortButton.tsx +25 -19
  139. package/src/components/ConfirmationDialog.tsx +4 -4
  140. package/src/components/DeleteEntityDialog.tsx +12 -11
  141. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +82 -43
  142. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
  143. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
  144. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
  145. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
  146. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +24 -44
  147. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
  148. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
  149. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
  150. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
  151. package/src/components/EntityCollectionView/Board.tsx +324 -0
  152. package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
  153. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
  154. package/src/components/EntityCollectionView/BoardSortableList.tsx +174 -0
  155. package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
  156. package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
  157. package/src/components/EntityCollectionView/EntityCard.tsx +235 -0
  158. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +706 -0
  159. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +236 -0
  160. package/src/components/EntityCollectionView/EntityCollectionView.tsx +531 -209
  161. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +35 -22
  162. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +86 -15
  163. package/src/components/EntityCollectionView/FiltersDialog.tsx +252 -0
  164. package/src/components/EntityCollectionView/ViewModeToggle.tsx +202 -0
  165. package/src/components/EntityCollectionView/board_types.ts +113 -0
  166. package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
  167. package/src/components/EntityJsonPreview.tsx +2 -1
  168. package/src/components/EntityPreview.tsx +1 -1
  169. package/src/components/EntityView.tsx +3 -2
  170. package/src/components/ErrorBoundary.tsx +27 -15
  171. package/src/components/ErrorTooltip.tsx +2 -1
  172. package/src/components/HomePage/DefaultHomePage.tsx +65 -22
  173. package/src/components/HomePage/HomePageDnD.tsx +59 -42
  174. package/src/components/HomePage/NavigationCard.tsx +20 -18
  175. package/src/components/HomePage/NavigationGroup.tsx +20 -17
  176. package/src/components/HomePage/RenameGroupDialog.tsx +15 -15
  177. package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
  178. package/src/components/LanguageToggle.tsx +66 -0
  179. package/src/components/NotFoundPage.tsx +5 -3
  180. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +12 -17
  181. package/src/components/ReferenceWidget.tsx +5 -6
  182. package/src/components/SearchIconsView.tsx +3 -1
  183. package/src/components/SelectableTable/SelectableTable.tsx +75 -67
  184. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
  185. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +50 -40
  186. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +53 -40
  187. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +60 -58
  188. package/src/components/UnsavedChangesDialog.tsx +6 -6
  189. package/src/components/UserDisplay.tsx +4 -4
  190. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +387 -0
  191. package/src/components/VirtualTable/VirtualTable.tsx +277 -121
  192. package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
  193. package/src/components/VirtualTable/VirtualTableHeader.tsx +76 -64
  194. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +163 -42
  195. package/src/components/VirtualTable/VirtualTableProps.tsx +21 -2
  196. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  197. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
  198. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +19 -6
  199. package/src/components/VirtualTable/types.tsx +3 -0
  200. package/src/components/common/default_entity_actions.tsx +4 -0
  201. package/src/components/common/useColumnsIds.tsx +95 -3
  202. package/src/components/common/useDataSourceTableController.tsx +12 -4
  203. package/src/components/index.tsx +5 -0
  204. package/src/contexts/BreacrumbsContext.tsx +15 -8
  205. package/src/contexts/index.ts +10 -0
  206. package/src/core/DefaultAppBar.tsx +49 -32
  207. package/src/core/DefaultDrawer.tsx +49 -57
  208. package/src/core/DrawerNavigationGroup.tsx +120 -0
  209. package/src/core/DrawerNavigationItem.tsx +4 -3
  210. package/src/core/EntityEditView.tsx +94 -50
  211. package/src/core/EntityEditViewFormActions.tsx +24 -17
  212. package/src/core/EntitySidePanel.tsx +34 -30
  213. package/src/core/FireCMS.tsx +33 -6
  214. package/src/core/SideDialogs.tsx +4 -2
  215. package/src/core/field_configs.tsx +18 -11
  216. package/src/core/index.tsx +1 -0
  217. package/src/editor/components/SlashCommandMenu.tsx +516 -0
  218. package/src/editor/components/editor-bubble-item.tsx +32 -0
  219. package/src/editor/components/editor-bubble.tsx +118 -0
  220. package/src/editor/components/image-bubble.tsx +156 -0
  221. package/src/editor/components/index.ts +14 -0
  222. package/src/editor/components/table-bubble.tsx +165 -0
  223. package/src/editor/editor.tsx +455 -0
  224. package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
  225. package/src/editor/extensions/Image/index.ts +133 -0
  226. package/src/editor/extensions/Image.ts +159 -0
  227. package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
  228. package/src/editor/extensions/clipboard.ts +72 -0
  229. package/src/editor/extensions/custom-keymap.ts +24 -0
  230. package/src/editor/extensions/drag-and-drop.tsx +480 -0
  231. package/src/editor/hooks/useProseMirror.ts +124 -0
  232. package/src/editor/hooks/useProseMirrorContext.ts +15 -0
  233. package/src/editor/index.ts +2 -0
  234. package/src/editor/markdown.ts +172 -0
  235. package/src/editor/nodeViews/ImageComponent.tsx +20 -0
  236. package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
  237. package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
  238. package/src/editor/nodeViews/index.ts +35 -0
  239. package/src/editor/plugins/index.ts +58 -0
  240. package/src/editor/plugins/inputrules.ts +82 -0
  241. package/src/editor/plugins/placeholderPlugin.ts +55 -0
  242. package/src/editor/plugins/slashCommandPlugin.ts +61 -0
  243. package/src/editor/schema.ts +240 -0
  244. package/src/editor/selectors/ai-selector.tsx +111 -0
  245. package/src/editor/selectors/color-selector.tsx +200 -0
  246. package/src/editor/selectors/link-selector.tsx +118 -0
  247. package/src/editor/selectors/node-selector.tsx +157 -0
  248. package/src/editor/selectors/text-buttons.tsx +86 -0
  249. package/src/editor/types.ts +6 -0
  250. package/src/editor/useProseMirror.ts +126 -0
  251. package/src/editor/utils/prosemirror-utils.ts +108 -0
  252. package/src/editor/utils/remove_classes.ts +17 -0
  253. package/src/editor/utils/useDebouncedCallback.ts +25 -0
  254. package/src/form/EntityForm.tsx +150 -75
  255. package/src/form/EntityFormActions.tsx +19 -12
  256. package/src/form/PropertyFieldBinding.tsx +68 -51
  257. package/src/form/components/ErrorFocus.tsx +3 -3
  258. package/src/form/components/LocalChangesMenu.tsx +19 -19
  259. package/src/form/components/StorageItemPreview.tsx +5 -3
  260. package/src/form/components/StorageUploadProgress.tsx +22 -6
  261. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +18 -5
  262. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +22 -10
  263. package/src/form/field_bindings/BlockFieldBinding.tsx +26 -9
  264. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -17
  265. package/src/form/field_bindings/KeyValueFieldBinding.tsx +46 -25
  266. package/src/form/field_bindings/MapFieldBinding.tsx +88 -70
  267. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +93 -52
  268. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +15 -1
  269. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +25 -11
  270. package/src/form/field_bindings/ReferenceFieldBinding.tsx +25 -11
  271. package/src/form/field_bindings/RepeatFieldBinding.tsx +21 -6
  272. package/src/form/field_bindings/SelectFieldBinding.tsx +7 -5
  273. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +110 -92
  274. package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -14
  275. package/src/form/field_bindings/TextFieldBinding.tsx +77 -38
  276. package/src/form/field_bindings/UserSelectFieldBinding.tsx +7 -5
  277. package/src/form/validation.ts +245 -160
  278. package/src/hooks/index.tsx +1 -0
  279. package/src/hooks/useBreadcrumbsController.tsx +18 -0
  280. package/src/hooks/useBuildNavigationController.tsx +91 -41
  281. package/src/hooks/useCollapsedGroups.ts +18 -9
  282. package/src/hooks/useTranslation.ts +31 -0
  283. package/src/hooks/useValidateAuthenticator.tsx +1 -1
  284. package/src/i18n/FireCMSi18nProvider.tsx +160 -0
  285. package/src/index.ts +5 -0
  286. package/src/internal/useBuildDataSource.ts +68 -34
  287. package/src/internal/useBuildSideDialogsController.tsx +11 -8
  288. package/src/internal/useBuildSideEntityController.tsx +24 -24
  289. package/src/internal/useRestoreScroll.tsx +26 -14
  290. package/src/locales/de.ts +718 -0
  291. package/src/locales/en.ts +730 -0
  292. package/src/locales/es.ts +730 -0
  293. package/src/locales/fr.ts +718 -0
  294. package/src/locales/hi.ts +718 -0
  295. package/src/locales/it.ts +718 -0
  296. package/src/locales/pt.ts +727 -0
  297. package/src/preview/PropertyPreview.tsx +43 -33
  298. package/src/preview/PropertyPreviewProps.tsx +6 -0
  299. package/src/preview/components/DatePreview.tsx +72 -4
  300. package/src/preview/components/EmptyValue.tsx +1 -1
  301. package/src/preview/components/ImagePreview.tsx +37 -21
  302. package/src/preview/components/ReferencePreview.tsx +8 -2
  303. package/src/preview/components/StorageThumbnail.tsx +16 -12
  304. package/src/preview/components/UrlComponentPreview.tsx +32 -27
  305. package/src/preview/components/UserPreview.tsx +3 -1
  306. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
  307. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
  308. package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
  309. package/src/preview/property_previews/MapPropertyPreview.tsx +49 -27
  310. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
  311. package/src/routes/CustomCMSRoute.tsx +1 -0
  312. package/src/routes/FireCMSRoute.tsx +87 -65
  313. package/src/types/analytics.ts +10 -0
  314. package/src/types/collections.ts +97 -3
  315. package/src/types/customization_controller.tsx +2 -1
  316. package/src/types/datasource.ts +54 -56
  317. package/src/types/entities.ts +10 -0
  318. package/src/types/firecms.tsx +2 -1
  319. package/src/types/index.ts +1 -0
  320. package/src/types/navigation.ts +2 -2
  321. package/src/types/plugins.tsx +77 -1
  322. package/src/types/properties.ts +369 -37
  323. package/src/types/storage.ts +11 -1
  324. package/src/types/translations.ts +752 -0
  325. package/src/util/__tests__/conditions.test.ts +506 -0
  326. package/src/util/__tests__/objects.test.ts +196 -0
  327. package/src/util/callbacks.ts +6 -3
  328. package/src/util/collections.ts +51 -6
  329. package/src/util/conditions.ts +339 -0
  330. package/src/util/entities.ts +29 -30
  331. package/src/util/entity_cache.ts +2 -1
  332. package/src/util/index.ts +3 -1
  333. package/src/util/join_collections.ts +10 -8
  334. package/src/util/lazy_eager.tsx +33 -0
  335. package/src/util/objects.ts +46 -13
  336. package/src/util/{references.ts → previews.ts} +16 -2
  337. package/src/util/property_utils.tsx +37 -11
  338. package/src/util/resolutions.ts +62 -58
  339. package/src/util/useStorageUploadController.tsx +34 -30
  340. /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
@@ -11,6 +11,7 @@ import {
11
11
  } from "../types";
12
12
 
13
13
  import { resolveProperty } from "../util";
14
+ import { jsonStringifyReplacer } from "../util/objects";
14
15
 
15
16
  import { PropertyPreviewProps } from "./PropertyPreviewProps";
16
17
  import { useAuthController, useCustomizationController } from "../hooks";
@@ -49,7 +50,8 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
49
50
  size,
50
51
  height,
51
52
  width,
52
- interactive
53
+ interactive,
54
+ fill
53
55
  } = props;
54
56
 
55
57
  const property = resolveProperty({
@@ -60,7 +62,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
60
62
  });
61
63
 
62
64
  if (property === null) {
63
- content = <EmptyValue/>;
65
+ content = <EmptyValue />;
64
66
  } else if (property.Preview) {
65
67
  content = createElement(property.Preview as React.ComponentType<PropertyPreviewProps>,
66
68
  {
@@ -74,7 +76,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
74
76
  customProps: property.customProps
75
77
  });
76
78
  } else if (value === undefined || value === null) {
77
- content = <EmptyValue/>;
79
+ content = <EmptyValue />;
78
80
  } else if (property.dataType === "string") {
79
81
  const stringProperty = property as ResolvedStringProperty;
80
82
  if (typeof value === "string") {
@@ -84,20 +86,23 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
84
86
  interactive={interactive}
85
87
  storeUrl={property.storage?.storeUrl ?? false}
86
88
  size={props.size}
87
- storagePathOrDownloadUrl={filePath}/>;
89
+ fill={fill}
90
+ storagePathOrDownloadUrl={filePath} />;
88
91
  } else if (stringProperty.url) {
89
92
  if (typeof stringProperty.url === "boolean")
90
93
  content =
91
94
  <UrlComponentPreview size={props.size}
92
- url={value}/>;
95
+ url={value}
96
+ fill={fill} />;
93
97
  else if (typeof stringProperty.url === "string")
94
98
  content =
95
99
  <UrlComponentPreview size={props.size}
96
- url={value}
97
- interactive={interactive}
98
- previewType={stringProperty.url}/>;
100
+ url={value}
101
+ interactive={interactive}
102
+ fill={fill}
103
+ previewType={stringProperty.url} />;
99
104
  } else if (stringProperty.markdown) {
100
- content = <Markdown source={value} size={"small"}/>;
105
+ content = <Markdown source={value} size={"small"} />;
101
106
  } else if (stringProperty.userSelect) {
102
107
  content = <UserPreview
103
108
  value={value}
@@ -116,13 +121,13 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
116
121
  reference={new EntityReference(value, stringProperty.reference.path)}
117
122
  />;
118
123
  } else {
119
- content = <EmptyValue/>;
124
+ content = <EmptyValue />;
120
125
  }
121
126
 
122
127
  } else {
123
128
  content = <StringPropertyPreview {...props}
124
- property={stringProperty}
125
- value={value}/>;
129
+ property={stringProperty}
130
+ value={value} />;
126
131
  }
127
132
  } else {
128
133
  content = buildWrongValueType(propertyKey, property.dataType, value);
@@ -137,43 +142,43 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
137
142
  if (arrayProperty.of) {
138
143
  if (Array.isArray(arrayProperty.of)) {
139
144
  content = <ArrayPropertyPreview {...props}
140
- value={value}
141
- property={property as ResolvedArrayProperty}/>;
145
+ value={value}
146
+ property={property as ResolvedArrayProperty} />;
142
147
  } else if (arrayProperty.of.dataType === "reference") {
143
148
  content = <ArrayOfReferencesPreview {...props}
144
- value={value}
145
- property={property as ResolvedArrayProperty}/>;
149
+ value={value}
150
+ property={property as ResolvedArrayProperty} />;
146
151
  } else if (arrayProperty.of.dataType === "string") {
147
152
  if (arrayProperty.of.enumValues) {
148
153
  content = <ArrayPropertyEnumPreview
149
154
  {...props}
150
155
  value={value as string[]}
151
- property={property as ResolvedArrayProperty}/>;
156
+ property={property as ResolvedArrayProperty} />;
152
157
  } else if (arrayProperty.of.storage) {
153
158
  content = <ArrayOfStorageComponentsPreview
154
159
  {...props}
155
160
  value={value}
156
- property={property as ResolvedArrayProperty}/>;
161
+ property={property as ResolvedArrayProperty} />;
157
162
  } else {
158
163
  content = <ArrayOfStringsPreview
159
164
  {...props}
160
165
  value={value as string[]}
161
- property={property as ResolvedArrayProperty}/>;
166
+ property={property as ResolvedArrayProperty} />;
162
167
  }
163
168
  } else if (arrayProperty.of.dataType === "number" && arrayProperty.of.enumValues) {
164
169
  content = <ArrayPropertyEnumPreview
165
170
  {...props}
166
171
  value={value as string[]}
167
- property={property as ResolvedArrayProperty}/>;
172
+ property={property as ResolvedArrayProperty} />;
168
173
  } else {
169
174
  content = <ArrayPropertyPreview {...props}
170
- value={value}
171
- property={property as ResolvedArrayProperty}/>;
175
+ value={value}
176
+ property={property as ResolvedArrayProperty} />;
172
177
  }
173
178
  } else if (arrayProperty.oneOf) {
174
179
  content = <ArrayOneOfPreview {...props}
175
- value={value}
176
- property={property as ResolvedArrayProperty}/>;
180
+ value={value}
181
+ property={property as ResolvedArrayProperty} />;
177
182
  }
178
183
  } else {
179
184
  content = buildWrongValueType(propertyKey, property.dataType, value);
@@ -182,13 +187,18 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
182
187
  if (typeof value === "object") {
183
188
  content =
184
189
  <MapPropertyPreview {...props}
185
- property={property as ResolvedMapProperty}/>;
190
+ value={value as Record<string, CMSType>}
191
+ property={property as ResolvedMapProperty} />;
186
192
  } else {
187
193
  content = buildWrongValueType(propertyKey, property.dataType, value);
188
194
  }
189
195
  } else if (property.dataType === "date") {
190
196
  if (value instanceof Date) {
191
- content = <DatePreview date={value}/>;
197
+ content = <DatePreview
198
+ date={value}
199
+ mode={property.mode}
200
+ timezone={property.timezone}
201
+ />;
192
202
  } else {
193
203
  content = buildWrongValueType(propertyKey, property.dataType, value);
194
204
  }
@@ -207,29 +217,29 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
207
217
  content = buildWrongValueType(propertyKey, property.dataType, value);
208
218
  }
209
219
  } else {
210
- content = <EmptyValue/>;
220
+ content = <EmptyValue />;
211
221
  }
212
222
 
213
223
  } else if (property.dataType === "boolean") {
214
224
  if (typeof value === "boolean") {
215
- content = <BooleanPreview value={value} size={size} property={property}/>;
225
+ content = <BooleanPreview value={value} size={size} property={property} />;
216
226
  } else {
217
227
  content = buildWrongValueType(propertyKey, property.dataType, value);
218
228
  }
219
229
  } else if (property.dataType === "number") {
220
230
  if (typeof value === "number") {
221
231
  content = <NumberPropertyPreview {...props}
222
- value={value}
223
- property={property as ResolvedNumberProperty}/>;
232
+ value={value}
233
+ property={property as ResolvedNumberProperty} />;
224
234
  } else {
225
235
  content = buildWrongValueType(propertyKey, property.dataType, value);
226
236
  }
227
237
  } else {
228
- content = JSON.stringify(value);
238
+ content = JSON.stringify(value, jsonStringifyReplacer);
229
239
  }
230
240
 
231
241
  return content === undefined || content === null || (Array.isArray(content) && content.length === 0)
232
- ? <EmptyValue/>
242
+ ? <EmptyValue />
233
243
  : content;
234
244
  }, equal);
235
245
 
@@ -237,6 +247,6 @@ function buildWrongValueType(name: string | undefined, dataType: string, value:
237
247
  console.warn(`Unexpected value for property ${name}, of type ${dataType}`, value);
238
248
  return (
239
249
  <ErrorView title={"Unexpected value"}
240
- error={`${JSON.stringify(value)}`}/>
250
+ error={`${JSON.stringify(value, jsonStringifyReplacer)}`} />
241
251
  );
242
252
  }
@@ -52,4 +52,10 @@ export interface PropertyPreviewProps<T extends CMSType = any, CustomProps = any
52
52
  */
53
53
  interactive?: boolean;
54
54
 
55
+ /**
56
+ * If true, image previews will fill their container completely.
57
+ * Only applies to image type properties.
58
+ */
59
+ fill?: boolean;
60
+
55
61
  }
@@ -5,18 +5,86 @@ import * as locales from "date-fns/locale";
5
5
  import { useCustomizationController } from "../../hooks";
6
6
  import { defaultDateFormat } from "../../util";
7
7
 
8
+ export interface DatePreviewProps {
9
+ date: Date;
10
+ /**
11
+ * Display mode: "date" for date-only, "date_time" for date and time
12
+ */
13
+ mode?: "date" | "date_time";
14
+ /**
15
+ * IANA timezone identifier (e.g., "America/New_York")
16
+ * When specified, the date will be displayed in this timezone
17
+ */
18
+ timezone?: string;
19
+ }
20
+
8
21
  /**
9
22
  * @group Preview components
10
23
  */
11
24
  export function DatePreview({
12
- date
13
- }: { date: Date }): React.ReactElement {
25
+ date,
26
+ mode = "date_time",
27
+ timezone
28
+ }: DatePreviewProps): React.ReactElement {
14
29
 
15
30
  const customizationController = useCustomizationController();
16
31
  // @ts-ignore
17
32
  const dateUtilsLocale = customizationController?.locale ? locales[customizationController?.locale] : undefined;
18
- const dateFormat: string = customizationController?.dateTimeFormat ?? defaultDateFormat;
19
- const formattedDate = date ? format(date, dateFormat, { locale: dateUtilsLocale }) : "";
33
+
34
+ if (!date) {
35
+ return <></>;
36
+ }
37
+
38
+ // If timezone is specified, format in that timezone using Intl.DateTimeFormat
39
+ if (timezone) {
40
+ const options: Intl.DateTimeFormatOptions = {
41
+ year: "numeric",
42
+ month: "short",
43
+ day: "numeric",
44
+ timeZone: timezone
45
+ };
46
+
47
+ if (mode === "date_time") {
48
+ options.hour = "2-digit";
49
+ options.minute = "2-digit";
50
+ }
51
+
52
+ const formatter = new Intl.DateTimeFormat(customizationController?.locale ?? "en-US", options);
53
+ const formattedDate = formatter.format(date);
54
+
55
+ // Get timezone abbreviation
56
+ const tzFormatter = new Intl.DateTimeFormat("en-US", {
57
+ timeZone: timezone,
58
+ timeZoneName: "short"
59
+ });
60
+ const parts = tzFormatter.formatToParts(date);
61
+ const tzAbbrev = parts.find(p => p.type === "timeZoneName")?.value ?? "";
62
+
63
+ return (
64
+ <span className="flex items-center gap-1">
65
+ {formattedDate}
66
+ {tzAbbrev && (
67
+ <span className="text-xs text-slate-500 dark:text-slate-400">
68
+ ({tzAbbrev})
69
+ </span>
70
+ )}
71
+ </span>
72
+ );
73
+ }
74
+
75
+ // No timezone specified: use local formatting with date-fns
76
+ let dateFormat: string;
77
+ if (mode === "date") {
78
+ // Date-only format (no time)
79
+ dateFormat = customizationController?.dateTimeFormat
80
+ ? customizationController.dateTimeFormat.replace(/[, ]*[HhKk].*$/, "").trim()
81
+ : "PP"; // e.g., "Apr 29, 2024"
82
+ } else {
83
+ // Full date-time format
84
+ dateFormat = customizationController?.dateTimeFormat ?? defaultDateFormat;
85
+ }
86
+
87
+ const formattedDate = format(date, dateFormat, { locale: dateUtilsLocale });
20
88
 
21
89
  return (
22
90
  <>
@@ -6,5 +6,5 @@ import React from "react";
6
6
  export function EmptyValue() {
7
7
 
8
8
  return <div
9
- className="rounded-full bg-surface-200 bg-opacity-30 dark:bg-opacity-20 w-5 h-2 inline-block"/>;
9
+ className="rounded-full bg-surface-200 bg-opacity-30 bg-surface-200/30 dark:bg-opacity-20 dark:bg-surface-200/20 w-5 h-2 inline-block"/>;
10
10
  }
@@ -9,39 +9,55 @@ import { ContentCopyIcon, IconButton, OpenInNewIcon, Tooltip } from "@firecms/ui
9
9
  */
10
10
  export interface ImagePreviewProps {
11
11
  size: PreviewSize,
12
- url: string
12
+ url: string,
13
+ /**
14
+ * If true, image fills its container completely with object-fit cover
15
+ */
16
+ fill?: boolean
13
17
  }
14
18
 
15
19
  /**
16
20
  * @group Preview components
17
21
  */
18
22
  export function ImagePreview({
19
- size,
20
- url
21
- }: ImagePreviewProps) {
23
+ size,
24
+ url,
25
+ fill
26
+ }: ImagePreviewProps) {
22
27
 
23
28
  const imageSize = useMemo(() => getThumbnailMeasure(size), [size]);
24
29
 
30
+ // Fill mode - image fills its container completely
31
+ if (fill) {
32
+ return (
33
+ <img src={url}
34
+ className={"w-full h-full object-cover"}
35
+ key={"fill_image_preview_" + url}
36
+ loading="lazy"
37
+ />
38
+ );
39
+ }
40
+
25
41
  if (size === "small") {
26
42
  return (
27
43
  <img src={url}
28
- className={"rounded-md"}
29
- key={"tiny_image_preview_" + url}
30
- style={{
31
- position: "relative",
32
- objectFit: "cover",
33
- width: imageSize,
34
- height: imageSize,
35
- maxHeight: "100%"
36
- }}/>
44
+ className={"rounded-md"}
45
+ key={"tiny_image_preview_" + url}
46
+ style={{
47
+ position: "relative",
48
+ objectFit: "cover",
49
+ width: imageSize,
50
+ height: imageSize,
51
+ maxHeight: "100%"
52
+ }} />
37
53
  );
38
54
  }
39
55
 
40
56
  const imageStyle: CSSProperties =
41
- {
42
- maxWidth: "100%",
43
- maxHeight: "100%"
44
- };
57
+ {
58
+ maxWidth: "100%",
59
+ maxHeight: "100%"
60
+ };
45
61
 
46
62
  return (
47
63
  <div
@@ -53,8 +69,8 @@ export function ImagePreview({
53
69
  key={"image_preview_" + url}>
54
70
 
55
71
  <img src={url}
56
- className={"rounded-md"}
57
- style={imageStyle}/>
72
+ className={"rounded-md"}
73
+ style={imageStyle} />
58
74
 
59
75
  <div className={"flex flex-row gap-2 absolute bottom-[-4px] right-[-4px] invisible group-hover:visible"}>
60
76
  {navigator && <Tooltip
@@ -69,7 +85,7 @@ export function ImagePreview({
69
85
  return navigator.clipboard.writeText(url);
70
86
  }}>
71
87
  <ContentCopyIcon className={"text-surface-700 dark:text-surface-300"}
72
- size={"smallest"}/>
88
+ size={"smallest"} />
73
89
  </IconButton>
74
90
  </Tooltip>}
75
91
 
@@ -85,7 +101,7 @@ export function ImagePreview({
85
101
  onClick={(e: any) => e.stopPropagation()}
86
102
  >
87
103
  <OpenInNewIcon className={"text-surface-700 dark:text-surface-300"}
88
- size={"smallest"}/>
104
+ size={"smallest"} />
89
105
  </IconButton>
90
106
  </Tooltip>
91
107
  </div>
@@ -6,6 +6,7 @@ import { PreviewSize } from "../PropertyPreviewProps";
6
6
  import { Skeleton } from "@firecms/ui";
7
7
  import { ErrorBoundary, ErrorView } from "../../components";
8
8
  import { EntityPreview, EntityPreviewContainer } from "../../components/EntityPreview";
9
+ import { jsonStringifyReplacer } from "../../util/objects";
9
10
 
10
11
  export type ReferencePreviewProps = {
11
12
  disabled?: boolean;
@@ -29,7 +30,7 @@ export const ReferencePreview = function ReferencePreview(props: ReferencePrevie
29
30
  onClick={props.onClick}
30
31
  size={props.size ?? "medium"}>
31
32
  <ErrorView error={"Unexpected value. Click to edit"}
32
- tooltip={JSON.stringify(reference)}/>
33
+ tooltip={JSON.stringify(reference, jsonStringifyReplacer)}/>
33
34
  </EntityPreviewContainer>;
34
35
  }
35
36
  return <ErrorBoundary>
@@ -57,7 +58,12 @@ function ReferencePreviewInternal({
57
58
  if (customizationController.components?.missingReference) {
58
59
  return <customizationController.components.missingReference path={reference.path}/>;
59
60
  } else {
60
- throw Error(`Couldn't find the corresponding collection view for the path: ${reference.path}`);
61
+ return <EntityPreviewContainer
62
+ onClick={onClick}
63
+ size={size ?? "medium"}>
64
+ <ErrorView error={"Unexpected reference value. Click to edit"}
65
+ tooltip={reference.pathWithId}/>
66
+ </EntityPreviewContainer>;
61
67
  }
62
68
  }
63
69
 
@@ -12,6 +12,7 @@ type StorageThumbnailProps = {
12
12
  storeUrl: boolean;
13
13
  size: PreviewSize;
14
14
  interactive?: boolean;
15
+ fill?: boolean;
15
16
  };
16
17
 
17
18
  /**
@@ -22,18 +23,20 @@ export const StorageThumbnail = React.memo<StorageThumbnailProps>(StorageThumbna
22
23
  function areEqual(prevProps: StorageThumbnailProps, nextProps: StorageThumbnailProps) {
23
24
  return prevProps.size === nextProps.size &&
24
25
  prevProps.storagePathOrDownloadUrl === nextProps.storagePathOrDownloadUrl &&
25
- prevProps.storeUrl === nextProps.storeUrl&&
26
- prevProps.interactive === nextProps.interactive;
26
+ prevProps.storeUrl === nextProps.storeUrl &&
27
+ prevProps.interactive === nextProps.interactive &&
28
+ prevProps.fill === nextProps.fill;
27
29
  }
28
30
 
29
31
  const URL_CACHE: Record<string, DownloadConfig> = {};
30
32
 
31
33
  export function StorageThumbnailInternal({
32
- storeUrl,
33
- interactive,
34
- storagePathOrDownloadUrl,
35
- size
36
- }: StorageThumbnailProps) {
34
+ storeUrl,
35
+ interactive,
36
+ storagePathOrDownloadUrl,
37
+ size,
38
+ fill
39
+ }: StorageThumbnailProps) {
37
40
 
38
41
  const [error, setError] = React.useState<Error | undefined>(undefined);
39
42
  const storage = useStorageSource();
@@ -70,11 +73,12 @@ export function StorageThumbnailInternal({
70
73
 
71
74
  return downloadConfig?.url
72
75
  ? <UrlComponentPreview previewType={previewType}
73
- url={downloadConfig.url}
74
- interactive={interactive}
75
- size={size}
76
- hint={storagePathOrDownloadUrl}/>
77
- : renderSkeletonImageThumbnail(size);
76
+ url={downloadConfig.url}
77
+ interactive={interactive}
78
+ size={size}
79
+ fill={fill}
80
+ hint={storagePathOrDownloadUrl} />
81
+ : renderSkeletonImageThumbnail(size, fill);
78
82
  }
79
83
 
80
84
  function getFiletype(input: string): FileType {
@@ -6,36 +6,41 @@ import { PreviewType } from "../../types";
6
6
  import { PreviewSize } from "../PropertyPreviewProps";
7
7
  import { cls, DescriptionIcon, OpenInNewIcon, Tooltip, Typography } from "@firecms/ui";
8
8
  import { EmptyValue } from "./EmptyValue";
9
+ import { useTranslation } from "../../hooks/useTranslation";
9
10
 
10
11
  /**
11
12
  * @group Preview components
12
13
  */
13
14
  export function UrlComponentPreview({
14
- url,
15
- previewType,
16
- size,
17
- hint,
18
- interactive = true
19
- }: {
15
+ url,
16
+ previewType,
17
+ size,
18
+ hint,
19
+ interactive = true,
20
+ fill
21
+ }: {
20
22
  url: string,
21
23
  previewType?: PreviewType,
22
24
  size: PreviewSize,
23
25
  hint?: string,
24
26
  // for video controls
25
- interactive?: boolean
27
+ interactive?: boolean,
28
+ fill?: boolean
26
29
  }): React.ReactElement {
27
30
 
31
+ const { t } = useTranslation();
32
+
28
33
  if (!previewType) {
29
- if (!url || !url.trim()) return <EmptyValue/>;
34
+ if (!url || !url.trim()) return <EmptyValue />;
30
35
  return (
31
36
  <a className="flex gap-4 break-words items-center font-medium text-primary visited:text-primary dark:visited:text-primary dark:text-primary"
32
- href={url}
33
- rel="noopener noreferrer"
34
- onMouseDown={(e: React.MouseEvent) => {
35
- e.preventDefault();
36
- }}
37
- target="_blank">
38
- <OpenInNewIcon size={"small"}/>
37
+ href={url}
38
+ rel="noopener noreferrer"
39
+ onMouseDown={(e: React.MouseEvent) => {
40
+ e.preventDefault();
41
+ }}
42
+ target="_blank">
43
+ <OpenInNewIcon size={"small"} />
39
44
  {url}
40
45
  </a>
41
46
  );
@@ -43,16 +48,16 @@ export function UrlComponentPreview({
43
48
 
44
49
  if (previewType === "image") {
45
50
  return <ImagePreview url={url}
46
- size={size}/>;
51
+ size={size}
52
+ fill={fill} />;
47
53
  } else if (previewType === "audio") {
48
54
  return <audio controls
49
- className={"max-w-100%"}
50
- src={url}>
51
- Your browser does not support the
52
- <code>audio</code> element.
55
+ className={"max-w-100%"}
56
+ src={url}>
57
+ {t("browser_does_not_support_audio")}
53
58
  </audio>;
54
59
  } else if (previewType === "video") {
55
- return <VideoPreview size={size} src={url} interactive={interactive}/>;
60
+ return <VideoPreview size={size} src={url} interactive={interactive} />;
56
61
  } else {
57
62
  return (
58
63
  <Tooltip title={hint}>
@@ -66,7 +71,7 @@ export function UrlComponentPreview({
66
71
  width: getThumbnailMeasure(size),
67
72
  height: getThumbnailMeasure(size)
68
73
  }}>
69
- <DescriptionIcon className="text-surface-700 dark:text-surface-300"/>
74
+ <DescriptionIcon className="text-surface-700 dark:text-surface-300" />
70
75
  {hint && <Typography
71
76
  className="max-w-full truncate rtl text-left"
72
77
  variant={"caption"}>{hint}</Typography>}
@@ -77,10 +82,10 @@ export function UrlComponentPreview({
77
82
  }
78
83
 
79
84
  function VideoPreview({
80
- size,
81
- src,
82
- interactive
83
- }: { size: PreviewSize, src: string, interactive: boolean }) {
85
+ size,
86
+ src,
87
+ interactive
88
+ }: { size: PreviewSize, src: string, interactive: boolean }) {
84
89
 
85
90
  const imageSize = useMemo(() => {
86
91
  if (size === "small")
@@ -106,6 +111,6 @@ function VideoPreview({
106
111
  }}
107
112
  {...videoProps}
108
113
  className={cls("max-w-100% rounded", { "pointer-events-none": !interactive })}>
109
- <source src={src}/>
114
+ <source src={src} />
110
115
  </video>;
111
116
  }
@@ -4,6 +4,7 @@ import { useInternalUserManagementController } from "../../hooks";
4
4
  import { UserDisplay } from "../../components/UserDisplay";
5
5
  import { EmptyValue } from "./EmptyValue";
6
6
  import { Typography } from "@firecms/ui";
7
+ import { useTranslation } from "../../hooks/useTranslation";
7
8
 
8
9
  /**
9
10
  * Preview component for displaying user information.
@@ -13,6 +14,7 @@ import { Typography } from "@firecms/ui";
13
14
  */
14
15
  export function UserPreview({ value }: PropertyPreviewProps<string>) {
15
16
  const { getUser } = useInternalUserManagementController();
17
+ const { t } = useTranslation();
16
18
 
17
19
  if (!value) {
18
20
  return <EmptyValue/>;
@@ -20,7 +22,7 @@ export function UserPreview({ value }: PropertyPreviewProps<string>) {
20
22
 
21
23
  const user = getUser(value);
22
24
  if (!user) {
23
- return <Typography variant={"caption"} color={"secondary"}>User not found: {value}</Typography>;
25
+ return <Typography variant={"caption"} color={"secondary"}>{t("user_not_found", { value })}</Typography>;
24
26
  }
25
27
 
26
28
  return <UserDisplay user={user}/>;