@gallop.software/studio 0.1.7 → 0.1.8

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.
@@ -50,8 +50,147 @@ function useStudio() {
50
50
  // src/components/StudioToolbar.tsx
51
51
 
52
52
 
53
+
54
+ // src/components/StudioModal.tsx
55
+
53
56
  var _jsxruntime = require('@emotion/react/jsx-runtime');
57
+ var fadeIn = _react3.keyframes`
58
+ from { opacity: 0; }
59
+ to { opacity: 1; }
60
+ `;
61
+ var slideIn = _react3.keyframes`
62
+ from {
63
+ opacity: 0;
64
+ transform: scale(0.95);
65
+ }
66
+ to {
67
+ opacity: 1;
68
+ transform: scale(1);
69
+ }
70
+ `;
54
71
  var styles = {
72
+ overlay: _react3.css`
73
+ position: fixed;
74
+ inset: 0;
75
+ background-color: rgba(0, 0, 0, 0.5);
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ z-index: 10000;
80
+ animation: ${fadeIn} 0.15s ease-out;
81
+ `,
82
+ modal: _react3.css`
83
+ background-color: white;
84
+ border-radius: 12px;
85
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
86
+ max-width: 400px;
87
+ width: 90%;
88
+ animation: ${slideIn} 0.15s ease-out;
89
+ `,
90
+ header: _react3.css`
91
+ padding: 20px 24px 0;
92
+ `,
93
+ title: _react3.css`
94
+ font-size: 18px;
95
+ font-weight: 600;
96
+ color: #111827;
97
+ margin: 0;
98
+ `,
99
+ body: _react3.css`
100
+ padding: 12px 24px 24px;
101
+ `,
102
+ message: _react3.css`
103
+ font-size: 14px;
104
+ color: #6b7280;
105
+ margin: 0;
106
+ line-height: 1.5;
107
+ `,
108
+ footer: _react3.css`
109
+ display: flex;
110
+ justify-content: flex-end;
111
+ gap: 12px;
112
+ padding: 16px 24px;
113
+ border-top: 1px solid #e5e7eb;
114
+ background-color: #f9fafb;
115
+ border-radius: 0 0 12px 12px;
116
+ `,
117
+ btn: _react3.css`
118
+ padding: 8px 16px;
119
+ font-size: 14px;
120
+ font-weight: 500;
121
+ border-radius: 8px;
122
+ cursor: pointer;
123
+ transition: all 0.15s;
124
+ `,
125
+ btnCancel: _react3.css`
126
+ background-color: white;
127
+ border: 1px solid #d1d5db;
128
+ color: #374151;
129
+
130
+ &:hover {
131
+ background-color: #f9fafb;
132
+ }
133
+ `,
134
+ btnConfirm: _react3.css`
135
+ background-color: #9333ea;
136
+ border: 1px solid #9333ea;
137
+ color: white;
138
+
139
+ &:hover {
140
+ background-color: #7c3aed;
141
+ }
142
+ `,
143
+ btnDanger: _react3.css`
144
+ background-color: #dc2626;
145
+ border: 1px solid #dc2626;
146
+ color: white;
147
+
148
+ &:hover {
149
+ background-color: #b91c1c;
150
+ }
151
+ `
152
+ };
153
+ function ConfirmModal({
154
+ title,
155
+ message,
156
+ confirmLabel = "Confirm",
157
+ cancelLabel = "Cancel",
158
+ variant = "default",
159
+ onConfirm,
160
+ onCancel
161
+ }) {
162
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles.overlay, onClick: onCancel, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles.modal, onClick: (e) => e.stopPropagation(), children: [
163
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles.header, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles.title, children: title }) }),
164
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles.body, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles.message, children: message }) }),
165
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles.footer, children: [
166
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: [styles.btn, styles.btnCancel], onClick: onCancel, children: cancelLabel }),
167
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
168
+ "button",
169
+ {
170
+ css: [styles.btn, variant === "danger" ? styles.btnDanger : styles.btnConfirm],
171
+ onClick: onConfirm,
172
+ children: confirmLabel
173
+ }
174
+ )
175
+ ] })
176
+ ] }) });
177
+ }
178
+ function AlertModal({
179
+ title,
180
+ message,
181
+ buttonLabel = "OK",
182
+ onClose
183
+ }) {
184
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles.overlay, onClick: onClose, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles.modal, onClick: (e) => e.stopPropagation(), children: [
185
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles.header, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles.title, children: title }) }),
186
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles.body, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles.message, children: message }) }),
187
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles.footer, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: [styles.btn, styles.btnConfirm], onClick: onClose, children: buttonLabel }) })
188
+ ] }) });
189
+ }
190
+
191
+ // src/components/StudioToolbar.tsx
192
+
193
+ var styles2 = {
55
194
  toolbar: _react3.css`
56
195
  display: flex;
57
196
  align-items: center;
@@ -151,6 +290,8 @@ function StudioToolbar() {
151
290
  const { selectedItems, viewMode, setViewMode, clearSelection, currentPath, triggerRefresh } = useStudio();
152
291
  const fileInputRef = _react.useRef.call(void 0, null);
153
292
  const [uploading, setUploading] = _react.useState.call(void 0, false);
293
+ const [showDeleteConfirm, setShowDeleteConfirm] = _react.useState.call(void 0, false);
294
+ const [alertMessage, setAlertMessage] = _react.useState.call(void 0, null);
154
295
  const handleUpload = _react.useCallback.call(void 0, () => {
155
296
  _optionalChain([fileInputRef, 'access', _ => _.current, 'optionalAccess', _2 => _2.click, 'call', _3 => _3()]);
156
297
  }, []);
@@ -170,13 +311,19 @@ function StudioToolbar() {
170
311
  if (!response.ok) {
171
312
  const error = await response.json();
172
313
  console.error("Upload failed:", error);
173
- alert(`Failed to upload ${file.name}: ${error.error || "Unknown error"}`);
314
+ setAlertMessage({
315
+ title: "Upload Failed",
316
+ message: `Failed to upload ${file.name}: ${error.error || "Unknown error"}`
317
+ });
174
318
  }
175
319
  }
176
320
  triggerRefresh();
177
321
  } catch (error) {
178
322
  console.error("Upload error:", error);
179
- alert("Upload failed. Check console for details.");
323
+ setAlertMessage({
324
+ title: "Upload Failed",
325
+ message: "Upload failed. Check console for details."
326
+ });
180
327
  } finally {
181
328
  setUploading(false);
182
329
  if (fileInputRef.current) {
@@ -187,9 +334,12 @@ function StudioToolbar() {
187
334
  const handleReprocess = _react.useCallback.call(void 0, () => {
188
335
  console.log("Reprocess clicked", selectedItems);
189
336
  }, [selectedItems]);
190
- const handleDelete = _react.useCallback.call(void 0, async () => {
337
+ const handleDeleteClick = _react.useCallback.call(void 0, () => {
191
338
  if (selectedItems.size === 0) return;
192
- if (!confirm(`Delete ${selectedItems.size} item(s)?`)) return;
339
+ setShowDeleteConfirm(true);
340
+ }, [selectedItems]);
341
+ const handleDeleteConfirm = _react.useCallback.call(void 0, async () => {
342
+ setShowDeleteConfirm(false);
193
343
  try {
194
344
  const response = await fetch("/api/studio/delete", {
195
345
  method: "POST",
@@ -201,11 +351,17 @@ function StudioToolbar() {
201
351
  triggerRefresh();
202
352
  } else {
203
353
  const error = await response.json();
204
- alert(`Delete failed: ${error.error || "Unknown error"}`);
354
+ setAlertMessage({
355
+ title: "Delete Failed",
356
+ message: error.error || "Unknown error"
357
+ });
205
358
  }
206
359
  } catch (error) {
207
360
  console.error("Delete error:", error);
208
- alert("Delete failed. Check console for details.");
361
+ setAlertMessage({
362
+ title: "Delete Failed",
363
+ message: "Delete failed. Check console for details."
364
+ });
209
365
  }
210
366
  }, [selectedItems, clearSelection, triggerRefresh]);
211
367
  const handleSyncCdn = _react.useCallback.call(void 0, () => {
@@ -215,83 +371,104 @@ function StudioToolbar() {
215
371
  console.log("Scan clicked");
216
372
  }, []);
217
373
  const hasSelection = selectedItems.size > 0;
218
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles.toolbar, children: [
219
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
220
- "input",
374
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
375
+ showDeleteConfirm && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
376
+ ConfirmModal,
221
377
  {
222
- ref: fileInputRef,
223
- type: "file",
224
- multiple: true,
225
- accept: "image/*",
226
- onChange: handleFileChange,
227
- style: { display: "none" }
378
+ title: "Delete Items",
379
+ message: `Are you sure you want to delete ${selectedItems.size} item(s)? This action cannot be undone.`,
380
+ confirmLabel: "Delete",
381
+ variant: "danger",
382
+ onConfirm: handleDeleteConfirm,
383
+ onCancel: () => setShowDeleteConfirm(false)
228
384
  }
229
385
  ),
230
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles.left, children: [
231
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
232
- ToolbarButton,
233
- {
234
- onClick: handleUpload,
235
- icon: "upload",
236
- label: uploading ? "Uploading..." : "Upload",
237
- disabled: uploading
238
- }
239
- ),
240
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
241
- ToolbarButton,
242
- {
243
- onClick: handleReprocess,
244
- icon: "refresh",
245
- label: "Reprocess",
246
- disabled: !hasSelection
247
- }
248
- ),
249
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
250
- ToolbarButton,
251
- {
252
- onClick: handleDelete,
253
- icon: "trash",
254
- label: "Delete",
255
- disabled: !hasSelection,
256
- variant: "danger"
257
- }
258
- ),
386
+ alertMessage && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
387
+ AlertModal,
388
+ {
389
+ title: alertMessage.title,
390
+ message: alertMessage.message,
391
+ onClose: () => setAlertMessage(null)
392
+ }
393
+ ),
394
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles2.toolbar, children: [
259
395
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
260
- ToolbarButton,
396
+ "input",
261
397
  {
262
- onClick: handleSyncCdn,
263
- icon: "cloud",
264
- label: "Sync CDN",
265
- disabled: !hasSelection
398
+ ref: fileInputRef,
399
+ type: "file",
400
+ multiple: true,
401
+ accept: "image/*",
402
+ onChange: handleFileChange,
403
+ style: { display: "none" }
266
404
  }
267
405
  ),
268
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ToolbarButton, { onClick: handleScan, icon: "scan", label: "Scan" })
269
- ] }),
270
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles.right, children: [
271
- hasSelection && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles.selectionCount, children: [
272
- selectedItems.size,
273
- " selected",
274
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles.clearBtn, onClick: clearSelection, children: "Clear" })
275
- ] }),
276
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles.viewToggle, children: [
406
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles2.left, children: [
277
407
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
278
- "button",
408
+ ToolbarButton,
279
409
  {
280
- css: [styles.viewBtn, viewMode === "grid" && styles.viewBtnActive],
281
- onClick: () => setViewMode("grid"),
282
- "aria-label": "Grid view",
283
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, GridIcon, {})
410
+ onClick: handleUpload,
411
+ icon: "upload",
412
+ label: uploading ? "Uploading..." : "Upload",
413
+ disabled: uploading
284
414
  }
285
415
  ),
286
416
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
287
- "button",
417
+ ToolbarButton,
288
418
  {
289
- css: [styles.viewBtn, viewMode === "list" && styles.viewBtnActive],
290
- onClick: () => setViewMode("list"),
291
- "aria-label": "List view",
292
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListIcon, {})
419
+ onClick: handleReprocess,
420
+ icon: "refresh",
421
+ label: "Reprocess",
422
+ disabled: !hasSelection
293
423
  }
294
- )
424
+ ),
425
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
426
+ ToolbarButton,
427
+ {
428
+ onClick: handleDeleteClick,
429
+ icon: "trash",
430
+ label: "Delete",
431
+ disabled: !hasSelection,
432
+ variant: "danger"
433
+ }
434
+ ),
435
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
436
+ ToolbarButton,
437
+ {
438
+ onClick: handleSyncCdn,
439
+ icon: "cloud",
440
+ label: "Sync CDN",
441
+ disabled: !hasSelection
442
+ }
443
+ ),
444
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ToolbarButton, { onClick: handleScan, icon: "scan", label: "Scan" })
445
+ ] }),
446
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles2.right, children: [
447
+ hasSelection && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles2.selectionCount, children: [
448
+ selectedItems.size,
449
+ " selected",
450
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles2.clearBtn, onClick: clearSelection, children: "Clear" })
451
+ ] }),
452
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles2.viewToggle, children: [
453
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
454
+ "button",
455
+ {
456
+ css: [styles2.viewBtn, viewMode === "grid" && styles2.viewBtnActive],
457
+ onClick: () => setViewMode("grid"),
458
+ "aria-label": "Grid view",
459
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, GridIcon, {})
460
+ }
461
+ ),
462
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
463
+ "button",
464
+ {
465
+ css: [styles2.viewBtn, viewMode === "list" && styles2.viewBtnActive],
466
+ onClick: () => setViewMode("list"),
467
+ "aria-label": "List view",
468
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListIcon, {})
469
+ }
470
+ )
471
+ ] })
295
472
  ] })
296
473
  ] })
297
474
  ] });
@@ -306,7 +483,7 @@ function ToolbarButton({
306
483
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
307
484
  "button",
308
485
  {
309
- css: [styles.btn, variant === "danger" ? styles.btnDanger : styles.btnDefault],
486
+ css: [styles2.btn, variant === "danger" ? styles2.btnDanger : styles2.btnDefault],
310
487
  onClick,
311
488
  disabled,
312
489
  children: [
@@ -319,30 +496,30 @@ function ToolbarButton({
319
496
  function IconComponent({ icon }) {
320
497
  switch (icon) {
321
498
  case "upload":
322
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" }) });
499
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles2.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" }) });
323
500
  case "refresh":
324
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) });
501
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles2.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) });
325
502
  case "trash":
326
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) });
503
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles2.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) });
327
504
  case "cloud":
328
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) });
505
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles2.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) });
329
506
  case "scan":
330
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) });
507
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles2.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) });
331
508
  default:
332
509
  return null;
333
510
  }
334
511
  }
335
512
  function GridIcon() {
336
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" }) });
513
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles2.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" }) });
337
514
  }
338
515
  function ListIcon() {
339
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) });
516
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles2.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) });
340
517
  }
341
518
 
342
519
  // src/components/StudioBreadcrumb.tsx
343
520
 
344
521
 
345
- var styles2 = {
522
+ var styles3 = {
346
523
  container: _react3.css`
347
524
  display: flex;
348
525
  align-items: center;
@@ -413,14 +590,14 @@ function StudioBreadcrumb() {
413
590
  const newPath = parts.slice(0, index + 1).join("/");
414
591
  setCurrentPath(newPath);
415
592
  };
416
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles2.container, children: [
417
- currentPath !== "public" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles2.backBtn, onClick: navigateUp, "aria-label": "Go back", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles2.backIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }),
418
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "nav", { css: styles2.nav, children: parts.map((part, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles2.item, children: [
419
- index > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles2.separator, children: "/" }),
593
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles3.container, children: [
594
+ currentPath !== "public" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles3.backBtn, onClick: navigateUp, "aria-label": "Go back", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles3.backIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }),
595
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "nav", { css: styles3.nav, children: parts.map((part, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles3.item, children: [
596
+ index > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles3.separator, children: "/" }),
420
597
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
421
598
  "button",
422
599
  {
423
- css: [styles2.btn, index === parts.length - 1 ? styles2.btnActive : styles2.btnInactive],
600
+ css: [styles3.btn, index === parts.length - 1 ? styles3.btnActive : styles3.btnInactive],
424
601
  onClick: () => handleClick(index),
425
602
  children: part
426
603
  }
@@ -436,7 +613,7 @@ function StudioBreadcrumb() {
436
613
  var spin = _react3.keyframes`
437
614
  to { transform: rotate(360deg); }
438
615
  `;
439
- var styles3 = {
616
+ var styles4 = {
440
617
  loading: _react3.css`
441
618
  display: flex;
442
619
  align-items: center;
@@ -597,13 +774,13 @@ function StudioFileGrid() {
597
774
  loadItems();
598
775
  }, [currentPath, refreshKey]);
599
776
  if (loading) {
600
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles3.loading, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles3.spinner }) });
777
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles4.loading, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles4.spinner }) });
601
778
  }
602
779
  if (items.length === 0) {
603
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles3.empty, children: [
604
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles3.emptyIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
605
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles3.emptyText, children: "No files in this folder" }),
606
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles3.emptyText, children: "Upload images to get started" })
780
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles4.empty, children: [
781
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles4.emptyIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
782
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles4.emptyText, children: "No files in this folder" }),
783
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles4.emptyText, children: "Upload images to get started" })
607
784
  ] });
608
785
  }
609
786
  const sortedItems = [...items].sort((a, b) => {
@@ -633,12 +810,12 @@ function StudioFileGrid() {
633
810
  }
634
811
  };
635
812
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
636
- files.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles3.selectAllRow, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { css: styles3.selectAllLabel, children: [
813
+ files.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles4.selectAllRow, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { css: styles4.selectAllLabel, children: [
637
814
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
638
815
  "input",
639
816
  {
640
817
  type: "checkbox",
641
- css: styles3.selectAllCheckbox,
818
+ css: styles4.selectAllCheckbox,
642
819
  checked: allFilesSelected,
643
820
  ref: (el) => {
644
821
  if (el) el.indeterminate = someFilesSelected && !allFilesSelected;
@@ -650,7 +827,7 @@ function StudioFileGrid() {
650
827
  files.length,
651
828
  ")"
652
829
  ] }) }),
653
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles3.grid, children: sortedItems.map((item) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
830
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles4.grid, children: sortedItems.map((item) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
654
831
  GridItem,
655
832
  {
656
833
  item,
@@ -663,31 +840,31 @@ function StudioFileGrid() {
663
840
  }
664
841
  function GridItem({ item, isSelected, onClick }) {
665
842
  const isFolder = item.type === "folder";
666
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: [styles3.item, isSelected && styles3.itemSelected], onClick, children: [
843
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: [styles4.item, isSelected && styles4.itemSelected], onClick, children: [
667
844
  !isFolder && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
668
845
  "input",
669
846
  {
670
847
  type: "checkbox",
671
- css: styles3.checkbox,
848
+ css: styles4.checkbox,
672
849
  checked: isSelected,
673
850
  onChange: () => {
674
851
  },
675
852
  onClick: (e) => e.stopPropagation()
676
853
  }
677
854
  ),
678
- item.cdnSynced && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles3.cdnBadge, children: "CDN" }),
679
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles3.content, children: isFolder ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles3.folderIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V8a2 2 0 00-2-2h-8l-2-2z" }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
855
+ item.cdnSynced && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles4.cdnBadge, children: "CDN" }),
856
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles4.content, children: isFolder ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles4.folderIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V8a2 2 0 00-2-2h-8l-2-2z" }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
680
857
  "img",
681
858
  {
682
- css: styles3.image,
859
+ css: styles4.image,
683
860
  src: item.path.replace("public", ""),
684
861
  alt: item.name,
685
862
  loading: "lazy"
686
863
  }
687
864
  ) }),
688
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles3.label, children: [
689
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles3.name, title: item.name, children: item.name }),
690
- item.size && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles3.size, children: formatFileSize(item.size) })
865
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles4.label, children: [
866
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles4.name, title: item.name, children: item.name }),
867
+ item.size && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles4.size, children: formatFileSize(item.size) })
691
868
  ] })
692
869
  ] });
693
870
  }
@@ -704,7 +881,7 @@ function formatFileSize(bytes) {
704
881
  var spin2 = _react3.keyframes`
705
882
  to { transform: rotate(360deg); }
706
883
  `;
707
- var styles4 = {
884
+ var styles5 = {
708
885
  loading: _react3.css`
709
886
  display: flex;
710
887
  align-items: center;
@@ -835,10 +1012,10 @@ function StudioFileList() {
835
1012
  loadItems();
836
1013
  }, [currentPath, refreshKey]);
837
1014
  if (loading) {
838
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles4.loading, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles4.spinner }) });
1015
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles5.loading, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles5.spinner }) });
839
1016
  }
840
1017
  if (items.length === 0) {
841
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles4.empty, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { children: "No files in this folder" }) });
1018
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles5.empty, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { children: "No files in this folder" }) });
842
1019
  }
843
1020
  const sortedItems = [...items].sort((a, b) => {
844
1021
  if (a.type === "folder" && b.type !== "folder") return -1;
@@ -866,13 +1043,13 @@ function StudioFileList() {
866
1043
  toggleSelection(item.path);
867
1044
  }
868
1045
  };
869
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "table", { css: styles4.table, children: [
1046
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "table", { css: styles5.table, children: [
870
1047
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "thead", { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "tr", { children: [
871
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: [styles4.th, styles4.thCheckbox], children: files.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1048
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: [styles5.th, styles5.thCheckbox], children: files.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
872
1049
  "input",
873
1050
  {
874
1051
  type: "checkbox",
875
- css: styles4.checkbox,
1052
+ css: styles5.checkbox,
876
1053
  checked: allFilesSelected,
877
1054
  ref: (el) => {
878
1055
  if (el) el.indeterminate = someFilesSelected && !allFilesSelected;
@@ -880,12 +1057,12 @@ function StudioFileList() {
880
1057
  onChange: handleSelectAll
881
1058
  }
882
1059
  ) }),
883
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: styles4.th, children: "Name" }),
884
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: [styles4.th, styles4.thSize], children: "Size" }),
885
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: [styles4.th, styles4.thDimensions], children: "Dimensions" }),
886
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: [styles4.th, styles4.thCdn], children: "CDN" })
1060
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: styles5.th, children: "Name" }),
1061
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: [styles5.th, styles5.thSize], children: "Size" }),
1062
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: [styles5.th, styles5.thDimensions], children: "Dimensions" }),
1063
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { css: [styles5.th, styles5.thCdn], children: "CDN" })
887
1064
  ] }) }),
888
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { css: styles4.tbody, children: sortedItems.map((item) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1065
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { css: styles5.tbody, children: sortedItems.map((item) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
889
1066
  ListRow,
890
1067
  {
891
1068
  item,
@@ -898,28 +1075,28 @@ function StudioFileList() {
898
1075
  }
899
1076
  function ListRow({ item, isSelected, onClick }) {
900
1077
  const isFolder = item.type === "folder";
901
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "tr", { css: [styles4.row, isSelected && styles4.rowSelected], onClick, children: [
902
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: styles4.td, children: !isFolder && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1078
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "tr", { css: [styles5.row, isSelected && styles5.rowSelected], onClick, children: [
1079
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: styles5.td, children: !isFolder && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
903
1080
  "input",
904
1081
  {
905
1082
  type: "checkbox",
906
- css: styles4.checkbox,
1083
+ css: styles5.checkbox,
907
1084
  checked: isSelected,
908
1085
  onChange: () => {
909
1086
  },
910
1087
  onClick: (e) => e.stopPropagation()
911
1088
  }
912
1089
  ) }),
913
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: styles4.td, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles4.nameCell, children: [
914
- isFolder ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles4.folderIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V8a2 2 0 00-2-2h-8l-2-2z" }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles4.fileIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
915
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles4.name, children: item.name })
1090
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: styles5.td, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.nameCell, children: [
1091
+ isFolder ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles5.folderIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V8a2 2 0 00-2-2h-8l-2-2z" }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles5.fileIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
1092
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles5.name, children: item.name })
916
1093
  ] }) }),
917
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: [styles4.td, styles4.meta], children: item.size ? formatFileSize2(item.size) : "--" }),
918
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: [styles4.td, styles4.meta], children: item.dimensions ? `${item.dimensions.width}x${item.dimensions.height}` : "--" }),
919
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: styles4.td, children: item.cdnSynced ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles4.cdnBadge, children: [
920
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles4.cdnIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }),
1094
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: [styles5.td, styles5.meta], children: item.size ? formatFileSize2(item.size) : "--" }),
1095
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: [styles5.td, styles5.meta], children: item.dimensions ? `${item.dimensions.width}x${item.dimensions.height}` : "--" }),
1096
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: styles5.td, children: item.cdnSynced ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles5.cdnBadge, children: [
1097
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles5.cdnIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }),
921
1098
  "Synced"
922
- ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles4.cdnEmpty, children: "--" }) })
1099
+ ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles5.cdnEmpty, children: "--" }) })
923
1100
  ] });
924
1101
  }
925
1102
  function formatFileSize2(bytes) {
@@ -931,7 +1108,8 @@ function formatFileSize2(bytes) {
931
1108
  // src/components/StudioPreview.tsx
932
1109
 
933
1110
 
934
- var styles5 = {
1111
+
1112
+ var styles6 = {
935
1113
  panel: _react3.css`
936
1114
  width: 320px;
937
1115
  border-left: 1px solid #e5e7eb;
@@ -1062,9 +1240,14 @@ var styles5 = {
1062
1240
  };
1063
1241
  function StudioPreview() {
1064
1242
  const { selectedItems, meta, triggerRefresh, clearSelection } = useStudio();
1065
- const handleDelete = async () => {
1243
+ const [showDeleteConfirm, setShowDeleteConfirm] = _react.useState.call(void 0, false);
1244
+ const [alertMessage, setAlertMessage] = _react.useState.call(void 0, null);
1245
+ const handleDeleteClick = () => {
1066
1246
  if (selectedItems.size === 0) return;
1067
- if (!confirm(`Delete ${selectedItems.size} item(s)?`)) return;
1247
+ setShowDeleteConfirm(true);
1248
+ };
1249
+ const handleDeleteConfirm = async () => {
1250
+ setShowDeleteConfirm(false);
1068
1251
  try {
1069
1252
  const response = await fetch("/api/studio/delete", {
1070
1253
  method: "POST",
@@ -1076,106 +1259,142 @@ function StudioPreview() {
1076
1259
  triggerRefresh();
1077
1260
  } else {
1078
1261
  const error = await response.json();
1079
- alert(`Delete failed: ${error.error || "Unknown error"}`);
1262
+ setAlertMessage({
1263
+ title: "Delete Failed",
1264
+ message: error.error || "Unknown error"
1265
+ });
1080
1266
  }
1081
1267
  } catch (error) {
1082
1268
  console.error("Delete error:", error);
1083
- alert("Delete failed. Check console for details.");
1269
+ setAlertMessage({
1270
+ title: "Delete Failed",
1271
+ message: "Delete failed. Check console for details."
1272
+ });
1084
1273
  }
1085
1274
  };
1275
+ const modals = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1276
+ showDeleteConfirm && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1277
+ ConfirmModal,
1278
+ {
1279
+ title: "Delete Items",
1280
+ message: `Are you sure you want to delete ${selectedItems.size} item(s)? This action cannot be undone.`,
1281
+ confirmLabel: "Delete",
1282
+ variant: "danger",
1283
+ onConfirm: handleDeleteConfirm,
1284
+ onCancel: () => setShowDeleteConfirm(false)
1285
+ }
1286
+ ),
1287
+ alertMessage && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1288
+ AlertModal,
1289
+ {
1290
+ title: alertMessage.title,
1291
+ message: alertMessage.message,
1292
+ onClose: () => setAlertMessage(null)
1293
+ }
1294
+ )
1295
+ ] });
1086
1296
  if (selectedItems.size === 0) {
1087
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.panel, children: [
1088
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles5.title, children: "Preview" }),
1089
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles5.emptyState, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles5.emptyText, children: "Select an image to preview" }) })
1297
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1298
+ modals,
1299
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.panel, children: [
1300
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles6.title, children: "Preview" }),
1301
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles6.emptyState, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.emptyText, children: "Select an image to preview" }) })
1302
+ ] })
1090
1303
  ] });
1091
1304
  }
1092
1305
  if (selectedItems.size > 1) {
1093
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.panel, children: [
1094
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "h3", { css: styles5.title, children: [
1095
- selectedItems.size,
1096
- " items selected"
1097
- ] }),
1098
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles5.actions, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { css: [styles5.actionBtn, styles5.actionBtnDanger], onClick: handleDelete, children: [
1099
- "Delete ",
1100
- selectedItems.size,
1101
- " items"
1102
- ] }) })
1306
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1307
+ modals,
1308
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.panel, children: [
1309
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "h3", { css: styles6.title, children: [
1310
+ selectedItems.size,
1311
+ " items selected"
1312
+ ] }),
1313
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles6.actions, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { css: [styles6.actionBtn, styles6.actionBtnDanger], onClick: handleDeleteClick, children: [
1314
+ "Delete ",
1315
+ selectedItems.size,
1316
+ " items"
1317
+ ] }) })
1318
+ ] })
1103
1319
  ] });
1104
1320
  }
1105
1321
  const selectedPath = Array.from(selectedItems)[0];
1106
1322
  const imageKey = selectedPath.replace(/^public\/images\//, "").replace(/^public\/originals\//, "");
1107
1323
  const imageData = _optionalChain([meta, 'optionalAccess', _4 => _4.images, 'optionalAccess', _5 => _5[imageKey]]);
1108
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.panel, children: [
1109
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles5.title, children: "Preview" }),
1110
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles5.imageContainer, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1111
- "img",
1112
- {
1113
- css: styles5.image,
1114
- src: selectedPath.replace("public", ""),
1115
- alt: "Preview"
1116
- }
1117
- ) }),
1118
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.info, children: [
1119
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfoRow, { label: "Filename", value: selectedPath.split("/").pop() || "" }),
1120
- imageData && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1121
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1122
- InfoRow,
1123
- {
1124
- label: "Original",
1125
- value: `${imageData.original.width}x${imageData.original.height}`
1126
- }
1127
- ),
1128
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1129
- InfoRow,
1130
- {
1131
- label: "File size",
1132
- value: formatFileSize3(imageData.original.fileSize)
1133
- }
1134
- ),
1135
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.section, children: [
1136
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles5.sectionTitle, children: "Generated sizes" }),
1137
- Object.entries(imageData.sizes).map(([size, data]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfoRow, { label: size, value: `${data.width}x${data.height}` }, size))
1138
- ] }),
1139
- _optionalChain([imageData, 'access', _6 => _6.cdn, 'optionalAccess', _7 => _7.synced]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.section, children: [
1140
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles5.sectionTitle, children: "CDN" }),
1141
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.cdnStatus, children: [
1142
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles5.cdnIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }),
1143
- "Synced to CDN"
1144
- ] }),
1324
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1325
+ modals,
1326
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.panel, children: [
1327
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles6.title, children: "Preview" }),
1328
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles6.imageContainer, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1329
+ "img",
1330
+ {
1331
+ css: styles6.image,
1332
+ src: selectedPath.replace("public", ""),
1333
+ alt: "Preview"
1334
+ }
1335
+ ) }),
1336
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.info, children: [
1337
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfoRow, { label: "Filename", value: selectedPath.split("/").pop() || "" }),
1338
+ imageData && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1145
1339
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1146
- "button",
1340
+ InfoRow,
1147
1341
  {
1148
- css: styles5.copyBtn,
1149
- onClick: () => {
1150
- navigator.clipboard.writeText(`${_optionalChain([imageData, 'access', _8 => _8.cdn, 'optionalAccess', _9 => _9.baseUrl])}${imageData.sizes.full.path}`);
1151
- },
1152
- children: "Copy CDN URL"
1342
+ label: "Original",
1343
+ value: `${imageData.original.width}x${imageData.original.height}`
1153
1344
  }
1154
- )
1155
- ] }),
1156
- imageData.blurhash && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.section, children: [
1157
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfoRow, { label: "Blurhash", value: imageData.blurhash, truncate: true }),
1345
+ ),
1158
1346
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1159
- "div",
1347
+ InfoRow,
1160
1348
  {
1161
- css: styles5.colorSwatch,
1162
- style: { backgroundColor: imageData.dominantColor },
1163
- title: `Dominant color: ${imageData.dominantColor}`
1349
+ label: "File size",
1350
+ value: formatFileSize3(imageData.original.fileSize)
1164
1351
  }
1165
- )
1352
+ ),
1353
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.section, children: [
1354
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.sectionTitle, children: "Generated sizes" }),
1355
+ Object.entries(imageData.sizes).map(([size, data]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfoRow, { label: size, value: `${data.width}x${data.height}` }, size))
1356
+ ] }),
1357
+ _optionalChain([imageData, 'access', _6 => _6.cdn, 'optionalAccess', _7 => _7.synced]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.section, children: [
1358
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.sectionTitle, children: "CDN" }),
1359
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.cdnStatus, children: [
1360
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.cdnIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }),
1361
+ "Synced to CDN"
1362
+ ] }),
1363
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1364
+ "button",
1365
+ {
1366
+ css: styles6.copyBtn,
1367
+ onClick: () => {
1368
+ navigator.clipboard.writeText(`${_optionalChain([imageData, 'access', _8 => _8.cdn, 'optionalAccess', _9 => _9.baseUrl])}${imageData.sizes.full.path}`);
1369
+ },
1370
+ children: "Copy CDN URL"
1371
+ }
1372
+ )
1373
+ ] }),
1374
+ imageData.blurhash && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.section, children: [
1375
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfoRow, { label: "Blurhash", value: imageData.blurhash, truncate: true }),
1376
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1377
+ "div",
1378
+ {
1379
+ css: styles6.colorSwatch,
1380
+ style: { backgroundColor: imageData.dominantColor },
1381
+ title: `Dominant color: ${imageData.dominantColor}`
1382
+ }
1383
+ )
1384
+ ] })
1166
1385
  ] })
1386
+ ] }),
1387
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.actions, children: [
1388
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles6.actionBtn, children: "Rename" }),
1389
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: [styles6.actionBtn, styles6.actionBtnDanger], onClick: handleDeleteClick, children: "Delete" })
1167
1390
  ] })
1168
- ] }),
1169
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.actions, children: [
1170
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles5.actionBtn, children: "Rename" }),
1171
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: [styles5.actionBtn, styles5.actionBtnDanger], onClick: handleDelete, children: "Delete" })
1172
1391
  ] })
1173
1392
  ] });
1174
1393
  }
1175
1394
  function InfoRow({ label, value, truncate }) {
1176
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles5.row, children: [
1177
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles5.label, children: label }),
1178
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: [styles5.value, truncate && styles5.valueTruncate], title: truncate ? value : void 0, children: value })
1395
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.row, children: [
1396
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles6.label, children: label }),
1397
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: [styles6.value, truncate && styles6.valueTruncate], title: truncate ? value : void 0, children: value })
1179
1398
  ] });
1180
1399
  }
1181
1400
  function formatFileSize3(bytes) {
@@ -1188,7 +1407,7 @@ function formatFileSize3(bytes) {
1188
1407
 
1189
1408
 
1190
1409
 
1191
- var styles6 = {
1410
+ var styles7 = {
1192
1411
  btn: _react3.css`
1193
1412
  padding: 8px;
1194
1413
  background: none;
@@ -1346,10 +1565,10 @@ var styles6 = {
1346
1565
  function StudioSettings() {
1347
1566
  const [isOpen, setIsOpen] = _react.useState.call(void 0, false);
1348
1567
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1349
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles6.btn, onClick: () => setIsOpen(true), "aria-label": "Settings", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1568
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles7.btn, onClick: () => setIsOpen(true), "aria-label": "Settings", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1350
1569
  "svg",
1351
1570
  {
1352
- css: styles6.icon,
1571
+ css: styles7.icon,
1353
1572
  xmlns: "http://www.w3.org/2000/svg",
1354
1573
  viewBox: "0 0 24 24",
1355
1574
  fill: "none",
@@ -1367,51 +1586,51 @@ function StudioSettings() {
1367
1586
  ] });
1368
1587
  }
1369
1588
  function SettingsPanel({ onClose }) {
1370
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.overlay, children: [
1371
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles6.backdrop, onClick: onClose }),
1372
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.panel, children: [
1373
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.header, children: [
1374
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { css: styles6.title, children: "Settings" }),
1375
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles6.closeBtn, onClick: onClose, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })
1589
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.overlay, children: [
1590
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles7.backdrop, onClick: onClose }),
1591
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.panel, children: [
1592
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.header, children: [
1593
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { css: styles7.title, children: "Settings" }),
1594
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles7.closeBtn, onClick: onClose, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })
1376
1595
  ] }),
1377
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.sections, children: [
1596
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.sections, children: [
1378
1597
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "section", { children: [
1379
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles6.sectionTitle, children: "Cloudflare R2" }),
1380
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.description, children: "Configure in .env.local file:" }),
1381
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.code, children: [
1382
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.codeLine, children: "CLOUDFLARE_R2_ACCOUNT_ID" }),
1383
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.codeLine, children: "CLOUDFLARE_R2_ACCESS_KEY_ID" }),
1384
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.codeLine, children: "CLOUDFLARE_R2_SECRET_ACCESS_KEY" }),
1385
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.codeLine, children: "CLOUDFLARE_R2_BUCKET_NAME" }),
1386
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.codeLine, children: "CLOUDFLARE_R2_PUBLIC_URL" })
1598
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles7.sectionTitle, children: "Cloudflare R2" }),
1599
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles7.description, children: "Configure in .env.local file:" }),
1600
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.code, children: [
1601
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles7.codeLine, children: "CLOUDFLARE_R2_ACCOUNT_ID" }),
1602
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles7.codeLine, children: "CLOUDFLARE_R2_ACCESS_KEY_ID" }),
1603
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles7.codeLine, children: "CLOUDFLARE_R2_SECRET_ACCESS_KEY" }),
1604
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles7.codeLine, children: "CLOUDFLARE_R2_BUCKET_NAME" }),
1605
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles7.codeLine, children: "CLOUDFLARE_R2_PUBLIC_URL" })
1387
1606
  ] })
1388
1607
  ] }),
1389
1608
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "section", { children: [
1390
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles6.sectionTitle, children: "Custom CDN URL" }),
1391
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.description, children: "Override the default R2 URL with a custom domain:" }),
1392
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { css: styles6.input, type: "text", placeholder: "https://cdn.yourdomain.com" })
1609
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles7.sectionTitle, children: "Custom CDN URL" }),
1610
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles7.description, children: "Override the default R2 URL with a custom domain:" }),
1611
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { css: styles7.input, type: "text", placeholder: "https://cdn.yourdomain.com" })
1393
1612
  ] }),
1394
1613
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "section", { children: [
1395
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles6.sectionTitle, children: "Thumbnail Sizes" }),
1396
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.grid, children: [
1614
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { css: styles7.sectionTitle, children: "Thumbnail Sizes" }),
1615
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.grid, children: [
1397
1616
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1398
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { css: styles6.label, children: "Small" }),
1399
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { css: styles6.input, type: "number", defaultValue: 300 })
1617
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { css: styles7.label, children: "Small" }),
1618
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { css: styles7.input, type: "number", defaultValue: 300 })
1400
1619
  ] }),
1401
1620
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1402
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { css: styles6.label, children: "Medium" }),
1403
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { css: styles6.input, type: "number", defaultValue: 700 })
1621
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { css: styles7.label, children: "Medium" }),
1622
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { css: styles7.input, type: "number", defaultValue: 700 })
1404
1623
  ] }),
1405
1624
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1406
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { css: styles6.label, children: "Large" }),
1407
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { css: styles6.input, type: "number", defaultValue: 1400 })
1625
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { css: styles7.label, children: "Large" }),
1626
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { css: styles7.input, type: "number", defaultValue: 1400 })
1408
1627
  ] })
1409
1628
  ] })
1410
1629
  ] })
1411
1630
  ] }),
1412
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.footer, children: [
1413
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles6.cancelBtn, onClick: onClose, children: "Cancel" }),
1414
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles6.saveBtn, children: "Save Changes" })
1631
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.footer, children: [
1632
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles7.cancelBtn, onClick: onClose, children: "Cancel" }),
1633
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: styles7.saveBtn, children: "Save Changes" })
1415
1634
  ] })
1416
1635
  ] })
1417
1636
  ] });
@@ -1419,7 +1638,7 @@ function SettingsPanel({ onClose }) {
1419
1638
 
1420
1639
  // src/components/StudioUI.tsx
1421
1640
 
1422
- var styles7 = {
1641
+ var styles8 = {
1423
1642
  container: _react3.css`
1424
1643
  display: flex;
1425
1644
  flex-direction: column;
@@ -1569,15 +1788,15 @@ function StudioUI({ onClose }) {
1569
1788
  refreshKey,
1570
1789
  triggerRefresh
1571
1790
  };
1572
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioContext.Provider, { value: contextValue, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.container, children: [
1573
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.header, children: [
1574
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { css: styles7.title, children: "Studio" }),
1575
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.headerActions, children: [
1791
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioContext.Provider, { value: contextValue, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.container, children: [
1792
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.header, children: [
1793
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { css: styles8.title, children: "Studio" }),
1794
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.headerActions, children: [
1576
1795
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioSettings, {}),
1577
1796
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1578
1797
  "button",
1579
1798
  {
1580
- css: styles7.closeBtn,
1799
+ css: styles8.closeBtn,
1581
1800
  onClick: onClose,
1582
1801
  "aria-label": "Close Studio",
1583
1802
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CloseIcon, {})
@@ -1587,8 +1806,8 @@ function StudioUI({ onClose }) {
1587
1806
  ] }),
1588
1807
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioToolbar, {}),
1589
1808
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioBreadcrumb, {}),
1590
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.content, children: [
1591
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles7.fileBrowser, children: viewMode === "grid" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioFileGrid, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioFileList, {}) }),
1809
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.content, children: [
1810
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles8.fileBrowser, children: viewMode === "grid" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioFileGrid, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioFileList, {}) }),
1592
1811
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StudioPreview, {})
1593
1812
  ] })
1594
1813
  ] }) });
@@ -1597,7 +1816,7 @@ function CloseIcon() {
1597
1816
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1598
1817
  "svg",
1599
1818
  {
1600
- css: styles7.closeIcon,
1819
+ css: styles8.closeIcon,
1601
1820
  xmlns: "http://www.w3.org/2000/svg",
1602
1821
  viewBox: "0 0 24 24",
1603
1822
  fill: "none",
@@ -1617,4 +1836,4 @@ var StudioUI_default = StudioUI;
1617
1836
 
1618
1837
 
1619
1838
  exports.StudioUI = StudioUI; exports.default = StudioUI_default;
1620
- //# sourceMappingURL=StudioUI-ZAD65UPD.js.map
1839
+ //# sourceMappingURL=StudioUI-ELH3QOUT.js.map