@gallop.software/studio 1.5.10 → 2.0.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 (60) hide show
  1. package/app/api/studio/[...path]/route.ts +1 -0
  2. package/app/layout.tsx +23 -0
  3. package/app/page.tsx +90 -0
  4. package/bin/studio.mjs +110 -0
  5. package/dist/handlers/index.js +77 -55
  6. package/dist/handlers/index.js.map +1 -1
  7. package/dist/handlers/index.mjs +128 -106
  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,219 @@
1
+ 'use client'
2
+
3
+ import { createContext, useContext } from 'react'
4
+ import type { FileItem, LeanMeta } from '../types'
5
+
6
+ /**
7
+ * Error message type for centralized error handling
8
+ */
9
+ export interface ErrorMessage {
10
+ title: string
11
+ message: string
12
+ }
13
+
14
+ /**
15
+ * Progress state for action modals
16
+ */
17
+ export interface ProgressState {
18
+ current: number
19
+ total: number
20
+ percent: number
21
+ status: 'processing' | 'complete' | 'error' | 'stopped' | 'cleanup'
22
+ currentFile?: string
23
+ message?: string
24
+ processed?: number
25
+ alreadyProcessed?: number
26
+ orphansRemoved?: number
27
+ orphanedFiles?: string[]
28
+ }
29
+
30
+ /**
31
+ * Action state for shared action handlers
32
+ */
33
+ export interface ActionState {
34
+ // Progress modal
35
+ showProgress: boolean
36
+ progressTitle: string
37
+ progressState: ProgressState
38
+
39
+ // Confirmation modals
40
+ showDeleteConfirm: boolean
41
+ showMoveModal: boolean
42
+ showSyncConfirm: boolean
43
+ showProcessConfirm: boolean
44
+
45
+ // Action-specific state
46
+ actionPaths: string[] // Paths being acted upon
47
+ syncImageCount: number
48
+ syncHasRemote: boolean
49
+ syncHasLocal: boolean
50
+ processMode: 'generate' | 'remove' // Mode for process modal
51
+ }
52
+
53
+ /**
54
+ * Studio state interface
55
+ * State is managed by StudioUI and provided to all child components
56
+ */
57
+ export interface StudioState {
58
+ isOpen: boolean
59
+ openStudio: () => void
60
+ closeStudio: () => void
61
+ toggleStudio: () => void
62
+
63
+ // Navigation
64
+ currentPath: string
65
+ setCurrentPath: (path: string) => void
66
+ navigateUp: () => void
67
+
68
+ // Selection
69
+ selectedItems: Set<string>
70
+ toggleSelection: (path: string) => void
71
+ selectRange: (fromPath: string, toPath: string, allItems: FileItem[]) => void
72
+ selectAll: (items: FileItem[]) => void
73
+ clearSelection: () => void
74
+ lastSelectedPath: string | null
75
+
76
+ // View
77
+ viewMode: 'grid' | 'list'
78
+ setViewMode: (mode: 'grid' | 'list') => void
79
+
80
+ // Focused item (for detail view)
81
+ focusedItem: FileItem | null
82
+ setFocusedItem: (item: FileItem | null) => void
83
+
84
+ // Meta
85
+ meta: LeanMeta | null
86
+ setMeta: (meta: LeanMeta) => void
87
+
88
+ // Loading
89
+ isLoading: boolean
90
+ setIsLoading: (loading: boolean) => void
91
+
92
+ // Refresh trigger
93
+ refreshKey: number
94
+ triggerRefresh: () => void
95
+
96
+ // Scan trigger
97
+ scanRequested: boolean
98
+ triggerScan: () => void
99
+ clearScanRequest: () => void
100
+
101
+ // Search
102
+ searchQuery: string
103
+ setSearchQuery: (query: string) => void
104
+
105
+ // Error handling
106
+ error: ErrorMessage | null
107
+ showError: (title: string, message: string) => void
108
+ clearError: () => void
109
+
110
+ // File items (for toolbar to check cloud status)
111
+ fileItems: FileItem[]
112
+ setFileItems: (items: FileItem[]) => void
113
+
114
+ // Shared action state
115
+ actionState: ActionState
116
+
117
+ // Shared action handlers (initiate confirmation)
118
+ requestDelete: (paths: string[]) => void
119
+ requestMove: (paths: string[]) => void
120
+ requestSync: (paths: string[], fileItems: FileItem[]) => void
121
+ requestProcess: (paths: string[]) => void
122
+ setProcessMode: (mode: 'generate' | 'remove') => void
123
+
124
+ // Action confirmations (execute action)
125
+ confirmDelete: () => Promise<void>
126
+ confirmMove: (destination: string) => Promise<void>
127
+ confirmSync: () => Promise<void>
128
+ confirmProcess: () => Promise<void>
129
+
130
+ // Cancel/close actions
131
+ cancelAction: () => void
132
+ closeProgress: () => void
133
+
134
+ // Stop processing
135
+ stopProcessing: () => void
136
+ abortController: AbortController | null
137
+
138
+ // Delete orphans (from scan)
139
+ deleteOrphans: () => Promise<void>
140
+ }
141
+
142
+ const defaultActionState: ActionState = {
143
+ showProgress: false,
144
+ progressTitle: '',
145
+ progressState: { current: 0, total: 0, percent: 0, status: 'processing' },
146
+ showDeleteConfirm: false,
147
+ showMoveModal: false,
148
+ showSyncConfirm: false,
149
+ showProcessConfirm: false,
150
+ actionPaths: [],
151
+ syncImageCount: 0,
152
+ syncHasRemote: false,
153
+ syncHasLocal: false,
154
+ processMode: 'generate',
155
+ }
156
+
157
+ const defaultState: StudioState = {
158
+ isOpen: false,
159
+ openStudio: () => {},
160
+ closeStudio: () => {},
161
+ toggleStudio: () => {},
162
+ currentPath: 'public',
163
+ setCurrentPath: () => {},
164
+ navigateUp: () => {},
165
+ selectedItems: new Set(),
166
+ toggleSelection: () => {},
167
+ selectRange: () => {},
168
+ selectAll: () => {},
169
+ clearSelection: () => {},
170
+ lastSelectedPath: null,
171
+ viewMode: 'grid',
172
+ setViewMode: () => {},
173
+ focusedItem: null,
174
+ setFocusedItem: () => {},
175
+ meta: null,
176
+ setMeta: () => {},
177
+ isLoading: false,
178
+ setIsLoading: () => {},
179
+ refreshKey: 0,
180
+ triggerRefresh: () => {},
181
+ scanRequested: false,
182
+ triggerScan: () => {},
183
+ clearScanRequest: () => {},
184
+ searchQuery: '',
185
+ setSearchQuery: () => {},
186
+ error: null,
187
+ showError: () => {},
188
+ clearError: () => {},
189
+ fileItems: [],
190
+ setFileItems: () => {},
191
+
192
+ // Shared action state
193
+ actionState: defaultActionState,
194
+
195
+ // Shared action handlers
196
+ requestDelete: () => {},
197
+ requestMove: () => {},
198
+ requestSync: () => {},
199
+ requestProcess: () => {},
200
+ setProcessMode: () => {},
201
+ confirmDelete: async () => {},
202
+ confirmMove: async () => {},
203
+ confirmSync: async () => {},
204
+ confirmProcess: async () => {},
205
+ cancelAction: () => {},
206
+ closeProgress: () => {},
207
+ stopProcessing: () => {},
208
+ abortController: null,
209
+ deleteOrphans: async () => {},
210
+ }
211
+
212
+ export const StudioContext = createContext<StudioState>(defaultState)
213
+
214
+ /**
215
+ * Hook to access Studio state from child components
216
+ */
217
+ export function useStudio() {
218
+ return useContext(StudioContext)
219
+ }