@firecms/core 3.0.0-canary.25 → 3.0.0-canary.250

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 (401) 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 +34 -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 +31 -12
  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 +20 -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/EntityJsonPreview.d.ts +3 -0
  25. package/dist/components/EntityPreview.d.ts +8 -5
  26. package/dist/components/ErrorView.d.ts +1 -1
  27. package/dist/components/HomePage/DefaultHomePage.d.ts +2 -15
  28. package/dist/components/HomePage/HomePageDnD.d.ts +76 -0
  29. package/dist/components/HomePage/NavigationCard.d.ts +3 -1
  30. package/dist/components/HomePage/NavigationCardBinding.d.ts +4 -3
  31. package/dist/components/HomePage/NavigationGroup.d.ts +7 -1
  32. package/dist/components/HomePage/RenameGroupDialog.d.ts +9 -0
  33. package/dist/components/PropertyConfigBadge.d.ts +2 -1
  34. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  35. package/dist/components/ReferenceWidget.d.ts +3 -1
  36. package/dist/components/SelectableTable/SelectableTable.d.ts +14 -4
  37. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  38. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  39. package/dist/components/VirtualTable/VirtualTableProps.d.ts +24 -12
  40. package/dist/components/VirtualTable/types.d.ts +3 -3
  41. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -3
  42. package/dist/components/common/index.d.ts +2 -1
  43. package/dist/components/common/table_height.d.ts +5 -0
  44. package/dist/components/common/types.d.ts +4 -6
  45. package/dist/components/common/useColumnsIds.d.ts +3 -1
  46. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +13 -2
  47. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  48. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  49. package/dist/components/index.d.ts +5 -2
  50. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  51. package/dist/core/DefaultAppBar.d.ts +29 -0
  52. package/dist/core/DefaultDrawer.d.ts +19 -0
  53. package/dist/core/DrawerNavigationItem.d.ts +10 -0
  54. package/dist/core/EntityEditView.d.ts +40 -11
  55. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  56. package/dist/core/FireCMS.d.ts +3 -3
  57. package/dist/core/FireCMSRouter.d.ts +4 -0
  58. package/dist/core/NavigationRoutes.d.ts +2 -3
  59. package/dist/core/SideDialogs.d.ts +4 -2
  60. package/dist/core/field_configs.d.ts +1 -1
  61. package/dist/core/index.d.ts +4 -4
  62. package/dist/form/EntityForm.d.ts +36 -64
  63. package/dist/form/EntityFormActions.d.ts +17 -0
  64. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  65. package/dist/form/components/ErrorFocus.d.ts +1 -1
  66. package/dist/form/components/FieldHelperText.d.ts +3 -3
  67. package/dist/form/components/FormEntry.d.ts +6 -0
  68. package/dist/form/components/FormLayout.d.ts +5 -0
  69. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  70. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  71. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  72. package/dist/form/components/index.d.ts +3 -1
  73. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  74. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  75. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  76. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  77. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  78. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  79. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  80. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  81. package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +9 -0
  82. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  83. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  84. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  85. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +5 -13
  86. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  87. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  88. package/dist/form/index.d.ts +17 -18
  89. package/dist/form/useClearRestoreValue.d.ts +2 -2
  90. package/dist/hooks/data/delete.d.ts +4 -4
  91. package/dist/hooks/data/save.d.ts +4 -5
  92. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  93. package/dist/hooks/data/useEntityFetch.d.ts +4 -3
  94. package/dist/hooks/index.d.ts +1 -0
  95. package/dist/hooks/useAuthController.d.ts +1 -1
  96. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  97. package/dist/hooks/useBuildNavigationController.d.ts +57 -13
  98. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  99. package/dist/hooks/useModeController.d.ts +1 -2
  100. package/dist/hooks/useProjectLog.d.ts +8 -2
  101. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  102. package/dist/hooks/useValidateAuthenticator.d.ts +4 -8
  103. package/dist/index.d.ts +1 -0
  104. package/dist/index.es.js +22839 -13875
  105. package/dist/index.es.js.map +1 -1
  106. package/dist/index.umd.js +25639 -588
  107. package/dist/index.umd.js.map +1 -1
  108. package/dist/internal/useBuildDataSource.d.ts +3 -17
  109. package/dist/internal/useBuildSideEntityController.d.ts +3 -3
  110. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  111. package/dist/preview/PropertyPreviewProps.d.ts +6 -1
  112. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  113. package/dist/preview/components/ReferencePreview.d.ts +3 -2
  114. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  115. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  116. package/dist/preview/util.d.ts +3 -3
  117. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  118. package/dist/routes/FireCMSRoute.d.ts +1 -0
  119. package/dist/routes/HomePageRoute.d.ts +3 -0
  120. package/dist/types/analytics.d.ts +1 -1
  121. package/dist/types/auth.d.ts +8 -10
  122. package/dist/types/collections.d.ts +106 -24
  123. package/dist/types/datasource.d.ts +52 -36
  124. package/dist/types/dialogs_controller.d.ts +7 -3
  125. package/dist/types/entities.d.ts +7 -2
  126. package/dist/types/entity_actions.d.ts +28 -4
  127. package/dist/types/entity_callbacks.d.ts +16 -16
  128. package/dist/types/entity_overrides.d.ts +2 -2
  129. package/dist/types/export_import.d.ts +4 -4
  130. package/dist/types/fields.d.ts +74 -42
  131. package/dist/types/firecms.d.ts +8 -3
  132. package/dist/types/firecms_context.d.ts +1 -1
  133. package/dist/types/index.d.ts +0 -1
  134. package/dist/types/navigation.d.ts +61 -18
  135. package/dist/types/permissions.d.ts +4 -4
  136. package/dist/types/plugins.d.ts +48 -12
  137. package/dist/types/properties.d.ts +80 -24
  138. package/dist/types/property_config.d.ts +1 -3
  139. package/dist/types/side_dialogs_controller.d.ts +10 -0
  140. package/dist/types/side_entity_controller.d.ts +10 -1
  141. package/dist/types/storage.d.ts +75 -0
  142. package/dist/types/user.d.ts +1 -0
  143. package/dist/util/builders.d.ts +3 -3
  144. package/dist/util/callbacks.d.ts +2 -0
  145. package/dist/util/createFormexStub.d.ts +2 -0
  146. package/dist/util/entities.d.ts +3 -3
  147. package/dist/util/entity_actions.d.ts +2 -0
  148. package/dist/util/entity_cache.d.ts +23 -0
  149. package/dist/util/icon_list.d.ts +5 -1
  150. package/dist/util/icon_synonyms.d.ts +1 -98
  151. package/dist/util/icons.d.ts +6 -3
  152. package/dist/util/index.d.ts +3 -0
  153. package/dist/util/navigation_from_path.d.ts +6 -1
  154. package/dist/util/navigation_utils.d.ts +15 -3
  155. package/dist/util/objects.d.ts +2 -1
  156. package/dist/util/permissions.d.ts +4 -4
  157. package/dist/util/plurals.d.ts +0 -2
  158. package/dist/util/property_utils.d.ts +4 -4
  159. package/dist/util/references.d.ts +2 -2
  160. package/dist/util/resolutions.d.ts +41 -17
  161. package/dist/util/storage.d.ts +23 -2
  162. package/dist/util/useStorageUploadController.d.ts +3 -3
  163. package/package.json +64 -48
  164. package/src/app/AppBar.tsx +18 -0
  165. package/src/app/Drawer.tsx +24 -0
  166. package/src/app/Scaffold.tsx +253 -0
  167. package/src/app/index.ts +4 -0
  168. package/src/app/useApp.tsx +32 -0
  169. package/src/components/ArrayContainer.tsx +447 -229
  170. package/src/components/CircularProgressCenter.tsx +2 -2
  171. package/src/components/ClearFilterSortButton.tsx +41 -0
  172. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +11 -11
  173. package/src/components/DeleteEntityDialog.tsx +13 -20
  174. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +59 -40
  175. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +38 -31
  176. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +30 -9
  177. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +72 -42
  178. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  179. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +30 -16
  180. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +19 -17
  181. package/src/components/EntityCollectionTable/index.tsx +1 -1
  182. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +32 -37
  183. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +49 -36
  184. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
  185. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +135 -105
  186. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +9 -9
  187. package/src/components/EntityCollectionView/EntityCollectionView.tsx +231 -117
  188. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  189. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  190. package/src/components/EntityCollectionView/useSelectionController.tsx +20 -7
  191. package/src/components/EntityCollectionView/utils.ts +19 -0
  192. package/src/components/EntityJsonPreview.tsx +66 -0
  193. package/src/components/EntityPreview.tsx +80 -59
  194. package/src/components/EntityView.tsx +13 -10
  195. package/src/components/ErrorView.tsx +4 -4
  196. package/src/components/HomePage/DefaultHomePage.tsx +486 -159
  197. package/src/components/HomePage/FavouritesView.tsx +9 -14
  198. package/src/components/HomePage/HomePageDnD.tsx +613 -0
  199. package/src/components/HomePage/NavigationCard.tsx +48 -39
  200. package/src/components/HomePage/NavigationCardBinding.tsx +17 -16
  201. package/src/components/HomePage/NavigationGroup.tsx +63 -29
  202. package/src/components/HomePage/RenameGroupDialog.tsx +113 -0
  203. package/src/components/HomePage/SmallNavigationCard.tsx +5 -6
  204. package/src/components/NotFoundPage.tsx +2 -2
  205. package/src/components/PropertyConfigBadge.tsx +9 -3
  206. package/src/components/PropertyIdCopyTooltip.tsx +47 -0
  207. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +21 -13
  208. package/src/components/ReferenceWidget.tsx +21 -11
  209. package/src/components/SearchIconsView.tsx +10 -7
  210. package/src/components/SelectableTable/SelectableTable.tsx +157 -145
  211. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  212. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +25 -8
  213. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +36 -12
  214. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +92 -23
  215. package/src/components/UnsavedChangesDialog.tsx +42 -0
  216. package/src/components/VirtualTable/VirtualTable.tsx +105 -51
  217. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  218. package/src/components/VirtualTable/VirtualTableHeader.tsx +10 -10
  219. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  220. package/src/components/VirtualTable/VirtualTableProps.tsx +28 -14
  221. package/src/components/VirtualTable/VirtualTableRow.tsx +5 -6
  222. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +5 -5
  223. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -2
  224. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  225. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
  226. package/src/components/VirtualTable/types.tsx +2 -3
  227. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +44 -40
  228. package/src/components/common/index.ts +2 -1
  229. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  230. package/src/components/common/types.tsx +4 -6
  231. package/src/components/common/useColumnsIds.tsx +24 -3
  232. package/src/components/common/useDataSourceTableController.tsx +420 -0
  233. package/src/components/common/useDebouncedCallback.tsx +20 -0
  234. package/src/components/common/useScrollRestoration.tsx +68 -0
  235. package/src/components/common/useTableSearchHelper.ts +53 -12
  236. package/src/components/index.tsx +6 -2
  237. package/src/contexts/BreacrumbsContext.tsx +38 -0
  238. package/src/contexts/DialogsProvider.tsx +5 -4
  239. package/src/contexts/ModeController.tsx +1 -3
  240. package/src/contexts/SnackbarProvider.tsx +2 -0
  241. package/src/core/DefaultAppBar.tsx +219 -0
  242. package/src/core/DefaultDrawer.tsx +185 -0
  243. package/src/core/DrawerNavigationItem.tsx +66 -0
  244. package/src/core/EntityEditView.tsx +408 -478
  245. package/src/core/EntityEditViewFormActions.tsx +199 -0
  246. package/src/core/EntitySidePanel.tsx +85 -21
  247. package/src/core/FireCMS.tsx +72 -58
  248. package/src/core/FireCMSRouter.tsx +17 -0
  249. package/src/core/NavigationRoutes.tsx +28 -38
  250. package/src/core/SideDialogs.tsx +22 -12
  251. package/src/core/field_configs.tsx +26 -13
  252. package/src/core/index.tsx +6 -5
  253. package/src/form/EntityForm.tsx +589 -535
  254. package/src/form/EntityFormActions.tsx +169 -0
  255. package/src/form/PropertyFieldBinding.tsx +88 -45
  256. package/src/form/components/CustomIdField.tsx +9 -3
  257. package/src/form/components/FieldHelperText.tsx +4 -4
  258. package/src/form/components/FormEntry.tsx +22 -0
  259. package/src/form/components/FormLayout.tsx +16 -0
  260. package/src/form/components/LabelWithIcon.tsx +30 -19
  261. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  262. package/src/form/components/StorageItemPreview.tsx +22 -12
  263. package/src/form/components/StorageUploadProgress.tsx +4 -5
  264. package/src/form/components/index.tsx +3 -1
  265. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +34 -19
  266. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +50 -36
  267. package/src/form/field_bindings/BlockFieldBinding.tsx +56 -34
  268. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -14
  269. package/src/form/field_bindings/KeyValueFieldBinding.tsx +61 -52
  270. package/src/form/field_bindings/MapFieldBinding.tsx +73 -55
  271. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +157 -0
  272. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +26 -21
  273. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +11 -16
  274. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +135 -0
  275. package/src/form/field_bindings/ReferenceFieldBinding.tsx +42 -31
  276. package/src/form/field_bindings/RepeatFieldBinding.tsx +62 -35
  277. package/src/form/field_bindings/SelectFieldBinding.tsx +24 -15
  278. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +265 -202
  279. package/src/form/field_bindings/SwitchFieldBinding.tsx +29 -24
  280. package/src/form/field_bindings/TextFieldBinding.tsx +28 -24
  281. package/src/form/index.tsx +17 -37
  282. package/src/form/useClearRestoreValue.tsx +2 -2
  283. package/src/form/validation.ts +13 -23
  284. package/src/hooks/data/delete.ts +6 -5
  285. package/src/hooks/data/save.ts +26 -33
  286. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  287. package/src/hooks/data/useDataSource.tsx +11 -3
  288. package/src/hooks/data/useEntityFetch.tsx +10 -6
  289. package/src/hooks/index.tsx +1 -0
  290. package/src/hooks/useAuthController.tsx +1 -1
  291. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  292. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  293. package/src/hooks/useBuildModeController.tsx +22 -29
  294. package/src/hooks/useBuildNavigationController.tsx +440 -119
  295. package/src/hooks/useFireCMSContext.tsx +3 -33
  296. package/src/hooks/useLargeLayout.tsx +0 -35
  297. package/src/hooks/useModeController.tsx +1 -2
  298. package/src/hooks/useProjectLog.tsx +32 -10
  299. package/src/hooks/useResolvedNavigationFrom.tsx +10 -12
  300. package/src/hooks/useValidateAuthenticator.tsx +17 -37
  301. package/src/index.ts +1 -0
  302. package/src/internal/useBuildDataSource.ts +79 -85
  303. package/src/internal/useBuildSideDialogsController.tsx +4 -2
  304. package/src/internal/useBuildSideEntityController.tsx +201 -77
  305. package/src/internal/useUnsavedChangesDialog.tsx +127 -91
  306. package/src/preview/PropertyPreview.tsx +34 -25
  307. package/src/preview/PropertyPreviewProps.tsx +7 -1
  308. package/src/preview/components/BooleanPreview.tsx +2 -2
  309. package/src/preview/components/EmptyValue.tsx +1 -1
  310. package/src/preview/components/EnumValuesChip.tsx +2 -2
  311. package/src/preview/components/ImagePreview.tsx +26 -37
  312. package/src/preview/components/ReferencePreview.tsx +23 -34
  313. package/src/preview/components/StorageThumbnail.tsx +5 -1
  314. package/src/preview/components/UrlComponentPreview.tsx +60 -28
  315. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +6 -6
  316. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +7 -5
  317. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +5 -4
  318. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -4
  319. package/src/preview/property_previews/ArrayOneOfPreview.tsx +7 -6
  320. package/src/preview/property_previews/ArrayPropertyPreview.tsx +7 -6
  321. package/src/preview/property_previews/MapPropertyPreview.tsx +12 -11
  322. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +13 -13
  323. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  324. package/src/preview/util.ts +10 -10
  325. package/src/routes/CustomCMSRoute.tsx +21 -0
  326. package/src/routes/FireCMSRoute.tsx +246 -0
  327. package/src/routes/HomePageRoute.tsx +17 -0
  328. package/src/types/analytics.ts +3 -0
  329. package/src/types/auth.tsx +9 -13
  330. package/src/types/collections.ts +128 -29
  331. package/src/types/customization_controller.tsx +0 -1
  332. package/src/types/datasource.ts +61 -43
  333. package/src/types/dialogs_controller.tsx +7 -3
  334. package/src/types/entities.ts +12 -2
  335. package/src/types/entity_actions.tsx +32 -7
  336. package/src/types/entity_callbacks.ts +18 -18
  337. package/src/types/entity_overrides.tsx +2 -2
  338. package/src/types/export_import.ts +4 -4
  339. package/src/types/fields.tsx +85 -46
  340. package/src/types/firecms.tsx +9 -4
  341. package/src/types/firecms_context.tsx +1 -1
  342. package/src/types/index.ts +0 -1
  343. package/src/types/navigation.ts +76 -23
  344. package/src/types/permissions.ts +5 -5
  345. package/src/types/plugins.tsx +57 -14
  346. package/src/types/properties.ts +95 -26
  347. package/src/types/property_config.tsx +1 -2
  348. package/src/types/side_dialogs_controller.tsx +15 -0
  349. package/src/types/side_entity_controller.tsx +11 -1
  350. package/src/types/storage.ts +83 -1
  351. package/src/types/user.ts +2 -0
  352. package/src/util/builders.ts +10 -8
  353. package/src/util/callbacks.ts +119 -0
  354. package/src/util/createFormexStub.tsx +62 -0
  355. package/src/util/entities.ts +9 -6
  356. package/src/util/entity_actions.ts +28 -0
  357. package/src/util/entity_cache.ts +204 -0
  358. package/src/util/enums.ts +1 -1
  359. package/src/util/icon_list.ts +16 -10
  360. package/src/util/icon_synonyms.ts +3 -100
  361. package/src/util/icons.tsx +21 -7
  362. package/src/util/index.ts +3 -0
  363. package/src/util/join_collections.ts +6 -1
  364. package/src/util/make_properties_editable.ts +13 -5
  365. package/src/util/navigation_from_path.ts +18 -7
  366. package/src/util/navigation_utils.ts +141 -25
  367. package/src/util/objects.ts +90 -33
  368. package/src/util/parent_references_from_path.ts +3 -3
  369. package/src/util/permissions.ts +9 -8
  370. package/src/util/plurals.ts +0 -2
  371. package/src/util/property_utils.tsx +17 -6
  372. package/src/util/references.ts +19 -8
  373. package/src/util/resolutions.ts +110 -48
  374. package/src/util/storage.ts +79 -21
  375. package/src/util/strings.ts +2 -2
  376. package/src/util/useStorageUploadController.tsx +91 -28
  377. package/dist/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.d.ts +0 -5
  378. package/dist/components/FireCMSAppBar.d.ts +0 -26
  379. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  380. package/dist/components/VirtualTable/common.d.ts +0 -2
  381. package/dist/core/Drawer.d.ts +0 -23
  382. package/dist/core/Scaffold.d.ts +0 -55
  383. package/dist/core/SideEntityView.d.ts +0 -7
  384. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  385. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  386. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  387. package/dist/internal/useLocaleConfig.d.ts +0 -1
  388. package/dist/types/appcheck.d.ts +0 -26
  389. package/src/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.tsx +0 -59
  390. package/src/components/FireCMSAppBar.tsx +0 -165
  391. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
  392. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -225
  393. package/src/core/Drawer.tsx +0 -191
  394. package/src/core/Scaffold.tsx +0 -281
  395. package/src/core/SideEntityView.tsx +0 -38
  396. package/src/form/components/FormikArrayContainer.tsx +0 -44
  397. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  398. package/src/internal/useBuildCustomizationController.tsx +0 -5
  399. package/src/internal/useLocaleConfig.tsx +0 -18
  400. package/src/types/appcheck.ts +0 -29
  401. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -1,50 +1,56 @@
1
- import React, { useCallback } from "react";
1
+ import React, { useCallback, useState } from "react";
2
2
 
3
3
  import {
4
- ArrayProperty,
5
- Entity,
6
- EntityCollection,
7
4
  FieldProps,
5
+ PropertyOrBuilder,
8
6
  ResolvedArrayProperty,
9
7
  ResolvedStringProperty,
10
8
  StorageConfig
11
9
  } from "../../types";
12
10
  import { useDropzone } from "react-dropzone";
13
11
  import { PreviewSize } from "../../preview";
14
- import { FieldHelperText, LabelWithIcon } from "../components";
12
+ import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
15
13
 
16
- import { getIconForProperty, isReadOnly } from "../../util";
17
- import { useSnackbarController, useStorageSource } from "../../hooks";
18
- import { DragDropContext, Draggable, Droppable } from "@hello-pangea/dnd";
14
+ import { getIconForProperty, isReadOnly, resolveProperty } from "../../util";
15
+ import { useAuthController, useSnackbarController, useStorageSource } from "../../hooks";
16
+ import {
17
+ closestCenter,
18
+ DndContext,
19
+ DragEndEvent,
20
+ DragStartEvent,
21
+ KeyboardSensor,
22
+ PointerSensor,
23
+ useSensor,
24
+ useSensors
25
+ } from "@dnd-kit/core";
26
+ import {
27
+ horizontalListSortingStrategy,
28
+ SortableContext,
29
+ sortableKeyboardCoordinates,
30
+ useSortable
31
+ } from "@dnd-kit/sortable";
32
+ import { CSS } from "@dnd-kit/utilities";
19
33
  import { StorageFieldItem, useStorageUploadController } from "../../util/useStorageUploadController";
20
34
  import { StorageUploadProgress } from "../components/StorageUploadProgress";
21
35
  import { StorageItemPreview } from "../components/StorageItemPreview";
22
36
  import {
23
- cn,
37
+ cls,
24
38
  fieldBackgroundDisabledMixin,
25
39
  fieldBackgroundHoverMixin,
26
40
  fieldBackgroundMixin,
27
- focusedMixin,
28
41
  Typography
29
42
  } from "@firecms/ui";
30
43
  import { useClearRestoreValue } from "../useClearRestoreValue";
31
44
 
32
45
  const dropZoneClasses = "box-border relative pt-[2px] items-center border border-transparent min-h-[254px] outline-none rounded-md duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid";
33
- const disabledClasses = "border-dotted-gray"
34
- const nonActiveDropClasses = "hover:bg-field-hover dark:hover:bg-field-hover-dark"
46
+ const disabledClasses = fieldBackgroundDisabledMixin;
47
+ const nonActiveDropClasses = fieldBackgroundHoverMixin
35
48
  const activeDropClasses = "pt-0 border-2 border-solid"
36
49
  const acceptDropClasses = "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-2 border-solid border-green-500"
37
50
  const rejectDropClasses = "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-2 border-solid border-red-500"
38
51
 
39
52
  type StorageUploadFieldProps = FieldProps<string | string[]>;
40
53
 
41
- /**
42
- * Field that allows to upload files to Google Cloud Storage.
43
- *
44
- * This is one of the internal components that get mapped natively inside forms
45
- * and tables to the specified properties.
46
- * @group Form fields
47
- */
48
54
  export function StorageUploadFieldBinding({
49
55
  propertyKey,
50
56
  value,
@@ -52,18 +58,20 @@ export function StorageUploadFieldBinding({
52
58
  error,
53
59
  showError,
54
60
  autoFocus,
55
- tableMode,
61
+ minimalistView,
56
62
  property,
57
63
  includeDescription,
58
64
  context,
59
65
  isSubmitting,
60
66
  }: StorageUploadFieldProps) {
61
67
 
68
+ const authController = useAuthController();
69
+
62
70
  if (!context.entityId)
63
71
  throw new Error("StorageUploadFieldBinding: Entity id is null");
64
72
 
65
73
  const storageSource = useStorageSource(context.collection);
66
- const disabled = isReadOnly(property) || !!property.disabled || isSubmitting;
74
+ const disabled = isReadOnly(property) || !!property.disabled || isSubmitting || context.disabled;
67
75
 
68
76
  const {
69
77
  internalValue,
@@ -81,7 +89,7 @@ export function StorageUploadFieldBinding({
81
89
  propertyKey,
82
90
  value,
83
91
  storageSource,
84
- disabled,
92
+ disabled: disabled ?? false,
85
93
  onChange: setValue
86
94
  });
87
95
 
@@ -91,33 +99,32 @@ export function StorageUploadFieldBinding({
91
99
  setValue
92
100
  });
93
101
 
94
- const entity: Entity<any> = {
95
- id: context.entityId,
96
- values: context.values,
97
- path: context.path
98
- };
102
+ const resolvedProperty = resolveProperty({
103
+ propertyOrBuilder: property as PropertyOrBuilder,
104
+ authController
105
+ }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
99
106
 
100
107
  return (
101
108
 
102
109
  <>
103
110
 
104
- {!tableMode &&
105
- <LabelWithIcon icon={getIconForProperty(property, "small")}
106
- required={property.validation?.required}
107
- title={property.name}
108
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
111
+ {!minimalistView &&
112
+ <LabelWithIconAndTooltip
113
+ propertyKey={propertyKey}
114
+ icon={getIconForProperty(property, "small")}
115
+ required={property.validation?.required}
116
+ title={property.name}
117
+ className={"h-8text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
109
118
 
110
119
  <StorageUpload
111
120
  value={internalValue}
112
- collection={context.collection}
113
121
  name={propertyKey}
114
- disabled={disabled}
115
- autoFocus={autoFocus}
116
- property={property}
122
+ disabled={disabled ?? false}
123
+ autoFocus={autoFocus ?? false}
124
+ property={resolvedProperty}
117
125
  onChange={setValue}
118
126
  setInternalValue={setInternalValue}
119
127
  onFilesAdded={onFilesAdded}
120
- entity={entity}
121
128
  onFileUploadComplete={onFileUploadComplete}
122
129
  storagePathBuilder={storagePathBuilder}
123
130
  storage={storage}
@@ -133,44 +140,129 @@ export function StorageUploadFieldBinding({
133
140
  );
134
141
  }
135
142
 
143
+ interface SortableStorageItemProps {
144
+ id: number;
145
+ entry: StorageFieldItem;
146
+ property: ResolvedStringProperty;
147
+ name: string;
148
+ metadata?: Record<string, unknown>;
149
+ storagePathBuilder: (file: File) => string;
150
+ onFileUploadComplete: (uploadedPath: string, entry: StorageFieldItem, fileMetadata?: any) => Promise<void>;
151
+ onClear: (clearedStoragePathOrDownloadUrl: string) => void;
152
+ disabled: boolean;
153
+ isSortable: boolean; // Kept for consistency, though dnd-kit handles sortability via context
154
+ }
155
+
156
+ function SortableStorageItem({
157
+ id,
158
+ entry,
159
+ property,
160
+ name,
161
+ metadata,
162
+ storagePathBuilder,
163
+ onFileUploadComplete,
164
+ onClear,
165
+ disabled,
166
+ isSortable // This prop might be redundant if SortableContext is always used for multiple items
167
+ }: SortableStorageItemProps) {
168
+
169
+ const {
170
+ attributes,
171
+ listeners,
172
+ setNodeRef,
173
+ transform,
174
+ transition,
175
+ isDragging
176
+ } = useSortable({ id });
177
+
178
+ const style: React.CSSProperties = {
179
+ transform: CSS.Transform.toString(transform),
180
+ transition,
181
+ zIndex: isDragging ? 100 : undefined, // Higher z-index when dragging
182
+ opacity: isDragging ? 0.8 : 1 // Slight opacity for dragged item
183
+ };
184
+
185
+ const getImageSizeNumber = (previewSize: PreviewSize): number => {
186
+ switch (previewSize) {
187
+ case "small":
188
+ return 40;
189
+ case "medium":
190
+ return 118; // As per original logic for multiple items
191
+ case "large":
192
+ return 220; // As per original logic for single item
193
+ default:
194
+ return 118;
195
+ }
196
+ };
197
+
198
+ let child: React.ReactNode;
199
+ if (entry.storagePathOrDownloadUrl) {
200
+ child = (
201
+ <StorageItemPreview
202
+ name={`storage_preview_${entry.storagePathOrDownloadUrl}`}
203
+ property={property}
204
+ disabled={disabled}
205
+ value={entry.storagePathOrDownloadUrl}
206
+ onRemove={() => onClear(entry.storagePathOrDownloadUrl!)}
207
+ size={entry.size}/>
208
+ );
209
+ } else if (entry.file) {
210
+ child = (
211
+ <StorageUploadProgress
212
+ entry={entry}
213
+ metadata={metadata}
214
+ storagePath={storagePathBuilder(entry.file)}
215
+ onFileUploadComplete={onFileUploadComplete}
216
+ imageSize={getImageSizeNumber(entry.size)}
217
+ simple={false}
218
+ />
219
+ );
220
+ }
221
+
222
+ return (
223
+ <div
224
+ ref={setNodeRef}
225
+ style={style}
226
+ {...attributes}
227
+ {...listeners}
228
+ className={cls("rounded-md m-1")} // Added margin for spacing between items
229
+ tabIndex={-1}
230
+ >
231
+ {child}
232
+ </div>
233
+ );
234
+ }
235
+
136
236
  function FileDropComponent({
137
237
  storage,
138
- collection,
139
238
  disabled,
140
- isDraggingOver,
141
239
  onFilesAdded,
142
240
  multipleFilesSupported,
143
- droppableProvided,
144
241
  autoFocus,
145
242
  internalValue,
146
243
  property,
147
- entity,
148
244
  onClear,
149
245
  metadata,
150
246
  storagePathBuilder,
151
247
  onFileUploadComplete,
152
- size,
153
248
  name,
154
- helpText
249
+ helpText,
250
+ isDndItemDragging // New prop to disable dropzone when internal D&D is active
155
251
  }: {
156
252
  storage: StorageConfig,
157
- collection: EntityCollection,
158
253
  disabled: boolean,
159
- isDraggingOver: boolean,
160
- droppableProvided: any,
161
- onFilesAdded: (acceptedFiles: File[]) => void,
254
+ onFilesAdded: (acceptedFiles: File[]) => Promise<void>, // useStorageUploadController returns Promise<void>
162
255
  multipleFilesSupported: boolean,
163
256
  autoFocus: boolean,
164
257
  internalValue: StorageFieldItem[],
165
258
  property: ResolvedStringProperty,
166
259
  onClear: (clearedStoragePathOrDownloadUrl: string) => void,
167
- metadata: any,
168
- entity: Entity<any>;
260
+ metadata?: any,
169
261
  storagePathBuilder: (file: File) => string,
170
262
  onFileUploadComplete: (uploadedPath: string, entry: StorageFieldItem, fileMetadata?: any) => Promise<void>,
171
- size: PreviewSize,
172
263
  name: string,
173
- helpText: string
264
+ helpText: string,
265
+ isDndItemDragging?: boolean
174
266
  }) {
175
267
 
176
268
  const snackbarContext = useSnackbarController();
@@ -178,22 +270,33 @@ function FileDropComponent({
178
270
  const {
179
271
  getRootProps,
180
272
  getInputProps,
181
- isDragActive,
273
+ isDragActive, // This is for files dragged from OS
182
274
  isDragAccept,
183
275
  isDragReject
184
276
  } = useDropzone({
185
- accept: storage.acceptedFiles ? storage.acceptedFiles.map(e => ({ [e]: [] })).reduce((a, b) => ({ ...a, ...b }), {}) : undefined,
186
- disabled: disabled || isDraggingOver,
277
+ accept: storage.acceptedFiles ? storage.acceptedFiles.reduce((acc, ext) => ({
278
+ ...acc,
279
+ [ext]: []
280
+ }), {}) : undefined,
281
+ disabled: disabled || isDndItemDragging, // Disable if form field is disabled OR an internal item is being dragged
187
282
  noDragEventsBubbling: true,
188
283
  maxSize: storage.maxSize,
189
284
  onDrop: onFilesAdded,
190
- onDropRejected: (fileRejections, event) => {
285
+ onDropRejected: (fileRejections) => {
191
286
  for (const fileRejection of fileRejections) {
192
287
  for (const error of fileRejection.errors) {
193
- snackbarContext.open({
194
- type: "error",
195
- message: `Error uploading file: File is larger than ${storage.maxSize} bytes`
196
- });
288
+ console.error("Error uploading file: ", error);
289
+ if (error.code === "file-too-large") {
290
+ snackbarContext.open({
291
+ type: "error",
292
+ message: `Error uploading file: File is larger than ${storage.maxSize} bytes`
293
+ });
294
+ } else if (error.code === "file-invalid-type") {
295
+ snackbarContext.open({
296
+ type: "error",
297
+ message: "Error uploading file: File type is not supported"
298
+ });
299
+ }
197
300
  }
198
301
  }
199
302
  }
@@ -203,103 +306,65 @@ function FileDropComponent({
203
306
  return (
204
307
  <div
205
308
  {...getRootProps()}
206
- className={cn(
309
+ className={cls(
207
310
  fieldBackgroundMixin,
208
311
  disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
312
+ disabled ? "text-surface-accent-600 dark:text-surface-accent-500" : "",
209
313
  dropZoneClasses,
210
- multipleFilesSupported && internalValue.length ? "" : "flex",
211
- focusedMixin,
314
+ multipleFilesSupported && internalValue.length === 0 && "flex", // Keep flex for empty state centering
212
315
  {
213
316
  [nonActiveDropClasses]: !isDragActive,
214
- [activeDropClasses]: isDragActive,
215
- [rejectDropClasses]: isDragReject,
216
- [acceptDropClasses]: isDragAccept,
217
- [disabledClasses]: disabled
317
+ [activeDropClasses]: isDragActive, // OS file drag active
318
+ [rejectDropClasses]: isDragReject, // OS file drag reject
319
+ [acceptDropClasses]: isDragAccept, // OS file drag accept
320
+ [disabledClasses]: disabled || isDndItemDragging // Visually disable if internal drag
218
321
  })}
219
322
  >
220
323
  <div
221
- {...droppableProvided.droppableProps}
222
- ref={droppableProvided.innerRef}
223
- className={cn("flex items-center p-1 no-scrollbar",
224
- multipleFilesSupported && internalValue.length ? "overflow-auto" : "",
225
- multipleFilesSupported && internalValue.length ? "min-h-[180px]" : "min-h-[250px]"
324
+ className={cls("flex items-center p-1 no-scrollbar",
325
+ multipleFilesSupported && internalValue.length ? "flex-row overflow-x-auto" : "flex-col", // flex-col for single or empty
326
+ internalValue.length === 0 && "min-h-[250px] justify-center", // Centering for empty dropzone
327
+ multipleFilesSupported && internalValue.length > 0 && "min-h-[180px]", // Min height for multiple items
328
+ !multipleFilesSupported && internalValue.length > 0 && "min-h-[250px]" // Min height for single item
226
329
  )}
227
330
  >
228
-
229
331
  <input
230
332
  autoFocus={autoFocus}
231
333
  {...getInputProps()} />
232
334
 
233
- {internalValue.map((entry, index) => {
234
- let child: any;
235
- if (entry.storagePathOrDownloadUrl) {
236
- child = (
237
- <StorageItemPreview
238
- collection={collection}
239
- name={`storage_preview_${entry.storagePathOrDownloadUrl}`}
240
- property={property}
241
- disabled={disabled}
242
- entity={entity}
243
- value={entry.storagePathOrDownloadUrl}
244
- onRemove={onClear}
245
- size={entry.size}/>
246
- );
247
- } else if (entry.file) {
248
- child = (
249
- <StorageUploadProgress
250
- entry={entry}
251
- metadata={metadata}
252
- storagePath={storagePathBuilder(entry.file)}
253
- onFileUploadComplete={onFileUploadComplete}
254
- imageSize={size === "medium" ? 220 : 118}
255
- simple={false}
256
- />
257
- );
258
- }
259
-
260
- return (
261
- <Draggable
262
- key={`array_field_${name}_${entry.id}`}
263
- draggableId={`array_field_${name}_${entry.id}`}
264
- index={index}>
265
- {(provided, snapshot) => (
266
- <div
267
- tabIndex={-1}
268
- ref={provided.innerRef}
269
- {...provided.draggableProps}
270
- {...provided.dragHandleProps}
271
- className={cn(focusedMixin, "rounded-md")}
272
- style={{
273
- ...provided.draggableProps.style
274
- }}
275
- >
276
- {child}
277
- </div>
278
- )}
279
- </Draggable>
280
- );
281
- })
282
- }
283
-
284
- {droppableProvided.placeholder}
285
-
335
+ {internalValue.map((entry) => (
336
+ <SortableStorageItem
337
+ key={entry.id}
338
+ id={entry.id}
339
+ entry={entry}
340
+ property={property}
341
+ name={name}
342
+ metadata={metadata}
343
+ storagePathBuilder={storagePathBuilder}
344
+ onFileUploadComplete={onFileUploadComplete}
345
+ onClear={onClear}
346
+ disabled={disabled}
347
+ isSortable={multipleFilesSupported}
348
+ />
349
+ ))}
350
+
351
+ {/* Placeholder for empty dropzone text is handled by the outer Typography */}
286
352
  </div>
287
353
 
288
354
  <div
289
355
  className="flex-grow min-h-[38px] box-border m-2 text-center">
290
356
  <Typography align={"center"}
291
- variant={"label"}>
357
+ variant={"label"}
358
+ className={disabled ? "text-surface-accent-600 dark:text-surface-accent-500" : ""}>
292
359
  {helpText}
293
360
  </Typography>
294
361
  </div>
295
-
296
362
  </div>
297
363
  );
298
364
  }
299
365
 
300
366
  export interface StorageUploadProps {
301
367
  value: StorageFieldItem[];
302
- collection: EntityCollection;
303
368
  setInternalValue: (v: StorageFieldItem[]) => void;
304
369
  name: string;
305
370
  property: ResolvedStringProperty | ResolvedArrayProperty<string[]>;
@@ -307,18 +372,16 @@ export interface StorageUploadProps {
307
372
  multipleFilesSupported: boolean;
308
373
  autoFocus: boolean;
309
374
  disabled: boolean;
310
- entity: Entity<any>;
311
375
  storage: StorageConfig;
312
- onFilesAdded: (acceptedFiles: File[]) => void;
376
+ onFilesAdded: (acceptedFiles: File[]) => Promise<void>; // Updated from useStorageUploadController
313
377
  storagePathBuilder: (file: File) => string;
314
378
  onFileUploadComplete: (uploadedPath: string, entry: StorageFieldItem, fileMetadata?: any) => Promise<void>;
315
379
  }
316
380
 
317
381
  export function StorageUpload({
318
- collection,
319
382
  property,
320
383
  name,
321
- value,
384
+ value, // This is internalValue from useStorageUploadController
322
385
  setInternalValue,
323
386
  onChange,
324
387
  multipleFilesSupported,
@@ -327,7 +390,6 @@ export function StorageUpload({
327
390
  onFilesAdded,
328
391
  autoFocus,
329
392
  storage,
330
- entity,
331
393
  storagePathBuilder,
332
394
  }: StorageUploadProps) {
333
395
 
@@ -346,10 +408,10 @@ export function StorageUpload({
346
408
  }
347
409
 
348
410
  const metadata: Record<string, unknown> | undefined = storage?.metadata;
349
- const size = multipleFilesSupported ? "small" : "medium";
411
+ const [isDndItemDragging, setIsDndItemDragging] = useState(false);
350
412
 
351
413
  const moveItem = useCallback((fromIndex: number, toIndex: number) => {
352
- if (!multipleFilesSupported) return;
414
+ if (!multipleFilesSupported || fromIndex === toIndex) return;
353
415
  const newValue = [...value];
354
416
  const item = newValue[fromIndex];
355
417
  newValue.splice(fromIndex, 1);
@@ -361,87 +423,88 @@ export function StorageUpload({
361
423
  onChange(fieldValue);
362
424
  }, [multipleFilesSupported, onChange, setInternalValue, value]);
363
425
 
364
- const onDragEnd = useCallback((result: any) => {
365
- // dropped outside the list
366
- if (!result.destination) {
367
- return;
368
- }
369
-
370
- moveItem(result.source.index, result.destination.index);
426
+ const sensors = useSensors(
427
+ useSensor(PointerSensor, {
428
+ activationConstraint: {
429
+ distance: 5, // Start dragging after 5px movement
430
+ },
431
+ }),
432
+ useSensor(KeyboardSensor, {
433
+ coordinateGetter: sortableKeyboardCoordinates,
434
+ })
435
+ );
371
436
 
372
- }, [moveItem])
437
+ const handleDragStart = useCallback((event: DragStartEvent) => {
438
+ setIsDndItemDragging(true);
439
+ }, []);
440
+
441
+ const handleDragEnd = useCallback((event: DragEndEvent) => {
442
+ setIsDndItemDragging(false);
443
+ const {
444
+ active,
445
+ over
446
+ } = event;
447
+ if (over && active.id !== over.id) {
448
+ const oldIndex = value.findIndex(item => item.id === active.id);
449
+ const newIndex = value.findIndex(item => item.id === over.id);
450
+ if (oldIndex !== -1 && newIndex !== -1) {
451
+ moveItem(oldIndex, newIndex);
452
+ }
453
+ }
454
+ }, [value, moveItem]);
373
455
 
374
456
  const onClear = useCallback((clearedStoragePathOrDownloadUrl: string) => {
457
+ let newValue: StorageFieldItem[];
375
458
  if (multipleFilesSupported) {
376
- const newValue: StorageFieldItem[] = value.filter(v => v.storagePathOrDownloadUrl !== clearedStoragePathOrDownloadUrl);
459
+ newValue = value.filter(v => v.storagePathOrDownloadUrl !== clearedStoragePathOrDownloadUrl);
377
460
  onChange(newValue.filter(v => !!v.storagePathOrDownloadUrl).map(v => v.storagePathOrDownloadUrl as string));
378
- setInternalValue(newValue);
379
461
  } else {
462
+ newValue = [];
380
463
  onChange(null);
381
- setInternalValue([]);
382
464
  }
383
- }, [value, multipleFilesSupported, onChange]);
465
+ setInternalValue(newValue);
466
+ }, [value, multipleFilesSupported, onChange, setInternalValue]);
384
467
 
385
468
  const helpText = multipleFilesSupported
386
- ? "Drag 'n' drop some files here, or click to select files"
469
+ ? "Drag 'n' drop some files here, or click to select files. Drag to reorder."
387
470
  : "Drag 'n' drop a file here, or click to select one";
388
471
 
389
472
  const renderProperty: ResolvedStringProperty = multipleFilesSupported
390
- ? (property as ArrayProperty<string[]>).of as ResolvedStringProperty
473
+ ? (property as ResolvedArrayProperty<string[]>).of as ResolvedStringProperty
391
474
  : property as ResolvedStringProperty;
392
475
 
393
- return (
394
- <DragDropContext onDragEnd={onDragEnd}>
395
- <Droppable
396
- droppableId={`droppable_${name}`}
397
- direction="horizontal"
398
- renderClone={(provided, snapshot, rubric) => {
399
- const entry = value[rubric.source.index];
400
- return (
401
- <div
402
- ref={provided.innerRef}
403
- {...provided.draggableProps}
404
- {...provided.dragHandleProps}
405
- style={
406
- provided.draggableProps.style
407
- }
408
- className="rounded"
409
- >
410
- <StorageItemPreview
411
- collection={collection}
412
- name={`storage_preview_${entry.storagePathOrDownloadUrl}`}
413
- property={renderProperty}
414
- disabled={true}
415
- entity={entity}
416
- value={entry.storagePathOrDownloadUrl as string}
417
- onRemove={onClear}
418
- size={entry.size}/>
419
- </div>
420
- );
421
- }}
422
- >
423
- {(provided, snapshot) => {
424
- return <FileDropComponent storage={storage}
425
- collection={collection}
426
- disabled={disabled}
427
- isDraggingOver={snapshot.isDraggingOver}
428
- droppableProvided={provided}
429
- onFilesAdded={onFilesAdded}
430
- multipleFilesSupported={multipleFilesSupported}
431
- autoFocus={autoFocus}
432
- internalValue={value}
433
- property={renderProperty}
434
- entity={entity}
435
- onClear={onClear}
436
- metadata={metadata}
437
- storagePathBuilder={storagePathBuilder}
438
- onFileUploadComplete={onFileUploadComplete}
439
- size={size}
440
- name={name}
441
- helpText={helpText}/>
442
- }}
443
- </Droppable>
444
- </DragDropContext>
445
- );
476
+ const fileDropProps = {
477
+ storage,
478
+ disabled,
479
+ onFilesAdded,
480
+ multipleFilesSupported,
481
+ autoFocus,
482
+ internalValue: value, // Pass current internalValue
483
+ property: renderProperty,
484
+ onClear,
485
+ metadata,
486
+ storagePathBuilder,
487
+ onFileUploadComplete,
488
+ name,
489
+ helpText,
490
+ isDndItemDragging // Pass this down
491
+ };
446
492
 
493
+ if (multipleFilesSupported) {
494
+ return (
495
+ <DndContext
496
+ sensors={sensors}
497
+ collisionDetection={closestCenter}
498
+ onDragStart={handleDragStart}
499
+ onDragEnd={handleDragEnd}
500
+ >
501
+ <SortableContext items={value.map(v => v.id)} strategy={horizontalListSortingStrategy}>
502
+ <FileDropComponent {...fileDropProps} />
503
+ </SortableContext>
504
+ </DndContext>
505
+ );
506
+ } else {
507
+ // For single file, no D&D context is needed
508
+ return <FileDropComponent {...fileDropProps} isDndItemDragging={false}/>;
509
+ }
447
510
  }