@firecms/core 3.0.0-canary.11 → 3.0.0-canary.110

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 (269) hide show
  1. package/README.md +1 -1
  2. package/dist/app/AppBar.d.ts +12 -0
  3. package/dist/app/Drawer.d.ts +17 -0
  4. package/dist/app/Scaffold.d.ts +30 -0
  5. package/dist/app/index.d.ts +4 -0
  6. package/dist/app/useApp.d.ts +16 -0
  7. package/dist/components/CircularProgressCenter.d.ts +1 -1
  8. package/dist/components/ClearFilterSortButton.d.ts +5 -0
  9. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +11 -12
  10. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  11. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +5 -3
  12. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +1 -0
  13. package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
  14. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +2 -0
  15. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
  16. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  17. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +2 -2
  18. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -2
  19. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  20. package/dist/components/EntityPreview.d.ts +5 -4
  21. package/dist/components/ErrorView.d.ts +1 -1
  22. package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
  23. package/dist/components/HomePage/NavigationCardBinding.d.ts +1 -1
  24. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  25. package/dist/components/ReferenceWidget.d.ts +3 -1
  26. package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
  27. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  28. package/dist/components/VirtualTable/VirtualTableProps.d.ts +15 -12
  29. package/dist/components/VirtualTable/types.d.ts +3 -3
  30. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
  31. package/dist/components/common/index.d.ts +1 -0
  32. package/dist/components/common/table_height.d.ts +5 -0
  33. package/dist/components/common/types.d.ts +4 -6
  34. package/dist/components/common/useColumnsIds.d.ts +2 -1
  35. package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
  36. package/dist/components/index.d.ts +3 -1
  37. package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +6 -9
  38. package/dist/core/DefaultDrawer.d.ts +19 -0
  39. package/dist/core/DrawerNavigationItem.d.ts +9 -0
  40. package/dist/core/EntityEditView.d.ts +18 -4
  41. package/dist/core/FireCMS.d.ts +1 -1
  42. package/dist/core/NavigationRoutes.d.ts +3 -3
  43. package/dist/core/index.d.ts +3 -4
  44. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  45. package/dist/form/components/ErrorFocus.d.ts +1 -1
  46. package/dist/form/components/FieldHelperText.d.ts +3 -3
  47. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  48. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  49. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  50. package/dist/form/components/index.d.ts +1 -0
  51. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  52. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  53. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  54. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  55. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  56. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  57. package/dist/form/field_bindings/MultiSelectBinding.d.ts +1 -1
  58. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  59. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  60. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  61. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -5
  62. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  63. package/dist/form/index.d.ts +2 -4
  64. package/dist/hooks/data/save.d.ts +1 -2
  65. package/dist/hooks/index.d.ts +1 -0
  66. package/dist/hooks/useBuildNavigationController.d.ts +1 -2
  67. package/dist/hooks/useProjectLog.d.ts +2 -2
  68. package/dist/hooks/useValidateAuthenticator.d.ts +4 -8
  69. package/dist/index.d.ts +1 -0
  70. package/dist/index.es.js +15627 -12442
  71. package/dist/index.es.js.map +1 -1
  72. package/dist/index.umd.js +19866 -587
  73. package/dist/index.umd.js.map +1 -1
  74. package/dist/internal/useBuildDataSource.d.ts +1 -16
  75. package/dist/preview/PropertyPreviewProps.d.ts +6 -1
  76. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  77. package/dist/preview/components/ReferencePreview.d.ts +2 -1
  78. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  79. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  80. package/dist/types/auth.d.ts +3 -3
  81. package/dist/types/collections.d.ts +39 -5
  82. package/dist/types/datasource.d.ts +45 -31
  83. package/dist/types/entities.d.ts +6 -1
  84. package/dist/types/entity_actions.d.ts +14 -0
  85. package/dist/types/fields.d.ts +45 -39
  86. package/dist/types/index.d.ts +0 -1
  87. package/dist/types/navigation.d.ts +6 -5
  88. package/dist/types/plugins.d.ts +14 -4
  89. package/dist/types/properties.d.ts +32 -19
  90. package/dist/types/storage.d.ts +11 -3
  91. package/dist/util/entities.d.ts +1 -1
  92. package/dist/util/icon_list.d.ts +5 -1
  93. package/dist/util/icon_synonyms.d.ts +1 -97
  94. package/dist/util/icons.d.ts +2 -2
  95. package/dist/util/index.d.ts +1 -0
  96. package/dist/util/navigation_utils.d.ts +2 -2
  97. package/dist/util/objects.d.ts +1 -1
  98. package/dist/util/plurals.d.ts +0 -2
  99. package/dist/util/resolutions.d.ts +14 -13
  100. package/dist/util/storage.d.ts +23 -2
  101. package/dist/util/useStorageUploadController.d.ts +1 -1
  102. package/package.json +128 -119
  103. package/src/app/AppBar.tsx +18 -0
  104. package/src/app/Drawer.tsx +25 -0
  105. package/src/app/Scaffold.tsx +245 -0
  106. package/src/app/index.ts +4 -0
  107. package/src/app/useApp.tsx +32 -0
  108. package/src/components/ArrayContainer.tsx +9 -7
  109. package/src/components/CircularProgressCenter.tsx +1 -1
  110. package/src/components/ClearFilterSortButton.tsx +41 -0
  111. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +12 -19
  112. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +21 -20
  113. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +10 -6
  114. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +41 -35
  115. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  116. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +22 -12
  117. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +14 -6
  118. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +29 -34
  119. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +17 -13
  120. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +19 -7
  121. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +7 -10
  122. package/src/components/EntityCollectionView/EntityCollectionView.tsx +75 -51
  123. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  124. package/src/components/EntityCollectionView/useSelectionController.tsx +19 -7
  125. package/src/components/EntityPreview.tsx +21 -15
  126. package/src/components/EntityView.tsx +5 -5
  127. package/src/components/ErrorView.tsx +1 -1
  128. package/src/components/HomePage/DefaultHomePage.tsx +24 -15
  129. package/src/components/HomePage/NavigationCard.tsx +3 -3
  130. package/src/components/HomePage/NavigationCardBinding.tsx +1 -1
  131. package/src/components/HomePage/SmallNavigationCard.tsx +5 -6
  132. package/src/components/PropertyIdCopyTooltip.tsx +48 -0
  133. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +2 -5
  134. package/src/components/ReferenceWidget.tsx +22 -12
  135. package/src/components/SearchIconsView.tsx +11 -7
  136. package/src/components/SelectableTable/SelectableTable.tsx +7 -7
  137. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  138. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +22 -7
  139. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +28 -6
  140. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
  141. package/src/components/VirtualTable/VirtualTable.tsx +70 -37
  142. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -1
  143. package/src/components/VirtualTable/VirtualTableHeader.tsx +4 -4
  144. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  145. package/src/components/VirtualTable/VirtualTableProps.tsx +18 -14
  146. package/src/components/VirtualTable/VirtualTableRow.tsx +4 -5
  147. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  148. package/src/components/VirtualTable/types.tsx +2 -3
  149. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +2 -2
  150. package/src/components/common/index.ts +1 -0
  151. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  152. package/src/components/common/types.tsx +4 -6
  153. package/src/components/common/useColumnsIds.tsx +23 -2
  154. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +11 -0
  155. package/src/components/common/useTableSearchHelper.ts +53 -12
  156. package/src/components/index.tsx +3 -1
  157. package/src/contexts/DialogsProvider.tsx +2 -2
  158. package/src/{components/FireCMSAppBar.tsx → core/DefaultAppBar.tsx} +52 -37
  159. package/src/core/DefaultDrawer.tsx +177 -0
  160. package/src/core/DrawerNavigationItem.tsx +64 -0
  161. package/src/core/EntityEditView.tsx +702 -137
  162. package/src/core/EntitySidePanel.tsx +1 -2
  163. package/src/core/FireCMS.tsx +39 -44
  164. package/src/core/NavigationRoutes.tsx +7 -8
  165. package/src/core/SideDialogs.tsx +4 -0
  166. package/src/core/field_configs.tsx +4 -5
  167. package/src/core/index.tsx +3 -4
  168. package/src/form/PropertyFieldBinding.tsx +53 -21
  169. package/src/form/components/CustomIdField.tsx +4 -2
  170. package/src/form/components/FieldHelperText.tsx +4 -4
  171. package/src/form/components/LabelWithIcon.tsx +27 -19
  172. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  173. package/src/form/components/StorageItemPreview.tsx +21 -11
  174. package/src/form/components/StorageUploadProgress.tsx +3 -4
  175. package/src/form/components/index.tsx +1 -0
  176. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +15 -11
  177. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +26 -21
  178. package/src/form/field_bindings/BlockFieldBinding.tsx +13 -12
  179. package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -14
  180. package/src/form/field_bindings/KeyValueFieldBinding.tsx +52 -46
  181. package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
  182. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +138 -0
  183. package/src/form/field_bindings/MultiSelectBinding.tsx +9 -5
  184. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +11 -16
  185. package/src/form/field_bindings/ReferenceFieldBinding.tsx +37 -27
  186. package/src/form/field_bindings/RepeatFieldBinding.tsx +20 -16
  187. package/src/form/field_bindings/SelectFieldBinding.tsx +47 -41
  188. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +31 -52
  189. package/src/form/field_bindings/SwitchFieldBinding.tsx +9 -5
  190. package/src/form/field_bindings/TextFieldBinding.tsx +26 -22
  191. package/src/form/index.tsx +6 -6
  192. package/src/form/validation.ts +1 -17
  193. package/src/hooks/data/save.ts +6 -1
  194. package/src/hooks/data/useDataSource.tsx +1 -1
  195. package/src/hooks/index.tsx +1 -0
  196. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  197. package/src/hooks/useBuildModeController.tsx +11 -5
  198. package/src/hooks/useBuildNavigationController.tsx +86 -29
  199. package/src/hooks/useProjectLog.tsx +19 -8
  200. package/src/hooks/useResolvedNavigationFrom.tsx +1 -1
  201. package/src/hooks/useValidateAuthenticator.tsx +21 -41
  202. package/src/index.ts +1 -0
  203. package/src/internal/useBuildDataSource.ts +84 -62
  204. package/src/internal/useBuildSideEntityController.tsx +90 -21
  205. package/src/internal/useUnsavedChangesDialog.tsx +3 -1
  206. package/src/preview/PropertyPreview.tsx +10 -17
  207. package/src/preview/PropertyPreviewProps.tsx +7 -1
  208. package/src/preview/components/BooleanPreview.tsx +2 -2
  209. package/src/preview/components/EnumValuesChip.tsx +2 -2
  210. package/src/preview/components/ImagePreview.tsx +24 -34
  211. package/src/preview/components/ReferencePreview.tsx +23 -23
  212. package/src/preview/components/StorageThumbnail.tsx +5 -1
  213. package/src/preview/components/UrlComponentPreview.tsx +44 -11
  214. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
  215. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +3 -2
  216. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +1 -2
  217. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
  218. package/src/preview/property_previews/ArrayOneOfPreview.tsx +3 -4
  219. package/src/preview/property_previews/ArrayPropertyPreview.tsx +3 -4
  220. package/src/preview/property_previews/MapPropertyPreview.tsx +6 -6
  221. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +2 -2
  222. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  223. package/src/preview/util.ts +2 -2
  224. package/src/types/auth.tsx +3 -3
  225. package/src/types/collections.ts +48 -7
  226. package/src/types/customization_controller.tsx +0 -1
  227. package/src/types/datasource.ts +53 -39
  228. package/src/types/entities.ts +11 -1
  229. package/src/types/entity_actions.tsx +16 -3
  230. package/src/types/fields.tsx +49 -43
  231. package/src/types/index.ts +0 -1
  232. package/src/types/navigation.ts +7 -7
  233. package/src/types/plugins.tsx +16 -6
  234. package/src/types/properties.ts +37 -20
  235. package/src/types/storage.ts +12 -3
  236. package/src/util/entities.ts +5 -4
  237. package/src/util/enums.ts +1 -1
  238. package/src/util/icon_list.ts +15 -10
  239. package/src/util/icon_synonyms.ts +3 -99
  240. package/src/util/index.ts +1 -0
  241. package/src/util/navigation_utils.ts +6 -6
  242. package/src/util/objects.ts +25 -28
  243. package/src/util/permissions.ts +1 -0
  244. package/src/util/plurals.ts +0 -2
  245. package/src/util/references.ts +3 -0
  246. package/src/util/resolutions.ts +44 -39
  247. package/src/util/storage.ts +76 -22
  248. package/src/util/strings.ts +2 -2
  249. package/src/util/useStorageUploadController.tsx +22 -4
  250. package/src/util/useTraceUpdate.tsx +1 -0
  251. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  252. package/dist/components/VirtualTable/common.d.ts +0 -2
  253. package/dist/core/Drawer.d.ts +0 -23
  254. package/dist/core/Scaffold.d.ts +0 -55
  255. package/dist/core/SideEntityView.d.ts +0 -7
  256. package/dist/form/EntityForm.d.ts +0 -77
  257. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  258. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  259. package/dist/internal/useLocaleConfig.d.ts +0 -1
  260. package/dist/types/appcheck.d.ts +0 -26
  261. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
  262. package/src/core/Drawer.tsx +0 -191
  263. package/src/core/Scaffold.tsx +0 -281
  264. package/src/core/SideEntityView.tsx +0 -38
  265. package/src/form/EntityForm.tsx +0 -728
  266. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  267. package/src/internal/useBuildCustomizationController.tsx +0 -5
  268. package/src/internal/useLocaleConfig.tsx +0 -18
  269. package/src/types/appcheck.ts +0 -29
@@ -3,13 +3,14 @@ import {
3
3
  EntityCollection,
4
4
  EntitySidePanelProps,
5
5
  NavigationController,
6
+ ResolvedProperty,
6
7
  SideDialogPanelProps,
7
8
  SideDialogsController,
8
9
  SideEntityController
9
10
  } from "../types";
10
11
  import { getNavigationEntriesFromPathInternal, NavigationViewInternal } from "../util/navigation_from_path";
11
12
  import { useLocation } from "react-router-dom";
12
- import { removeInitialAndTrailingSlashes, resolveDefaultSelectedView } from "../util";
13
+ import { removeInitialAndTrailingSlashes, resolveCollection, resolveDefaultSelectedView } from "../util";
13
14
  import { ADDITIONAL_TAB_WIDTH, CONTAINER_FULL_WIDTH, FORM_CONTAINER_WIDTH } from "./common";
14
15
  import { useLargeLayout } from "../hooks";
15
16
  import { EntitySidePanel } from "../core/EntitySidePanel";
@@ -19,8 +20,67 @@ const NEW_URL_HASH = "new";
19
20
  export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean): string {
20
21
  if (small) return CONTAINER_FULL_WIDTH;
21
22
  const mainViewSelected = !props.selectedSubPath;
22
- const resolvedWidth: string | undefined = typeof props.width === "number" ? `${props.width}px` : props.width;
23
- return !mainViewSelected ? `calc(${ADDITIONAL_TAB_WIDTH} + ${resolvedWidth ?? FORM_CONTAINER_WIDTH})` : resolvedWidth ?? FORM_CONTAINER_WIDTH
23
+ let resolvedWidth: string | undefined;
24
+ if (props.width) {
25
+ resolvedWidth = typeof props.width === "number" ? `${props.width}px` : props.width;
26
+ } else if (props.collection?.sideDialogWidth) {
27
+ resolvedWidth = typeof props.collection.sideDialogWidth === "number" ? `${props.collection.sideDialogWidth}px` : props.collection.sideDialogWidth;
28
+ }
29
+
30
+ if (!mainViewSelected) {
31
+ return `calc(${ADDITIONAL_TAB_WIDTH} + ${resolvedWidth ?? FORM_CONTAINER_WIDTH})`
32
+ } else {
33
+ if (resolvedWidth) {
34
+ return resolvedWidth
35
+ } else if (!props.collection) {
36
+ return FORM_CONTAINER_WIDTH;
37
+ } else {
38
+ return calculateCollectionDesiredWidth(props.collection);
39
+ }
40
+ }
41
+ }
42
+
43
+ const collectionViewWidthCache: { [key: string]: string } = {};
44
+
45
+ function calculateCollectionDesiredWidth(collection: EntityCollection<any>): string {
46
+ if (collectionViewWidthCache[collection.id]) {
47
+ return collectionViewWidthCache[collection.id];
48
+ }
49
+ const resolvedCollection = resolveCollection({
50
+ collection,
51
+ path: "__ignored",
52
+ ignoreMissingFields: true
53
+ });
54
+
55
+ let result = FORM_CONTAINER_WIDTH
56
+ if (resolvedCollection?.properties) {
57
+ const values = Object.values(resolvedCollection.properties).map((p: ResolvedProperty) => getNestedPropertiesDepth(p));
58
+ const maxDepth = Math.max(...values);
59
+ if (maxDepth < 3) {
60
+ result = FORM_CONTAINER_WIDTH;
61
+ } else {
62
+ result = 768 + 32 * (maxDepth - 2) + "px";
63
+ }
64
+ }
65
+ collectionViewWidthCache[collection.id] = result;
66
+ return result;
67
+ }
68
+
69
+ function getNestedPropertiesDepth(property: ResolvedProperty, accumulator: number = 0): number {
70
+ if (property.dataType === "map" && property.properties) {
71
+ const values = Object.values(property.properties).flatMap((property) => getNestedPropertiesDepth(property, accumulator + 1));
72
+ return Math.max(...values);
73
+ } else if (property.dataType === "array" && property.oneOf) {
74
+ return accumulator + 3;
75
+ } else if (property.dataType === "array" && property.of) {
76
+ if (Array.isArray(property.of)) {
77
+ return Math.max(...property.of.map((p) => getNestedPropertiesDepth(p, accumulator + 1)));
78
+ } else {
79
+ return getNestedPropertiesDepth(property.of, accumulator + 1);
80
+ }
81
+ } else {
82
+ return accumulator + 1;
83
+ }
24
84
  }
25
85
 
26
86
  export const useBuildSideEntityController = (navigation: NavigationController,
@@ -34,23 +94,26 @@ export const useBuildSideEntityController = (navigation: NavigationController,
34
94
  // only on initialisation, create panels from URL
35
95
  useEffect(() => {
36
96
  if (!navigation.loading && !initialised.current) {
97
+ console.debug("Initialising side entity controller");
37
98
  if (navigation.isUrlCollectionPath(location.pathname)) {
38
99
  const newFlag = location.hash === `#${NEW_URL_HASH}`;
39
100
  const entityOrCollectionPath = navigation.urlPathToDataPath(location.pathname);
40
101
  const panelsFromUrl = buildSidePanelsFromUrl(entityOrCollectionPath, navigation.collections ?? [], newFlag);
41
102
  for (let i = 0; i < panelsFromUrl.length; i++) {
42
- const panel = panelsFromUrl[i];
103
+ const props = panelsFromUrl[i];
43
104
  setTimeout(() => {
44
105
  if (i === 0)
45
- sideDialogsController.replace(propsToSidePanel(panel, navigation, smallLayout));
106
+ sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout));
46
107
  else
47
- sideDialogsController.open(propsToSidePanel(panel, navigation, smallLayout))
108
+ sideDialogsController.open(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout))
48
109
  }, 1);
49
110
  }
111
+ } else {
112
+ // console.warn("Location path is not a collection path");
50
113
  }
51
114
  initialised.current = true;
52
115
  }
53
- }, [location, navigation, sideDialogsController, smallLayout]);
116
+ }, [location, navigation.loading, navigation.isUrlCollectionPath, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, sideDialogsController, smallLayout, navigation]);
54
117
 
55
118
  const close = useCallback(() => {
56
119
  sideDialogsController.close();
@@ -73,9 +136,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
73
136
  sideDialogsController.open(propsToSidePanel({
74
137
  selectedSubPath: defaultSelectedView,
75
138
  ...props,
76
- }, navigation, smallLayout));
139
+ }, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout));
77
140
 
78
- }, [sideDialogsController, navigation, smallLayout]);
141
+ }, [sideDialogsController, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout]);
79
142
 
80
143
  const replace = useCallback((props: EntitySidePanelProps<any>) => {
81
144
 
@@ -83,9 +146,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
83
146
  throw Error("If you want to copy an entity you need to provide an entityId");
84
147
  }
85
148
 
86
- sideDialogsController.replace(propsToSidePanel(props, navigation, smallLayout));
149
+ sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout));
87
150
 
88
- }, [navigation, sideDialogsController, smallLayout]);
151
+ }, [navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, sideDialogsController, smallLayout]);
89
152
 
90
153
  return {
91
154
  close,
@@ -116,7 +179,8 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
116
179
  sidePanels.push({
117
180
  path: navigationEntry.path,
118
181
  entityId: navigationEntry.entityId,
119
- copy: false
182
+ copy: false,
183
+ width: navigationEntry.parentCollection?.sideDialogWidth
120
184
  }
121
185
  );
122
186
  } else if (navigationEntry.type === "custom_view") {
@@ -146,27 +210,32 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
146
210
  return sidePanels;
147
211
  }
148
212
 
149
- const propsToSidePanel = (props: EntitySidePanelProps<any>, navigation: NavigationController, smallLayout: boolean): SideDialogPanelProps => {
213
+ const propsToSidePanel = (props: EntitySidePanelProps<any>,
214
+ buildUrlCollectionPath: (path: string) => string,
215
+ resolveAliasesFrom: (pathWithAliases: string) => string,
216
+ smallLayout: boolean): SideDialogPanelProps => {
150
217
 
151
218
  const collectionPath = removeInitialAndTrailingSlashes(props.path);
152
219
 
153
220
  const newPath = props.entityId
154
- ? navigation.buildUrlCollectionPath(`${collectionPath}/${props.entityId}/${props.selectedSubPath || ""}`)
155
- : navigation.buildUrlCollectionPath(`${collectionPath}#${NEW_URL_HASH}`);
156
- const resolvedPath = navigation.resolveAliasesFrom(props.path);
221
+ ? buildUrlCollectionPath(`${collectionPath}/${props.entityId}/${props.selectedSubPath || ""}`)
222
+ : buildUrlCollectionPath(`${collectionPath}#${NEW_URL_HASH}`);
223
+ const resolvedPath = resolveAliasesFrom(props.path);
157
224
 
158
225
  const resolvedPanelProps: EntitySidePanelProps<any> = {
159
226
  ...props,
160
- path: resolvedPath
227
+ path: resolvedPath,
161
228
  };
162
229
 
163
- return ({
230
+ const entityViewWidth = getEntityViewWidth(props, smallLayout);
231
+
232
+ return {
164
233
  key: `${props.path}/${props.entityId}`,
165
234
  component: <EntitySidePanel {...resolvedPanelProps}/>,
166
235
  urlPath: newPath,
167
- parentUrlPath: navigation.buildUrlCollectionPath(collectionPath),
168
- width: getEntityViewWidth(props, smallLayout),
236
+ parentUrlPath: buildUrlCollectionPath(collectionPath),
237
+ width: entityViewWidth,
169
238
  onClose: props.onClose
170
- });
239
+ };
171
240
  }
172
241
  ;
@@ -84,8 +84,10 @@ export function UnsavedChangesDialog({
84
84
 
85
85
  return (
86
86
  <Dialog
87
+ onEscapeKeyDown={() => {
88
+ handleCancel();
89
+ }}
87
90
  open={open}
88
- onOpenChange={(open) => open ? handleCancel() : handleOk()}
89
91
  >
90
92
  <DialogContent>
91
93
  <Typography variant={"h6"}>{title}</Typography>
@@ -47,13 +47,12 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
47
47
  size,
48
48
  height,
49
49
  width,
50
- // entity
50
+ interactive
51
51
  } = props;
52
52
 
53
53
  const property = resolveProperty({
54
54
  propertyKey,
55
55
  propertyOrBuilder: inputProperty,
56
- propertyValue: value,
57
56
  fields: customizationController.propertyConfigs
58
57
  });
59
58
 
@@ -85,14 +84,17 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
85
84
  content =
86
85
  <UrlComponentPreview size={props.size}
87
86
  url={value}
87
+ interactive={interactive}
88
88
  previewType={stringProperty.url}/>;
89
+ } else if (stringProperty.markdown) {
90
+ content = <Markdown source={value} size={"small"}/>;
89
91
  } else if (stringProperty.storage) {
92
+ const filePath = stringProperty.storage.previewUrl ? stringProperty.storage.previewUrl(value) : value;
90
93
  content = <StorageThumbnail
94
+ interactive={interactive}
91
95
  storeUrl={property.storage?.storeUrl ?? false}
92
96
  size={props.size}
93
- storagePathOrDownloadUrl={value}/>;
94
- } else if (stringProperty.markdown) {
95
- content = <Markdown source={value}/>;
97
+ storagePathOrDownloadUrl={filePath}/>;
96
98
  } else {
97
99
  content = <StringPropertyPreview {...props}
98
100
  property={stringProperty}
@@ -113,17 +115,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
113
115
  content = <ArrayPropertyPreview {...props}
114
116
  value={value}
115
117
  property={property as ResolvedArrayProperty}/>;
116
- }
117
- // else if (arrayProperty.of.dataType === "map") {
118
- // content =
119
- // <ArrayOfMapsPreview propertyKey={propertyKey}
120
- // property={property as ResolvedArrayProperty}
121
- // value={value as Record<string, any>[]} // This might be wrong
122
- // entity={entity}
123
- // size={size}
124
- // />;
125
- // }
126
- else if (arrayProperty.of.dataType === "reference") {
118
+ } else if (arrayProperty.of.dataType === "reference") {
127
119
  content = <ArrayOfReferencesPreview {...props}
128
120
  value={value}
129
121
  property={property as ResolvedArrayProperty}/>;
@@ -182,8 +174,9 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
182
174
  content = <ReferencePreview
183
175
  disabled={!property.path}
184
176
  previewProperties={property.previewProperties}
177
+ includeId={property.includeId}
178
+ includeEntityLink={property.includeEntityLink}
185
179
  size={props.size}
186
- // onClick={props.onClick}
187
180
  reference={value as EntityReference}
188
181
  />;
189
182
  } else {
@@ -3,7 +3,7 @@ import { CMSType, Property, ResolvedProperty } from "../types";
3
3
  /**
4
4
  * @group Preview components
5
5
  */
6
- export type PreviewSize = "medium" | "small" | "tiny";
6
+ export type PreviewSize = "medium" | "small" | "smallest";
7
7
 
8
8
  /**
9
9
  * @group Preview components
@@ -46,4 +46,10 @@ export interface PropertyPreviewProps<T extends CMSType = any, CustomProps = any
46
46
  */
47
47
  customProps?: CustomProps;
48
48
 
49
+ /**
50
+ * If the preview should be interactive or not.
51
+ * This applies only to videos.
52
+ */
53
+ interactive?: boolean;
54
+
49
55
  }
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Checkbox, cn } from "@firecms/ui";
2
+ import { Checkbox, cls } from "@firecms/ui";
3
3
  import { PreviewSize } from "../PropertyPreviewProps";
4
4
  import { Property } from "../../types";
5
5
 
@@ -21,6 +21,6 @@ export function BooleanPreview({
21
21
  size={size}
22
22
  color={"secondary"}/>
23
23
  {property.name && <span
24
- className={cn("text-text-secondary dark:text-text-secondary-dark", size === "tiny" ? "text-sm" : "")}>{property.name}</span>}
24
+ className={cls("text-text-secondary dark:text-text-secondary-dark", size === "smallest" ? "text-sm" : "")}>{property.name}</span>}
25
25
  </div>;
26
26
  }
@@ -1,12 +1,12 @@
1
1
  import React from "react";
2
+ import { Chip } from "@firecms/ui";
2
3
  import { EnumValues } from "../../types";
3
4
  import { buildEnumLabel, enumToObjectEntries, getColorScheme, getLabelOrConfigFrom } from "../../util/enums";
4
- import { Chip } from "@firecms/ui";
5
5
 
6
6
  export interface EnumValuesChipProps {
7
7
  enumValues?: EnumValues;
8
8
  enumKey: string | number;
9
- size: "tiny" | "small" | "medium";
9
+ size: "smallest" | "small" | "medium";
10
10
  className?: string;
11
11
  children?: React.ReactNode;
12
12
  }
@@ -1,4 +1,4 @@
1
- import React, { CSSProperties, useMemo, useState } from "react";
1
+ import React, { CSSProperties, useMemo } from "react";
2
2
 
3
3
  import { getThumbnailMeasure } from "../util";
4
4
  import { PreviewSize } from "../PropertyPreviewProps";
@@ -20,11 +20,9 @@ export function ImagePreview({
20
20
  url
21
21
  }: ImagePreviewProps) {
22
22
 
23
- const [onHover, setOnHover] = useState(false);
24
-
25
23
  const imageSize = useMemo(() => getThumbnailMeasure(size), [size]);
26
24
 
27
- if (size === "tiny") {
25
+ if (size === "smallest") {
28
26
  return (
29
27
  <img src={url}
30
28
  className={"rounded-md"}
@@ -47,60 +45,52 @@ export function ImagePreview({
47
45
 
48
46
  return (
49
47
  <div
50
- className="relative flex items-center justify-center max-w-full max-h-full"
48
+ className="relative flex items-center justify-center max-w-full max-h-full group"
51
49
  style={{
52
50
  width: imageSize,
53
51
  height: imageSize
54
52
  }}
55
- key={"image_preview_" + url}
56
- onMouseEnter={() => setOnHover(true)}
57
- onMouseMove={() => setOnHover(true)}
58
- onMouseLeave={() => setOnHover(false)}>
53
+ key={"image_preview_" + url}>
59
54
 
60
55
  <img src={url}
61
56
  className={"rounded-md"}
62
57
  style={imageStyle}/>
63
58
 
64
- {onHover && <>
65
59
 
66
- {navigator && <Tooltip title="Copy url to clipboard">
67
- <div
68
- className="rounded-full absolute bottom-[-4px] right-8">
69
- <IconButton
70
- variant={"filled"}
71
- size={"small"}
72
- onClick={(e) => {
73
- e.stopPropagation();
74
- e.preventDefault();
75
- return navigator.clipboard.writeText(url);
76
- }}>
77
- <ContentCopyIcon className={"text-gray-500"}
78
- size={"small"}/>
79
- </IconButton>
80
- </div>
60
+ <div className={"flex flex-row gap-2 absolute bottom-[-4px] right-[-4px] invisible group-hover:visible"}>
61
+ {navigator && <Tooltip
62
+ asChild={true}
63
+ title="Copy url to clipboard" side={"bottom"}>
64
+ <IconButton
65
+ variant={"filled"}
66
+ size={"small"}
67
+ onClick={(e) => {
68
+ e.stopPropagation();
69
+ e.preventDefault();
70
+ return navigator.clipboard.writeText(url);
71
+ }}>
72
+ <ContentCopyIcon className={"text-gray-700 dark:text-gray-300"}
73
+ size={"small"}/>
74
+ </IconButton>
81
75
  </Tooltip>}
82
76
 
83
- <Tooltip title="Open image in new tab">
77
+ <Tooltip title="Open image in new tab" side={"bottom"}>
84
78
  <IconButton
79
+ className="invisible group-hover:visible"
85
80
  variant={"filled"}
86
81
  component={"a" as React.ElementType}
87
- style={{
88
- position: "absolute",
89
- bottom: -4,
90
- right: -4
91
- }}
92
82
  href={url}
93
83
  rel="noopener noreferrer"
94
84
  target="_blank"
95
85
  size={"small"}
96
86
  onClick={(e: any) => e.stopPropagation()}
97
87
  >
98
- <OpenInNewIcon className={"text-gray-500"}
88
+ <OpenInNewIcon className={"text-gray-700 dark:text-gray-300"}
99
89
  size={"small"}/>
100
90
  </IconButton>
101
91
  </Tooltip>
102
- </>
103
- }
92
+ </div>
93
+
104
94
  </div>
105
95
  );
106
96
  }
@@ -1,16 +1,10 @@
1
1
  import * as React from "react";
2
2
 
3
3
  import { Entity, EntityCollection, EntityReference } from "../../types";
4
- import {
5
- useCustomizationController,
6
- useEntityFetch,
7
- useNavigationController,
8
- useSideEntityController
9
- } from "../../hooks";
4
+ import { useCustomizationController, useEntityFetch, useNavigationController } from "../../hooks";
10
5
  import { PreviewSize } from "../PropertyPreviewProps";
11
- import { IconButton, KeyboardTabIcon, Skeleton, Tooltip } from "@firecms/ui";
6
+ import { Skeleton } from "@firecms/ui";
12
7
  import { ErrorView } from "../../components";
13
- import { useAnalyticsController } from "../../hooks/useAnalyticsController";
14
8
  import { EntityPreview, EntityPreviewContainer } from "../../components/EntityPreview";
15
9
 
16
10
  export type ReferencePreviewProps = {
@@ -20,7 +14,8 @@ export type ReferencePreviewProps = {
20
14
  previewProperties?: string[];
21
15
  onClick?: (e: React.SyntheticEvent) => void;
22
16
  hover?: boolean;
23
- allowEntityNavigation?: boolean;
17
+ includeEntityLink?: boolean;
18
+ includeId?: boolean;
24
19
  };
25
20
 
26
21
  /**
@@ -46,25 +41,27 @@ function areEqual(prevProps: ReferencePreviewProps, nextProps: ReferencePreviewP
46
41
  prevProps.hover === nextProps.hover &&
47
42
  prevProps.reference?.id === nextProps.reference?.id &&
48
43
  prevProps.reference?.path === nextProps.reference?.path &&
49
- prevProps.allowEntityNavigation === nextProps.allowEntityNavigation
44
+ prevProps.includeEntityLink === nextProps.includeEntityLink &&
45
+ prevProps.onClick === nextProps.onClick
50
46
  ;
51
47
  }
52
48
 
53
- function ReferencePreviewInternal<M extends Record<string, any>>({
54
- disabled,
55
- reference,
56
- previewProperties,
57
- size,
58
- hover,
59
- onClick,
60
- allowEntityNavigation = true
61
- }: ReferencePreviewProps) {
49
+ function ReferencePreviewInternal({
50
+ disabled,
51
+ reference,
52
+ previewProperties,
53
+ size,
54
+ hover,
55
+ onClick,
56
+ includeEntityLink = true,
57
+ includeId = true
58
+ }: ReferencePreviewProps) {
62
59
 
63
60
  const customizationController = useCustomizationController();
64
61
 
65
62
  const navigationController = useNavigationController();
66
63
 
67
- const collection = navigationController.getCollection<EntityCollection<M>>(reference.path);
64
+ const collection = navigationController.getCollection(reference.path);
68
65
  if (!collection) {
69
66
  if (customizationController.components?.missingReference) {
70
67
  return <customizationController.components.missingReference path={reference.path}/>;
@@ -79,7 +76,8 @@ function ReferencePreviewInternal<M extends Record<string, any>>({
79
76
  previewProperties={previewProperties}
80
77
  size={size}
81
78
  disabled={disabled}
82
- allowEntityNavigation={allowEntityNavigation}
79
+ includeEntityLink={includeEntityLink}
80
+ includeId={includeId}
83
81
  onClick={onClick}
84
82
  hover={hover}/>
85
83
  }
@@ -90,7 +88,8 @@ function ReferencePreviewExisting<M extends Record<string, any> = any>({
90
88
  previewProperties,
91
89
  size,
92
90
  disabled,
93
- allowEntityNavigation,
91
+ includeEntityLink,
92
+ includeId,
94
93
  onClick,
95
94
  hover
96
95
  }: ReferencePreviewProps & {
@@ -158,7 +157,8 @@ function ReferencePreviewExisting<M extends Record<string, any> = any>({
158
157
  entity={usedEntity}
159
158
  collection={collection}
160
159
  onClick={onClick}
161
- includeEntityNavigation={allowEntityNavigation}
160
+ includeEntityLink={includeEntityLink}
161
+ includeId={includeId}
162
162
  hover={hover}/>;
163
163
 
164
164
  }
@@ -11,6 +11,7 @@ type StorageThumbnailProps = {
11
11
  storagePathOrDownloadUrl: string;
12
12
  storeUrl: boolean;
13
13
  size: PreviewSize;
14
+ interactive?: boolean;
14
15
  };
15
16
 
16
17
  /**
@@ -21,13 +22,15 @@ export const StorageThumbnail = React.memo<StorageThumbnailProps>(StorageThumbna
21
22
  function areEqual(prevProps: StorageThumbnailProps, nextProps: StorageThumbnailProps) {
22
23
  return prevProps.size === nextProps.size &&
23
24
  prevProps.storagePathOrDownloadUrl === nextProps.storagePathOrDownloadUrl &&
24
- prevProps.storeUrl === nextProps.storeUrl;
25
+ prevProps.storeUrl === nextProps.storeUrl&&
26
+ prevProps.interactive === nextProps.interactive;
25
27
  }
26
28
 
27
29
  const URL_CACHE: Record<string, DownloadConfig> = {};
28
30
 
29
31
  export function StorageThumbnailInternal({
30
32
  storeUrl,
33
+ interactive,
31
34
  storagePathOrDownloadUrl,
32
35
  size
33
36
  }: StorageThumbnailProps) {
@@ -68,6 +71,7 @@ export function StorageThumbnailInternal({
68
71
  return downloadConfig?.url
69
72
  ? <UrlComponentPreview previewType={previewType}
70
73
  url={downloadConfig.url}
74
+ interactive={interactive}
71
75
  size={size}
72
76
  hint={storagePathOrDownloadUrl}/>
73
77
  : renderSkeletonImageThumbnail(size);
@@ -1,10 +1,10 @@
1
- import React from "react";
1
+ import React, { useMemo } from "react";
2
2
 
3
3
  import { ImagePreview } from "./ImagePreview";
4
4
  import { getThumbnailMeasure } from "../util";
5
5
  import { PreviewType } from "../../types";
6
6
  import { PreviewSize } from "../PropertyPreviewProps";
7
- import { DescriptionIcon, OpenInNewIcon, Tooltip, Typography } from "@firecms/ui";
7
+ import { cls, DescriptionIcon, OpenInNewIcon, Tooltip, Typography } from "@firecms/ui";
8
8
  import { EmptyValue } from "./EmptyValue";
9
9
 
10
10
  /**
@@ -14,12 +14,15 @@ export function UrlComponentPreview({
14
14
  url,
15
15
  previewType,
16
16
  size,
17
- hint
17
+ hint,
18
+ interactive = true
18
19
  }: {
19
20
  url: string,
20
21
  previewType?: PreviewType,
21
22
  size: PreviewSize,
22
- hint?: string
23
+ hint?: string,
24
+ // for video controls
25
+ interactive?: boolean
23
26
  }): React.ReactElement {
24
27
 
25
28
  if (!previewType) {
@@ -43,17 +46,13 @@ export function UrlComponentPreview({
43
46
  size={size}/>;
44
47
  } else if (previewType === "audio") {
45
48
  return <audio controls
49
+ className={"max-w-100%"}
46
50
  src={url}>
47
51
  Your browser does not support the
48
52
  <code>audio</code> element.
49
53
  </audio>;
50
54
  } else if (previewType === "video") {
51
- return <video
52
- className={`max-w-${size === "small" ? "sm" : "md"}`}
53
- controls
54
- >
55
- <source src={url}/>
56
- </video>;
55
+ return <VideoPreview size={size} src={url} interactive={interactive}/>;
57
56
  } else {
58
57
  return (
59
58
  <a
@@ -66,7 +65,7 @@ export function UrlComponentPreview({
66
65
  width: getThumbnailMeasure(size),
67
66
  height: getThumbnailMeasure(size)
68
67
  }}>
69
- <DescriptionIcon className="flex-grow"/>
68
+ <DescriptionIcon className="text-gray-700 dark:text-gray-300"/>
70
69
  {hint &&
71
70
  <Tooltip title={hint}>
72
71
  <Typography
@@ -77,3 +76,37 @@ export function UrlComponentPreview({
77
76
  );
78
77
  }
79
78
  }
79
+
80
+ function VideoPreview({
81
+ size,
82
+ src,
83
+ interactive
84
+ }: { size: PreviewSize, src: string, interactive: boolean }) {
85
+
86
+ const imageSize = useMemo(() => {
87
+ if (size === "smallest")
88
+ return "140px";
89
+ else if (size === "small")
90
+ return "240px";
91
+ else if (size === "medium")
92
+ return "100%";
93
+ else throw new Error("Invalid size");
94
+ }, [size]);
95
+
96
+ const videoProps = {
97
+ controls: interactive
98
+ };
99
+ return <video
100
+ style={{
101
+ position: "relative",
102
+ objectFit: "cover",
103
+ width: imageSize,
104
+ minWidth: "140px",
105
+ // height: imageSize,
106
+ maxHeight: "100%"
107
+ }}
108
+ {...videoProps}
109
+ className={cls("max-w-100% rounded", { "pointer-events-none": !interactive })}>
110
+ <source src={src}/>
111
+ </video>;
112
+ }
@@ -20,7 +20,6 @@ export function ArrayOfMapsPreview({
20
20
  const property = resolveArrayProperty({
21
21
  propertyKey,
22
22
  property: inputProperty,
23
- propertyValue: value,
24
23
  fields: customizationController.propertyConfigs
25
24
  });
26
25