@rebasepro/studio 0.5.0 → 0.6.1

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 (369) hide show
  1. package/dist/ApiExplorer-CdIwR9Ga.js +963 -0
  2. package/dist/ApiExplorer-CdIwR9Ga.js.map +1 -0
  3. package/dist/AuthSimulationSelector-iEZ-Or_1.js +56 -0
  4. package/dist/AuthSimulationSelector-iEZ-Or_1.js.map +1 -0
  5. package/dist/BranchesView-DncIRcZt.js +461 -0
  6. package/dist/BranchesView-DncIRcZt.js.map +1 -0
  7. package/dist/CronJobsView-4gdtJvoe.js +500 -0
  8. package/dist/CronJobsView-4gdtJvoe.js.map +1 -0
  9. package/dist/JSEditor-BhAbEjCP.js +1573 -0
  10. package/dist/JSEditor-BhAbEjCP.js.map +1 -0
  11. package/dist/LogsExplorer-CqtKILj8.js +240 -0
  12. package/dist/LogsExplorer-CqtKILj8.js.map +1 -0
  13. package/dist/MonacoEditor-COZqrIJ1.js +246 -0
  14. package/dist/MonacoEditor-COZqrIJ1.js.map +1 -0
  15. package/dist/RLSEditor-DpF1u9EC.js +1369 -0
  16. package/dist/RLSEditor-DpF1u9EC.js.map +1 -0
  17. package/dist/SQLEditor-BLuq_zDM.js +1964 -0
  18. package/dist/SQLEditor-BLuq_zDM.js.map +1 -0
  19. package/dist/SchemaVisualizer-BJK2u3C0.js +1068 -0
  20. package/dist/SchemaVisualizer-BJK2u3C0.js.map +1 -0
  21. package/dist/StorageView-CvrnHmDG.js +1395 -0
  22. package/dist/StorageView-CvrnHmDG.js.map +1 -0
  23. package/dist/{studio/src/components → components}/ApiExplorer/ApiExplorer.d.ts +2 -1
  24. package/dist/{studio/src/components → components}/ApiExplorer/EndpointDetail.d.ts +2 -1
  25. package/dist/{studio/src/components → components}/ApiExplorer/TryItPanel.d.ts +2 -1
  26. package/dist/{studio/src/components → components}/AuthSimulationSelector.d.ts +2 -1
  27. package/dist/components/Branches/BranchesView.d.ts +2 -0
  28. package/dist/components/CronJobs/CronJobsView.d.ts +2 -0
  29. package/dist/components/JSEditor/JSEditor.d.ts +2 -0
  30. package/dist/{studio/src/components → components}/JSEditor/JSEditorSidebar.d.ts +2 -1
  31. package/dist/{studio/src/components → components}/JSEditor/JSMonacoEditor.d.ts +2 -1
  32. package/dist/components/LogsExplorer/LogsExplorer.d.ts +2 -0
  33. package/dist/{studio/src/components → components}/RLSEditor/PolicyEditor.d.ts +2 -1
  34. package/dist/{studio/src/components → components}/RLSEditor/RLSEditor.d.ts +2 -1
  35. package/dist/{studio/src/components → components}/SQLEditor/MonacoEditor.d.ts +2 -1
  36. package/dist/{studio/src/components → components}/SQLEditor/SQLEditor.d.ts +2 -1
  37. package/dist/{studio/src/components → components}/SQLEditor/SQLEditorSidebar.d.ts +2 -1
  38. package/dist/{studio/src/components → components}/SQLEditor/SchemaBrowser.d.ts +2 -1
  39. package/dist/{studio/src/components → components}/SchemaVisualizer/RelationEdge.d.ts +1 -1
  40. package/dist/components/SchemaVisualizer/SchemaVisualizer.d.ts +3 -0
  41. package/dist/{studio/src/components → components}/SchemaVisualizer/TableNode.d.ts +1 -1
  42. package/dist/components/StorageView/StorageView.d.ts +2 -0
  43. package/dist/{studio/src/components → components}/StudioHomePage.d.ts +1 -1
  44. package/dist/index.es.js +688 -746
  45. package/dist/index.es.js.map +1 -1
  46. package/dist/index.umd.js +10323 -9572
  47. package/dist/index.umd.js.map +1 -1
  48. package/package.json +22 -22
  49. package/src/components/ApiExplorer/TryItPanel.tsx +15 -18
  50. package/src/components/CronJobs/CronJobsView.tsx +1 -1
  51. package/src/components/JSEditor/JSEditor.tsx +9 -14
  52. package/src/components/LogsExplorer/LogsExplorer.tsx +6 -3
  53. package/src/components/RLSEditor/PolicyEditor.tsx +1 -1
  54. package/src/components/SQLEditor/SQLEditor.tsx +40 -30
  55. package/src/components/StorageView/StorageView.tsx +25 -14
  56. package/src/components/StudioHomePage.tsx +51 -15
  57. package/src/utils/parseSpec.test.ts +41 -20
  58. package/src/utils/pgColumnToProperty.ts +1 -1
  59. package/dist/ApiExplorer-CGHEF1uL.js +0 -1052
  60. package/dist/ApiExplorer-CGHEF1uL.js.map +0 -1
  61. package/dist/AuthSimulationSelector-DGoXkWSg.js +0 -105
  62. package/dist/AuthSimulationSelector-DGoXkWSg.js.map +0 -1
  63. package/dist/BranchesView-BiTEwIhd.js +0 -291
  64. package/dist/BranchesView-BiTEwIhd.js.map +0 -1
  65. package/dist/CronJobsView-3PM_qR8v.js +0 -472
  66. package/dist/CronJobsView-3PM_qR8v.js.map +0 -1
  67. package/dist/JSEditor-DfwRLBZg.js +0 -1297
  68. package/dist/JSEditor-DfwRLBZg.js.map +0 -1
  69. package/dist/LogsExplorer-_4sZadKn.js +0 -162
  70. package/dist/LogsExplorer-_4sZadKn.js.map +0 -1
  71. package/dist/MonacoEditor-CMYEjiRf.js +0 -161
  72. package/dist/MonacoEditor-CMYEjiRf.js.map +0 -1
  73. package/dist/RLSEditor-CHEExeSB.js +0 -1871
  74. package/dist/RLSEditor-CHEExeSB.js.map +0 -1
  75. package/dist/SQLEditor-CQXaI0iU.js +0 -1797
  76. package/dist/SQLEditor-CQXaI0iU.js.map +0 -1
  77. package/dist/SchemaVisualizer-BGpmzyXT.js +0 -1069
  78. package/dist/SchemaVisualizer-BGpmzyXT.js.map +0 -1
  79. package/dist/StorageView-B7AsN2qX.js +0 -869
  80. package/dist/StorageView-B7AsN2qX.js.map +0 -1
  81. package/dist/common/src/collections/CollectionRegistry.d.ts +0 -56
  82. package/dist/common/src/collections/default-collections.d.ts +0 -9
  83. package/dist/common/src/collections/index.d.ts +0 -2
  84. package/dist/common/src/data/buildRebaseData.d.ts +0 -14
  85. package/dist/common/src/data/query_builder.d.ts +0 -55
  86. package/dist/common/src/index.d.ts +0 -4
  87. package/dist/common/src/util/builders.d.ts +0 -57
  88. package/dist/common/src/util/callbacks.d.ts +0 -6
  89. package/dist/common/src/util/collections.d.ts +0 -11
  90. package/dist/common/src/util/common.d.ts +0 -2
  91. package/dist/common/src/util/conditions.d.ts +0 -26
  92. package/dist/common/src/util/entities.d.ts +0 -58
  93. package/dist/common/src/util/enums.d.ts +0 -3
  94. package/dist/common/src/util/index.d.ts +0 -16
  95. package/dist/common/src/util/navigation_from_path.d.ts +0 -34
  96. package/dist/common/src/util/navigation_utils.d.ts +0 -20
  97. package/dist/common/src/util/parent_references_from_path.d.ts +0 -6
  98. package/dist/common/src/util/paths.d.ts +0 -14
  99. package/dist/common/src/util/permissions.d.ts +0 -14
  100. package/dist/common/src/util/references.d.ts +0 -2
  101. package/dist/common/src/util/relations.d.ts +0 -22
  102. package/dist/common/src/util/resolutions.d.ts +0 -72
  103. package/dist/common/src/util/storage.d.ts +0 -24
  104. package/dist/core/src/components/AIIcon.d.ts +0 -16
  105. package/dist/core/src/components/BootstrapAdminBanner.d.ts +0 -4
  106. package/dist/core/src/components/ConfirmationDialog.d.ts +0 -9
  107. package/dist/core/src/components/Debug/UIReferenceView.d.ts +0 -1
  108. package/dist/core/src/components/Debug/UIStyleGuide.d.ts +0 -1
  109. package/dist/core/src/components/ErrorTooltip.d.ts +0 -2
  110. package/dist/core/src/components/ErrorView.d.ts +0 -21
  111. package/dist/core/src/components/LanguageToggle.d.ts +0 -1
  112. package/dist/core/src/components/LoginView/LoginView.d.ts +0 -109
  113. package/dist/core/src/components/LoginView/index.d.ts +0 -2
  114. package/dist/core/src/components/NotFoundPage.d.ts +0 -1
  115. package/dist/core/src/components/RebaseAuth.d.ts +0 -10
  116. package/dist/core/src/components/RebaseLogo.d.ts +0 -7
  117. package/dist/core/src/components/UnsavedChangesDialog.d.ts +0 -9
  118. package/dist/core/src/components/UserDisplay.d.ts +0 -7
  119. package/dist/core/src/components/UserSelectPopover.d.ts +0 -62
  120. package/dist/core/src/components/UserSettingsView.d.ts +0 -1
  121. package/dist/core/src/components/common/index.d.ts +0 -6
  122. package/dist/core/src/components/common/table_height.d.ts +0 -5
  123. package/dist/core/src/components/common/types.d.ts +0 -66
  124. package/dist/core/src/components/common/useColumnsIds.d.ts +0 -9
  125. package/dist/core/src/components/common/useDataTableController.d.ts +0 -45
  126. package/dist/core/src/components/common/useDebouncedData.d.ts +0 -9
  127. package/dist/core/src/components/common/useScrollRestoration.d.ts +0 -14
  128. package/dist/core/src/components/index.d.ts +0 -17
  129. package/dist/core/src/contexts/AdminModeController.d.ts +0 -4
  130. package/dist/core/src/contexts/AnalyticsContext.d.ts +0 -3
  131. package/dist/core/src/contexts/AuthControllerContext.d.ts +0 -3
  132. package/dist/core/src/contexts/CustomizationControllerContext.d.ts +0 -3
  133. package/dist/core/src/contexts/DataDriverContext.d.ts +0 -3
  134. package/dist/core/src/contexts/DatabaseAdminContext.d.ts +0 -3
  135. package/dist/core/src/contexts/DialogsProvider.d.ts +0 -4
  136. package/dist/core/src/contexts/EffectiveRoleController.d.ts +0 -4
  137. package/dist/core/src/contexts/InternalUserManagementContext.d.ts +0 -3
  138. package/dist/core/src/contexts/ModeController.d.ts +0 -4
  139. package/dist/core/src/contexts/RebaseClientInstanceContext.d.ts +0 -6
  140. package/dist/core/src/contexts/RebaseDataContext.d.ts +0 -3
  141. package/dist/core/src/contexts/SnackbarProvider.d.ts +0 -2
  142. package/dist/core/src/contexts/StorageSourceContext.d.ts +0 -3
  143. package/dist/core/src/contexts/UserConfigurationPersistenceContext.d.ts +0 -3
  144. package/dist/core/src/contexts/index.d.ts +0 -13
  145. package/dist/core/src/core/PluginLifecycleManager.d.ts +0 -17
  146. package/dist/core/src/core/PluginProviderStack.d.ts +0 -21
  147. package/dist/core/src/core/Rebase.d.ts +0 -14
  148. package/dist/core/src/core/RebaseProps.d.ts +0 -147
  149. package/dist/core/src/core/RebaseRouter.d.ts +0 -4
  150. package/dist/core/src/core/RebaseRoutes.d.ts +0 -17
  151. package/dist/core/src/core/index.d.ts +0 -4
  152. package/dist/core/src/hooks/ApiConfigContext.d.ts +0 -24
  153. package/dist/core/src/hooks/data/delete.d.ts +0 -31
  154. package/dist/core/src/hooks/data/save.d.ts +0 -34
  155. package/dist/core/src/hooks/data/useCollectionFetch.d.ts +0 -62
  156. package/dist/core/src/hooks/data/useData.d.ts +0 -13
  157. package/dist/core/src/hooks/data/useDataOrder.d.ts +0 -12
  158. package/dist/core/src/hooks/data/useEntityFetch.d.ts +0 -43
  159. package/dist/core/src/hooks/data/useRelationSelector.d.ts +0 -52
  160. package/dist/core/src/hooks/data/useUserSelector.d.ts +0 -31
  161. package/dist/core/src/hooks/index.d.ts +0 -37
  162. package/dist/core/src/hooks/useAdminModeController.d.ts +0 -19
  163. package/dist/core/src/hooks/useAnalyticsController.d.ts +0 -5
  164. package/dist/core/src/hooks/useAuthController.d.ts +0 -11
  165. package/dist/core/src/hooks/useAuthSubscription.d.ts +0 -2
  166. package/dist/core/src/hooks/useBackendStorageSource.d.ts +0 -30
  167. package/dist/core/src/hooks/useBridgeRegistration.d.ts +0 -18
  168. package/dist/core/src/hooks/useBrowserTitleAndIcon.d.ts +0 -6
  169. package/dist/core/src/hooks/useBuildAdminModeController.d.ts +0 -6
  170. package/dist/core/src/hooks/useBuildEffectiveRoleController.d.ts +0 -8
  171. package/dist/core/src/hooks/useBuildLocalConfigurationPersistence.d.ts +0 -2
  172. package/dist/core/src/hooks/useBuildModeController.d.ts +0 -6
  173. package/dist/core/src/hooks/useClipboard.d.ts +0 -57
  174. package/dist/core/src/hooks/useCollapsedGroups.d.ts +0 -27
  175. package/dist/core/src/hooks/useCustomizationController.d.ts +0 -11
  176. package/dist/core/src/hooks/useDialogsController.d.ts +0 -11
  177. package/dist/core/src/hooks/useEffectiveRoleController.d.ts +0 -7
  178. package/dist/core/src/hooks/useInternalUserManagementController.d.ts +0 -12
  179. package/dist/core/src/hooks/useLargeLayout.d.ts +0 -1
  180. package/dist/core/src/hooks/useModeController.d.ts +0 -19
  181. package/dist/core/src/hooks/usePermissions.d.ts +0 -12
  182. package/dist/core/src/hooks/useRebaseClient.d.ts +0 -5
  183. package/dist/core/src/hooks/useRebaseContext.d.ts +0 -11
  184. package/dist/core/src/hooks/useRebaseRegistry.d.ts +0 -34
  185. package/dist/core/src/hooks/useResolvedComponent.d.ts +0 -47
  186. package/dist/core/src/hooks/useSlot.d.ts +0 -18
  187. package/dist/core/src/hooks/useSnackbarController.d.ts +0 -20
  188. package/dist/core/src/hooks/useStorageSource.d.ts +0 -7
  189. package/dist/core/src/hooks/useStudioBridge.d.ts +0 -91
  190. package/dist/core/src/hooks/useTranslation.d.ts +0 -17
  191. package/dist/core/src/hooks/useUnsavedChangesDialog.d.ts +0 -12
  192. package/dist/core/src/hooks/useUserConfigurationPersistence.d.ts +0 -8
  193. package/dist/core/src/i18n/RebaseI18nProvider.d.ts +0 -33
  194. package/dist/core/src/index.d.ts +0 -15
  195. package/dist/core/src/internal/common.d.ts +0 -3
  196. package/dist/core/src/internal/useRestoreScroll.d.ts +0 -6
  197. package/dist/core/src/locales/de.d.ts +0 -2
  198. package/dist/core/src/locales/en.d.ts +0 -10
  199. package/dist/core/src/locales/es.d.ts +0 -10
  200. package/dist/core/src/locales/fr.d.ts +0 -2
  201. package/dist/core/src/locales/hi.d.ts +0 -2
  202. package/dist/core/src/locales/it.d.ts +0 -2
  203. package/dist/core/src/locales/pt.d.ts +0 -7
  204. package/dist/core/src/util/constants.d.ts +0 -1
  205. package/dist/core/src/util/createFormexStub.d.ts +0 -2
  206. package/dist/core/src/util/entity_cache.d.ts +0 -22
  207. package/dist/core/src/util/enums.d.ts +0 -5
  208. package/dist/core/src/util/icon_list.d.ts +0 -5
  209. package/dist/core/src/util/icons.d.ts +0 -20
  210. package/dist/core/src/util/index.d.ts +0 -8
  211. package/dist/core/src/util/previews.d.ts +0 -4
  212. package/dist/core/src/util/useStorageUploadController.d.ts +0 -38
  213. package/dist/formex/src/Field.d.ts +0 -52
  214. package/dist/formex/src/Formex.d.ts +0 -7
  215. package/dist/formex/src/index.d.ts +0 -5
  216. package/dist/formex/src/types.d.ts +0 -40
  217. package/dist/formex/src/useCreateFormex.d.ts +0 -14
  218. package/dist/formex/src/utils.d.ts +0 -16
  219. package/dist/studio/src/components/Branches/BranchesView.d.ts +0 -1
  220. package/dist/studio/src/components/CronJobs/CronJobsView.d.ts +0 -1
  221. package/dist/studio/src/components/JSEditor/JSEditor.d.ts +0 -1
  222. package/dist/studio/src/components/LogsExplorer/LogsExplorer.d.ts +0 -1
  223. package/dist/studio/src/components/SchemaVisualizer/SchemaVisualizer.d.ts +0 -2
  224. package/dist/studio/src/components/StorageView/StorageView.d.ts +0 -1
  225. package/dist/types/src/controllers/analytics_controller.d.ts +0 -7
  226. package/dist/types/src/controllers/auth.d.ts +0 -104
  227. package/dist/types/src/controllers/client.d.ts +0 -168
  228. package/dist/types/src/controllers/collection_registry.d.ts +0 -46
  229. package/dist/types/src/controllers/customization_controller.d.ts +0 -60
  230. package/dist/types/src/controllers/data.d.ts +0 -207
  231. package/dist/types/src/controllers/data_driver.d.ts +0 -218
  232. package/dist/types/src/controllers/database_admin.d.ts +0 -11
  233. package/dist/types/src/controllers/dialogs_controller.d.ts +0 -36
  234. package/dist/types/src/controllers/effective_role.d.ts +0 -4
  235. package/dist/types/src/controllers/email.d.ts +0 -36
  236. package/dist/types/src/controllers/index.d.ts +0 -18
  237. package/dist/types/src/controllers/local_config_persistence.d.ts +0 -20
  238. package/dist/types/src/controllers/navigation.d.ts +0 -225
  239. package/dist/types/src/controllers/registry.d.ts +0 -63
  240. package/dist/types/src/controllers/side_dialogs_controller.d.ts +0 -67
  241. package/dist/types/src/controllers/side_entity_controller.d.ts +0 -97
  242. package/dist/types/src/controllers/snackbar.d.ts +0 -24
  243. package/dist/types/src/controllers/storage.d.ts +0 -171
  244. package/dist/types/src/index.d.ts +0 -4
  245. package/dist/types/src/rebase_context.d.ts +0 -122
  246. package/dist/types/src/types/auth_adapter.d.ts +0 -301
  247. package/dist/types/src/types/backend.d.ts +0 -571
  248. package/dist/types/src/types/backend_hooks.d.ts +0 -172
  249. package/dist/types/src/types/builders.d.ts +0 -15
  250. package/dist/types/src/types/chips.d.ts +0 -5
  251. package/dist/types/src/types/collections.d.ts +0 -961
  252. package/dist/types/src/types/component_ref.d.ts +0 -47
  253. package/dist/types/src/types/cron.d.ts +0 -102
  254. package/dist/types/src/types/data_source.d.ts +0 -64
  255. package/dist/types/src/types/database_adapter.d.ts +0 -94
  256. package/dist/types/src/types/entities.d.ts +0 -145
  257. package/dist/types/src/types/entity_actions.d.ts +0 -104
  258. package/dist/types/src/types/entity_callbacks.d.ts +0 -173
  259. package/dist/types/src/types/entity_link_builder.d.ts +0 -7
  260. package/dist/types/src/types/entity_overrides.d.ts +0 -10
  261. package/dist/types/src/types/entity_views.d.ts +0 -87
  262. package/dist/types/src/types/export_import.d.ts +0 -21
  263. package/dist/types/src/types/formex.d.ts +0 -40
  264. package/dist/types/src/types/index.d.ts +0 -28
  265. package/dist/types/src/types/locales.d.ts +0 -4
  266. package/dist/types/src/types/modify_collections.d.ts +0 -5
  267. package/dist/types/src/types/plugins.d.ts +0 -282
  268. package/dist/types/src/types/properties.d.ts +0 -1173
  269. package/dist/types/src/types/property_config.d.ts +0 -74
  270. package/dist/types/src/types/relations.d.ts +0 -336
  271. package/dist/types/src/types/slots.d.ts +0 -262
  272. package/dist/types/src/types/translations.d.ts +0 -900
  273. package/dist/types/src/types/user_management_delegate.d.ts +0 -86
  274. package/dist/types/src/types/websockets.d.ts +0 -78
  275. package/dist/types/src/users/index.d.ts +0 -1
  276. package/dist/types/src/users/user.d.ts +0 -50
  277. package/dist/ui/src/components/Alert.d.ts +0 -12
  278. package/dist/ui/src/components/Autocomplete.d.ts +0 -21
  279. package/dist/ui/src/components/Avatar.d.ts +0 -11
  280. package/dist/ui/src/components/Badge.d.ts +0 -8
  281. package/dist/ui/src/components/BooleanSwitch.d.ts +0 -14
  282. package/dist/ui/src/components/BooleanSwitchWithLabel.d.ts +0 -17
  283. package/dist/ui/src/components/Button.d.ts +0 -14
  284. package/dist/ui/src/components/Card.d.ts +0 -8
  285. package/dist/ui/src/components/CenteredView.d.ts +0 -9
  286. package/dist/ui/src/components/Checkbox.d.ts +0 -13
  287. package/dist/ui/src/components/Chip.d.ts +0 -26
  288. package/dist/ui/src/components/CircularProgress.d.ts +0 -5
  289. package/dist/ui/src/components/CircularProgressCenter.d.ts +0 -11
  290. package/dist/ui/src/components/Collapse.d.ts +0 -9
  291. package/dist/ui/src/components/ColorPicker.d.ts +0 -30
  292. package/dist/ui/src/components/Container.d.ts +0 -8
  293. package/dist/ui/src/components/DateTimeField.d.ts +0 -24
  294. package/dist/ui/src/components/DebouncedTextField.d.ts +0 -2
  295. package/dist/ui/src/components/Dialog.d.ts +0 -39
  296. package/dist/ui/src/components/DialogActions.d.ts +0 -7
  297. package/dist/ui/src/components/DialogContent.d.ts +0 -7
  298. package/dist/ui/src/components/DialogTitle.d.ts +0 -10
  299. package/dist/ui/src/components/ErrorBoundary.d.ts +0 -33
  300. package/dist/ui/src/components/ExpandablePanel.d.ts +0 -12
  301. package/dist/ui/src/components/FileUpload.d.ts +0 -23
  302. package/dist/ui/src/components/FilterChip.d.ts +0 -34
  303. package/dist/ui/src/components/IconButton.d.ts +0 -12
  304. package/dist/ui/src/components/InfoLabel.d.ts +0 -5
  305. package/dist/ui/src/components/InputLabel.d.ts +0 -11
  306. package/dist/ui/src/components/Label.d.ts +0 -7
  307. package/dist/ui/src/components/LoadingButton.d.ts +0 -7
  308. package/dist/ui/src/components/Markdown.d.ts +0 -10
  309. package/dist/ui/src/components/Menu.d.ts +0 -23
  310. package/dist/ui/src/components/Menubar.d.ts +0 -80
  311. package/dist/ui/src/components/MultiSelect.d.ts +0 -48
  312. package/dist/ui/src/components/Paper.d.ts +0 -6
  313. package/dist/ui/src/components/Popover.d.ts +0 -24
  314. package/dist/ui/src/components/RadioGroup.d.ts +0 -28
  315. package/dist/ui/src/components/ResizablePanels.d.ts +0 -18
  316. package/dist/ui/src/components/SearchBar.d.ts +0 -26
  317. package/dist/ui/src/components/Select.d.ts +0 -43
  318. package/dist/ui/src/components/Separator.d.ts +0 -5
  319. package/dist/ui/src/components/Sheet.d.ts +0 -22
  320. package/dist/ui/src/components/Skeleton.d.ts +0 -6
  321. package/dist/ui/src/components/Slider.d.ts +0 -21
  322. package/dist/ui/src/components/Table.d.ts +0 -34
  323. package/dist/ui/src/components/Tabs.d.ts +0 -19
  324. package/dist/ui/src/components/TextField.d.ts +0 -58
  325. package/dist/ui/src/components/TextareaAutosize.d.ts +0 -43
  326. package/dist/ui/src/components/ToggleButtonGroup.d.ts +0 -30
  327. package/dist/ui/src/components/Tooltip.d.ts +0 -19
  328. package/dist/ui/src/components/Typography.d.ts +0 -36
  329. package/dist/ui/src/components/VirtualTable/VirtualTable.d.ts +0 -11
  330. package/dist/ui/src/components/VirtualTable/VirtualTableCell.d.ts +0 -21
  331. package/dist/ui/src/components/VirtualTable/VirtualTableHeader.d.ts +0 -29
  332. package/dist/ui/src/components/VirtualTable/VirtualTableHeaderRow.d.ts +0 -2
  333. package/dist/ui/src/components/VirtualTable/VirtualTableProps.d.ts +0 -249
  334. package/dist/ui/src/components/VirtualTable/VirtualTableRow.d.ts +0 -3
  335. package/dist/ui/src/components/VirtualTable/index.d.ts +0 -3
  336. package/dist/ui/src/components/VirtualTable/types.d.ts +0 -38
  337. package/dist/ui/src/components/common/SelectInputLabel.d.ts +0 -5
  338. package/dist/ui/src/components/index.d.ts +0 -58
  339. package/dist/ui/src/hooks/PortalContainerContext.d.ts +0 -31
  340. package/dist/ui/src/hooks/index.d.ts +0 -6
  341. package/dist/ui/src/hooks/useDebounceCallback.d.ts +0 -1
  342. package/dist/ui/src/hooks/useDebounceValue.d.ts +0 -1
  343. package/dist/ui/src/hooks/useDebouncedCallback.d.ts +0 -1
  344. package/dist/ui/src/hooks/useInjectStyles.d.ts +0 -7
  345. package/dist/ui/src/hooks/useOutsideAlerter.d.ts +0 -5
  346. package/dist/ui/src/icons/GitHubIcon.d.ts +0 -2
  347. package/dist/ui/src/icons/HandleIcon.d.ts +0 -1
  348. package/dist/ui/src/icons/Icon.d.ts +0 -20
  349. package/dist/ui/src/icons/cool_icon_keys.d.ts +0 -1
  350. package/dist/ui/src/icons/icon_keys.d.ts +0 -1
  351. package/dist/ui/src/icons/index.d.ts +0 -8
  352. package/dist/ui/src/index.d.ts +0 -5
  353. package/dist/ui/src/styles.d.ts +0 -12
  354. package/dist/ui/src/util/chip_colors.d.ts +0 -4
  355. package/dist/ui/src/util/cls.d.ts +0 -2
  356. package/dist/ui/src/util/debounce.d.ts +0 -10
  357. package/dist/ui/src/util/hash.d.ts +0 -1
  358. package/dist/ui/src/util/index.d.ts +0 -4
  359. package/dist/ui/src/util/key_to_icon_component.d.ts +0 -1
  360. /package/dist/{studio/src/components → components}/ApiExplorer/parseSpec.d.ts +0 -0
  361. /package/dist/{studio/src/components → components}/ApiExplorer/types.d.ts +0 -0
  362. /package/dist/{studio/src/components → components}/RLSEditor/index.d.ts +0 -0
  363. /package/dist/{studio/src/components → components}/RebaseStudio.d.ts +0 -0
  364. /package/dist/{studio/src/components → components}/SQLEditor/ExplainVisualizer.d.ts +0 -0
  365. /package/dist/{studio/src/components → components}/SchemaVisualizer/schema-visualizer.utils.d.ts +0 -0
  366. /package/dist/{studio/src/components → components}/SchemaVisualizer/useSchemaGraph.d.ts +0 -0
  367. /package/dist/{studio/src/index.d.ts → index.d.ts} +0 -0
  368. /package/dist/{studio/src/utils → utils}/pgColumnToProperty.d.ts +0 -0
  369. /package/dist/{studio/src/utils → utils}/sql_utils.d.ts +0 -0
@@ -0,0 +1,1395 @@
1
+ import { ErrorView, useApiConfig, useSnackbarController, useStorageSource } from "@rebasepro/core";
2
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { ArrowLeftIcon, Button, CheckIcon, Checkbox, Chip, CircularProgress, CopyIcon, Dialog, DialogActions, DialogContent, DialogTitle, DownloadIcon, FileTextIcon, FileUpload, FolderIcon, FolderPlusIcon, IconButton, ImageIcon, LayoutGridIcon, ListIcon, LoadingButton, Music2Icon, PlusIcon, RefreshCwIcon, TextField, Tooltip, Trash2Icon, Typography, UploadCloudIcon, VideoIcon, XIcon, cls, defaultBorderMixin, iconSize } from "@rebasepro/ui";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import { useSearchParams } from "react-router-dom";
6
+ import { useDropzone } from "react-dropzone";
7
+ //#region src/components/StorageView/StorageView.tsx
8
+ function formatFileSize(bytes) {
9
+ if (bytes < 1024) return `${bytes} B`;
10
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
11
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
12
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
13
+ }
14
+ function getFileIcon(contentType) {
15
+ if (!contentType) return FileTextIcon;
16
+ if (contentType.startsWith("image/")) return ImageIcon;
17
+ if (contentType.startsWith("video/")) return VideoIcon;
18
+ if (contentType.startsWith("audio/")) return Music2Icon;
19
+ return FileTextIcon;
20
+ }
21
+ function getExtension(name) {
22
+ const parts = name.split(".");
23
+ return parts.length > 1 ? parts[parts.length - 1].toUpperCase() : "";
24
+ }
25
+ function breadcrumbSegments(path) {
26
+ if (!path || path === "/") return [{
27
+ label: "Root",
28
+ path: ""
29
+ }];
30
+ const parts = path.split("/").filter(Boolean);
31
+ const segments = [{
32
+ label: "Root",
33
+ path: ""
34
+ }];
35
+ let accumulated = "";
36
+ for (const part of parts) {
37
+ accumulated = accumulated ? `${accumulated}/${part}` : part;
38
+ segments.push({
39
+ label: part,
40
+ path: accumulated
41
+ });
42
+ }
43
+ return segments;
44
+ }
45
+ function UploadDialog({ open, currentPath, onClose, onUpload }) {
46
+ const [uploading, setUploading] = useState(false);
47
+ const [selectedFiles, setSelectedFiles] = useState([]);
48
+ const [error, setError] = useState(null);
49
+ const handleFilesAdded = useCallback((files) => {
50
+ setSelectedFiles((prev) => [...prev, ...files]);
51
+ }, []);
52
+ const handleRemoveFile = useCallback((index) => {
53
+ setSelectedFiles((prev) => prev.filter((_, i) => i !== index));
54
+ }, []);
55
+ const handleUpload = useCallback(async () => {
56
+ if (selectedFiles.length === 0) return;
57
+ setUploading(true);
58
+ setError(null);
59
+ try {
60
+ await onUpload(selectedFiles);
61
+ setSelectedFiles([]);
62
+ onClose();
63
+ } catch (err) {
64
+ setError(err instanceof Error ? err.message : "Upload failed");
65
+ } finally {
66
+ setUploading(false);
67
+ }
68
+ }, [
69
+ selectedFiles,
70
+ onUpload,
71
+ onClose
72
+ ]);
73
+ const handleClose = useCallback(() => {
74
+ if (!uploading) {
75
+ setSelectedFiles([]);
76
+ setError(null);
77
+ onClose();
78
+ }
79
+ }, [uploading, onClose]);
80
+ return /* @__PURE__ */ jsxs(Dialog, {
81
+ open,
82
+ onOpenChange: (o) => !o && handleClose(),
83
+ maxWidth: "md",
84
+ children: [
85
+ /* @__PURE__ */ jsxs(DialogTitle, { children: ["Upload Files", /* @__PURE__ */ jsxs(Typography, {
86
+ variant: "caption",
87
+ className: "text-text-secondary dark:text-text-secondary-dark mt-0.5 block",
88
+ children: ["to ", /* @__PURE__ */ jsxs("span", {
89
+ className: "font-mono text-primary",
90
+ children: ["/", currentPath || "root"]
91
+ })]
92
+ })] }),
93
+ /* @__PURE__ */ jsxs(DialogContent, {
94
+ className: "space-y-4",
95
+ children: [
96
+ /* @__PURE__ */ jsx(FileUpload, {
97
+ onFilesAdded: handleFilesAdded,
98
+ size: "large",
99
+ uploadDescription: /* @__PURE__ */ jsxs("div", {
100
+ className: "flex flex-col items-center justify-center pointer-events-none",
101
+ children: [
102
+ /* @__PURE__ */ jsx(UploadCloudIcon, { className: "text-surface-accent-400 mb-2 w-8 h-8" }),
103
+ /* @__PURE__ */ jsx(Typography, {
104
+ variant: "label",
105
+ children: "Drop files here or click to browse"
106
+ }),
107
+ /* @__PURE__ */ jsx(Typography, {
108
+ variant: "caption",
109
+ color: "secondary",
110
+ children: "Any file type supported"
111
+ })
112
+ ]
113
+ })
114
+ }),
115
+ error && /* @__PURE__ */ jsx(Typography, {
116
+ variant: "caption",
117
+ className: "text-red-500 block whitespace-pre-line",
118
+ children: error
119
+ }),
120
+ selectedFiles.length > 0 && /* @__PURE__ */ jsxs("div", {
121
+ className: "space-y-2",
122
+ children: [/* @__PURE__ */ jsxs(Typography, {
123
+ variant: "caption",
124
+ color: "secondary",
125
+ children: [
126
+ "Selected files (",
127
+ selectedFiles.length,
128
+ ")"
129
+ ]
130
+ }), /* @__PURE__ */ jsx("div", {
131
+ className: "max-h-40 overflow-auto space-y-1",
132
+ children: selectedFiles.map((file, index) => /* @__PURE__ */ jsxs("div", {
133
+ className: "flex items-center justify-between p-2 rounded bg-surface-100 dark:bg-surface-800",
134
+ children: [/* @__PURE__ */ jsxs("div", {
135
+ className: "flex-1 min-w-0 mr-2",
136
+ children: [/* @__PURE__ */ jsx(Typography, {
137
+ variant: "body2",
138
+ className: "truncate",
139
+ children: file.name
140
+ }), /* @__PURE__ */ jsx(Typography, {
141
+ variant: "caption",
142
+ color: "secondary",
143
+ children: formatFileSize(file.size)
144
+ })]
145
+ }), /* @__PURE__ */ jsx(IconButton, {
146
+ size: "small",
147
+ onClick: (e) => {
148
+ e.stopPropagation();
149
+ handleRemoveFile(index);
150
+ },
151
+ disabled: uploading,
152
+ children: /* @__PURE__ */ jsx(XIcon, { size: 14 })
153
+ })]
154
+ }, `${file.name}-${index}`))
155
+ })]
156
+ })
157
+ ]
158
+ }),
159
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
160
+ variant: "text",
161
+ onClick: handleClose,
162
+ disabled: uploading,
163
+ children: "Cancel"
164
+ }), /* @__PURE__ */ jsx(Button, {
165
+ variant: "filled",
166
+ onClick: handleUpload,
167
+ disabled: selectedFiles.length === 0 || uploading,
168
+ startIcon: uploading ? /* @__PURE__ */ jsx(CircularProgress, { size: "smallest" }) : /* @__PURE__ */ jsx(UploadCloudIcon, { size: 14 }),
169
+ children: uploading ? "Uploading..." : `Upload${selectedFiles.length > 0 ? ` (${selectedFiles.length})` : ""}`
170
+ })] })
171
+ ]
172
+ });
173
+ }
174
+ function FilePreviewPanel({ file, onClose, onDelete, downloadUrl }) {
175
+ file.contentType?.startsWith("image/");
176
+ file.contentType?.startsWith("video/");
177
+ file.contentType?.startsWith("audio/");
178
+ const FileIconComponent = getFileIcon(file.contentType);
179
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
180
+ const [urlCopied, setUrlCopied] = useState(false);
181
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
182
+ className: cls("flex flex-col h-full border-l", defaultBorderMixin, "bg-white dark:bg-surface-800"),
183
+ children: [
184
+ /* @__PURE__ */ jsxs("div", {
185
+ className: cls("flex items-center justify-between p-3 border-b shrink-0", defaultBorderMixin),
186
+ children: [/* @__PURE__ */ jsx(Typography, {
187
+ variant: "body2",
188
+ className: "font-medium truncate flex-1 mr-2",
189
+ children: file.name
190
+ }), /* @__PURE__ */ jsxs("div", {
191
+ className: "flex items-center gap-0.5",
192
+ children: [
193
+ downloadUrl && /* @__PURE__ */ jsx(Tooltip, {
194
+ title: "Download",
195
+ children: /* @__PURE__ */ jsx(IconButton, {
196
+ size: "small",
197
+ onClick: () => window.open(downloadUrl, "_blank"),
198
+ children: /* @__PURE__ */ jsx(DownloadIcon, { size: iconSize.smallest })
199
+ })
200
+ }),
201
+ /* @__PURE__ */ jsx(Tooltip, {
202
+ title: "Delete",
203
+ children: /* @__PURE__ */ jsx(IconButton, {
204
+ size: "small",
205
+ onClick: () => setDeleteDialogOpen(true),
206
+ className: "text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20",
207
+ children: /* @__PURE__ */ jsx(Trash2Icon, { size: iconSize.smallest })
208
+ })
209
+ }),
210
+ /* @__PURE__ */ jsx(IconButton, {
211
+ size: "small",
212
+ onClick: onClose,
213
+ children: /* @__PURE__ */ jsx(XIcon, { size: iconSize.smallest })
214
+ })
215
+ ]
216
+ })]
217
+ }),
218
+ /* @__PURE__ */ jsx("div", {
219
+ className: "flex-1 overflow-auto",
220
+ children: /* @__PURE__ */ jsx("div", {
221
+ className: cls("flex flex-col items-center justify-center min-h-[200px] p-4 bg-surface-50 dark:bg-surface-800 border-b", defaultBorderMixin),
222
+ children: (() => {
223
+ const ext = getExtension(file.name)?.toLowerCase() || "";
224
+ const isImage = file.contentType?.startsWith("image/") || [
225
+ "jpg",
226
+ "jpeg",
227
+ "png",
228
+ "gif",
229
+ "webp",
230
+ "svg"
231
+ ].includes(ext);
232
+ const isVideo = file.contentType?.startsWith("video/") || [
233
+ "mp4",
234
+ "webm",
235
+ "ogg",
236
+ "mov"
237
+ ].includes(ext);
238
+ const isAudio = file.contentType?.startsWith("audio/") || [
239
+ "mp3",
240
+ "wav",
241
+ "ogg",
242
+ "m4a"
243
+ ].includes(ext);
244
+ const downloadUrl = file.downloadUrl;
245
+ if (isImage && downloadUrl) return /* @__PURE__ */ jsx("img", {
246
+ src: downloadUrl,
247
+ alt: file.name,
248
+ className: "max-w-full max-h-[400px] object-contain rounded-md shadow-sm"
249
+ });
250
+ else if (isVideo && downloadUrl) return /* @__PURE__ */ jsx("video", {
251
+ src: downloadUrl,
252
+ className: "max-w-full max-h-[400px] rounded-md",
253
+ controls: true
254
+ });
255
+ else if (isAudio && downloadUrl) return /* @__PURE__ */ jsxs("div", {
256
+ className: "flex flex-col items-center gap-4",
257
+ children: [/* @__PURE__ */ jsx(Music2Icon, { className: "text-surface-accent-400 w-10 h-10" }), /* @__PURE__ */ jsx("audio", {
258
+ src: downloadUrl,
259
+ controls: true,
260
+ className: "w-full max-w-xs"
261
+ })]
262
+ });
263
+ else return /* @__PURE__ */ jsxs("div", {
264
+ className: "flex flex-col items-center gap-3 text-surface-accent-400",
265
+ children: [/* @__PURE__ */ jsx(FileIconComponent, { className: "w-10 h-10" }), /* @__PURE__ */ jsx(Typography, {
266
+ variant: "caption",
267
+ className: "text-text-disabled dark:text-text-disabled-dark",
268
+ children: "No preview available"
269
+ })]
270
+ });
271
+ })()
272
+ })
273
+ }),
274
+ /* @__PURE__ */ jsxs("div", {
275
+ className: "p-4 space-y-3",
276
+ children: [
277
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Typography, {
278
+ variant: "caption",
279
+ className: "text-text-disabled dark:text-text-disabled-dark text-[10px] uppercase tracking-wider font-bold mb-1 block",
280
+ children: "File Info"
281
+ }) }),
282
+ /* @__PURE__ */ jsxs("div", {
283
+ className: "grid grid-cols-2 gap-3",
284
+ children: [
285
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
286
+ variant: "caption",
287
+ className: "text-surface-accent-500 text-[11px]",
288
+ children: "Name"
289
+ }), /* @__PURE__ */ jsx(Typography, {
290
+ variant: "body2",
291
+ className: "text-[13px] break-all",
292
+ children: file.name
293
+ })] }),
294
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
295
+ variant: "caption",
296
+ className: "text-surface-accent-500 text-[11px]",
297
+ children: "Type"
298
+ }), /* @__PURE__ */ jsx(Typography, {
299
+ variant: "body2",
300
+ className: "text-[13px]",
301
+ children: file.contentType || "Unknown"
302
+ })] }),
303
+ file.size !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
304
+ variant: "caption",
305
+ className: "text-surface-accent-500 text-[11px]",
306
+ children: "Size"
307
+ }), /* @__PURE__ */ jsx(Typography, {
308
+ variant: "body2",
309
+ className: "text-[13px]",
310
+ children: formatFileSize(file.size)
311
+ })] }),
312
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
313
+ variant: "caption",
314
+ className: "text-surface-accent-500 text-[11px]",
315
+ children: "Extension"
316
+ }), /* @__PURE__ */ jsx(Typography, {
317
+ variant: "body2",
318
+ className: "text-[13px] font-mono",
319
+ children: getExtension(file.name) || "—"
320
+ })] }),
321
+ /* @__PURE__ */ jsxs("div", {
322
+ className: "col-span-2",
323
+ children: [/* @__PURE__ */ jsx(Typography, {
324
+ variant: "caption",
325
+ className: "text-surface-accent-500 text-[11px]",
326
+ children: "Path"
327
+ }), /* @__PURE__ */ jsx(Typography, {
328
+ variant: "body2",
329
+ className: "text-[13px] font-mono break-all",
330
+ children: file.fullPath
331
+ })]
332
+ })
333
+ ]
334
+ }),
335
+ downloadUrl && /* @__PURE__ */ jsxs("div", {
336
+ className: "pt-2",
337
+ children: [/* @__PURE__ */ jsx(Typography, {
338
+ variant: "caption",
339
+ className: "text-surface-accent-500 text-[11px] block mb-1",
340
+ children: "URL"
341
+ }), /* @__PURE__ */ jsxs("div", {
342
+ className: cls("flex items-center gap-2 p-2 rounded cursor-pointer transition-colors", "bg-surface-100 dark:bg-surface-800 hover:bg-surface-200 dark:hover:bg-surface-700"),
343
+ onClick: () => {
344
+ const fullUrl = downloadUrl.startsWith("http") ? downloadUrl : `${window.location.origin}${downloadUrl.startsWith("/") ? "" : "/"}${downloadUrl}`;
345
+ navigator.clipboard.writeText(fullUrl).then(() => {
346
+ setUrlCopied(true);
347
+ setTimeout(() => setUrlCopied(false), 2e3);
348
+ });
349
+ },
350
+ children: [/* @__PURE__ */ jsx(Typography, {
351
+ variant: "caption",
352
+ className: "font-mono text-[11px] truncate flex-1 min-w-0 text-primary",
353
+ children: (() => {
354
+ return downloadUrl.startsWith("http") ? downloadUrl : `${window.location.origin}${downloadUrl.startsWith("/") ? "" : "/"}${downloadUrl}`;
355
+ })()
356
+ }), /* @__PURE__ */ jsx(Tooltip, {
357
+ title: urlCopied ? "Copied!" : "Copy URL",
358
+ children: /* @__PURE__ */ jsx("div", {
359
+ className: "shrink-0",
360
+ children: urlCopied ? /* @__PURE__ */ jsx(CheckIcon, {
361
+ size: 14,
362
+ className: "text-green-500"
363
+ }) : /* @__PURE__ */ jsx(CopyIcon, {
364
+ size: 14,
365
+ className: "text-surface-accent-400"
366
+ })
367
+ })
368
+ })]
369
+ })]
370
+ })
371
+ ]
372
+ })
373
+ ]
374
+ }), /* @__PURE__ */ jsxs(Dialog, {
375
+ open: deleteDialogOpen,
376
+ onOpenChange: setDeleteDialogOpen,
377
+ children: [
378
+ /* @__PURE__ */ jsx(DialogTitle, {
379
+ hidden: true,
380
+ children: "Delete File"
381
+ }),
382
+ /* @__PURE__ */ jsxs(DialogContent, { children: [/* @__PURE__ */ jsx(Typography, {
383
+ variant: "subtitle1",
384
+ className: "mb-2",
385
+ children: "Delete File?"
386
+ }), /* @__PURE__ */ jsxs(Typography, {
387
+ className: "text-surface-accent-600 dark:text-surface-accent-400",
388
+ children: [
389
+ "Are you sure you want to delete \"",
390
+ file.name,
391
+ "\"? This action cannot be undone."
392
+ ]
393
+ })] }),
394
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
395
+ variant: "text",
396
+ onClick: () => setDeleteDialogOpen(false),
397
+ children: "Cancel"
398
+ }), /* @__PURE__ */ jsx(Button, {
399
+ variant: "filled",
400
+ color: "error",
401
+ onClick: () => {
402
+ setDeleteDialogOpen(false);
403
+ onDelete();
404
+ },
405
+ children: "Delete"
406
+ })] })
407
+ ]
408
+ })] });
409
+ }
410
+ var StorageView = () => {
411
+ const storageSource = useStorageSource();
412
+ const snackbarController = useSnackbarController();
413
+ const [searchParams, setSearchParams] = useSearchParams();
414
+ const currentPath = searchParams.get("path") || "";
415
+ const [loading, setLoading] = useState(true);
416
+ const [error, setError] = useState(null);
417
+ const [folders, setFolders] = useState([]);
418
+ const [files, setFiles] = useState([]);
419
+ const [selectedFile, setSelectedFile] = useState(null);
420
+ const [selectedDownloadUrl, setSelectedDownloadUrl] = useState(null);
421
+ const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
422
+ const [viewMode, setViewMode] = useState("grid");
423
+ const [selectedPaths, setSelectedPaths] = useState(/* @__PURE__ */ new Set());
424
+ const lastClickedRef = useRef(null);
425
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
426
+ const [deleteDialogTarget, setDeleteDialogTarget] = useState(null);
427
+ const [deleting, setDeleting] = useState(false);
428
+ const [newFolderDialogOpen, setNewFolderDialogOpen] = useState(false);
429
+ const [newFolderName, setNewFolderName] = useState("");
430
+ const [creatingFolder, setCreatingFolder] = useState(false);
431
+ const apiConfig = useApiConfig();
432
+ const storageSourceRef = React.useRef(storageSource);
433
+ useEffect(() => {
434
+ storageSourceRef.current = storageSource;
435
+ }, [storageSource]);
436
+ const fetchContents = useCallback(async (path) => {
437
+ setLoading(true);
438
+ setError(null);
439
+ try {
440
+ const result = await storageSourceRef.current.listObjects(path);
441
+ const folderItems = (result.prefixes ?? []).map((ref) => ({
442
+ name: ref.name,
443
+ fullPath: ref.fullPath,
444
+ isFolder: true
445
+ }));
446
+ const fileItems = await Promise.all((result.items ?? []).map(async (ref) => {
447
+ try {
448
+ const downloadConfig = await storageSourceRef.current.getSignedUrl(ref.fullPath);
449
+ return {
450
+ name: ref.name,
451
+ fullPath: ref.fullPath,
452
+ isFolder: false,
453
+ size: downloadConfig.metadata?.size,
454
+ contentType: downloadConfig.metadata?.contentType,
455
+ downloadUrl: downloadConfig.url ?? void 0
456
+ };
457
+ } catch {
458
+ return {
459
+ name: ref.name,
460
+ fullPath: ref.fullPath,
461
+ isFolder: false
462
+ };
463
+ }
464
+ }));
465
+ setFolders(folderItems);
466
+ setFiles(fileItems);
467
+ } catch (e) {
468
+ console.error("Storage list error:", e);
469
+ setError(e instanceof Error ? e.message : String(e));
470
+ } finally {
471
+ setLoading(false);
472
+ }
473
+ }, []);
474
+ useEffect(() => {
475
+ fetchContents(currentPath);
476
+ }, [currentPath, fetchContents]);
477
+ const handleNavigate = useCallback((path) => {
478
+ if (!path) setSearchParams({});
479
+ else setSearchParams({ path });
480
+ setSelectedFile(null);
481
+ setSelectedDownloadUrl(null);
482
+ setSelectedPaths(/* @__PURE__ */ new Set());
483
+ lastClickedRef.current = null;
484
+ }, [setSearchParams]);
485
+ const handleNavigateUp = useCallback(() => {
486
+ const parts = currentPath.split("/").filter(Boolean);
487
+ parts.pop();
488
+ handleNavigate(parts.join("/"));
489
+ }, [currentPath, handleNavigate]);
490
+ const allItems = useMemo(() => [...folders, ...files], [folders, files]);
491
+ const handleItemClick = useCallback((item, e) => {
492
+ const path = item.fullPath;
493
+ if (e.metaKey || e.ctrlKey) {
494
+ setSelectedPaths((prev) => {
495
+ const next = new Set(prev);
496
+ if (next.has(path)) next.delete(path);
497
+ else next.add(path);
498
+ return next;
499
+ });
500
+ lastClickedRef.current = path;
501
+ } else if (e.shiftKey && lastClickedRef.current) {
502
+ const allPaths = allItems.map((i) => i.fullPath);
503
+ const anchorIdx = allPaths.indexOf(lastClickedRef.current);
504
+ const currentIdx = allPaths.indexOf(path);
505
+ if (anchorIdx >= 0 && currentIdx >= 0) {
506
+ const [start, end] = anchorIdx < currentIdx ? [anchorIdx, currentIdx] : [currentIdx, anchorIdx];
507
+ setSelectedPaths((prev) => {
508
+ const next = new Set(prev);
509
+ for (let i = start; i <= end; i++) next.add(allPaths[i]);
510
+ return next;
511
+ });
512
+ }
513
+ } else {
514
+ setSelectedPaths(new Set([path]));
515
+ lastClickedRef.current = path;
516
+ if (!item.isFolder) {
517
+ setSelectedFile(item);
518
+ if (item.downloadUrl) setSelectedDownloadUrl(item.downloadUrl);
519
+ else storageSourceRef.current.getSignedUrl(item.fullPath).then((config) => setSelectedDownloadUrl(config.url)).catch(() => setSelectedDownloadUrl(null));
520
+ } else {
521
+ setSelectedFile(null);
522
+ setSelectedDownloadUrl(null);
523
+ }
524
+ }
525
+ }, [allItems]);
526
+ const handleItemDoubleClick = useCallback((item) => {
527
+ if (item.isFolder) handleNavigate(item.fullPath);
528
+ else {
529
+ setSelectedFile(item);
530
+ if (item.downloadUrl) setSelectedDownloadUrl(item.downloadUrl);
531
+ else storageSourceRef.current.getSignedUrl(item.fullPath).then((config) => setSelectedDownloadUrl(config.url)).catch(() => setSelectedDownloadUrl(null));
532
+ }
533
+ }, [handleNavigate]);
534
+ const handleUpload = useCallback(async (uploadFiles) => {
535
+ for (const file of uploadFiles) {
536
+ const key = currentPath ? `${currentPath}/${file.name}` : file.name;
537
+ await storageSourceRef.current.putObject({
538
+ file,
539
+ key
540
+ });
541
+ }
542
+ snackbarController.open({
543
+ type: "success",
544
+ message: `${uploadFiles.length} file${uploadFiles.length > 1 ? "s" : ""} uploaded successfully`
545
+ });
546
+ await fetchContents(currentPath);
547
+ }, [
548
+ currentPath,
549
+ snackbarController,
550
+ fetchContents
551
+ ]);
552
+ const handleCreateFolder = useCallback(async () => {
553
+ if (!newFolderName.trim() || !apiConfig?.apiUrl) return;
554
+ const name = newFolderName.trim();
555
+ if (name.includes("/") || name.includes("\\")) {
556
+ snackbarController.open({
557
+ type: "error",
558
+ message: "Folder name cannot contain slashes"
559
+ });
560
+ return;
561
+ }
562
+ if (folders.find((f) => f.name === name)) {
563
+ snackbarController.open({
564
+ type: "error",
565
+ message: `Folder "${name}" already exists`
566
+ });
567
+ return;
568
+ }
569
+ setCreatingFolder(true);
570
+ try {
571
+ const folderPath = currentPath ? `default/${currentPath}/${name}` : `default/${name}`;
572
+ const token = apiConfig.getAuthToken ? await apiConfig.getAuthToken() : null;
573
+ const response = await fetch(`${apiConfig.apiUrl}/api/storage/folder`, {
574
+ method: "POST",
575
+ headers: {
576
+ "Content-Type": "application/json",
577
+ ...token ? { "Authorization": `Bearer ${token}` } : {}
578
+ },
579
+ body: JSON.stringify({ path: folderPath })
580
+ });
581
+ if (!response.ok) {
582
+ const err = await response.json().catch(() => ({ error: "Failed to create folder" }));
583
+ throw new Error(err.error || "Failed to create folder");
584
+ }
585
+ snackbarController.open({
586
+ type: "success",
587
+ message: `Folder "${name}" created`
588
+ });
589
+ setNewFolderDialogOpen(false);
590
+ setNewFolderName("");
591
+ await fetchContents(currentPath);
592
+ } catch (e) {
593
+ snackbarController.open({
594
+ type: "error",
595
+ message: e instanceof Error ? e.message : String(e)
596
+ });
597
+ } finally {
598
+ setCreatingFolder(false);
599
+ }
600
+ }, [
601
+ newFolderName,
602
+ currentPath,
603
+ apiConfig,
604
+ snackbarController,
605
+ fetchContents,
606
+ folders
607
+ ]);
608
+ const { getRootProps: getDropRootProps, getInputProps: getDropInputProps, isDragActive } = useDropzone({
609
+ onDrop: useCallback(async (droppedFiles) => {
610
+ if (droppedFiles.length === 0) return;
611
+ try {
612
+ for (const file of droppedFiles) {
613
+ const key = currentPath ? `${currentPath}/${file.name}` : file.name;
614
+ await storageSourceRef.current.putObject({
615
+ file,
616
+ key
617
+ });
618
+ }
619
+ snackbarController.open({
620
+ type: "success",
621
+ message: `${droppedFiles.length} file${droppedFiles.length > 1 ? "s" : ""} uploaded successfully`
622
+ });
623
+ await fetchContents(currentPath);
624
+ } catch (e) {
625
+ snackbarController.open({
626
+ type: "error",
627
+ message: e instanceof Error ? e.message : String(e)
628
+ });
629
+ }
630
+ }, [
631
+ currentPath,
632
+ snackbarController,
633
+ fetchContents
634
+ ]),
635
+ noClick: true,
636
+ noKeyboard: true,
637
+ noDragEventsBubbling: true
638
+ });
639
+ const deleteFolderRecursive = useCallback(async (prefix) => {
640
+ const result = await storageSourceRef.current.listObjects(prefix);
641
+ for (const item of result.items ?? []) await storageSourceRef.current.deleteObject(item.fullPath);
642
+ for (const sub of result.prefixes ?? []) await deleteFolderRecursive(sub.fullPath);
643
+ try {
644
+ await storageSourceRef.current.deleteObject(prefix);
645
+ } catch {}
646
+ }, []);
647
+ const handleDeleteFile = useCallback(async (file) => {
648
+ try {
649
+ if (file.isFolder) await deleteFolderRecursive(file.fullPath);
650
+ else await storageSourceRef.current.deleteObject(file.fullPath);
651
+ snackbarController.open({
652
+ type: "success",
653
+ message: `"${file.name}" deleted`
654
+ });
655
+ setSelectedFile(null);
656
+ setSelectedDownloadUrl(null);
657
+ setSelectedPaths((prev) => {
658
+ const next = new Set(prev);
659
+ next.delete(file.fullPath);
660
+ return next;
661
+ });
662
+ fetchContents(currentPath);
663
+ } catch (e) {
664
+ snackbarController.open({
665
+ type: "error",
666
+ message: e instanceof Error ? e.message : String(e)
667
+ });
668
+ }
669
+ }, [
670
+ currentPath,
671
+ snackbarController,
672
+ fetchContents,
673
+ deleteFolderRecursive
674
+ ]);
675
+ const handleBulkDelete = useCallback(async () => {
676
+ setDeleting(true);
677
+ try {
678
+ const items = allItems.filter((i) => selectedPaths.has(i.fullPath));
679
+ for (const item of items) if (item.isFolder) await deleteFolderRecursive(item.fullPath);
680
+ else await storageSourceRef.current.deleteObject(item.fullPath);
681
+ snackbarController.open({
682
+ type: "success",
683
+ message: `${items.length} item${items.length !== 1 ? "s" : ""} deleted`
684
+ });
685
+ setSelectedPaths(/* @__PURE__ */ new Set());
686
+ setSelectedFile(null);
687
+ setSelectedDownloadUrl(null);
688
+ await fetchContents(currentPath);
689
+ } catch (e) {
690
+ snackbarController.open({
691
+ type: "error",
692
+ message: e instanceof Error ? e.message : String(e)
693
+ });
694
+ } finally {
695
+ setDeleting(false);
696
+ setDeleteDialogOpen(false);
697
+ setDeleteDialogTarget(null);
698
+ }
699
+ }, [
700
+ allItems,
701
+ selectedPaths,
702
+ currentPath,
703
+ snackbarController,
704
+ fetchContents,
705
+ deleteFolderRecursive
706
+ ]);
707
+ const handleConfirmDeleteFolder = useCallback(async () => {
708
+ if (!deleteDialogTarget || deleteDialogTarget === "selection") return;
709
+ setDeleting(true);
710
+ try {
711
+ await deleteFolderRecursive(deleteDialogTarget.fullPath);
712
+ snackbarController.open({
713
+ type: "success",
714
+ message: `Folder "${deleteDialogTarget.name}" deleted`
715
+ });
716
+ setSelectedPaths((prev) => {
717
+ const next = new Set(prev);
718
+ next.delete(deleteDialogTarget.fullPath);
719
+ return next;
720
+ });
721
+ await fetchContents(currentPath);
722
+ } catch (e) {
723
+ snackbarController.open({
724
+ type: "error",
725
+ message: e instanceof Error ? e.message : String(e)
726
+ });
727
+ } finally {
728
+ setDeleting(false);
729
+ setDeleteDialogOpen(false);
730
+ setDeleteDialogTarget(null);
731
+ }
732
+ }, [
733
+ deleteDialogTarget,
734
+ currentPath,
735
+ snackbarController,
736
+ fetchContents,
737
+ deleteFolderRecursive
738
+ ]);
739
+ const handleSelectAll = useCallback(() => {
740
+ if (selectedPaths.size === allItems.length) setSelectedPaths(/* @__PURE__ */ new Set());
741
+ else setSelectedPaths(new Set(allItems.map((i) => i.fullPath)));
742
+ }, [allItems, selectedPaths]);
743
+ useEffect(() => {
744
+ const handler = (e) => {
745
+ if (deleteDialogOpen || uploadDialogOpen || newFolderDialogOpen) return;
746
+ if ((e.metaKey || e.ctrlKey) && e.key === "a") {
747
+ e.preventDefault();
748
+ handleSelectAll();
749
+ }
750
+ if (e.key === "Escape") {
751
+ setSelectedPaths(/* @__PURE__ */ new Set());
752
+ setSelectedFile(null);
753
+ setSelectedDownloadUrl(null);
754
+ }
755
+ if ((e.key === "Delete" || e.key === "Backspace") && selectedPaths.size > 0 && !e.metaKey && !e.ctrlKey) {
756
+ if (e.target?.tagName === "INPUT" || e.target?.tagName === "TEXTAREA") return;
757
+ e.preventDefault();
758
+ setDeleteDialogTarget("selection");
759
+ setDeleteDialogOpen(true);
760
+ }
761
+ };
762
+ window.addEventListener("keydown", handler);
763
+ return () => window.removeEventListener("keydown", handler);
764
+ }, [
765
+ handleSelectAll,
766
+ selectedPaths,
767
+ deleteDialogOpen,
768
+ uploadDialogOpen,
769
+ newFolderDialogOpen
770
+ ]);
771
+ const handleRefresh = useCallback(() => {
772
+ fetchContents(currentPath);
773
+ }, [currentPath, fetchContents]);
774
+ const segments = breadcrumbSegments(currentPath);
775
+ const renderContents = () => {
776
+ if (loading) return /* @__PURE__ */ jsx("div", {
777
+ className: "flex-grow flex items-center justify-center",
778
+ children: /* @__PURE__ */ jsxs("div", {
779
+ className: "text-center",
780
+ children: [/* @__PURE__ */ jsx(CircularProgress, { size: "medium" }), /* @__PURE__ */ jsx(Typography, {
781
+ variant: "body2",
782
+ className: "mt-4 text-text-secondary dark:text-text-secondary-dark font-mono tracking-tight animate-pulse",
783
+ children: "Loading..."
784
+ })]
785
+ })
786
+ });
787
+ if (error) return /* @__PURE__ */ jsx("div", {
788
+ className: "flex-grow flex items-center justify-center p-6 overflow-auto",
789
+ children: /* @__PURE__ */ jsx(ErrorView, {
790
+ title: "Error loading storage",
791
+ error,
792
+ onRetry: handleRefresh
793
+ })
794
+ });
795
+ if (allItems.length === 0) return /* @__PURE__ */ jsx("div", {
796
+ className: "flex-grow flex items-center justify-center text-text-disabled dark:text-text-disabled-dark",
797
+ children: /* @__PURE__ */ jsxs("div", {
798
+ className: "text-center",
799
+ children: [
800
+ /* @__PURE__ */ jsx("svg", {
801
+ className: "w-12 h-12 mx-auto mb-4 opacity-50",
802
+ fill: "none",
803
+ stroke: "currentColor",
804
+ viewBox: "0 0 24 24",
805
+ children: /* @__PURE__ */ jsx("path", {
806
+ strokeLinecap: "round",
807
+ strokeLinejoin: "round",
808
+ strokeWidth: 1,
809
+ d: "M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
810
+ })
811
+ }),
812
+ /* @__PURE__ */ jsx(Typography, {
813
+ variant: "body2",
814
+ children: "This folder is empty"
815
+ }),
816
+ /* @__PURE__ */ jsxs("div", {
817
+ className: "flex items-center gap-2 mt-3",
818
+ children: [/* @__PURE__ */ jsxs(Button, {
819
+ variant: "text",
820
+ onClick: () => {
821
+ setNewFolderName("");
822
+ setNewFolderDialogOpen(true);
823
+ },
824
+ children: [/* @__PURE__ */ jsx(FolderPlusIcon, { size: iconSize.smallest }), "New folder"]
825
+ }), /* @__PURE__ */ jsxs(Button, {
826
+ onClick: () => setUploadDialogOpen(true),
827
+ children: [/* @__PURE__ */ jsx(PlusIcon, { size: iconSize.smallest }), "Upload files"]
828
+ })]
829
+ })
830
+ ]
831
+ })
832
+ });
833
+ if (viewMode === "list") return /* @__PURE__ */ jsx("div", {
834
+ className: "flex-grow overflow-auto",
835
+ children: /* @__PURE__ */ jsxs("table", {
836
+ className: "w-full",
837
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", {
838
+ className: cls("border-b text-left text-[10px] uppercase tracking-wider text-text-disabled dark:text-text-disabled-dark", defaultBorderMixin),
839
+ children: [
840
+ /* @__PURE__ */ jsx("th", {
841
+ className: "pl-3 pr-0 py-2 w-8",
842
+ children: /* @__PURE__ */ jsx(Checkbox, {
843
+ size: "small",
844
+ checked: allItems.length > 0 && selectedPaths.size === allItems.length,
845
+ indeterminate: selectedPaths.size > 0 && selectedPaths.size < allItems.length,
846
+ onCheckedChange: handleSelectAll
847
+ })
848
+ }),
849
+ /* @__PURE__ */ jsx("th", {
850
+ className: "px-2 py-2 font-bold",
851
+ children: "Name"
852
+ }),
853
+ /* @__PURE__ */ jsx("th", {
854
+ className: "px-4 py-2 font-bold w-24",
855
+ children: "Type"
856
+ }),
857
+ /* @__PURE__ */ jsx("th", {
858
+ className: "px-4 py-2 font-bold w-24 text-right",
859
+ children: "Size"
860
+ }),
861
+ /* @__PURE__ */ jsx("th", { className: "px-2 py-2 w-10" })
862
+ ]
863
+ }) }), /* @__PURE__ */ jsxs("tbody", { children: [folders.map((folder) => {
864
+ const isChecked = selectedPaths.has(folder.fullPath);
865
+ return /* @__PURE__ */ jsxs("tr", {
866
+ "data-storage-item": true,
867
+ className: cls("cursor-pointer transition-colors border-b group", defaultBorderMixin, isChecked ? "bg-primary/5 dark:bg-primary/10" : "hover:bg-surface-100 dark:hover:bg-surface-800"),
868
+ onClick: (e) => handleItemClick(folder, e),
869
+ onDoubleClick: () => handleItemDoubleClick(folder),
870
+ children: [
871
+ /* @__PURE__ */ jsx("td", {
872
+ className: "pl-3 pr-0 py-2.5",
873
+ onClick: (e) => e.stopPropagation(),
874
+ children: /* @__PURE__ */ jsx(Checkbox, {
875
+ size: "small",
876
+ checked: isChecked,
877
+ onCheckedChange: () => {
878
+ setSelectedPaths((prev) => {
879
+ const next = new Set(prev);
880
+ if (next.has(folder.fullPath)) next.delete(folder.fullPath);
881
+ else next.add(folder.fullPath);
882
+ return next;
883
+ });
884
+ }
885
+ })
886
+ }),
887
+ /* @__PURE__ */ jsx("td", {
888
+ className: "px-2 py-2.5",
889
+ children: /* @__PURE__ */ jsxs("div", {
890
+ className: "flex items-center gap-2",
891
+ children: [/* @__PURE__ */ jsx(FolderIcon, {
892
+ size: iconSize.smallest,
893
+ className: "text-amber-500 dark:text-amber-400 shrink-0"
894
+ }), /* @__PURE__ */ jsx(Typography, {
895
+ variant: "body2",
896
+ className: "text-[13px] font-medium truncate",
897
+ children: folder.name
898
+ })]
899
+ })
900
+ }),
901
+ /* @__PURE__ */ jsx("td", {
902
+ className: "px-4 py-2.5",
903
+ children: /* @__PURE__ */ jsx(Typography, {
904
+ variant: "caption",
905
+ className: "text-text-secondary dark:text-text-secondary-dark",
906
+ children: "Folder"
907
+ })
908
+ }),
909
+ /* @__PURE__ */ jsx("td", {
910
+ className: "px-4 py-2.5 text-right",
911
+ children: /* @__PURE__ */ jsx(Typography, {
912
+ variant: "caption",
913
+ className: "text-text-disabled dark:text-text-disabled-dark",
914
+ children: "—"
915
+ })
916
+ }),
917
+ /* @__PURE__ */ jsx("td", { className: "px-2 py-2.5" })
918
+ ]
919
+ }, folder.fullPath);
920
+ }), files.map((file) => {
921
+ const FileIconComp = getFileIcon(file.contentType);
922
+ const isChecked = selectedPaths.has(file.fullPath);
923
+ return /* @__PURE__ */ jsxs("tr", {
924
+ "data-storage-item": true,
925
+ className: cls("cursor-pointer transition-colors border-b group", defaultBorderMixin, isChecked ? "bg-primary/5 dark:bg-primary/10" : "hover:bg-surface-100 dark:hover:bg-surface-800"),
926
+ onClick: (e) => handleItemClick(file, e),
927
+ onDoubleClick: () => handleItemDoubleClick(file),
928
+ children: [
929
+ /* @__PURE__ */ jsx("td", {
930
+ className: "pl-3 pr-0 py-2.5",
931
+ onClick: (e) => e.stopPropagation(),
932
+ children: /* @__PURE__ */ jsx(Checkbox, {
933
+ size: "small",
934
+ checked: isChecked,
935
+ onCheckedChange: () => {
936
+ setSelectedPaths((prev) => {
937
+ const next = new Set(prev);
938
+ if (next.has(file.fullPath)) next.delete(file.fullPath);
939
+ else next.add(file.fullPath);
940
+ return next;
941
+ });
942
+ }
943
+ })
944
+ }),
945
+ /* @__PURE__ */ jsx("td", {
946
+ className: "px-2 py-2.5",
947
+ children: /* @__PURE__ */ jsxs("div", {
948
+ className: "flex items-center gap-2",
949
+ children: [/* @__PURE__ */ jsx(FileIconComp, {
950
+ size: iconSize.smallest,
951
+ className: "text-surface-accent-400 shrink-0"
952
+ }), /* @__PURE__ */ jsx(Typography, {
953
+ variant: "body2",
954
+ className: "text-[13px] truncate",
955
+ children: file.name
956
+ })]
957
+ })
958
+ }),
959
+ /* @__PURE__ */ jsx("td", {
960
+ className: "px-4 py-2.5",
961
+ children: /* @__PURE__ */ jsx(Typography, {
962
+ variant: "caption",
963
+ className: "text-text-secondary dark:text-text-secondary-dark",
964
+ children: getExtension(file.name) || file.contentType?.split("/")[1]?.toUpperCase() || "—"
965
+ })
966
+ }),
967
+ /* @__PURE__ */ jsx("td", {
968
+ className: "px-4 py-2.5 text-right",
969
+ children: /* @__PURE__ */ jsx(Typography, {
970
+ variant: "caption",
971
+ className: "text-text-secondary dark:text-text-secondary-dark font-mono text-[11px]",
972
+ children: file.size !== void 0 ? formatFileSize(file.size) : "—"
973
+ })
974
+ }),
975
+ /* @__PURE__ */ jsx("td", {
976
+ className: "px-2 py-2.5",
977
+ onClick: (e) => e.stopPropagation(),
978
+ children: /* @__PURE__ */ jsx(IconButton, {
979
+ size: "smallest",
980
+ className: "opacity-0 group-hover:opacity-100 transition-opacity",
981
+ onClick: () => handleDeleteFile(file),
982
+ children: /* @__PURE__ */ jsx(Trash2Icon, { size: 14 })
983
+ })
984
+ })
985
+ ]
986
+ }, file.fullPath);
987
+ })] })]
988
+ })
989
+ });
990
+ return /* @__PURE__ */ jsxs("div", {
991
+ className: "flex-grow overflow-auto p-4",
992
+ children: [folders.length > 0 && /* @__PURE__ */ jsxs("div", {
993
+ className: "mb-4",
994
+ children: [/* @__PURE__ */ jsx(Typography, {
995
+ variant: "caption",
996
+ className: "text-[10px] uppercase tracking-wider font-bold text-text-disabled dark:text-text-disabled-dark mb-2 block",
997
+ children: "Folders"
998
+ }), /* @__PURE__ */ jsx("div", {
999
+ className: "grid gap-3 grid-cols-[repeat(auto-fill,minmax(140px,1fr))]",
1000
+ children: folders.map((folder) => {
1001
+ return /* @__PURE__ */ jsxs("div", {
1002
+ "data-storage-item": true,
1003
+ className: cls("rounded-lg p-3 cursor-pointer border", "transition-colors duration-150", defaultBorderMixin, "hover:bg-surface-100 dark:hover:bg-surface-800 hover:shadow-sm", "flex items-center gap-2", selectedPaths.has(folder.fullPath) && "ring-2 ring-primary bg-primary/5 dark:bg-primary/10"),
1004
+ onClick: (e) => handleItemClick(folder, e),
1005
+ onDoubleClick: () => handleItemDoubleClick(folder),
1006
+ children: [/* @__PURE__ */ jsx(FolderIcon, {
1007
+ size: iconSize.smallest,
1008
+ className: "text-amber-500 dark:text-amber-400 shrink-0"
1009
+ }), /* @__PURE__ */ jsx(Typography, {
1010
+ variant: "body2",
1011
+ className: "text-[13px] font-medium truncate",
1012
+ children: folder.name
1013
+ })]
1014
+ }, folder.fullPath);
1015
+ })
1016
+ })]
1017
+ }), files.length > 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(Typography, {
1018
+ variant: "caption",
1019
+ className: "text-[10px] uppercase tracking-wider font-bold text-text-disabled dark:text-text-disabled-dark mb-2 block",
1020
+ children: [
1021
+ "Files (",
1022
+ files.length,
1023
+ ")"
1024
+ ]
1025
+ }), /* @__PURE__ */ jsx("div", {
1026
+ className: "grid gap-3 grid-cols-[repeat(auto-fill,minmax(140px,1fr))]",
1027
+ children: files.map((file) => {
1028
+ const FileIconComp = getFileIcon(file.contentType);
1029
+ const ext = getExtension(file.name)?.toLowerCase() || "";
1030
+ const isImage = file.contentType?.startsWith("image/") || [
1031
+ "jpg",
1032
+ "jpeg",
1033
+ "png",
1034
+ "gif",
1035
+ "webp",
1036
+ "svg"
1037
+ ].includes(ext);
1038
+ return /* @__PURE__ */ jsxs("div", {
1039
+ "data-storage-item": true,
1040
+ className: cls("rounded-lg overflow-hidden cursor-pointer border", "transition-shadow duration-150", defaultBorderMixin, "hover:shadow-md", selectedPaths.has(file.fullPath) && "ring-2 ring-primary"),
1041
+ onClick: (e) => handleItemClick(file, e),
1042
+ onDoubleClick: () => handleItemDoubleClick(file),
1043
+ children: [/* @__PURE__ */ jsxs("div", {
1044
+ className: "aspect-square relative overflow-hidden bg-surface-100 dark:bg-surface-800 flex items-center justify-center",
1045
+ children: [isImage && file.downloadUrl ? /* @__PURE__ */ jsx("img", {
1046
+ src: file.downloadUrl,
1047
+ alt: file.name,
1048
+ className: "w-full h-full object-cover",
1049
+ loading: "lazy"
1050
+ }) : /* @__PURE__ */ jsx(FileIconComp, { className: "text-surface-accent-400 dark:text-surface-accent-500 w-8 h-8" }), getExtension(file.name) && /* @__PURE__ */ jsx("div", {
1051
+ className: "absolute bottom-1.5 right-1.5 px-1.5 py-0.5 rounded text-[9px] font-bold uppercase bg-black/50 text-white backdrop-blur-sm",
1052
+ children: getExtension(file.name)
1053
+ })]
1054
+ }), /* @__PURE__ */ jsxs("div", {
1055
+ className: "p-2.5",
1056
+ children: [/* @__PURE__ */ jsx(Typography, {
1057
+ variant: "body2",
1058
+ className: "text-[12px] font-medium truncate text-surface-900 dark:text-white",
1059
+ children: file.name
1060
+ }), /* @__PURE__ */ jsx(Typography, {
1061
+ variant: "caption",
1062
+ color: "secondary",
1063
+ className: "truncate block mt-0.5 text-[11px]",
1064
+ children: file.size !== void 0 ? formatFileSize(file.size) : "—"
1065
+ })]
1066
+ })]
1067
+ }, file.fullPath);
1068
+ })
1069
+ })] })]
1070
+ });
1071
+ };
1072
+ return /* @__PURE__ */ jsxs("div", {
1073
+ className: "flex h-full w-full bg-white dark:bg-surface-800 overflow-hidden text-text-primary dark:text-text-primary-dark",
1074
+ children: [
1075
+ /* @__PURE__ */ jsxs("div", {
1076
+ className: "flex h-full w-full",
1077
+ children: [/* @__PURE__ */ jsxs("div", {
1078
+ className: "flex-grow flex flex-col min-w-0 h-full",
1079
+ children: [
1080
+ /* @__PURE__ */ jsxs("div", {
1081
+ className: cls("flex items-center justify-between pr-2 border-b bg-white dark:bg-surface-800 shrink-0 h-10", defaultBorderMixin),
1082
+ children: [/* @__PURE__ */ jsxs("div", {
1083
+ className: "flex items-center gap-1.5 flex-grow overflow-hidden px-3 py-2",
1084
+ children: [
1085
+ currentPath && /* @__PURE__ */ jsx(Tooltip, {
1086
+ title: "Go up",
1087
+ children: /* @__PURE__ */ jsx(IconButton, {
1088
+ size: "small",
1089
+ onClick: handleNavigateUp,
1090
+ children: /* @__PURE__ */ jsx(ArrowLeftIcon, { size: iconSize.smallest })
1091
+ })
1092
+ }),
1093
+ /* @__PURE__ */ jsx("div", {
1094
+ className: "flex items-center gap-0.5 overflow-x-auto no-scrollbar",
1095
+ children: segments.map((seg, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [i > 0 && /* @__PURE__ */ jsx(Typography, {
1096
+ variant: "caption",
1097
+ className: "text-text-disabled dark:text-text-disabled-dark mx-0.5",
1098
+ children: "/"
1099
+ }), /* @__PURE__ */ jsx(Button, {
1100
+ variant: "text",
1101
+ size: "small",
1102
+ className: cls("px-1.5 py-0.5 min-h-0 min-w-0 h-6 text-xs whitespace-nowrap normal-case font-normal", i === segments.length - 1 ? "text-text-primary dark:text-text-primary-dark font-medium" : "text-text-secondary dark:text-text-secondary-dark"),
1103
+ onClick: () => handleNavigate(seg.path),
1104
+ children: seg.label
1105
+ })] }, seg.path))
1106
+ }),
1107
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
1108
+ selectedPaths.size > 0 ? /* @__PURE__ */ jsxs("div", {
1109
+ className: "flex items-center gap-1.5 shrink-0",
1110
+ children: [
1111
+ /* @__PURE__ */ jsxs(Typography, {
1112
+ variant: "body2",
1113
+ className: "text-[13px] font-medium whitespace-nowrap",
1114
+ children: [selectedPaths.size, " selected"]
1115
+ }),
1116
+ /* @__PURE__ */ jsxs(Button, {
1117
+ size: "small",
1118
+ variant: "text",
1119
+ onClick: () => {
1120
+ setDeleteDialogTarget("selection");
1121
+ setDeleteDialogOpen(true);
1122
+ },
1123
+ children: [/* @__PURE__ */ jsx(Trash2Icon, {
1124
+ size: 14,
1125
+ className: "mr-1"
1126
+ }), "Delete"]
1127
+ }),
1128
+ /* @__PURE__ */ jsxs(Button, {
1129
+ size: "small",
1130
+ variant: "text",
1131
+ onClick: () => {
1132
+ setSelectedPaths(/* @__PURE__ */ new Set());
1133
+ setSelectedFile(null);
1134
+ setSelectedDownloadUrl(null);
1135
+ },
1136
+ children: [/* @__PURE__ */ jsx(XIcon, {
1137
+ size: 14,
1138
+ className: "mr-1"
1139
+ }), "Deselect"]
1140
+ })
1141
+ ]
1142
+ }) : !loading ? /* @__PURE__ */ jsxs(Chip, {
1143
+ size: "small",
1144
+ className: "shrink-0 text-[10px]",
1145
+ children: [
1146
+ files.length,
1147
+ " file",
1148
+ files.length !== 1 ? "s" : "",
1149
+ folders.length > 0 ? `, ${folders.length} folder${folders.length !== 1 ? "s" : ""}` : ""
1150
+ ]
1151
+ }) : null
1152
+ ]
1153
+ }), /* @__PURE__ */ jsxs("div", {
1154
+ className: "flex shrink-0 items-center justify-end gap-1.5 pr-1",
1155
+ children: [
1156
+ /* @__PURE__ */ jsx(Tooltip, {
1157
+ title: "Grid view",
1158
+ children: /* @__PURE__ */ jsx(IconButton, {
1159
+ size: "small",
1160
+ onClick: () => setViewMode("grid"),
1161
+ className: cls(viewMode === "grid" && "bg-surface-100 dark:bg-surface-800"),
1162
+ children: /* @__PURE__ */ jsx(LayoutGridIcon, { size: iconSize.smallest })
1163
+ })
1164
+ }),
1165
+ /* @__PURE__ */ jsx(Tooltip, {
1166
+ title: "List view",
1167
+ children: /* @__PURE__ */ jsx(IconButton, {
1168
+ size: "small",
1169
+ onClick: () => setViewMode("list"),
1170
+ className: cls(viewMode === "list" && "bg-surface-100 dark:bg-surface-800"),
1171
+ children: /* @__PURE__ */ jsx(ListIcon, { size: iconSize.smallest })
1172
+ })
1173
+ }),
1174
+ /* @__PURE__ */ jsx("div", { className: cls("h-4 w-px mx-0.5", defaultBorderMixin, "bg-surface-200 dark:bg-surface-700") }),
1175
+ /* @__PURE__ */ jsx(Tooltip, {
1176
+ title: "Refresh",
1177
+ children: /* @__PURE__ */ jsx(IconButton, {
1178
+ size: "small",
1179
+ onClick: handleRefresh,
1180
+ disabled: loading,
1181
+ children: /* @__PURE__ */ jsx(RefreshCwIcon, { size: iconSize.smallest })
1182
+ })
1183
+ }),
1184
+ /* @__PURE__ */ jsx(Tooltip, {
1185
+ title: "New folder",
1186
+ children: /* @__PURE__ */ jsx(IconButton, {
1187
+ size: "small",
1188
+ onClick: () => {
1189
+ setNewFolderName("");
1190
+ setNewFolderDialogOpen(true);
1191
+ },
1192
+ children: /* @__PURE__ */ jsx(FolderPlusIcon, { size: iconSize.smallest })
1193
+ })
1194
+ }),
1195
+ /* @__PURE__ */ jsxs(Button, {
1196
+ size: "small",
1197
+ color: "primary",
1198
+ onClick: () => setUploadDialogOpen(true),
1199
+ children: [/* @__PURE__ */ jsx(UploadCloudIcon, {
1200
+ size: iconSize.smallest,
1201
+ className: "mr-1"
1202
+ }), "Upload"]
1203
+ })
1204
+ ]
1205
+ })]
1206
+ }),
1207
+ /* @__PURE__ */ jsxs("div", {
1208
+ ...getDropRootProps(),
1209
+ className: "flex-grow flex flex-col overflow-hidden min-h-0 relative",
1210
+ onClick: (e) => {
1211
+ if (!e.target.closest("[data-storage-item]") && selectedPaths.size > 0) {
1212
+ setSelectedPaths(/* @__PURE__ */ new Set());
1213
+ setSelectedFile(null);
1214
+ setSelectedDownloadUrl(null);
1215
+ }
1216
+ },
1217
+ children: [
1218
+ /* @__PURE__ */ jsx("input", { ...getDropInputProps() }),
1219
+ renderContents(),
1220
+ isDragActive && /* @__PURE__ */ jsx("div", {
1221
+ className: "absolute inset-0 z-10 flex items-center justify-center bg-primary/5 dark:bg-primary/10 backdrop-blur-[2px]",
1222
+ children: /* @__PURE__ */ jsxs("div", {
1223
+ className: "flex flex-col items-center gap-2 p-6 rounded-xl border-2 border-dashed border-primary bg-white/80 dark:bg-surface-900/80",
1224
+ children: [
1225
+ /* @__PURE__ */ jsx(UploadCloudIcon, { className: "w-10 h-10 text-primary" }),
1226
+ /* @__PURE__ */ jsx(Typography, {
1227
+ variant: "subtitle2",
1228
+ className: "text-primary font-semibold",
1229
+ children: "Drop files to upload"
1230
+ }),
1231
+ /* @__PURE__ */ jsxs(Typography, {
1232
+ variant: "caption",
1233
+ color: "secondary",
1234
+ children: ["to /", currentPath || "root"]
1235
+ })
1236
+ ]
1237
+ })
1238
+ })
1239
+ ]
1240
+ }),
1241
+ /* @__PURE__ */ jsxs("div", {
1242
+ className: cls("px-4 py-1.5 border-t bg-surface-50 dark:bg-surface-800 flex items-center justify-between shrink-0", defaultBorderMixin),
1243
+ children: [/* @__PURE__ */ jsxs("div", {
1244
+ className: "flex items-center gap-4 text-[11px]",
1245
+ children: [/* @__PURE__ */ jsx("span", {
1246
+ className: "text-text-disabled dark:text-text-disabled-dark font-bold uppercase tracking-tighter",
1247
+ children: "Path"
1248
+ }), /* @__PURE__ */ jsxs("span", {
1249
+ className: "font-mono text-text-secondary dark:text-text-secondary-dark",
1250
+ children: ["/", currentPath || ""]
1251
+ })]
1252
+ }), selectedPaths.size > 0 ? /* @__PURE__ */ jsxs("div", {
1253
+ className: "text-[11px] text-text-secondary dark:text-text-secondary-dark",
1254
+ children: [
1255
+ selectedPaths.size,
1256
+ " item",
1257
+ selectedPaths.size !== 1 ? "s" : "",
1258
+ " selected"
1259
+ ]
1260
+ }) : selectedFile ? /* @__PURE__ */ jsxs("div", {
1261
+ className: "text-[11px] text-text-secondary dark:text-text-secondary-dark",
1262
+ children: ["Selected: ", /* @__PURE__ */ jsx("span", {
1263
+ className: "font-mono",
1264
+ children: selectedFile.name
1265
+ })]
1266
+ }) : null]
1267
+ })
1268
+ ]
1269
+ }), selectedFile && /* @__PURE__ */ jsx("div", {
1270
+ className: "w-80 lg:w-96 shrink-0",
1271
+ children: /* @__PURE__ */ jsx(FilePreviewPanel, {
1272
+ file: selectedFile,
1273
+ downloadUrl: selectedDownloadUrl,
1274
+ onClose: () => {
1275
+ setSelectedFile(null);
1276
+ setSelectedDownloadUrl(null);
1277
+ },
1278
+ onDelete: () => handleDeleteFile(selectedFile)
1279
+ })
1280
+ })]
1281
+ }),
1282
+ /* @__PURE__ */ jsx(UploadDialog, {
1283
+ open: uploadDialogOpen,
1284
+ currentPath,
1285
+ onClose: () => setUploadDialogOpen(false),
1286
+ onUpload: handleUpload
1287
+ }),
1288
+ /* @__PURE__ */ jsxs(Dialog, {
1289
+ open: deleteDialogOpen,
1290
+ onOpenChange: (open) => {
1291
+ if (!open && !deleting) {
1292
+ setDeleteDialogOpen(false);
1293
+ setDeleteDialogTarget(null);
1294
+ }
1295
+ },
1296
+ children: [
1297
+ /* @__PURE__ */ jsx(DialogTitle, {
1298
+ hidden: true,
1299
+ children: "Delete Confirmation"
1300
+ }),
1301
+ /* @__PURE__ */ jsxs(DialogContent, { children: [/* @__PURE__ */ jsx(Typography, {
1302
+ variant: "subtitle1",
1303
+ className: "font-semibold mb-2",
1304
+ children: deleteDialogTarget === "selection" ? `Delete ${selectedPaths.size} item${selectedPaths.size !== 1 ? "s" : ""}?` : deleteDialogTarget ? `Delete folder "${deleteDialogTarget.name}"?` : "Delete?"
1305
+ }), /* @__PURE__ */ jsx(Typography, {
1306
+ variant: "body2",
1307
+ color: "secondary",
1308
+ children: deleteDialogTarget === "selection" ? "This will permanently delete all selected files and folders, including their contents. This action cannot be undone." : "This will permanently delete the folder and all of its contents. This action cannot be undone."
1309
+ })] }),
1310
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
1311
+ variant: "text",
1312
+ onClick: () => {
1313
+ setDeleteDialogOpen(false);
1314
+ setDeleteDialogTarget(null);
1315
+ },
1316
+ disabled: deleting,
1317
+ children: "Cancel"
1318
+ }), /* @__PURE__ */ jsxs(LoadingButton, {
1319
+ color: "error",
1320
+ loading: deleting,
1321
+ onClick: deleteDialogTarget === "selection" ? handleBulkDelete : handleConfirmDeleteFolder,
1322
+ children: [/* @__PURE__ */ jsx(Trash2Icon, {
1323
+ size: 14,
1324
+ className: "mr-1"
1325
+ }), "Delete"]
1326
+ })] })
1327
+ ]
1328
+ }),
1329
+ /* @__PURE__ */ jsxs(Dialog, {
1330
+ open: newFolderDialogOpen,
1331
+ onOpenChange: (open) => {
1332
+ if (!open && !creatingFolder) {
1333
+ setNewFolderDialogOpen(false);
1334
+ setNewFolderName("");
1335
+ }
1336
+ },
1337
+ children: [
1338
+ /* @__PURE__ */ jsx(DialogTitle, {
1339
+ hidden: true,
1340
+ children: "New Folder"
1341
+ }),
1342
+ /* @__PURE__ */ jsxs(DialogContent, { children: [/* @__PURE__ */ jsx(TextField, {
1343
+ autoFocus: true,
1344
+ size: "small",
1345
+ label: "Folder name",
1346
+ value: newFolderName,
1347
+ onChange: (e) => setNewFolderName(e.target.value),
1348
+ onKeyDown: (e) => {
1349
+ if (e.key === "Enter" && newFolderName.trim()) {
1350
+ e.preventDefault();
1351
+ handleCreateFolder();
1352
+ }
1353
+ },
1354
+ disabled: creatingFolder,
1355
+ placeholder: "Enter folder name"
1356
+ }), currentPath && /* @__PURE__ */ jsxs(Typography, {
1357
+ variant: "caption",
1358
+ color: "secondary",
1359
+ className: "mt-2",
1360
+ children: ["Will be created in ", /* @__PURE__ */ jsxs("span", {
1361
+ className: "font-mono",
1362
+ children: [
1363
+ "/",
1364
+ currentPath,
1365
+ "/"
1366
+ ]
1367
+ })]
1368
+ })] }),
1369
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
1370
+ variant: "text",
1371
+ onClick: () => {
1372
+ setNewFolderDialogOpen(false);
1373
+ setNewFolderName("");
1374
+ },
1375
+ disabled: creatingFolder,
1376
+ children: "Cancel"
1377
+ }), /* @__PURE__ */ jsxs(LoadingButton, {
1378
+ color: "primary",
1379
+ loading: creatingFolder,
1380
+ disabled: !newFolderName.trim(),
1381
+ onClick: handleCreateFolder,
1382
+ children: [/* @__PURE__ */ jsx(FolderPlusIcon, {
1383
+ size: 14,
1384
+ className: "mr-1"
1385
+ }), "Create"]
1386
+ })] })
1387
+ ]
1388
+ })
1389
+ ]
1390
+ });
1391
+ };
1392
+ //#endregion
1393
+ export { StorageView };
1394
+
1395
+ //# sourceMappingURL=StorageView-CvrnHmDG.js.map