@gallop.software/studio 0.1.115 → 1.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.
@@ -341,6 +341,7 @@ function ProgressModal({
341
341
  title,
342
342
  progress,
343
343
  onClose,
344
+ onDeleteOrphans,
344
345
  onStop
345
346
  }) {
346
347
  const isComplete = progress.status === "complete";
@@ -437,6 +438,12 @@ function ProgressModal({
437
438
  ] }) }),
438
439
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles.footer, children: [
439
440
  isRunning && onStop && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: [styles.btn, styles.btnDanger], onClick: onStop, children: "Stop" }),
441
+ canClose && progress.orphanedFiles && progress.orphanedFiles.length > 0 && onDeleteOrphans && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { css: [styles.btn, styles.btnDanger], onClick: onDeleteOrphans, children: [
442
+ "Delete ",
443
+ progress.orphanedFiles.length,
444
+ " Orphan",
445
+ progress.orphanedFiles.length !== 1 ? "s" : ""
446
+ ] }),
440
447
  canClose && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { css: [styles.btn, styles.btnConfirm], onClick: onClose, children: "Done" })
441
448
  ] })
442
449
  ] }) });
@@ -1701,6 +1708,8 @@ function StudioToolbar() {
1701
1708
  const [showProcessConfirm, setShowProcessConfirm] = _react.useState.call(void 0, false);
1702
1709
  const [showSyncConfirm, setShowSyncConfirm] = _react.useState.call(void 0, false);
1703
1710
  const [syncImageCount, setSyncImageCount] = _react.useState.call(void 0, 0);
1711
+ const [syncHasRemote, setSyncHasRemote] = _react.useState.call(void 0, false);
1712
+ const [syncHasLocal, setSyncHasLocal] = _react.useState.call(void 0, false);
1704
1713
  const [showProgress, setShowProgress] = _react.useState.call(void 0, false);
1705
1714
  const [progressTitle, setProgressTitle] = _react.useState.call(void 0, "Processing Images");
1706
1715
  const [progressState, setProgressState] = _react.useState.call(void 0, {
@@ -1764,7 +1773,16 @@ function StudioToolbar() {
1764
1773
  status: "processing",
1765
1774
  currentFile: data.currentFile
1766
1775
  });
1776
+ } else if (data.type === "cleanup") {
1777
+ setProgressState((prev) => ({
1778
+ ...prev,
1779
+ message: data.message
1780
+ }));
1767
1781
  } else if (data.type === "complete") {
1782
+ let message = data.renamed > 0 ? `${data.renamed} file(s) renamed due to conflicts. ` : "";
1783
+ if (data.orphanedFiles && data.orphanedFiles.length > 0) {
1784
+ message += `Found ${data.orphanedFiles.length} orphaned thumbnail(s) in images folder.`;
1785
+ }
1768
1786
  setProgressState({
1769
1787
  current: data.total || 0,
1770
1788
  total: data.total || 0,
@@ -1773,7 +1791,8 @@ function StudioToolbar() {
1773
1791
  processed: data.added,
1774
1792
  alreadyProcessed: data.existingCount,
1775
1793
  errors: data.errors,
1776
- message: data.renamed > 0 ? `${data.renamed} file(s) renamed due to conflicts` : void 0,
1794
+ orphanedFiles: data.orphanedFiles,
1795
+ message: message || void 0,
1777
1796
  isScan: true
1778
1797
  });
1779
1798
  triggerRefresh();
@@ -2119,6 +2138,38 @@ function StudioToolbar() {
2119
2138
  abortControllerRef.current.abort();
2120
2139
  }
2121
2140
  }, []);
2141
+ const handleDeleteOrphans = _react.useCallback.call(void 0, async () => {
2142
+ const orphanedFiles = progressState.orphanedFiles;
2143
+ if (!orphanedFiles || orphanedFiles.length === 0) return;
2144
+ try {
2145
+ const response = await fetch("/api/studio/delete-orphans", {
2146
+ method: "POST",
2147
+ headers: { "Content-Type": "application/json" },
2148
+ body: JSON.stringify({ paths: orphanedFiles })
2149
+ });
2150
+ const data = await response.json();
2151
+ if (response.ok) {
2152
+ setProgressState((prev) => ({
2153
+ ...prev,
2154
+ orphanedFiles: void 0,
2155
+ orphansRemoved: data.deleted,
2156
+ message: `Deleted ${data.deleted} orphaned thumbnail${data.deleted !== 1 ? "s" : ""}.`
2157
+ }));
2158
+ triggerRefresh();
2159
+ } else {
2160
+ setAlertMessage({
2161
+ title: "Delete Failed",
2162
+ message: data.error || "Failed to delete orphaned files."
2163
+ });
2164
+ }
2165
+ } catch (error) {
2166
+ console.error("Delete orphans error:", error);
2167
+ setAlertMessage({
2168
+ title: "Delete Failed",
2169
+ message: "Failed to delete orphaned files. Check console for details."
2170
+ });
2171
+ }
2172
+ }, [progressState.orphanedFiles, triggerRefresh]);
2122
2173
  const handleDeleteClick = _react.useCallback.call(void 0, () => {
2123
2174
  if (selectedItems.size === 0) return;
2124
2175
  setShowDeleteConfirm(true);
@@ -2181,9 +2232,23 @@ function StudioToolbar() {
2181
2232
  });
2182
2233
  return;
2183
2234
  }
2235
+ let hasRemote = false;
2236
+ let hasLocal = false;
2237
+ for (const imgPath of selectedImagePaths) {
2238
+ const item = fileItems.find((f) => f.path === imgPath);
2239
+ if (item) {
2240
+ if (item.isRemote) {
2241
+ hasRemote = true;
2242
+ } else if (!item.cdnPushed) {
2243
+ hasLocal = true;
2244
+ }
2245
+ }
2246
+ }
2184
2247
  setSyncImageCount(selectedImagePaths.length);
2248
+ setSyncHasRemote(hasRemote);
2249
+ setSyncHasLocal(hasLocal);
2185
2250
  setShowSyncConfirm(true);
2186
- }, [selectedItems]);
2251
+ }, [selectedItems, fileItems]);
2187
2252
  const handleSyncConfirm = _react.useCallback.call(void 0, async () => {
2188
2253
  setShowSyncConfirm(false);
2189
2254
  const selectedPaths2 = Array.from(selectedItems);
@@ -2440,7 +2505,7 @@ function StudioToolbar() {
2440
2505
  ConfirmModal,
2441
2506
  {
2442
2507
  title: "Push to CDN",
2443
- message: `Push ${syncImageCount} image${syncImageCount !== 1 ? "s" : ""} to Cloudflare R2? Local images must be processed first. Remote images will be downloaded first. After pushing, local files will be deleted.`,
2508
+ message: `Push ${syncImageCount} image${syncImageCount !== 1 ? "s" : ""} to Cloudflare R2?${syncHasRemote ? " Remote images will be downloaded first." : ""}${syncHasLocal ? " After pushing, local files will be deleted." : ""}`,
2444
2509
  confirmLabel: "Push",
2445
2510
  onConfirm: handleSyncConfirm,
2446
2511
  onCancel: () => setShowSyncConfirm(false)
@@ -2462,6 +2527,7 @@ function StudioToolbar() {
2462
2527
  title: progressTitle,
2463
2528
  progress: progressState,
2464
2529
  onStop: handleStopProcessing,
2530
+ onDeleteOrphans: handleDeleteOrphans,
2465
2531
  onClose: () => {
2466
2532
  setShowProgress(false);
2467
2533
  setProgressState({
@@ -3371,7 +3437,7 @@ function GridItem({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3371
3437
  const [showCopied, setShowCopied] = _react.useState.call(void 0, false);
3372
3438
  const isFolder = item.type === "folder";
3373
3439
  const isImage = !isFolder && item.thumbnail !== void 0;
3374
- const isImagesFolder = isFolder && (item.name === "images" || item.path.includes("/images/"));
3440
+ const isProtected = item.isProtected || isFolder && item.name === "images" && item.path === "public/images";
3375
3441
  const handleCopyPath = (e) => {
3376
3442
  e.stopPropagation();
3377
3443
  const pathToCopy = "/" + item.path.replace(/^public\//, "");
@@ -3379,13 +3445,21 @@ function GridItem({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3379
3445
  setShowCopied(true);
3380
3446
  setTimeout(() => setShowCopied(false), 1500);
3381
3447
  };
3448
+ const handleClick = (e) => {
3449
+ if (isProtected) {
3450
+ e.stopPropagation();
3451
+ onOpen();
3452
+ return;
3453
+ }
3454
+ onClick(e);
3455
+ };
3382
3456
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3383
3457
  "div",
3384
3458
  {
3385
- css: [styles6.item, isSelected && styles6.itemSelected],
3386
- onClick,
3459
+ css: [styles6.item, isSelected && !isProtected && styles6.itemSelected],
3460
+ onClick: handleClick,
3387
3461
  children: [
3388
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3462
+ !isProtected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3389
3463
  "div",
3390
3464
  {
3391
3465
  css: styles6.checkboxWrapper,
@@ -3402,7 +3476,7 @@ function GridItem({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3402
3476
  }
3403
3477
  ),
3404
3478
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.content, children: [
3405
- item.cdnPushed && !item.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles6.statusBtn, title: "Pushed to CDN", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.cloudIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z" }) }) }),
3479
+ item.cdnPushed && !item.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles6.statusBtn, title: "Pushed to CDN", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.cloudIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" }) }) }),
3406
3480
  item.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles6.statusBtn, title: "Remote image", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.globeIcon, 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 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" }) }) }),
3407
3481
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3408
3482
  "button",
@@ -3427,7 +3501,7 @@ function GridItem({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3427
3501
  children: "Open"
3428
3502
  }
3429
3503
  ),
3430
- isFolder ? isImagesFolder ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.imagesFolderWrapper, children: [
3504
+ isFolder ? isProtected ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.imagesFolderWrapper, children: [
3431
3505
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.imagesFolderIcon, 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" }) }),
3432
3506
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.lockIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { fillRule: "evenodd", d: "M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z", clipRule: "evenodd" }) })
3433
3507
  ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.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" }) }) : isImage && item.thumbnail ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -3915,7 +3989,7 @@ function ListRow({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3915
3989
  const [showCopied, setShowCopied] = _react.useState.call(void 0, false);
3916
3990
  const isFolder = item.type === "folder";
3917
3991
  const isImage = !isFolder && item.thumbnail !== void 0;
3918
- const isImagesFolder = isFolder && (item.name === "images" || item.path.includes("/images/"));
3992
+ const isProtected = item.isProtected || isFolder && item.name === "images" && item.path === "public/images";
3919
3993
  const handleCopyPath = (e) => {
3920
3994
  e.stopPropagation();
3921
3995
  const pathToCopy = "/" + item.path.replace(/^public\//, "");
@@ -3923,18 +3997,26 @@ function ListRow({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3923
3997
  setShowCopied(true);
3924
3998
  setTimeout(() => setShowCopied(false), 1500);
3925
3999
  };
4000
+ const handleClick = (e) => {
4001
+ if (isProtected) {
4002
+ e.stopPropagation();
4003
+ onOpen();
4004
+ return;
4005
+ }
4006
+ onClick(e);
4007
+ };
3926
4008
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3927
4009
  "tr",
3928
4010
  {
3929
- css: [styles7.row, isSelected && styles7.rowSelected],
3930
- onClick,
4011
+ css: [styles7.row, isSelected && !isProtected && styles7.rowSelected],
4012
+ onClick: handleClick,
3931
4013
  children: [
3932
4014
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3933
4015
  "td",
3934
4016
  {
3935
4017
  css: [styles7.td, styles7.checkboxCell],
3936
4018
  onClick: (e) => e.stopPropagation(),
3937
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4019
+ children: !isProtected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3938
4020
  "input",
3939
4021
  {
3940
4022
  type: "checkbox",
@@ -3946,13 +4028,13 @@ function ListRow({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3946
4028
  }
3947
4029
  ),
3948
4030
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: styles7.td, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.nameCell, children: [
3949
- isFolder ? isImagesFolder ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.imagesFolderWrapper, children: [
4031
+ isFolder ? isProtected ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.imagesFolderWrapper, children: [
3950
4032
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.imagesFolderIcon, 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" }) }),
3951
4033
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.lockIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { fillRule: "evenodd", d: "M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z", clipRule: "evenodd" }) })
3952
4034
  ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles7.folderIconWrapper, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.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" }) }) }) : isImage && item.thumbnail ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles7.thumbnailWrapper, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { css: styles7.thumbnail, src: item.thumbnail, alt: item.name, loading: "lazy" }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles7.thumbnailWrapper, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.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: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) }) }),
3953
4035
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles7.name, title: item.name, children: truncateMiddle(item.name) }),
3954
4036
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.actionsCell, children: [
3955
- item.cdnPushed && !item.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles7.statusBtn, title: "Pushed to CDN", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.cloudIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z" }) }) }),
4037
+ item.cdnPushed && !item.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles7.statusBtn, title: "Pushed to CDN", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.cloudIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" }) }) }),
3956
4038
  item.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles7.statusBtn, title: "Remote image", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.globeIcon, 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 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" }) }) }),
3957
4039
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3958
4040
  "button",
@@ -4613,7 +4695,7 @@ function StudioDetailView() {
4613
4695
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles8.overlay, onClick: handleClose, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.container, onClick: (e) => e.stopPropagation(), children: [
4614
4696
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.main, children: [
4615
4697
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.headerButtons, children: [
4616
- focusedItem.cdnPushed && !focusedItem.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles8.statusIcon, title: "Pushed to CDN", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles8.cloudIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z" }) }) }),
4698
+ focusedItem.cdnPushed && !focusedItem.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles8.statusIcon, title: "Pushed to CDN", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles8.cloudIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" }) }) }),
4617
4699
  focusedItem.isRemote && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles8.statusIcon, title: "Remote image", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles8.globeIcon, 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 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" }) }) }),
4618
4700
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { css: styles8.copyBtn, onClick: handleCopyPath, title: "Copy file path", children: [
4619
4701
  showCopied && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles8.tooltip, children: "Copied!" }),
@@ -5680,4 +5762,4 @@ var StudioUI_default = StudioUI;
5680
5762
 
5681
5763
 
5682
5764
  exports.StudioUI = StudioUI; exports.default = StudioUI_default;
5683
- //# sourceMappingURL=StudioUI-OVL65ONP.js.map
5765
+ //# sourceMappingURL=StudioUI-GWMM47P7.js.map