@rebasepro/studio 0.4.0 → 0.6.0

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