@firecms/core 3.0.0-canary.99 → 3.0.0-rc.2

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 (371) hide show
  1. package/README.md +2 -2
  2. package/dist/app/Drawer.d.ts +0 -1
  3. package/dist/app/Scaffold.d.ts +4 -0
  4. package/dist/components/ArrayContainer.d.ts +31 -12
  5. package/dist/components/{DeleteConfirmationDialog.d.ts → ConfirmationDialog.d.ts} +1 -1
  6. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +3 -1
  7. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  8. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +17 -3
  9. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +1 -1
  10. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  11. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +6 -3
  12. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +8 -0
  13. package/dist/components/EntityCollectionView/utils.d.ts +3 -0
  14. package/dist/components/EntityJsonPreview.d.ts +3 -0
  15. package/dist/components/EntityPreview.d.ts +8 -6
  16. package/dist/components/HomePage/DefaultHomePage.d.ts +2 -15
  17. package/dist/components/HomePage/HomePageDnD.d.ts +76 -0
  18. package/dist/components/HomePage/NavigationCard.d.ts +3 -1
  19. package/dist/components/HomePage/NavigationCardBinding.d.ts +3 -2
  20. package/dist/components/HomePage/NavigationGroup.d.ts +8 -1
  21. package/dist/components/HomePage/RenameGroupDialog.d.ts +9 -0
  22. package/dist/components/PropertyConfigBadge.d.ts +2 -1
  23. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  24. package/dist/components/SelectableTable/SelectableTable.d.ts +13 -3
  25. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
  26. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  27. package/dist/components/UserDisplay.d.ts +7 -0
  28. package/dist/components/VirtualTable/VirtualTableProps.d.ts +11 -2
  29. package/dist/components/VirtualTable/fields/VirtualTableUserSelect.d.ts +12 -0
  30. package/dist/components/common/default_entity_actions.d.ts +0 -2
  31. package/dist/components/common/index.d.ts +1 -1
  32. package/dist/components/common/useColumnsIds.d.ts +1 -0
  33. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
  34. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  35. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  36. package/dist/components/index.d.ts +3 -1
  37. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  38. package/dist/contexts/InternalUserManagementContext.d.ts +3 -0
  39. package/dist/core/DefaultAppBar.d.ts +8 -2
  40. package/dist/core/DrawerNavigationItem.d.ts +2 -1
  41. package/dist/core/EntityEditView.d.ts +40 -22
  42. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  43. package/dist/core/FireCMS.d.ts +2 -3
  44. package/dist/core/FireCMSRouter.d.ts +4 -0
  45. package/dist/core/NavigationRoutes.d.ts +0 -1
  46. package/dist/core/SideDialogs.d.ts +4 -2
  47. package/dist/core/field_configs.d.ts +1 -1
  48. package/dist/core/index.d.ts +2 -1
  49. package/dist/form/EntityForm.d.ts +50 -0
  50. package/dist/form/EntityFormActions.d.ts +21 -0
  51. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  52. package/dist/form/components/FormEntry.d.ts +6 -0
  53. package/dist/form/components/FormLayout.d.ts +5 -0
  54. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  55. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  56. package/dist/form/components/index.d.ts +3 -1
  57. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  58. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  59. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  60. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  61. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  62. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  63. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  64. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  65. package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +9 -0
  66. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  67. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  68. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  69. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +4 -10
  70. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  71. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  72. package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +12 -0
  73. package/dist/form/index.d.ts +17 -16
  74. package/dist/form/useClearRestoreValue.d.ts +2 -2
  75. package/dist/hooks/data/delete.d.ts +4 -4
  76. package/dist/hooks/data/save.d.ts +3 -3
  77. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  78. package/dist/hooks/data/useEntityFetch.d.ts +4 -3
  79. package/dist/hooks/index.d.ts +2 -0
  80. package/dist/hooks/useAuthController.d.ts +1 -1
  81. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  82. package/dist/hooks/useBuildNavigationController.d.ts +57 -12
  83. package/dist/hooks/useCollapsedGroups.d.ts +9 -0
  84. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  85. package/dist/hooks/useInternalUserManagementController.d.ts +12 -0
  86. package/dist/hooks/useModeController.d.ts +1 -2
  87. package/dist/hooks/useProjectLog.d.ts +7 -1
  88. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  89. package/dist/hooks/useValidateAuthenticator.d.ts +3 -3
  90. package/dist/index.es.js +20480 -14434
  91. package/dist/index.es.js.map +1 -1
  92. package/dist/index.umd.js +20250 -14209
  93. package/dist/index.umd.js.map +1 -1
  94. package/dist/internal/useBuildDataSource.d.ts +3 -2
  95. package/dist/internal/useBuildSideEntityController.d.ts +3 -3
  96. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  97. package/dist/preview/PropertyPreviewProps.d.ts +1 -1
  98. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  99. package/dist/preview/components/ReferencePreview.d.ts +2 -2
  100. package/dist/preview/components/UserPreview.d.ts +8 -0
  101. package/dist/preview/index.d.ts +1 -0
  102. package/dist/preview/util.d.ts +3 -3
  103. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  104. package/dist/routes/FireCMSRoute.d.ts +1 -0
  105. package/dist/routes/HomePageRoute.d.ts +3 -0
  106. package/dist/types/analytics.d.ts +1 -1
  107. package/dist/types/auth.d.ts +7 -9
  108. package/dist/types/collections.d.ts +88 -25
  109. package/dist/types/customization_controller.d.ts +8 -0
  110. package/dist/types/datasource.d.ts +19 -17
  111. package/dist/types/dialogs_controller.d.ts +7 -3
  112. package/dist/types/entities.d.ts +7 -2
  113. package/dist/types/entity_actions.d.ts +58 -8
  114. package/dist/types/entity_callbacks.d.ts +16 -16
  115. package/dist/types/entity_overrides.d.ts +2 -2
  116. package/dist/types/export_import.d.ts +4 -4
  117. package/dist/types/fields.d.ts +43 -17
  118. package/dist/types/firecms.d.ts +31 -3
  119. package/dist/types/firecms_context.d.ts +17 -1
  120. package/dist/types/index.d.ts +1 -0
  121. package/dist/types/internal_user_management.d.ts +20 -0
  122. package/dist/types/navigation.d.ts +60 -17
  123. package/dist/types/permissions.d.ts +4 -4
  124. package/dist/types/plugins.d.ts +44 -9
  125. package/dist/types/properties.d.ts +74 -22
  126. package/dist/types/property_config.d.ts +1 -3
  127. package/dist/types/roles.d.ts +3 -0
  128. package/dist/types/side_dialogs_controller.d.ts +10 -0
  129. package/dist/types/side_entity_controller.d.ts +14 -1
  130. package/dist/types/storage.d.ts +75 -0
  131. package/dist/types/user.d.ts +2 -1
  132. package/dist/util/builders.d.ts +3 -3
  133. package/dist/util/callbacks.d.ts +2 -0
  134. package/dist/util/createFormexStub.d.ts +2 -0
  135. package/dist/util/entities.d.ts +2 -2
  136. package/dist/util/entity_actions.d.ts +2 -0
  137. package/dist/util/entity_cache.d.ts +23 -0
  138. package/dist/util/icon_synonyms.d.ts +0 -1
  139. package/dist/util/icons.d.ts +5 -2
  140. package/dist/util/index.d.ts +3 -0
  141. package/dist/util/navigation_from_path.d.ts +10 -1
  142. package/dist/util/navigation_utils.d.ts +13 -1
  143. package/dist/util/objects.d.ts +2 -1
  144. package/dist/util/permissions.d.ts +4 -4
  145. package/dist/util/property_utils.d.ts +4 -4
  146. package/dist/util/references.d.ts +2 -2
  147. package/dist/util/resolutions.d.ts +30 -6
  148. package/dist/util/storage.d.ts +1 -1
  149. package/dist/util/useStorageUploadController.d.ts +2 -2
  150. package/package.json +133 -125
  151. package/src/app/Drawer.tsx +0 -1
  152. package/src/app/Scaffold.tsx +33 -29
  153. package/src/components/ArrayContainer.tsx +447 -229
  154. package/src/components/CircularProgressCenter.tsx +1 -1
  155. package/src/components/ClearFilterSortButton.tsx +1 -1
  156. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +12 -11
  157. package/src/components/DeleteEntityDialog.tsx +13 -20
  158. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +59 -25
  159. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +23 -17
  160. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +20 -3
  161. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +47 -9
  162. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +21 -16
  163. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +6 -12
  164. package/src/components/EntityCollectionTable/index.tsx +1 -1
  165. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +6 -6
  166. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +35 -26
  167. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
  168. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +132 -101
  169. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +9 -9
  170. package/src/components/EntityCollectionView/EntityCollectionView.tsx +178 -85
  171. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +7 -4
  172. package/src/components/EntityCollectionView/useSelectionController.tsx +5 -4
  173. package/src/components/EntityCollectionView/utils.ts +19 -0
  174. package/src/components/EntityJsonPreview.tsx +66 -0
  175. package/src/components/EntityPreview.tsx +75 -57
  176. package/src/components/EntityView.tsx +8 -5
  177. package/src/components/ErrorView.tsx +3 -3
  178. package/src/components/FireCMSLogo.tsx +7 -51
  179. package/src/components/HomePage/DefaultHomePage.tsx +506 -161
  180. package/src/components/HomePage/FavouritesView.tsx +9 -14
  181. package/src/components/HomePage/HomePageDnD.tsx +600 -0
  182. package/src/components/HomePage/NavigationCard.tsx +47 -38
  183. package/src/components/HomePage/NavigationCardBinding.tsx +16 -15
  184. package/src/components/HomePage/NavigationGroup.tsx +144 -30
  185. package/src/components/HomePage/RenameGroupDialog.tsx +123 -0
  186. package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
  187. package/src/components/NotFoundPage.tsx +2 -2
  188. package/src/components/PropertyConfigBadge.tsx +10 -4
  189. package/src/components/PropertyIdCopyTooltip.tsx +47 -0
  190. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +22 -13
  191. package/src/components/SearchIconsView.tsx +2 -2
  192. package/src/components/SelectableTable/SelectableTable.tsx +154 -142
  193. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +4 -2
  194. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +10 -8
  195. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +60 -11
  196. package/src/components/UnsavedChangesDialog.tsx +46 -0
  197. package/src/components/UserDisplay.tsx +55 -0
  198. package/src/components/VirtualTable/VirtualTable.tsx +65 -44
  199. package/src/components/VirtualTable/VirtualTableCell.tsx +0 -8
  200. package/src/components/VirtualTable/VirtualTableHeader.tsx +8 -8
  201. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +1 -1
  202. package/src/components/VirtualTable/VirtualTableProps.tsx +12 -2
  203. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  204. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +4 -4
  205. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -2
  206. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  207. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
  208. package/src/components/VirtualTable/fields/VirtualTableUserSelect.tsx +99 -0
  209. package/src/components/common/default_entity_actions.tsx +62 -42
  210. package/src/components/common/index.ts +1 -1
  211. package/src/components/common/useColumnsIds.tsx +2 -9
  212. package/src/components/common/useDataSourceTableController.tsx +420 -0
  213. package/src/components/common/useDebouncedCallback.tsx +20 -0
  214. package/src/components/common/useScrollRestoration.tsx +68 -0
  215. package/src/components/common/useTableSearchHelper.ts +1 -0
  216. package/src/components/index.tsx +4 -1
  217. package/src/contexts/BreacrumbsContext.tsx +38 -0
  218. package/src/contexts/DialogsProvider.tsx +3 -2
  219. package/src/contexts/InternalUserManagementContext.tsx +4 -0
  220. package/src/contexts/ModeController.tsx +1 -3
  221. package/src/contexts/SnackbarProvider.tsx +2 -0
  222. package/src/core/DefaultAppBar.tsx +124 -85
  223. package/src/core/DefaultDrawer.tsx +30 -22
  224. package/src/core/DrawerNavigationItem.tsx +32 -28
  225. package/src/core/EntityEditView.tsx +388 -995
  226. package/src/core/EntityEditViewFormActions.tsx +329 -0
  227. package/src/core/EntitySidePanel.tsx +88 -20
  228. package/src/core/FireCMS.tsx +58 -28
  229. package/src/core/FireCMSRouter.tsx +17 -0
  230. package/src/core/NavigationRoutes.tsx +23 -32
  231. package/src/core/SideDialogs.tsx +22 -12
  232. package/src/core/field_configs.tsx +39 -11
  233. package/src/core/index.tsx +4 -2
  234. package/src/form/EntityForm.tsx +814 -0
  235. package/src/form/EntityFormActions.tsx +211 -0
  236. package/src/form/PropertyFieldBinding.tsx +59 -41
  237. package/src/form/components/CustomIdField.tsx +9 -3
  238. package/src/form/components/FieldHelperText.tsx +1 -1
  239. package/src/form/components/FormEntry.tsx +22 -0
  240. package/src/form/components/FormLayout.tsx +16 -0
  241. package/src/form/components/LabelWithIcon.tsx +30 -19
  242. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  243. package/src/form/components/StorageItemPreview.tsx +5 -4
  244. package/src/form/components/StorageUploadProgress.tsx +2 -3
  245. package/src/form/components/index.tsx +3 -1
  246. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +30 -18
  247. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +47 -36
  248. package/src/form/field_bindings/BlockFieldBinding.tsx +55 -33
  249. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -14
  250. package/src/form/field_bindings/KeyValueFieldBinding.tsx +19 -15
  251. package/src/form/field_bindings/MapFieldBinding.tsx +72 -62
  252. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +159 -0
  253. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +26 -21
  254. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +10 -8
  255. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +135 -0
  256. package/src/form/field_bindings/ReferenceFieldBinding.tsx +28 -19
  257. package/src/form/field_bindings/RepeatFieldBinding.tsx +56 -32
  258. package/src/form/field_bindings/SelectFieldBinding.tsx +22 -13
  259. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +247 -168
  260. package/src/form/field_bindings/SwitchFieldBinding.tsx +29 -24
  261. package/src/form/field_bindings/TextFieldBinding.tsx +28 -24
  262. package/src/form/field_bindings/UserSelectFieldBinding.tsx +94 -0
  263. package/src/form/index.tsx +17 -37
  264. package/src/form/useClearRestoreValue.tsx +2 -2
  265. package/src/form/validation.ts +12 -6
  266. package/src/hooks/data/delete.ts +6 -5
  267. package/src/hooks/data/save.ts +26 -35
  268. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  269. package/src/hooks/data/useDataSource.tsx +10 -2
  270. package/src/hooks/data/useEntityFetch.tsx +10 -6
  271. package/src/hooks/index.tsx +3 -0
  272. package/src/hooks/useAuthController.tsx +1 -1
  273. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  274. package/src/hooks/useBrowserTitleAndIcon.tsx +1 -1
  275. package/src/hooks/useBuildModeController.tsx +15 -28
  276. package/src/hooks/useBuildNavigationController.tsx +386 -124
  277. package/src/hooks/useCollapsedGroups.ts +64 -0
  278. package/src/hooks/useFireCMSContext.tsx +9 -35
  279. package/src/hooks/useInternalUserManagementController.tsx +16 -0
  280. package/src/hooks/useLargeLayout.tsx +0 -35
  281. package/src/hooks/useModeController.tsx +1 -2
  282. package/src/hooks/useProjectLog.tsx +16 -5
  283. package/src/hooks/useResolvedNavigationFrom.tsx +9 -11
  284. package/src/hooks/useValidateAuthenticator.tsx +3 -3
  285. package/src/internal/useBuildDataSource.ts +67 -80
  286. package/src/internal/useBuildSideDialogsController.tsx +4 -2
  287. package/src/internal/useBuildSideEntityController.tsx +149 -86
  288. package/src/internal/useUnsavedChangesDialog.tsx +127 -91
  289. package/src/preview/PropertyPreview.tsx +36 -12
  290. package/src/preview/PropertyPreviewProps.tsx +1 -1
  291. package/src/preview/components/BooleanPreview.tsx +1 -1
  292. package/src/preview/components/EmptyValue.tsx +1 -1
  293. package/src/preview/components/EnumValuesChip.tsx +1 -1
  294. package/src/preview/components/ImagePreview.tsx +10 -9
  295. package/src/preview/components/ReferencePreview.tsx +10 -18
  296. package/src/preview/components/UrlComponentPreview.tsx +20 -21
  297. package/src/preview/components/UserPreview.tsx +27 -0
  298. package/src/preview/index.ts +1 -0
  299. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +6 -5
  300. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +5 -4
  301. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +5 -3
  302. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -3
  303. package/src/preview/property_previews/ArrayOneOfPreview.tsx +6 -4
  304. package/src/preview/property_previews/ArrayPropertyPreview.tsx +6 -4
  305. package/src/preview/property_previews/MapPropertyPreview.tsx +7 -6
  306. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +13 -13
  307. package/src/preview/property_previews/StringPropertyPreview.tsx +2 -2
  308. package/src/preview/util.ts +10 -10
  309. package/src/routes/CustomCMSRoute.tsx +21 -0
  310. package/src/routes/FireCMSRoute.tsx +246 -0
  311. package/src/routes/HomePageRoute.tsx +17 -0
  312. package/src/types/analytics.ts +3 -0
  313. package/src/types/auth.tsx +8 -12
  314. package/src/types/collections.ts +103 -28
  315. package/src/types/customization_controller.tsx +9 -0
  316. package/src/types/datasource.ts +21 -20
  317. package/src/types/dialogs_controller.tsx +7 -3
  318. package/src/types/entities.ts +10 -2
  319. package/src/types/entity_actions.tsx +71 -8
  320. package/src/types/entity_callbacks.ts +18 -18
  321. package/src/types/entity_overrides.tsx +2 -2
  322. package/src/types/export_import.ts +4 -4
  323. package/src/types/fields.tsx +52 -19
  324. package/src/types/firecms.tsx +34 -4
  325. package/src/types/firecms_context.tsx +18 -1
  326. package/src/types/index.ts +1 -0
  327. package/src/types/internal_user_management.ts +24 -0
  328. package/src/types/navigation.ts +76 -22
  329. package/src/types/permissions.ts +5 -5
  330. package/src/types/plugins.tsx +53 -9
  331. package/src/types/properties.ts +84 -22
  332. package/src/types/property_config.tsx +2 -2
  333. package/src/types/roles.ts +3 -0
  334. package/src/types/side_dialogs_controller.tsx +15 -0
  335. package/src/types/side_entity_controller.tsx +16 -1
  336. package/src/types/storage.ts +82 -0
  337. package/src/types/user.ts +3 -1
  338. package/src/util/builders.ts +10 -8
  339. package/src/util/callbacks.ts +119 -0
  340. package/src/util/createFormexStub.tsx +62 -0
  341. package/src/util/entities.ts +6 -4
  342. package/src/util/entity_actions.ts +28 -0
  343. package/src/util/entity_cache.ts +204 -0
  344. package/src/util/icon_list.ts +1 -1
  345. package/src/util/icon_synonyms.ts +0 -1
  346. package/src/util/icons.tsx +36 -11
  347. package/src/util/index.ts +3 -0
  348. package/src/util/join_collections.ts +9 -2
  349. package/src/util/make_properties_editable.ts +13 -5
  350. package/src/util/navigation_from_path.ts +33 -12
  351. package/src/util/navigation_utils.ts +135 -19
  352. package/src/util/objects.ts +74 -14
  353. package/src/util/parent_references_from_path.ts +3 -3
  354. package/src/util/permissions.ts +8 -8
  355. package/src/util/property_utils.tsx +17 -6
  356. package/src/util/references.ts +19 -8
  357. package/src/util/resolutions.ts +93 -24
  358. package/src/util/storage.ts +6 -2
  359. package/src/util/useStorageUploadController.tsx +74 -29
  360. package/dist/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.d.ts +0 -5
  361. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  362. package/dist/form/PropertiesForm.d.ts +0 -8
  363. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  364. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  365. package/src/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.tsx +0 -59
  366. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -27
  367. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
  368. package/src/form/PropertiesForm.tsx +0 -81
  369. package/src/form/components/FormikArrayContainer.tsx +0 -44
  370. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  371. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -1,10 +1,10 @@
1
1
  import { useNavigate } from "react-router-dom";
2
2
  import { useNavigationController } from "../../hooks";
3
3
  import { useUserConfigurationPersistence } from "../../hooks/useUserConfigurationPersistence";
4
- import { TopNavigationEntry } from "../../types";
5
- import { Chip, Collapse, StarBorderIcon, StarIcon } from "@firecms/ui";
4
+ import { NavigationEntry } from "../../types";
5
+ import { Chip, Collapse, StarIcon } from "@firecms/ui";
6
6
 
7
- function NavigationChip({ entry }: { entry: TopNavigationEntry }) {
7
+ function NavigationChip({ entry }: { entry: NavigationEntry }) {
8
8
 
9
9
  const navigate = useNavigate();
10
10
  const userConfigurationPersistence = useUserConfigurationPersistence();
@@ -29,16 +29,11 @@ function NavigationChip({ entry }: { entry: TopNavigationEntry }) {
29
29
  return <Chip
30
30
  key={entry.path}
31
31
  onClick={() => navigate(entry.url)}
32
- icon={
33
- favourite
34
- ? <StarIcon
35
- onClick={onIconClick}
36
- size={18}
37
- className={"text-secondary"}/>
38
- : <StarBorderIcon
39
- onClick={onIconClick}
40
- size={18}
41
- className={"text-gray-400 dark:text-gray-500"}/>}>
32
+ icon={<StarIcon
33
+ onClick={onIconClick}
34
+ size={18}
35
+ className={favourite ? "text-secondary" : "text-surface-400 dark:text-surface-500"}/>
36
+ }>
42
37
  {entry.name}
43
38
  </Chip>;
44
39
  }
@@ -53,7 +48,7 @@ export function FavouritesView({ hidden }: { hidden: boolean }) {
53
48
 
54
49
  const favouriteCollections = (userConfigurationPersistence?.favouritePaths ?? [])
55
50
  .map((path) => navigationController.topLevelNavigation?.navigationEntries.find((entry) => entry.path === path))
56
- .filter(Boolean) as TopNavigationEntry[];
51
+ .filter(Boolean) as NavigationEntry[];
57
52
 
58
53
  return <Collapse in={favouriteCollections.length > 0}>
59
54
  <div className="flex flex-row flex-wrap gap-2 pb-2 min-h-[32px]">
@@ -0,0 +1,600 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from "react";
2
+ import {
3
+ Active,
4
+ closestCenter,
5
+ closestCorners,
6
+ CollisionDetection,
7
+ DropAnimation,
8
+ getFirstCollision,
9
+ KeyboardSensor,
10
+ MouseSensor,
11
+ pointerWithin,
12
+ rectIntersection,
13
+ TouchSensor,
14
+ UniqueIdentifier,
15
+ useDndMonitor,
16
+ useDroppable,
17
+ useSensor,
18
+ useSensors
19
+ } from "@dnd-kit/core";
20
+ import {
21
+ AnimateLayoutChanges,
22
+ arrayMove,
23
+ defaultAnimateLayoutChanges,
24
+ rectSortingStrategy,
25
+ SortableContext,
26
+ useSortable
27
+ } from "@dnd-kit/sortable";
28
+ import { CSS } from "@dnd-kit/utilities";
29
+
30
+ import { NavigationCardBinding } from "./NavigationCardBinding";
31
+ import { NavigationEntry } from "../../types";
32
+ import { cls } from "@firecms/ui";
33
+
34
+ const animateLayoutChanges: AnimateLayoutChanges = (args) =>
35
+ defaultAnimateLayoutChanges({
36
+ ...args,
37
+ wasDragging: true
38
+ });
39
+
40
+ const dropAnimationConfig: DropAnimation = {};
41
+
42
+ const cloneSerializableNavigationEntry = (entry: NavigationEntry): NavigationEntry => {
43
+ const clonedEntry: Partial<NavigationEntry> = {
44
+ id: entry.id,
45
+ path: entry.path,
46
+ url: entry.url,
47
+ name: entry.name,
48
+ type: entry.type,
49
+ collection: entry.collection ? { ...entry.collection } : undefined,
50
+ view: entry.view ? { ...entry.view } : undefined,
51
+ ...(entry.group && { group: entry.group }),
52
+ ...(entry.description && { description: entry.description })
53
+ };
54
+ return clonedEntry as NavigationEntry;
55
+ };
56
+
57
+ const cloneItemsForDnd = (items: { name: string; entries: NavigationEntry[] }[]) =>
58
+ items.map((g) => ({
59
+ name: g.name,
60
+ entries: g.entries.map(cloneSerializableNavigationEntry)
61
+ }));
62
+
63
+ /* ─────────────────────────────────────────────────────────── */
64
+ /* Sortable card & group */
65
+
66
+ /* ─────────────────────────────────────────────────────────── */
67
+ export function SortableNavigationCard({
68
+ entry,
69
+ onClick
70
+ }: {
71
+ entry: NavigationEntry;
72
+ onClick?: () => void;
73
+ }) {
74
+ const {
75
+ setNodeRef,
76
+ listeners,
77
+ attributes,
78
+ transform,
79
+ transition,
80
+ isDragging
81
+ } =
82
+ useSortable({
83
+ id: entry.url,
84
+ animateLayoutChanges
85
+ });
86
+
87
+ const style = {
88
+ transform: transform ? CSS.Transform.toString(transform) : undefined,
89
+ transition,
90
+ opacity: isDragging ? 0 : 1
91
+ };
92
+
93
+ return (
94
+ <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
95
+ <NavigationCardBinding {...entry} onClick={onClick}/>
96
+ </div>
97
+ );
98
+ }
99
+
100
+ export function NavigationGroupDroppable({
101
+ id,
102
+ itemIds,
103
+ children,
104
+ isPotentialCardDropTarget = false
105
+ }: {
106
+ id: UniqueIdentifier;
107
+ itemIds: UniqueIdentifier[];
108
+ children: React.ReactNode;
109
+ isPotentialCardDropTarget?: boolean;
110
+ }) {
111
+ const { setNodeRef } = useDroppable({ id });
112
+
113
+ return (
114
+ <div
115
+ ref={setNodeRef}
116
+ className={cls(
117
+ isPotentialCardDropTarget
118
+ ? "p-2 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg"
119
+ : undefined,
120
+ "transition-all duration-200 ease-in-out"
121
+ )}
122
+ >
123
+ <SortableContext items={itemIds} strategy={rectSortingStrategy}>
124
+ {children}
125
+ </SortableContext>
126
+ </div>
127
+ );
128
+ }
129
+
130
+ export function SortableNavigationGroup({
131
+ groupName,
132
+ children,
133
+ disabled
134
+ }: {
135
+ groupName: string;
136
+ children: React.ReactNode;
137
+ disabled?: boolean;
138
+ }) {
139
+ const {
140
+ attributes,
141
+ listeners,
142
+ setNodeRef,
143
+ transform,
144
+ transition,
145
+ isDragging
146
+ } =
147
+ useSortable({
148
+ id: groupName,
149
+ animateLayoutChanges,
150
+ disabled
151
+ });
152
+
153
+ const style = {
154
+ transform: transform ? CSS.Transform.toString(transform) : undefined,
155
+ transition,
156
+ opacity: isDragging ? 0 : 1
157
+ };
158
+
159
+ return (
160
+ <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
161
+ {children}
162
+ </div>
163
+ );
164
+ }
165
+
166
+ /* ─────────────────────────────────────────────────────────── */
167
+ /* Main DnD hook */
168
+
169
+ /* ─────────────────────────────────────────────────────────── */
170
+ export function useHomePageDnd({
171
+ items: dndItems,
172
+ setItems: setDndItems,
173
+ disabled,
174
+ onCardMovedBetweenGroups,
175
+ onGroupMoved,
176
+ onNewGroupDrop,
177
+ onPersist
178
+ }: {
179
+ items: { name: string; entries: NavigationEntry[] }[];
180
+ setItems: (
181
+ newItemsOrUpdater:
182
+ | { name: string; entries: NavigationEntry[] }[]
183
+ | ((
184
+ currentItems: { name: string; entries: NavigationEntry[] }[]
185
+ ) => { name: string; entries: NavigationEntry[] }[])
186
+ ) => void;
187
+ disabled: boolean;
188
+ onCardMovedBetweenGroups?: (card: NavigationEntry) => void;
189
+ onGroupMoved?: (groupName: string, oldIndex: number, newIndex: number) => void;
190
+ onNewGroupDrop?: () => void;
191
+ onPersist?: (latest: { name: string; entries: NavigationEntry[] }[]) => void;
192
+ }) {
193
+ /* ---------------- local state ---------------- */
194
+ const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);
195
+ const [activeIsGroup, setActiveIsGroup] = useState(false);
196
+ const [currentDraggingGroupId, setCurrentDraggingGroupId] =
197
+ useState<UniqueIdentifier | null>(null);
198
+ const [dndKitActiveNode, setDndKitActiveNode] = useState<Active | null>(null);
199
+ const [isDraggingCardOnly, setIsDraggingCardOnly] = useState(false);
200
+ const [dialogOpenForGroup, setDialogOpenForGroup] = useState<string | null>(null);
201
+ const [isHoveringNewGroupDropZone, setIsHoveringNewGroupDropZone] =
202
+ useState(false);
203
+
204
+ /* store interim state for cross-group moves */
205
+ const interimItemsRef = useRef<
206
+ { name: string; entries: NavigationEntry[] }[] | null
207
+ >(null);
208
+ useEffect(() => {
209
+ interimItemsRef.current = dndItems;
210
+ }, [dndItems]);
211
+
212
+ /* ---------------- sensors ---------------- */
213
+ const mouseSensor = useSensor(MouseSensor, { activationConstraint: { distance: 10 } });
214
+ const touchSensor = useSensor(TouchSensor, {
215
+ activationConstraint: {
216
+ delay: 150,
217
+ tolerance: 5
218
+ }
219
+ });
220
+ const keyboardSensor = useSensor(KeyboardSensor);
221
+ const sensors = useSensors(mouseSensor, touchSensor, keyboardSensor);
222
+
223
+ /* ---------------- helpers ---------------- */
224
+ const dndContainers = dndItems.map((g) => g.name);
225
+
226
+ const findDndContainer = useCallback(
227
+ (id: UniqueIdentifier): string | undefined => {
228
+ if (!id) return undefined;
229
+ const group = dndItems.find((g) => g.name === id);
230
+ if (group) return group.name;
231
+ for (const g of dndItems) {
232
+ if (g.entries.some((e) => e.url === id)) return g.name;
233
+ }
234
+ return undefined;
235
+ },
236
+ [dndItems]
237
+ );
238
+
239
+ /* ---------------- collision detection ---------------- */
240
+ const lastOverId = useRef<UniqueIdentifier | null>(null);
241
+ const recentlyMovedToNewContainer = useRef(false);
242
+
243
+ const collisionDetection: CollisionDetection = useCallback(
244
+ (args) => {
245
+ if (disabled || !activeId) return [];
246
+ if (activeIsGroup) {
247
+ const groups = args.droppableContainers.filter((c) =>
248
+ dndItems.some((g) => g.name === c.id)
249
+ );
250
+ if (!groups.length) return [];
251
+ return closestCenter({
252
+ ...args,
253
+ droppableContainers: groups
254
+ });
255
+ }
256
+
257
+ const pointer = pointerWithin(args);
258
+ if (pointer.length) {
259
+ const zone = pointer.find((c) => c.id === "new-group-drop-zone");
260
+ if (zone) return [zone];
261
+
262
+ const container = pointer.find((c) =>
263
+ dndItems.some((g) => g.name === c.id)
264
+ );
265
+ if (container) {
266
+ const itemsIn = dndItems.find((g) => g.name === container.id)
267
+ ?.entries;
268
+ if (itemsIn?.length) {
269
+ const closest = closestCorners({
270
+ ...args,
271
+ droppableContainers: args.droppableContainers.filter(
272
+ (c) => itemsIn.some((e) => e.url === c.id)
273
+ )
274
+ });
275
+ if (closest.length) return closest;
276
+ }
277
+ return [container];
278
+ }
279
+ const first = getFirstCollision(pointer, "id");
280
+ if (first) return [{ id: first }];
281
+ }
282
+
283
+ const rects = rectIntersection(args);
284
+ const zoneRect = rects.find((c) => c.id === "new-group-drop-zone");
285
+ if (zoneRect) return [zoneRect];
286
+
287
+ let overId = getFirstCollision(rects, "id");
288
+ if (overId != null) {
289
+ const overIsContainer = dndItems.some((g) => g.name === overId);
290
+ if (overIsContainer) {
291
+ const itemsIn = dndItems.find((g) => g.name === overId)
292
+ ?.entries;
293
+ if (itemsIn?.length) {
294
+ const closestItem = closestCorners({
295
+ ...args,
296
+ droppableContainers: args.droppableContainers.filter(
297
+ (c) => itemsIn.some((e) => e.url === c.id)
298
+ )
299
+ })[0]?.id;
300
+ if (closestItem) overId = closestItem;
301
+ }
302
+ }
303
+ lastOverId.current = overId;
304
+ return [{ id: overId }];
305
+ }
306
+
307
+ if (
308
+ recentlyMovedToNewContainer.current &&
309
+ lastOverId.current &&
310
+ !activeIsGroup
311
+ )
312
+ return [{ id: lastOverId.current }];
313
+
314
+ return [];
315
+ },
316
+ [activeId, dndItems, disabled, activeIsGroup]
317
+ );
318
+
319
+ /* ---------------- drag handlers ---------------- */
320
+ const handleDragStart = ({ active }: { active: Active }) => {
321
+ setDndKitActiveNode(active);
322
+ if (disabled) return;
323
+
324
+ const isGroup = dndItems.some((g) => g.name === active.id);
325
+ if (!active.data.current) active.data.current = {};
326
+ active.data.current.type = isGroup ? "group" : "item";
327
+
328
+ setActiveId(active.id);
329
+ setActiveIsGroup(isGroup);
330
+ setIsDraggingCardOnly(!isGroup);
331
+ if (isGroup) setCurrentDraggingGroupId(active.id);
332
+ recentlyMovedToNewContainer.current = false;
333
+ };
334
+
335
+ const handleDragOver = ({
336
+ active,
337
+ over
338
+ }: { active: Active; over: any }) => {
339
+ if (disabled || !over) return;
340
+
341
+ const activeIdNow = active.id;
342
+ const overIdNow = over.id;
343
+ if (activeIdNow === overIdNow) return;
344
+ if (activeIsGroup) return;
345
+
346
+ const activeCont = findDndContainer(activeIdNow);
347
+ const overCont = findDndContainer(overIdNow);
348
+ if (!activeCont) return;
349
+
350
+ if (overCont && activeCont !== overCont) {
351
+ recentlyMovedToNewContainer.current = true;
352
+ const newState = cloneItemsForDnd(dndItems);
353
+ const srcIdx = newState.findIndex((g) => g.name === activeCont);
354
+ const tgtIdx = newState.findIndex((g) => g.name === overCont);
355
+ if (srcIdx === -1 || tgtIdx === -1) return;
356
+ const src = newState[srcIdx];
357
+ const tgt = newState[tgtIdx];
358
+ const idxInSrc = src.entries.findIndex((e) => e.url === activeIdNow);
359
+ if (idxInSrc === -1) return;
360
+ const [moved] = src.entries.splice(idxInSrc, 1);
361
+ tgt.entries.push(moved);
362
+ interimItemsRef.current = newState;
363
+ setDndItems(newState);
364
+ } else if (activeCont === overCont) {
365
+ recentlyMovedToNewContainer.current = false;
366
+ }
367
+ };
368
+
369
+ const handleDragEnd = ({
370
+ active,
371
+ over
372
+ }: { active: Active; over: any }) => {
373
+ if (disabled || !over) {
374
+ resetDragState();
375
+ return;
376
+ }
377
+
378
+ const activeIdNow = active.id;
379
+ const overIdNow = over.id;
380
+
381
+ /* ─── group reorder ─── */
382
+ if (activeIsGroup) {
383
+ if (
384
+ activeIdNow !== overIdNow &&
385
+ dndItems.some((g) => g.name === overIdNow)
386
+ ) {
387
+ const from = dndItems.findIndex((g) => g.name === activeIdNow);
388
+ const to = dndItems.findIndex((g) => g.name === overIdNow);
389
+ if (from !== -1 && to !== -1) {
390
+ const newState = arrayMove(dndItems, from, to);
391
+ setDndItems(newState);
392
+ onPersist?.(newState);
393
+ onGroupMoved?.(activeIdNow as string, from, to);
394
+ }
395
+ }
396
+ }
397
+ /* ─── card move ─── */
398
+ else {
399
+ const activeCont = findDndContainer(activeIdNow);
400
+
401
+ /* drop on new-group zone */
402
+ if (overIdNow === "new-group-drop-zone") {
403
+ if (activeCont) {
404
+ const newState = cloneItemsForDnd(dndItems);
405
+ const srcIdx = newState.findIndex((g) => g.name === activeCont);
406
+ if (srcIdx !== -1) {
407
+ const src = newState[srcIdx];
408
+ const idxInSrc = src.entries.findIndex(
409
+ (e) => e.url === activeIdNow
410
+ );
411
+ if (idxInSrc !== -1) {
412
+ const [dragged] = src.entries.splice(idxInSrc, 1);
413
+ if (src.entries.length === 0) newState.splice(srcIdx, 1);
414
+
415
+ let tentative = "New Group";
416
+ let counter = 1;
417
+ while (newState.some((g) => g.name === tentative))
418
+ tentative = `New Group ${counter++}`;
419
+
420
+ newState.push({
421
+ name: tentative,
422
+ entries: [dragged]
423
+ });
424
+ setDndItems(newState);
425
+ onPersist?.(newState);
426
+ setDialogOpenForGroup(tentative);
427
+ onNewGroupDrop?.();
428
+ }
429
+ }
430
+ }
431
+ }
432
+ /* reorder inside same container */
433
+ else {
434
+ const overCont = findDndContainer(overIdNow);
435
+ if (activeCont === overCont) {
436
+ const grpIdx = dndItems.findIndex((g) => g.name === activeCont);
437
+ if (grpIdx !== -1) {
438
+ const group = dndItems[grpIdx];
439
+ const oldIdx = group.entries.findIndex(
440
+ (e) => e.url === activeIdNow
441
+ );
442
+ let newIdx = group.entries.findIndex(
443
+ (e) => e.url === overIdNow
444
+ );
445
+ if (newIdx === -1 && overIdNow === activeCont)
446
+ newIdx = group.entries.length - 1;
447
+ if (
448
+ oldIdx !== -1 &&
449
+ newIdx !== -1 &&
450
+ oldIdx !== newIdx
451
+ ) {
452
+ const reordered = arrayMove(group.entries, oldIdx, newIdx);
453
+ const newState = [...dndItems];
454
+ newState[grpIdx] = {
455
+ ...group,
456
+ entries: reordered
457
+ };
458
+ setDndItems(newState);
459
+ onPersist?.(newState);
460
+ }
461
+ }
462
+ } else if (
463
+ recentlyMovedToNewContainer.current &&
464
+ interimItemsRef.current
465
+ ) {
466
+ onPersist?.(interimItemsRef.current);
467
+ }
468
+
469
+ onCardMovedBetweenGroups?.(
470
+ dndItems
471
+ .flatMap((g) => g.entries)
472
+ .find((e) => e.url === activeIdNow)!
473
+ );
474
+ }
475
+ }
476
+
477
+ resetDragState();
478
+ };
479
+
480
+ const resetDragState = () => {
481
+ setDndKitActiveNode(null);
482
+ setActiveId(null);
483
+ setActiveIsGroup(false);
484
+ setCurrentDraggingGroupId(null);
485
+ setIsDraggingCardOnly(false);
486
+ recentlyMovedToNewContainer.current = false;
487
+ };
488
+
489
+ const handleDragCancel = () => resetDragState();
490
+
491
+ /* ---------------- group rename ---------------- */
492
+ const handleRenameGroup = (oldName: string, newName: string) => {
493
+ setDndItems((current) => {
494
+ const idx = current.findIndex((g) => g.name === oldName);
495
+ if (idx === -1) return current;
496
+ if (current.some((g) => g.name === newName && g.name !== oldName))
497
+ return current;
498
+
499
+ const updated = [...current];
500
+ updated[idx] = {
501
+ ...updated[idx],
502
+ name: newName
503
+ };
504
+ onPersist?.(updated); // <- ensure rename is saved
505
+ return updated;
506
+ });
507
+ setDialogOpenForGroup(null);
508
+ };
509
+
510
+ /* ---------------- public API ---------------- */
511
+ const activeItemForOverlay =
512
+ disabled || !activeId || activeIsGroup
513
+ ? null
514
+ : dndItems.flatMap((g) => g.entries).find((e) => e.url === activeId) || null;
515
+
516
+ const activeGroupData =
517
+ disabled || !activeId || !activeIsGroup
518
+ ? null
519
+ : dndItems.find((g) => g.name === activeId) || null;
520
+
521
+ return {
522
+ sensors,
523
+ collisionDetection,
524
+ onDragStart: handleDragStart,
525
+ onDragOver: handleDragOver,
526
+ onDragEnd: handleDragEnd,
527
+ onDragCancel: handleDragCancel,
528
+ dropAnimation: dropAnimationConfig,
529
+ activeItemForOverlay,
530
+ activeGroupData,
531
+ draggingGroupId: currentDraggingGroupId,
532
+ containers: dndContainers,
533
+ dndKitActiveNode,
534
+ isDraggingCardOnly,
535
+ dialogOpenForGroup,
536
+ setDialogOpenForGroup,
537
+ handleRenameGroup,
538
+ isHoveringNewGroupDropZone,
539
+ setIsHoveringNewGroupDropZone
540
+ };
541
+ }
542
+
543
+ /* ─────────────────────────────────────────────────────────── */
544
+ /* New-group drop-zone component */
545
+
546
+ /* ─────────────────────────────────────────────────────────── */
547
+ export function NewGroupDropZone({
548
+ disabled,
549
+ setIsHovering
550
+ }: {
551
+ disabled: boolean;
552
+ setIsHovering: (v: boolean) => void;
553
+ }) {
554
+ const {
555
+ setNodeRef,
556
+ isOver
557
+ } = useDroppable({
558
+ id: "new-group-drop-zone",
559
+ disabled
560
+ });
561
+ const [isVisible, setIsVisible] = useState(false);
562
+
563
+ useDndMonitor({
564
+ onDragStart({ active }) {
565
+ if (disabled) return;
566
+ const tp = active.data.current?.type;
567
+ setIsVisible(tp === "item");
568
+ },
569
+ onDragEnd() {
570
+ setIsVisible(false);
571
+ },
572
+ onDragCancel() {
573
+ setIsVisible(false);
574
+ }
575
+ });
576
+
577
+ useEffect(() => {
578
+ setIsHovering(isOver && isVisible);
579
+ }, [isOver, isVisible, setIsHovering]);
580
+
581
+ if (!isVisible || disabled) return null;
582
+
583
+ return (
584
+ <div
585
+ ref={setNodeRef}
586
+ className={cls(
587
+ "fixed right-8 top-1/2 -translate-y-1/2 w-[200px] h-[120px] border border-dashed rounded-lg flex items-center justify-center transition-all",
588
+ isOver
589
+ ? "bg-surface-accent-100 dark:bg-surface-accent-800 border-surface-300 dark:border-surface-600"
590
+ : "bg-surface-50 dark:bg-surface-900 border-surface-200 dark:border-surface-700"
591
+ )}
592
+ >
593
+ <div className="text-center p-4">
594
+ <span className="block font-medium text-sm">
595
+ Drop here to create a new group
596
+ </span>
597
+ </div>
598
+ </div>
599
+ );
600
+ }