@firecms/core 3.0.0-canary.18 → 3.0.0-canary.180

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 (366) hide show
  1. package/README.md +3 -3
  2. package/dist/app/AppBar.d.ts +12 -0
  3. package/dist/app/Drawer.d.ts +16 -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/ArrayContainer.d.ts +23 -6
  8. package/dist/components/CircularProgressCenter.d.ts +1 -1
  9. package/dist/components/ClearFilterSortButton.d.ts +5 -0
  10. package/dist/components/{DeleteConfirmationDialog.d.ts → ConfirmationDialog.d.ts} +1 -1
  11. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +13 -13
  12. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  13. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +22 -6
  14. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +1 -0
  15. package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
  16. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +3 -1
  17. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  18. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
  19. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  20. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +7 -4
  21. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +16 -2
  22. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  23. package/dist/components/EntityCollectionView/utils.d.ts +3 -0
  24. package/dist/components/EntityPreview.d.ts +5 -4
  25. package/dist/components/ErrorView.d.ts +1 -1
  26. package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
  27. package/dist/components/HomePage/NavigationCardBinding.d.ts +1 -1
  28. package/dist/components/PropertyConfigBadge.d.ts +2 -1
  29. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  30. package/dist/components/ReferenceWidget.d.ts +3 -1
  31. package/dist/components/SelectableTable/SelectableTable.d.ts +13 -3
  32. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  33. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  34. package/dist/components/VirtualTable/VirtualTableProps.d.ts +28 -12
  35. package/dist/components/VirtualTable/types.d.ts +3 -3
  36. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -3
  37. package/dist/components/common/index.d.ts +2 -1
  38. package/dist/components/common/table_height.d.ts +5 -0
  39. package/dist/components/common/types.d.ts +4 -6
  40. package/dist/components/common/useColumnsIds.d.ts +3 -1
  41. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +13 -2
  42. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  43. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  44. package/dist/components/index.d.ts +4 -2
  45. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  46. package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +6 -9
  47. package/dist/core/DefaultDrawer.d.ts +19 -0
  48. package/dist/core/DrawerNavigationItem.d.ts +10 -0
  49. package/dist/core/EntityEditView.d.ts +41 -9
  50. package/dist/core/FireCMS.d.ts +2 -2
  51. package/dist/core/FireCMSRouter.d.ts +4 -0
  52. package/dist/core/NavigationRoutes.d.ts +2 -3
  53. package/dist/core/index.d.ts +4 -4
  54. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  55. package/dist/form/components/ErrorFocus.d.ts +1 -1
  56. package/dist/form/components/FieldHelperText.d.ts +3 -3
  57. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  58. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  59. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  60. package/dist/form/components/index.d.ts +1 -1
  61. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  62. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  63. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  64. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  65. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  66. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  67. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  68. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  69. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  70. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  71. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  72. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -5
  73. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  74. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  75. package/dist/form/index.d.ts +3 -5
  76. package/dist/form/useClearRestoreValue.d.ts +2 -2
  77. package/dist/hooks/data/delete.d.ts +4 -4
  78. package/dist/hooks/data/save.d.ts +4 -5
  79. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  80. package/dist/hooks/data/useEntityFetch.d.ts +4 -3
  81. package/dist/hooks/index.d.ts +1 -0
  82. package/dist/hooks/useAuthController.d.ts +1 -1
  83. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  84. package/dist/hooks/useBuildNavigationController.d.ts +3 -5
  85. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  86. package/dist/hooks/useProjectLog.d.ts +8 -2
  87. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  88. package/dist/hooks/useValidateAuthenticator.d.ts +4 -8
  89. package/dist/index.d.ts +1 -0
  90. package/dist/index.es.js +21537 -14243
  91. package/dist/index.es.js.map +1 -1
  92. package/dist/index.umd.js +23973 -588
  93. package/dist/index.umd.js.map +1 -1
  94. package/dist/internal/useBuildDataSource.d.ts +1 -16
  95. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  96. package/dist/preview/PropertyPreviewProps.d.ts +6 -1
  97. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  98. package/dist/preview/components/ReferencePreview.d.ts +3 -2
  99. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  100. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  101. package/dist/preview/util.d.ts +3 -3
  102. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  103. package/dist/routes/FireCMSRoute.d.ts +1 -0
  104. package/dist/routes/HomePageRoute.d.ts +3 -0
  105. package/dist/types/auth.d.ts +8 -10
  106. package/dist/types/collections.d.ts +71 -22
  107. package/dist/types/datasource.d.ts +52 -36
  108. package/dist/types/dialogs_controller.d.ts +7 -3
  109. package/dist/types/entities.d.ts +7 -2
  110. package/dist/types/entity_actions.d.ts +28 -4
  111. package/dist/types/entity_callbacks.d.ts +16 -16
  112. package/dist/types/entity_overrides.d.ts +2 -2
  113. package/dist/types/export_import.d.ts +4 -4
  114. package/dist/types/fields.d.ts +66 -42
  115. package/dist/types/firecms.d.ts +6 -2
  116. package/dist/types/firecms_context.d.ts +1 -1
  117. package/dist/types/index.d.ts +0 -1
  118. package/dist/types/navigation.d.ts +31 -14
  119. package/dist/types/permissions.d.ts +4 -4
  120. package/dist/types/plugins.d.ts +23 -12
  121. package/dist/types/properties.d.ts +51 -23
  122. package/dist/types/property_config.d.ts +0 -2
  123. package/dist/types/side_dialogs_controller.d.ts +10 -0
  124. package/dist/types/side_entity_controller.d.ts +1 -1
  125. package/dist/types/storage.d.ts +86 -3
  126. package/dist/types/user.d.ts +1 -0
  127. package/dist/util/builders.d.ts +3 -3
  128. package/dist/util/entities.d.ts +3 -3
  129. package/dist/util/entity_actions.d.ts +2 -0
  130. package/dist/util/entity_cache.d.ts +23 -0
  131. package/dist/util/icon_list.d.ts +5 -1
  132. package/dist/util/icon_synonyms.d.ts +1 -98
  133. package/dist/util/icons.d.ts +6 -3
  134. package/dist/util/index.d.ts +2 -0
  135. package/dist/util/navigation_from_path.d.ts +5 -1
  136. package/dist/util/navigation_utils.d.ts +14 -3
  137. package/dist/util/objects.d.ts +2 -1
  138. package/dist/util/permissions.d.ts +4 -4
  139. package/dist/util/plurals.d.ts +0 -2
  140. package/dist/util/property_utils.d.ts +3 -3
  141. package/dist/util/resolutions.d.ts +30 -16
  142. package/dist/util/storage.d.ts +23 -2
  143. package/dist/util/useStorageUploadController.d.ts +3 -3
  144. package/package.json +61 -48
  145. package/src/app/AppBar.tsx +18 -0
  146. package/src/app/Drawer.tsx +24 -0
  147. package/src/app/Scaffold.tsx +243 -0
  148. package/src/app/index.ts +4 -0
  149. package/src/app/useApp.tsx +32 -0
  150. package/src/components/ArrayContainer.tsx +126 -40
  151. package/src/components/CircularProgressCenter.tsx +2 -2
  152. package/src/components/ClearFilterSortButton.tsx +41 -0
  153. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +3 -3
  154. package/src/components/DeleteEntityDialog.tsx +10 -19
  155. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +54 -37
  156. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +38 -31
  157. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +30 -9
  158. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +47 -39
  159. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  160. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +30 -16
  161. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +19 -17
  162. package/src/components/EntityCollectionTable/index.tsx +1 -1
  163. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +31 -36
  164. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +36 -34
  165. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
  166. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +84 -77
  167. package/src/components/EntityCollectionView/EntityCollectionView.tsx +206 -112
  168. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  169. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  170. package/src/components/EntityCollectionView/useSelectionController.tsx +20 -7
  171. package/src/components/EntityCollectionView/utils.ts +19 -0
  172. package/src/components/EntityPreview.tsx +62 -52
  173. package/src/components/EntityView.tsx +10 -10
  174. package/src/components/ErrorView.tsx +4 -4
  175. package/src/components/HomePage/DefaultHomePage.tsx +26 -19
  176. package/src/components/HomePage/FavouritesView.tsx +6 -11
  177. package/src/components/HomePage/NavigationCard.tsx +3 -3
  178. package/src/components/HomePage/NavigationCardBinding.tsx +5 -10
  179. package/src/components/HomePage/NavigationGroup.tsx +2 -2
  180. package/src/components/HomePage/SmallNavigationCard.tsx +5 -6
  181. package/src/components/NotFoundPage.tsx +2 -2
  182. package/src/components/PropertyConfigBadge.tsx +9 -3
  183. package/src/components/PropertyIdCopyTooltip.tsx +47 -0
  184. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +19 -13
  185. package/src/components/ReferenceWidget.tsx +21 -11
  186. package/src/components/SearchIconsView.tsx +10 -7
  187. package/src/components/SelectableTable/SelectableTable.tsx +27 -12
  188. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  189. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +25 -8
  190. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +36 -12
  191. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +92 -23
  192. package/src/components/UnsavedChangesDialog.tsx +42 -0
  193. package/src/components/VirtualTable/VirtualTable.tsx +96 -48
  194. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  195. package/src/components/VirtualTable/VirtualTableHeader.tsx +10 -10
  196. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  197. package/src/components/VirtualTable/VirtualTableProps.tsx +33 -14
  198. package/src/components/VirtualTable/VirtualTableRow.tsx +5 -6
  199. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +5 -5
  200. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +3 -2
  201. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  202. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
  203. package/src/components/VirtualTable/types.tsx +2 -3
  204. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +33 -40
  205. package/src/components/common/index.ts +2 -1
  206. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  207. package/src/components/common/types.tsx +4 -6
  208. package/src/components/common/useColumnsIds.tsx +24 -3
  209. package/src/components/common/useDataSourceTableController.tsx +420 -0
  210. package/src/components/common/useDebouncedCallback.tsx +20 -0
  211. package/src/components/common/useScrollRestoration.tsx +68 -0
  212. package/src/components/common/useTableSearchHelper.ts +53 -12
  213. package/src/components/index.tsx +4 -2
  214. package/src/contexts/BreacrumbsContext.tsx +38 -0
  215. package/src/contexts/DialogsProvider.tsx +5 -4
  216. package/src/contexts/SnackbarProvider.tsx +2 -0
  217. package/src/core/DefaultAppBar.tsx +201 -0
  218. package/src/core/DefaultDrawer.tsx +185 -0
  219. package/src/core/DrawerNavigationItem.tsx +66 -0
  220. package/src/core/EntityEditView.tsx +1001 -213
  221. package/src/core/EntitySidePanel.tsx +80 -17
  222. package/src/core/FireCMS.tsx +56 -49
  223. package/src/core/FireCMSRouter.tsx +17 -0
  224. package/src/core/NavigationRoutes.tsx +20 -34
  225. package/src/core/SideDialogs.tsx +12 -6
  226. package/src/core/field_configs.tsx +11 -12
  227. package/src/core/index.tsx +6 -5
  228. package/src/form/PropertyFieldBinding.tsx +85 -44
  229. package/src/form/components/CustomIdField.tsx +6 -2
  230. package/src/form/components/FieldHelperText.tsx +4 -4
  231. package/src/form/components/LabelWithIcon.tsx +30 -19
  232. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  233. package/src/form/components/StorageItemPreview.tsx +22 -12
  234. package/src/form/components/StorageUploadProgress.tsx +3 -4
  235. package/src/form/components/index.tsx +1 -1
  236. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +31 -17
  237. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +47 -35
  238. package/src/form/field_bindings/BlockFieldBinding.tsx +56 -34
  239. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -14
  240. package/src/form/field_bindings/KeyValueFieldBinding.tsx +60 -51
  241. package/src/form/field_bindings/MapFieldBinding.tsx +72 -53
  242. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +150 -0
  243. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +25 -20
  244. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +11 -16
  245. package/src/form/field_bindings/ReferenceFieldBinding.tsx +42 -31
  246. package/src/form/field_bindings/RepeatFieldBinding.tsx +56 -35
  247. package/src/form/field_bindings/SelectFieldBinding.tsx +22 -14
  248. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +37 -47
  249. package/src/form/field_bindings/SwitchFieldBinding.tsx +29 -24
  250. package/src/form/field_bindings/TextFieldBinding.tsx +28 -24
  251. package/src/form/index.tsx +4 -9
  252. package/src/form/useClearRestoreValue.tsx +2 -2
  253. package/src/form/validation.ts +1 -17
  254. package/src/hooks/data/delete.ts +6 -5
  255. package/src/hooks/data/save.ts +13 -9
  256. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  257. package/src/hooks/data/useDataSource.tsx +11 -3
  258. package/src/hooks/data/useEntityFetch.tsx +10 -6
  259. package/src/hooks/index.tsx +1 -0
  260. package/src/hooks/useAuthController.tsx +1 -1
  261. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  262. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  263. package/src/hooks/useBuildModeController.tsx +11 -5
  264. package/src/hooks/useBuildNavigationController.tsx +150 -50
  265. package/src/hooks/useFireCMSContext.tsx +5 -5
  266. package/src/hooks/useLargeLayout.tsx +0 -35
  267. package/src/hooks/useProjectLog.tsx +32 -10
  268. package/src/hooks/useResolvedNavigationFrom.tsx +10 -12
  269. package/src/hooks/useValidateAuthenticator.tsx +17 -37
  270. package/src/index.ts +1 -0
  271. package/src/internal/useBuildDataSource.ts +72 -82
  272. package/src/internal/useBuildSideDialogsController.tsx +4 -2
  273. package/src/internal/useBuildSideEntityController.tsx +230 -70
  274. package/src/internal/useUnsavedChangesDialog.tsx +127 -91
  275. package/src/preview/PropertyPreview.tsx +13 -20
  276. package/src/preview/PropertyPreviewProps.tsx +7 -1
  277. package/src/preview/components/BooleanPreview.tsx +2 -2
  278. package/src/preview/components/EmptyValue.tsx +1 -1
  279. package/src/preview/components/EnumValuesChip.tsx +2 -2
  280. package/src/preview/components/ImagePreview.tsx +25 -36
  281. package/src/preview/components/ReferencePreview.tsx +22 -33
  282. package/src/preview/components/StorageThumbnail.tsx +5 -1
  283. package/src/preview/components/UrlComponentPreview.tsx +44 -11
  284. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -3
  285. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  286. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -3
  287. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -2
  288. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -5
  289. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -5
  290. package/src/preview/property_previews/MapPropertyPreview.tsx +9 -9
  291. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
  292. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  293. package/src/preview/util.ts +10 -10
  294. package/src/routes/CustomCMSRoute.tsx +21 -0
  295. package/src/routes/FireCMSRoute.tsx +230 -0
  296. package/src/routes/HomePageRoute.tsx +17 -0
  297. package/src/types/auth.tsx +9 -13
  298. package/src/types/collections.ts +87 -27
  299. package/src/types/customization_controller.tsx +0 -1
  300. package/src/types/datasource.ts +61 -43
  301. package/src/types/dialogs_controller.tsx +7 -3
  302. package/src/types/entities.ts +12 -2
  303. package/src/types/entity_actions.tsx +32 -7
  304. package/src/types/entity_callbacks.ts +18 -18
  305. package/src/types/entity_overrides.tsx +2 -2
  306. package/src/types/export_import.ts +4 -4
  307. package/src/types/fields.tsx +72 -46
  308. package/src/types/firecms.tsx +7 -2
  309. package/src/types/firecms_context.tsx +1 -1
  310. package/src/types/index.ts +0 -1
  311. package/src/types/navigation.ts +37 -18
  312. package/src/types/permissions.ts +5 -5
  313. package/src/types/plugins.tsx +25 -14
  314. package/src/types/properties.ts +59 -24
  315. package/src/types/property_config.tsx +0 -2
  316. package/src/types/side_dialogs_controller.tsx +13 -0
  317. package/src/types/side_entity_controller.tsx +1 -1
  318. package/src/types/storage.ts +94 -3
  319. package/src/types/user.ts +2 -0
  320. package/src/util/builders.ts +10 -8
  321. package/src/util/entities.ts +9 -6
  322. package/src/util/entity_actions.ts +28 -0
  323. package/src/util/entity_cache.ts +196 -0
  324. package/src/util/enums.ts +1 -1
  325. package/src/util/icon_list.ts +16 -10
  326. package/src/util/icon_synonyms.ts +3 -100
  327. package/src/util/icons.tsx +17 -7
  328. package/src/util/index.ts +2 -0
  329. package/src/util/join_collections.ts +3 -0
  330. package/src/util/make_properties_editable.ts +13 -5
  331. package/src/util/navigation_from_path.ts +10 -2
  332. package/src/util/navigation_utils.ts +59 -7
  333. package/src/util/objects.ts +45 -28
  334. package/src/util/parent_references_from_path.ts +3 -3
  335. package/src/util/permissions.ts +9 -8
  336. package/src/util/plurals.ts +0 -2
  337. package/src/util/property_utils.tsx +11 -4
  338. package/src/util/references.ts +11 -2
  339. package/src/util/resolutions.ts +79 -46
  340. package/src/util/storage.ts +79 -21
  341. package/src/util/strings.ts +2 -2
  342. package/src/util/useStorageUploadController.tsx +34 -8
  343. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  344. package/dist/components/VirtualTable/common.d.ts +0 -2
  345. package/dist/core/Drawer.d.ts +0 -23
  346. package/dist/core/Scaffold.d.ts +0 -55
  347. package/dist/core/SideEntityView.d.ts +0 -7
  348. package/dist/form/EntityForm.d.ts +0 -77
  349. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  350. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  351. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  352. package/dist/internal/useLocaleConfig.d.ts +0 -1
  353. package/dist/types/appcheck.d.ts +0 -26
  354. package/src/components/FireCMSAppBar.tsx +0 -165
  355. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
  356. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -225
  357. package/src/core/Drawer.tsx +0 -191
  358. package/src/core/Scaffold.tsx +0 -281
  359. package/src/core/SideEntityView.tsx +0 -38
  360. package/src/form/EntityForm.tsx +0 -728
  361. package/src/form/components/FormikArrayContainer.tsx +0 -44
  362. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  363. package/src/internal/useBuildCustomizationController.tsx +0 -5
  364. package/src/internal/useLocaleConfig.tsx +0 -18
  365. package/src/types/appcheck.ts +0 -29
  366. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -3,24 +3,85 @@ 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
- import { getNavigationEntriesFromPathInternal, NavigationViewInternal } from "../util/navigation_from_path";
11
+ import { getNavigationEntriesFromPath, 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";
16
17
 
17
- const NEW_URL_HASH = "new";
18
+ const NEW_URL_HASH = "new_side";
19
+ const SIDE_URL_HASH = "side";
18
20
 
19
21
  export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean): string {
20
22
  if (small) return CONTAINER_FULL_WIDTH;
21
- 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
+ const mainViewSelected = !props.selectedTab;
24
+ let resolvedWidth: string | undefined;
25
+ if (props.width) {
26
+ resolvedWidth = typeof props.width === "number" ? `${props.width}px` : props.width;
27
+ } else if (props.collection?.sideDialogWidth) {
28
+ resolvedWidth = typeof props.collection.sideDialogWidth === "number" ? `${props.collection.sideDialogWidth}px` : props.collection.sideDialogWidth;
29
+ }
30
+
31
+ if (!mainViewSelected) {
32
+ return `calc(${ADDITIONAL_TAB_WIDTH} + ${resolvedWidth ?? FORM_CONTAINER_WIDTH})`
33
+ } else {
34
+ if (resolvedWidth) {
35
+ return resolvedWidth
36
+ } else if (!props.collection) {
37
+ return FORM_CONTAINER_WIDTH;
38
+ } else {
39
+ return calculateCollectionDesiredWidth(props.collection);
40
+ }
41
+ }
42
+ }
43
+
44
+ const collectionViewWidthCache: { [key: string]: string } = {};
45
+
46
+ function calculateCollectionDesiredWidth(collection: EntityCollection<any>): string {
47
+ if (collectionViewWidthCache[collection.id]) {
48
+ return collectionViewWidthCache[collection.id];
49
+ }
50
+ const resolvedCollection = resolveCollection({
51
+ collection,
52
+ path: "__ignored",
53
+ ignoreMissingFields: true
54
+ });
55
+
56
+ let result = FORM_CONTAINER_WIDTH
57
+ if (resolvedCollection?.properties) {
58
+ const values = Object.values(resolvedCollection.properties).map((p: ResolvedProperty) => getNestedPropertiesDepth(p));
59
+ const maxDepth = Math.max(...values);
60
+ if (maxDepth < 3) {
61
+ result = FORM_CONTAINER_WIDTH;
62
+ } else {
63
+ result = 768 + 32 * (maxDepth - 2) + "px";
64
+ }
65
+ }
66
+ collectionViewWidthCache[collection.id] = result;
67
+ return result;
68
+ }
69
+
70
+ function getNestedPropertiesDepth(property: ResolvedProperty, accumulator: number = 0): number {
71
+ if (property.dataType === "map" && property.properties) {
72
+ const values = Object.values(property.properties).flatMap((property) => getNestedPropertiesDepth(property, accumulator + 1));
73
+ return Math.max(...values);
74
+ } else if (property.dataType === "array" && property.oneOf) {
75
+ return accumulator + 3;
76
+ } else if (property.dataType === "array" && property.of) {
77
+ if (Array.isArray(property.of)) {
78
+ return Math.max(...property.of.map((p) => getNestedPropertiesDepth(p, accumulator + 1)));
79
+ } else {
80
+ return getNestedPropertiesDepth(property.of, accumulator + 1);
81
+ }
82
+ } else {
83
+ return accumulator + 1;
84
+ }
24
85
  }
25
86
 
26
87
  export const useBuildSideEntityController = (navigation: NavigationController,
@@ -33,24 +94,60 @@ export const useBuildSideEntityController = (navigation: NavigationController,
33
94
 
34
95
  // only on initialisation, create panels from URL
35
96
  useEffect(() => {
36
- if (!navigation.loading && !initialised.current) {
37
- if (navigation.isUrlCollectionPath(location.pathname)) {
38
- const newFlag = location.hash === `#${NEW_URL_HASH}`;
97
+
98
+ const newFlag = location.hash === `#${NEW_URL_HASH}`;
99
+ const sideFlag = location.hash === `#${SIDE_URL_HASH}`;
100
+
101
+ if (!navigation.loading) {
102
+ if ((newFlag || sideFlag) && navigation.isUrlCollectionPath(location.pathname)) {
39
103
  const entityOrCollectionPath = navigation.urlPathToDataPath(location.pathname);
40
104
  const panelsFromUrl = buildSidePanelsFromUrl(entityOrCollectionPath, navigation.collections ?? [], newFlag);
41
105
  for (let i = 0; i < panelsFromUrl.length; i++) {
42
- const panel = panelsFromUrl[i];
43
- setTimeout(() => {
44
- if (i === 0)
45
- sideDialogsController.replace(propsToSidePanel(panel, navigation, smallLayout));
46
- else
47
- sideDialogsController.open(propsToSidePanel(panel, navigation, smallLayout))
48
- }, 1);
106
+ const props = panelsFromUrl[i];
107
+ // setTimeout(() => {
108
+ if (i === 0)
109
+ sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout));
110
+ else
111
+ sideDialogsController.open(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout))
112
+ // }, 1);
49
113
  }
50
114
  }
51
115
  initialised.current = true;
52
116
  }
53
- }, [location, navigation, sideDialogsController, smallLayout]);
117
+ }, [navigation.loading]);
118
+
119
+ // sync panels if URL changes with #side
120
+ const currentPanelKeys = sideDialogsController.sidePanels.map(p => p.key);
121
+ useEffect(() => {
122
+ if (initialised.current) {
123
+ const sideFlag = location.hash === `#${SIDE_URL_HASH}`;
124
+ if (sideFlag) {
125
+ const entityOrCollectionPath = navigation.urlPathToDataPath(location.pathname);
126
+ const panelsFromUrl = buildSidePanelsFromUrl(entityOrCollectionPath, navigation.collections ?? [], false);
127
+ // if we have more panels than determined by the url, we ignore the url. We might have references open
128
+ if (panelsFromUrl.length <= currentPanelKeys.length) {
129
+ return;
130
+ }
131
+ const lastPanel = panelsFromUrl[panelsFromUrl.length - 1];
132
+ const panelProps = propsToSidePanel(lastPanel, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout);
133
+ const lastCurrentPanel = currentPanelKeys.length > 0 ? currentPanelKeys[currentPanelKeys.length - 1] : undefined;
134
+ if (!lastCurrentPanel || lastCurrentPanel !== panelProps.key) {
135
+ sideDialogsController.replace(panelProps);
136
+ }
137
+ }
138
+ }
139
+ }, [location.pathname, location.hash, currentPanelKeys]);
140
+
141
+ // update side panels to match browser size
142
+ useEffect(() => {
143
+ const updatedSidePanels = sideDialogsController.sidePanels.map(sidePanelProps => {
144
+ if (sidePanelProps.additional) {
145
+ return propsToSidePanel(sidePanelProps.additional, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout);
146
+ }
147
+ return sidePanelProps;
148
+ });
149
+ sideDialogsController.setSidePanels(updatedSidePanels);
150
+ }, [smallLayout]);
54
151
 
55
152
  const close = useCallback(() => {
56
153
  sideDialogsController.close();
@@ -70,12 +167,17 @@ export const useBuildSideEntityController = (navigation: NavigationController,
70
167
  }
71
168
  );
72
169
 
73
- sideDialogsController.open(propsToSidePanel({
74
- selectedSubPath: defaultSelectedView,
75
- ...props,
76
- }, navigation, smallLayout));
170
+ sideDialogsController.open(
171
+ propsToSidePanel({
172
+ selectedTab: defaultSelectedView,
173
+ ...props
174
+ },
175
+ navigation.buildUrlCollectionPath,
176
+ navigation.resolveIdsFrom,
177
+ smallLayout
178
+ ));
77
179
 
78
- }, [sideDialogsController, navigation, smallLayout]);
180
+ }, [sideDialogsController, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout]);
79
181
 
80
182
  const replace = useCallback((props: EntitySidePanelProps<any>) => {
81
183
 
@@ -83,9 +185,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
83
185
  throw Error("If you want to copy an entity you need to provide an entityId");
84
186
  }
85
187
 
86
- sideDialogsController.replace(propsToSidePanel(props, navigation, smallLayout));
188
+ sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout));
87
189
 
88
- }, [navigation, sideDialogsController, smallLayout]);
190
+ }, [navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, sideDialogsController, smallLayout]);
89
191
 
90
192
  return {
91
193
  close,
@@ -96,12 +198,12 @@ export const useBuildSideEntityController = (navigation: NavigationController,
96
198
 
97
199
  export function buildSidePanelsFromUrl(path: string, collections: EntityCollection[], newFlag: boolean): EntitySidePanelProps<any>[] {
98
200
 
99
- const navigationViewsForPath: NavigationViewInternal<any>[] = getNavigationEntriesFromPathInternal({
201
+ const navigationViewsForPath: NavigationViewInternal<any>[] = getNavigationEntriesFromPath({
100
202
  path,
101
203
  collections
102
204
  });
103
205
 
104
- const sidePanels: EntitySidePanelProps<any>[] = [];
206
+ let sidePanel: EntitySidePanelProps<any> | undefined = undefined;
105
207
  let lastCollectionPath = "";
106
208
  for (let i = 0; i < navigationViewsForPath.length; i++) {
107
209
  const navigationEntry = navigationViewsForPath[i];
@@ -110,63 +212,121 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
110
212
  lastCollectionPath = navigationEntry.path;
111
213
  }
112
214
 
113
- if (i > 0) { // the first collection is handled by the main navigation
114
- const previousEntry = navigationViewsForPath[i - 1];
115
- if (navigationEntry.type === "entity") {
116
- sidePanels.push({
117
- path: navigationEntry.path,
118
- entityId: navigationEntry.entityId,
119
- copy: false
120
- }
121
- );
122
- } else if (navigationEntry.type === "custom_view") {
123
- if (previousEntry.type === "entity") {
124
- const lastSidePanel: EntitySidePanelProps<any> = sidePanels[sidePanels.length - 1];
125
- if (lastSidePanel)
126
- lastSidePanel.selectedSubPath = navigationEntry.view.key;
127
- }
128
- } else if (navigationEntry.type === "collection") {
129
- if (previousEntry.type === "entity") {
130
- const lastSidePanel: EntitySidePanelProps<any> = sidePanels[sidePanels.length - 1];
131
- if (lastSidePanel)
132
- lastSidePanel.selectedSubPath = navigationEntry.collection.id ?? navigationEntry.collection.path;
133
- }
215
+ const previousEntry = navigationViewsForPath[i - 1];
216
+ if (navigationEntry.type === "entity") {
217
+ sidePanel = {
218
+ path: navigationEntry.path,
219
+ entityId: navigationEntry.entityId,
220
+ copy: false,
221
+ width: navigationEntry.parentCollection?.sideDialogWidth
222
+ };
223
+ } else if (navigationEntry.type === "custom_view") {
224
+ if (previousEntry?.type === "entity") {
225
+ if (sidePanel)
226
+ sidePanel.selectedTab = navigationEntry.view.key;
227
+ }
228
+ } else if (navigationEntry.type === "collection") {
229
+ if (previousEntry?.type === "entity") {
230
+ if (sidePanel)
231
+ sidePanel.selectedTab = navigationEntry.collection.id ?? navigationEntry.collection.path;
134
232
  }
135
233
  }
136
234
 
137
235
  }
138
236
 
139
237
  if (newFlag) {
140
- sidePanels.push({
238
+ sidePanel = {
141
239
  path: lastCollectionPath,
142
240
  copy: false
143
- });
241
+ }
144
242
  }
145
243
 
146
- return sidePanels;
244
+ return sidePanel ? [sidePanel] : [];
147
245
  }
148
246
 
149
- const propsToSidePanel = (props: EntitySidePanelProps<any>, navigation: NavigationController, smallLayout: boolean): SideDialogPanelProps => {
247
+ // export function buildSidePanelsFromUrl(path: string, collections: EntityCollection[], newFlag: boolean): EntitySidePanelProps<any>[] {
248
+ //
249
+ // const navigationViewsForPath: NavigationViewInternal<any>[] = getNavigationEntriesFromPathInternal({
250
+ // path,
251
+ // collections
252
+ // });
253
+ //
254
+ // const sidePanels: EntitySidePanelProps<any>[] = [];
255
+ // let lastCollectionPath = "";
256
+ // for (let i = 0; i < navigationViewsForPath.length; i++) {
257
+ // const navigationEntry = navigationViewsForPath[i];
258
+ //
259
+ // if (navigationEntry.type === "collection") {
260
+ // lastCollectionPath = navigationEntry.path;
261
+ // }
262
+ //
263
+ // if (i > 0) { // the first collection is handled by the main navigation
264
+ // const previousEntry = navigationViewsForPath[i - 1];
265
+ // if (navigationEntry.type === "entity") {
266
+ // sidePanels.push({
267
+ // path: navigationEntry.path,
268
+ // entityId: navigationEntry.entityId,
269
+ // copy: false,
270
+ // width: navigationEntry.parentCollection?.sideDialogWidth
271
+ // }
272
+ // );
273
+ // } else if (navigationEntry.type === "custom_view") {
274
+ // if (previousEntry.type === "entity") {
275
+ // const lastSidePanel: EntitySidePanelProps<any> = sidePanels[sidePanels.length - 1];
276
+ // if (lastSidePanel)
277
+ // lastSidePanel.selectedTab = navigationEntry.view.key;
278
+ // }
279
+ // } else if (navigationEntry.type === "collection") {
280
+ // if (previousEntry.type === "entity") {
281
+ // const lastSidePanel: EntitySidePanelProps<any> = sidePanels[sidePanels.length - 1];
282
+ // if (lastSidePanel)
283
+ // lastSidePanel.selectedTab = navigationEntry.collection.id ?? navigationEntry.collection.path;
284
+ // }
285
+ // }
286
+ // }
287
+ //
288
+ // }
289
+ //
290
+ // if (newFlag) {
291
+ // sidePanels.push({
292
+ // path: lastCollectionPath,
293
+ // copy: false
294
+ // });
295
+ // }
296
+ //
297
+ // return sidePanels;
298
+ // }
150
299
 
151
- const collectionPath = removeInitialAndTrailingSlashes(props.path);
300
+ const propsToSidePanel = (props: EntitySidePanelProps,
301
+ buildUrlCollectionPath: (path: string) => string,
302
+ resolveIdsFrom: (pathWithAliases: string) => string,
303
+ smallLayout: boolean): SideDialogPanelProps => {
152
304
 
153
- 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);
305
+ const collectionPath = removeInitialAndTrailingSlashes(props.path);
157
306
 
158
- const resolvedPanelProps: EntitySidePanelProps<any> = {
159
- ...props,
160
- path: resolvedPath
161
- };
307
+ const newPath = props.entityId
308
+ ? buildUrlCollectionPath(`${collectionPath}/${props.entityId}${props.selectedTab ? "/" + props.selectedTab : ""}#${SIDE_URL_HASH}`)
309
+ : buildUrlCollectionPath(`${collectionPath}#${NEW_URL_HASH}`);
310
+ const resolvedPath = resolveIdsFrom(props.path);
162
311
 
163
- return ({
164
- key: `${props.path}/${props.entityId}`,
165
- component: <EntitySidePanel {...resolvedPanelProps}/>,
166
- urlPath: newPath,
167
- parentUrlPath: navigation.buildUrlCollectionPath(collectionPath),
168
- width: getEntityViewWidth(props, smallLayout),
169
- onClose: props.onClose
170
- });
171
- }
172
- ;
312
+ const resolvedPanelProps: EntitySidePanelProps<any> = {
313
+ ...props,
314
+ path: resolvedPath,
315
+ };
316
+
317
+ const entityViewWidth = getEntityViewWidth(props, smallLayout);
318
+
319
+ return {
320
+ key: `${props.path}/${props.entityId}`,
321
+ component: <EntitySidePanel {...resolvedPanelProps}/>,
322
+ urlPath: newPath,
323
+ parentUrlPath: buildUrlCollectionPath(collectionPath),
324
+ width: entityViewWidth,
325
+ onClose: props.onClose,
326
+ additional: props
327
+ };
328
+ }
329
+
330
+ function isSideUrl(url: string): boolean {
331
+ return url.endsWith("#" + SIDE_URL_HASH) || url.endsWith("#" + NEW_URL_HASH);
332
+ }
@@ -1,106 +1,142 @@
1
- import React, { useCallback } from "react";
2
- import { Blocker, Transition } from "history";
3
- import { UNSAFE_NavigationContext, useNavigate } from "react-router-dom";
4
- import { Button, Dialog, DialogActions, DialogContent, Typography } from "@firecms/ui";
1
+ import React, { useCallback, useEffect, useState } from "react";
2
+ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@firecms/ui";
5
3
 
6
- export function useNavigationUnsavedChangesDialog(when: boolean, onSuccess: () => void):
7
- {
8
- navigationWasBlocked: boolean,
9
- handleCancel: () => void,
10
- handleOk: () => void
11
- } {
12
-
13
- const [nextLocation, setNextLocation] = React.useState<any | undefined>();
14
- const { navigator } = React.useContext(UNSAFE_NavigationContext);
4
+ /**
5
+ * Type representing a pending navigation action.
6
+ */
7
+ type PendingNavigation =
8
+ | {
9
+ type: "popstate";
10
+ delta: number;
11
+ }
12
+ | {
13
+ type: "link";
14
+ href: string;
15
+ }
16
+ | null;
15
17
 
16
- const navigate = useNavigate();
18
+ /**
19
+ * Custom hook to handle navigation blocking when there are unsaved changes.
20
+ *
21
+ * @param when - Indicates whether to block navigation.
22
+ * @param onSuccess - Callback invoked when navigation is confirmed.
23
+ * @returns An object containing the state of navigation blocking and handlers.
24
+ */
25
+ export function useNavigationUnsavedChangesDialog(
26
+ when: boolean,
27
+ onSuccess: () => void
28
+ ): {
29
+ navigationWasBlocked: boolean;
30
+ handleCancel: () => void;
31
+ handleOk: () => void;
32
+ } {
33
+ const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
34
+ const [pendingNavigation, setPendingNavigation] = useState<PendingNavigation>(null);
17
35
 
18
- const handleCancel = () => {
19
- setNextLocation(undefined);
20
- };
36
+ /**
37
+ * Handler to cancel the navigation attempt.
38
+ */
39
+ const handleCancel = useCallback(() => {
40
+ setIsDialogOpen(false);
41
+ setPendingNavigation(null);
42
+ }, []);
21
43
 
22
- const handleOk = () => {
23
- onSuccess();
24
- setNextLocation(undefined);
25
- navigate(-1);
26
- };
44
+ /**
45
+ * Handler to confirm and proceed with the navigation.
46
+ */
47
+ const handleOk = useCallback(() => {
48
+ setIsDialogOpen(false);
49
+ if (pendingNavigation) {
50
+ onSuccess();
51
+ if (pendingNavigation.type === "popstate") {
52
+ window.history.go(pendingNavigation.delta);
53
+ } else if (pendingNavigation.type === "link") {
54
+ window.location.href = pendingNavigation.href;
55
+ }
56
+ setPendingNavigation(null);
57
+ }
58
+ }, [onSuccess, pendingNavigation]);
27
59
 
28
- const blocker: Blocker = useCallback(({
29
- action,
30
- location: nextLocation,
31
- retry
32
- }) => {
33
- switch (action) {
34
- case "REPLACE": {
35
- retry();
36
- return;
60
+ /**
61
+ * Event handler for beforeunload to handle page refresh or tab close.
62
+ */
63
+ const handleBeforeUnload = useCallback(
64
+ (e: BeforeUnloadEvent) => {
65
+ if (when) {
66
+ e.preventDefault();
67
+ e.returnValue = "";
37
68
  }
38
- case "POP": {
39
- setNextLocation(nextLocation);
69
+ },
70
+ [when]
71
+ );
72
+
73
+ /**
74
+ * Event handler for popstate to handle back and forward browser buttons.
75
+ */
76
+ const handlePopState = useCallback(
77
+ (e: PopStateEvent) => {
78
+ if (when) {
79
+ e.preventDefault();
80
+ // Assuming backward navigation; adjust delta as needed
81
+ setPendingNavigation({
82
+ type: "popstate",
83
+ delta: -1
84
+ });
85
+ setIsDialogOpen(true);
40
86
  }
41
- }
42
- }, []);
87
+ },
88
+ [when]
89
+ );
90
+
91
+ /**
92
+ * Event handler to intercept link clicks within the application.
93
+ */
94
+ const handleLinkClick = useCallback(
95
+ (e: MouseEvent) => {
96
+ if (!when) return;
43
97
 
44
- React.useEffect(() => {
45
- if (!when) return;
46
- if (nextLocation) return;
47
- if (!("block" in navigator)) return;
48
- const unblock = (navigator as any).block((tx: Transition) => {
49
- const autoUnblockingTx = {
50
- ...tx,
51
- retry() {
52
- unblock();
53
- tx.retry();
98
+ const target = e.target as HTMLElement;
99
+ const anchor = target.closest("a[href]") as HTMLAnchorElement | null;
100
+ if (anchor && anchor.host === window.location.host) {
101
+ e.preventDefault();
102
+ const href = anchor.getAttribute("href");
103
+ if (href) {
104
+ setPendingNavigation({
105
+ type: "link",
106
+ href
107
+ });
108
+ setIsDialogOpen(true);
54
109
  }
55
- };
56
- blocker(autoUnblockingTx);
57
- });
110
+ }
111
+ },
112
+ [when]
113
+ );
114
+
115
+ /**
116
+ * Effect hook to add and clean up event listeners based on the `when` condition.
117
+ */
118
+ useEffect(() => {
119
+ if (when) {
120
+ window.addEventListener("beforeunload", handleBeforeUnload);
121
+ window.addEventListener("popstate", handlePopState);
122
+ document.addEventListener("click", handleLinkClick);
123
+ } else {
124
+ window.removeEventListener("beforeunload", handleBeforeUnload);
125
+ window.removeEventListener("popstate", handlePopState);
126
+ document.removeEventListener("click", handleLinkClick);
127
+ }
58
128
 
59
- return unblock;
60
- }, [navigator, blocker, when, nextLocation]);
129
+ // Cleanup on unmount or when `when` changes
130
+ return () => {
131
+ window.removeEventListener("beforeunload", handleBeforeUnload);
132
+ window.removeEventListener("popstate", handlePopState);
133
+ document.removeEventListener("click", handleLinkClick);
134
+ };
135
+ }, [when, handleBeforeUnload, handlePopState, handleLinkClick]);
61
136
 
62
137
  return {
63
- navigationWasBlocked: Boolean(nextLocation),
138
+ navigationWasBlocked: isDialogOpen,
64
139
  handleCancel,
65
- handleOk
140
+ handleOk,
66
141
  };
67
142
  }
68
-
69
- export interface UnsavedChangesDialogProps {
70
- open: boolean;
71
- body?: React.ReactNode;
72
- title?: string;
73
- handleOk: () => void;
74
- handleCancel: () => void;
75
- }
76
-
77
- export function UnsavedChangesDialog({
78
- open,
79
- handleOk,
80
- handleCancel,
81
- body,
82
- title
83
- }: UnsavedChangesDialogProps) {
84
-
85
- return (
86
- <Dialog
87
- open={open}
88
- onOpenChange={(open) => open ? handleCancel() : handleOk()}
89
- >
90
- <DialogContent>
91
- <Typography variant={"h6"}>{title}</Typography>
92
-
93
- {body}
94
-
95
- <Typography>
96
- Are you sure you want to leave this page?
97
- </Typography>
98
-
99
- </DialogContent>
100
- <DialogActions>
101
- <Button variant="text" onClick={handleCancel} autoFocus> Cancel </Button>
102
- <Button onClick={handleOk}> Ok </Button>
103
- </DialogActions>
104
- </Dialog>
105
- );
106
- }