@gallop.software/studio 1.5.9 → 2.0.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 (60) hide show
  1. package/app/api/studio/[...path]/route.ts +1 -0
  2. package/app/layout.tsx +20 -0
  3. package/app/page.tsx +82 -0
  4. package/bin/studio.mjs +110 -0
  5. package/dist/handlers/index.js +84 -63
  6. package/dist/handlers/index.js.map +1 -1
  7. package/dist/handlers/index.mjs +135 -114
  8. package/dist/handlers/index.mjs.map +1 -1
  9. package/dist/index.d.mts +14 -10
  10. package/dist/index.d.ts +14 -10
  11. package/dist/index.js +2 -177
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +4 -179
  14. package/dist/index.mjs.map +1 -1
  15. package/next.config.mjs +22 -0
  16. package/package.json +18 -10
  17. package/src/components/AddNewModal.tsx +402 -0
  18. package/src/components/ErrorModal.tsx +89 -0
  19. package/src/components/R2SetupModal.tsx +400 -0
  20. package/src/components/StudioBreadcrumb.tsx +115 -0
  21. package/src/components/StudioButton.tsx +200 -0
  22. package/src/components/StudioContext.tsx +219 -0
  23. package/src/components/StudioDetailView.tsx +714 -0
  24. package/src/components/StudioFileGrid.tsx +704 -0
  25. package/src/components/StudioFileList.tsx +743 -0
  26. package/src/components/StudioFolderPicker.tsx +342 -0
  27. package/src/components/StudioModal.tsx +473 -0
  28. package/src/components/StudioPreview.tsx +399 -0
  29. package/src/components/StudioSettings.tsx +536 -0
  30. package/src/components/StudioToolbar.tsx +1448 -0
  31. package/src/components/StudioUI.tsx +731 -0
  32. package/src/components/styles/common.ts +236 -0
  33. package/src/components/tokens.ts +78 -0
  34. package/src/components/useStudioActions.tsx +497 -0
  35. package/src/config/index.ts +7 -0
  36. package/src/config/workspace.ts +52 -0
  37. package/src/handlers/favicon.ts +152 -0
  38. package/src/handlers/files.ts +784 -0
  39. package/src/handlers/images.ts +949 -0
  40. package/src/handlers/import.ts +190 -0
  41. package/src/handlers/index.ts +168 -0
  42. package/src/handlers/list.ts +627 -0
  43. package/src/handlers/scan.ts +311 -0
  44. package/src/handlers/utils/cdn.ts +234 -0
  45. package/src/handlers/utils/files.ts +64 -0
  46. package/src/handlers/utils/index.ts +4 -0
  47. package/src/handlers/utils/meta.ts +102 -0
  48. package/src/handlers/utils/thumbnails.ts +98 -0
  49. package/src/hooks/useFileList.ts +143 -0
  50. package/src/index.tsx +36 -0
  51. package/src/lib/api.ts +176 -0
  52. package/src/types.ts +119 -0
  53. package/dist/StudioUI-GJK45R3T.js +0 -6500
  54. package/dist/StudioUI-GJK45R3T.js.map +0 -1
  55. package/dist/StudioUI-QZ54STXE.mjs +0 -6500
  56. package/dist/StudioUI-QZ54STXE.mjs.map +0 -1
  57. package/dist/chunk-N6JYTJCB.js +0 -68
  58. package/dist/chunk-N6JYTJCB.js.map +0 -1
  59. package/dist/chunk-RHI3UROE.mjs +0 -68
  60. package/dist/chunk-RHI3UROE.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ export { GET, POST, DELETE } from '../../../../src/handlers'
package/app/layout.tsx ADDED
@@ -0,0 +1,20 @@
1
+ import type { Metadata } from 'next'
2
+
3
+ export const metadata: Metadata = {
4
+ title: 'Studio - Media Manager',
5
+ description: 'Manage images and media files for your project',
6
+ }
7
+
8
+ export default function RootLayout({
9
+ children,
10
+ }: {
11
+ children: React.ReactNode
12
+ }) {
13
+ return (
14
+ <html lang="en">
15
+ <body style={{ margin: 0, padding: 0 }}>
16
+ {children}
17
+ </body>
18
+ </html>
19
+ )
20
+ }
package/app/page.tsx ADDED
@@ -0,0 +1,82 @@
1
+ 'use client'
2
+
3
+ import dynamic from 'next/dynamic'
4
+ import { css } from '@emotion/react'
5
+ import { colors, fontStack } from '../src/components/tokens'
6
+
7
+ // Dynamically import StudioUI to avoid SSR issues with Emotion
8
+ const StudioUI = dynamic(() => import('../src/components/StudioUI'), {
9
+ ssr: false,
10
+ loading: () => <LoadingState />,
11
+ })
12
+
13
+ const styles = {
14
+ container: css`
15
+ position: fixed;
16
+ top: 0;
17
+ left: 0;
18
+ right: 0;
19
+ bottom: 0;
20
+ background: ${colors.background};
21
+ font-family: ${fontStack};
22
+ `,
23
+ loading: css`
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ height: 100vh;
28
+ background: ${colors.background};
29
+ font-family: ${fontStack};
30
+ `,
31
+ loadingContent: css`
32
+ display: flex;
33
+ flex-direction: column;
34
+ align-items: center;
35
+ gap: 16px;
36
+ `,
37
+ spinner: css`
38
+ width: 36px;
39
+ height: 36px;
40
+ border-radius: 50%;
41
+ border: 3px solid ${colors.border};
42
+ border-top-color: ${colors.primary};
43
+ animation: spin 0.8s linear infinite;
44
+
45
+ @keyframes spin {
46
+ to {
47
+ transform: rotate(360deg);
48
+ }
49
+ }
50
+ `,
51
+ loadingText: css`
52
+ color: ${colors.textSecondary};
53
+ font-size: 14px;
54
+ font-weight: 500;
55
+ margin: 0;
56
+ `,
57
+ }
58
+
59
+ function LoadingState() {
60
+ return (
61
+ <div css={styles.loading}>
62
+ <div css={styles.loadingContent}>
63
+ <div css={styles.spinner} />
64
+ <p css={styles.loadingText}>Loading Studio...</p>
65
+ </div>
66
+ </div>
67
+ )
68
+ }
69
+
70
+ export default function StudioPage() {
71
+ const workspace = process.env.NEXT_PUBLIC_STUDIO_WORKSPACE || 'Unknown'
72
+
73
+ return (
74
+ <div css={styles.container}>
75
+ <StudioUI
76
+ isVisible={true}
77
+ standaloneMode={true}
78
+ workspacePath={workspace}
79
+ />
80
+ </div>
81
+ )
82
+ }
package/bin/studio.mjs ADDED
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawn } from 'child_process'
4
+ import { resolve, dirname } from 'path'
5
+ import { fileURLToPath } from 'url'
6
+ import { existsSync } from 'fs'
7
+
8
+ const __filename = fileURLToPath(import.meta.url)
9
+ const __dirname = dirname(__filename)
10
+
11
+ // Parse command line arguments
12
+ const args = process.argv.slice(2)
13
+ let workspace = process.cwd()
14
+ let shouldOpen = false
15
+
16
+ for (let i = 0; i < args.length; i++) {
17
+ if (args[i] === '--workspace' && args[i + 1]) {
18
+ workspace = resolve(args[i + 1])
19
+ i++
20
+ } else if (args[i] === '--open' || args[i] === '-o') {
21
+ shouldOpen = true
22
+ } else if (args[i] === '--help' || args[i] === '-h') {
23
+ console.log(`
24
+ Studio - Media Manager
25
+
26
+ Usage:
27
+ studio [options]
28
+
29
+ Options:
30
+ --workspace <path> Path to the project workspace (default: current directory)
31
+ --open, -o Open browser automatically
32
+ --help, -h Show this help message
33
+
34
+ Examples:
35
+ studio # Run in current directory
36
+ studio --workspace ~/my-project # Run for specific project
37
+ studio --workspace . --open # Open browser automatically
38
+ `)
39
+ process.exit(0)
40
+ }
41
+ }
42
+
43
+ // Validate workspace exists
44
+ if (!existsSync(workspace)) {
45
+ console.error(`Error: Workspace path does not exist: ${workspace}`)
46
+ process.exit(1)
47
+ }
48
+
49
+ // Check for public folder
50
+ const publicPath = resolve(workspace, 'public')
51
+ if (!existsSync(publicPath)) {
52
+ console.error(`Error: No 'public' folder found in workspace: ${workspace}`)
53
+ console.error('Studio requires a public folder to manage media files.')
54
+ process.exit(1)
55
+ }
56
+
57
+ console.log(`
58
+ ┌─────────────────────────────────────┐
59
+ │ Studio - Media Manager │
60
+ ├─────────────────────────────────────┤
61
+ │ Workspace: ${workspace.length > 24 ? '...' + workspace.slice(-21) : workspace.padEnd(24)}│
62
+ │ URL: http://localhost:3001 │
63
+ └─────────────────────────────────────┘
64
+ `)
65
+
66
+ // Find the next binary
67
+ const studioRoot = resolve(__dirname, '..')
68
+ const nextBin = resolve(studioRoot, 'node_modules', '.bin', 'next')
69
+
70
+ if (!existsSync(nextBin)) {
71
+ console.error('Error: Next.js not found. Please run: npm install')
72
+ process.exit(1)
73
+ }
74
+
75
+ // Set up environment
76
+ const env = {
77
+ ...process.env,
78
+ STUDIO_WORKSPACE: workspace,
79
+ NODE_ENV: 'development',
80
+ }
81
+
82
+ // Start Next.js dev server
83
+ const child = spawn(nextBin, ['dev', '-p', '3001'], {
84
+ stdio: 'inherit',
85
+ cwd: studioRoot,
86
+ env,
87
+ })
88
+
89
+ // Open browser if requested
90
+ if (shouldOpen) {
91
+ setTimeout(async () => {
92
+ const open = (await import('open')).default
93
+ open('http://localhost:3001')
94
+ }, 2000)
95
+ }
96
+
97
+ // Handle process termination
98
+ process.on('SIGINT', () => {
99
+ child.kill('SIGINT')
100
+ process.exit(0)
101
+ })
102
+
103
+ process.on('SIGTERM', () => {
104
+ child.kill('SIGTERM')
105
+ process.exit(0)
106
+ })
107
+
108
+ child.on('close', (code) => {
109
+ process.exit(code || 0)
110
+ })