@gallop.software/studio 0.1.83 → 0.1.84

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.
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-HXE6XCG2.mjs";
8
8
 
9
9
  // src/components/StudioUI.tsx
10
- import { useEffect as useEffect3, useCallback as useCallback3, useState as useState8 } from "react";
10
+ import { useEffect as useEffect3, useCallback as useCallback3, useState as useState9 } from "react";
11
11
  import { css as css10 } from "@emotion/react";
12
12
 
13
13
  // src/components/StudioContext.tsx
@@ -65,7 +65,7 @@ function useStudio() {
65
65
  }
66
66
 
67
67
  // src/components/StudioToolbar.tsx
68
- import { useCallback, useRef, useState as useState2 } from "react";
68
+ import { useCallback, useRef, useState as useState3 } from "react";
69
69
  import { css as css4, keyframes as keyframes3 } from "@emotion/react";
70
70
 
71
71
  // src/components/StudioModal.tsx
@@ -675,8 +675,14 @@ function StudioFolderPicker({ selectedItems, currentPath, onMove, onCancel }) {
675
675
  }
676
676
 
677
677
  // src/components/R2SetupModal.tsx
678
+ import { useState as useState2 } from "react";
678
679
  import { css as css3 } from "@emotion/react";
679
680
  import { jsx as jsx3, jsxs as jsxs3 } from "@emotion/react/jsx-runtime";
681
+ var ENV_TEMPLATE = `CLOUDFLARE_R2_ACCOUNT_ID=your_account_id
682
+ CLOUDFLARE_R2_ACCESS_KEY_ID=your_access_key
683
+ CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_secret_key
684
+ CLOUDFLARE_R2_BUCKET_NAME=your_bucket_name
685
+ CLOUDFLARE_R2_PUBLIC_URL=https://pub-xxx.r2.dev`;
680
686
  var styles3 = {
681
687
  overlay: css3`
682
688
  position: fixed;
@@ -793,12 +799,16 @@ var styles3 = {
793
799
  text-decoration: underline;
794
800
  }
795
801
  `,
802
+ envVarsWrapper: css3`
803
+ position: relative;
804
+ margin-top: 20px;
805
+ `,
796
806
  envVars: css3`
797
807
  background: ${colors.background};
798
808
  border: 1px solid ${colors.border};
799
809
  border-radius: 8px;
800
810
  padding: 16px;
801
- margin-top: 20px;
811
+ padding-right: 48px;
802
812
  font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
803
813
  font-size: 13px;
804
814
  line-height: 1.8;
@@ -814,6 +824,57 @@ var styles3 = {
814
824
  envValue: css3`
815
825
  color: ${colors.textSecondary};
816
826
  `,
827
+ copyBtn: css3`
828
+ position: absolute;
829
+ top: 8px;
830
+ right: 8px;
831
+ width: 32px;
832
+ height: 32px;
833
+ display: flex;
834
+ align-items: center;
835
+ justify-content: center;
836
+ background: ${colors.surface};
837
+ border: 1px solid ${colors.border};
838
+ border-radius: 6px;
839
+ cursor: pointer;
840
+ color: ${colors.textMuted};
841
+ transition: all 0.15s ease;
842
+
843
+ &:hover {
844
+ background: ${colors.surfaceHover};
845
+ color: ${colors.text};
846
+ border-color: #d0d5dd;
847
+ }
848
+ `,
849
+ copyIcon: css3`
850
+ width: 16px;
851
+ height: 16px;
852
+ `,
853
+ copiedTooltip: css3`
854
+ position: absolute;
855
+ top: 50%;
856
+ right: 100%;
857
+ transform: translateY(-50%);
858
+ background: #1a1f36;
859
+ color: white;
860
+ padding: 4px 8px;
861
+ border-radius: 4px;
862
+ font-size: 12px;
863
+ white-space: nowrap;
864
+ margin-right: 6px;
865
+ pointer-events: none;
866
+
867
+ &::before {
868
+ content: '';
869
+ position: absolute;
870
+ right: -4px;
871
+ top: 50%;
872
+ transform: translateY(-50%);
873
+ border-left: 4px solid #1a1f36;
874
+ border-top: 4px solid transparent;
875
+ border-bottom: 4px solid transparent;
876
+ }
877
+ `,
817
878
  footer: css3`
818
879
  padding: 16px 24px;
819
880
  border-top: 1px solid ${colors.border};
@@ -862,6 +923,16 @@ var styles3 = {
862
923
  `
863
924
  };
864
925
  function R2SetupModal({ isOpen, onClose }) {
926
+ const [copied, setCopied] = useState2(false);
927
+ const handleCopy = async () => {
928
+ try {
929
+ await navigator.clipboard.writeText(ENV_TEMPLATE);
930
+ setCopied(true);
931
+ setTimeout(() => setCopied(false), 2e3);
932
+ } catch (error) {
933
+ console.error("Failed to copy:", error);
934
+ }
935
+ };
865
936
  if (!isOpen) return null;
866
937
  return /* @__PURE__ */ jsx3("div", { css: styles3.overlay, onClick: onClose, children: /* @__PURE__ */ jsxs3("div", { css: styles3.modal, onClick: (e) => e.stopPropagation(), children: [
867
938
  /* @__PURE__ */ jsxs3("div", { css: styles3.header, children: [
@@ -926,31 +997,37 @@ function R2SetupModal({ isOpen, onClose }) {
926
997
  ] })
927
998
  ] })
928
999
  ] }),
929
- /* @__PURE__ */ jsxs3("div", { css: styles3.envVars, children: [
930
- /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
931
- /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_ACCOUNT_ID" }),
932
- "=",
933
- /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "your_account_id" })
934
- ] }),
935
- /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
936
- /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_ACCESS_KEY_ID" }),
937
- "=",
938
- /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "your_access_key" })
939
- ] }),
940
- /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
941
- /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_SECRET_ACCESS_KEY" }),
942
- "=",
943
- /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "your_secret_key" })
944
- ] }),
945
- /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
946
- /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_BUCKET_NAME" }),
947
- "=",
948
- /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "your_bucket_name" })
1000
+ /* @__PURE__ */ jsxs3("div", { css: styles3.envVarsWrapper, children: [
1001
+ /* @__PURE__ */ jsxs3("div", { css: styles3.envVars, children: [
1002
+ /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
1003
+ /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_ACCOUNT_ID" }),
1004
+ "=",
1005
+ /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "your_account_id" })
1006
+ ] }),
1007
+ /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
1008
+ /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_ACCESS_KEY_ID" }),
1009
+ "=",
1010
+ /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "your_access_key" })
1011
+ ] }),
1012
+ /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
1013
+ /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_SECRET_ACCESS_KEY" }),
1014
+ "=",
1015
+ /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "your_secret_key" })
1016
+ ] }),
1017
+ /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
1018
+ /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_BUCKET_NAME" }),
1019
+ "=",
1020
+ /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "your_bucket_name" })
1021
+ ] }),
1022
+ /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
1023
+ /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_PUBLIC_URL" }),
1024
+ "=",
1025
+ /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "https://pub-xxx.r2.dev" })
1026
+ ] })
949
1027
  ] }),
950
- /* @__PURE__ */ jsxs3("span", { css: styles3.envVar, children: [
951
- /* @__PURE__ */ jsx3("span", { css: styles3.envKey, children: "CLOUDFLARE_R2_PUBLIC_URL" }),
952
- "=",
953
- /* @__PURE__ */ jsx3("span", { css: styles3.envValue, children: "https://pub-xxx.r2.dev" })
1028
+ /* @__PURE__ */ jsxs3("button", { css: styles3.copyBtn, onClick: handleCopy, title: "Copy to clipboard", children: [
1029
+ copied && /* @__PURE__ */ jsx3("span", { css: styles3.copiedTooltip, children: "Copied!" }),
1030
+ /* @__PURE__ */ jsx3("svg", { css: styles3.copyIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" }) })
954
1031
  ] })
955
1032
  ] })
956
1033
  ] }),
@@ -1178,27 +1255,27 @@ function StudioToolbar() {
1178
1255
  const { selectedItems, viewMode, setViewMode, clearSelection, currentPath, triggerRefresh, focusedItem } = useStudio();
1179
1256
  const fileInputRef = useRef(null);
1180
1257
  const abortControllerRef = useRef(null);
1181
- const [uploading, setUploading] = useState2(false);
1182
- const [refreshing, setRefreshing] = useState2(false);
1183
- const [processing, setProcessing] = useState2(false);
1184
- const [showDeleteConfirm, setShowDeleteConfirm] = useState2(false);
1185
- const [showProcessConfirm, setShowProcessConfirm] = useState2(false);
1186
- const [showProgress, setShowProgress] = useState2(false);
1187
- const [progressState, setProgressState] = useState2({
1258
+ const [uploading, setUploading] = useState3(false);
1259
+ const [refreshing, setRefreshing] = useState3(false);
1260
+ const [processing, setProcessing] = useState3(false);
1261
+ const [showDeleteConfirm, setShowDeleteConfirm] = useState3(false);
1262
+ const [showProcessConfirm, setShowProcessConfirm] = useState3(false);
1263
+ const [showProgress, setShowProgress] = useState3(false);
1264
+ const [progressState, setProgressState] = useState3({
1188
1265
  current: 0,
1189
1266
  total: 0,
1190
1267
  percent: 0,
1191
1268
  status: "processing"
1192
1269
  });
1193
- const [processCount, setProcessCount] = useState2(0);
1194
- const [processMode, setProcessMode] = useState2("all");
1195
- const [imagesToProcess, setImagesToProcess] = useState2([]);
1196
- const [alertMessage, setAlertMessage] = useState2(null);
1197
- const [showNewFolderModal, setShowNewFolderModal] = useState2(false);
1198
- const [showRenameFolderModal, setShowRenameFolderModal] = useState2(false);
1199
- const [showMoveModal, setShowMoveModal] = useState2(false);
1200
- const [showR2SetupModal, setShowR2SetupModal] = useState2(false);
1201
- const [syncing, setSyncing] = useState2(false);
1270
+ const [processCount, setProcessCount] = useState3(0);
1271
+ const [processMode, setProcessMode] = useState3("all");
1272
+ const [imagesToProcess, setImagesToProcess] = useState3([]);
1273
+ const [alertMessage, setAlertMessage] = useState3(null);
1274
+ const [showNewFolderModal, setShowNewFolderModal] = useState3(false);
1275
+ const [showRenameFolderModal, setShowRenameFolderModal] = useState3(false);
1276
+ const [showMoveModal, setShowMoveModal] = useState3(false);
1277
+ const [showR2SetupModal, setShowR2SetupModal] = useState3(false);
1278
+ const [syncing, setSyncing] = useState3(false);
1202
1279
  const isInImagesFolder = currentPath === "public/images" || currentPath.startsWith("public/images/");
1203
1280
  const handleUpload = useCallback(() => {
1204
1281
  fileInputRef.current?.click();
@@ -1915,11 +1992,11 @@ function ImageStackIcon() {
1915
1992
  }
1916
1993
 
1917
1994
  // src/components/StudioFileGrid.tsx
1918
- import { useState as useState4 } from "react";
1995
+ import { useState as useState5 } from "react";
1919
1996
  import { css as css5, keyframes as keyframes4 } from "@emotion/react";
1920
1997
 
1921
1998
  // src/hooks/useFileList.ts
1922
- import { useEffect as useEffect2, useState as useState3, useRef as useRef2, useCallback as useCallback2 } from "react";
1999
+ import { useEffect as useEffect2, useState as useState4, useRef as useRef2, useCallback as useCallback2 } from "react";
1923
2000
 
1924
2001
  // src/lib/api.ts
1925
2002
  var StudioApiClient = class {
@@ -2018,8 +2095,8 @@ function useFileList() {
2018
2095
  searchQuery,
2019
2096
  showError
2020
2097
  } = useStudio();
2021
- const [items, setItems] = useState3([]);
2022
- const [loading, setLoading] = useState3(true);
2098
+ const [items, setItems] = useState4([]);
2099
+ const [loading, setLoading] = useState4(true);
2023
2100
  const isInitialLoad = useRef2(true);
2024
2101
  const lastPath = useRef2(currentPath);
2025
2102
  useEffect2(() => {
@@ -2499,7 +2576,7 @@ function StudioFileGrid() {
2499
2576
  ] });
2500
2577
  }
2501
2578
  function GridItem({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
2502
- const [showCopied, setShowCopied] = useState4(false);
2579
+ const [showCopied, setShowCopied] = useState5(false);
2503
2580
  const isFolder = item.type === "folder";
2504
2581
  const isImage = !isFolder && item.thumbnail !== void 0;
2505
2582
  const isImagesFolder = isFolder && (item.name === "images" || item.path.includes("/images/"));
@@ -2616,7 +2693,7 @@ function truncateMiddle(str, maxLength = 24) {
2616
2693
  }
2617
2694
 
2618
2695
  // src/components/StudioFileList.tsx
2619
- import { useState as useState5 } from "react";
2696
+ import { useState as useState6 } from "react";
2620
2697
  import { css as css6, keyframes as keyframes5 } from "@emotion/react";
2621
2698
  import { jsx as jsx6, jsxs as jsxs6 } from "@emotion/react/jsx-runtime";
2622
2699
  var spin3 = keyframes5`
@@ -2993,7 +3070,7 @@ function StudioFileList() {
2993
3070
  ] }) });
2994
3071
  }
2995
3072
  function ListRow({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
2996
- const [showCopied, setShowCopied] = useState5(false);
3073
+ const [showCopied, setShowCopied] = useState6(false);
2997
3074
  const isFolder = item.type === "folder";
2998
3075
  const isImage = !isFolder && item.thumbnail !== void 0;
2999
3076
  const isImagesFolder = isFolder && (item.name === "images" || item.path.includes("/images/"));
@@ -3099,7 +3176,7 @@ function truncateMiddle2(str, maxLength = 32) {
3099
3176
  }
3100
3177
 
3101
3178
  // src/components/StudioDetailView.tsx
3102
- import { useState as useState6 } from "react";
3179
+ import { useState as useState7 } from "react";
3103
3180
  import { css as css7 } from "@emotion/react";
3104
3181
  import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "@emotion/react/jsx-runtime";
3105
3182
  var IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".ico", ".bmp", ".tiff", ".tif"];
@@ -3360,14 +3437,14 @@ var styles7 = {
3360
3437
  };
3361
3438
  function StudioDetailView() {
3362
3439
  const { focusedItem, setFocusedItem, triggerRefresh, clearSelection } = useStudio();
3363
- const [showDeleteConfirm, setShowDeleteConfirm] = useState6(false);
3364
- const [showRenameModal, setShowRenameModal] = useState6(false);
3365
- const [showProcessConfirm, setShowProcessConfirm] = useState6(false);
3366
- const [showR2SetupModal, setShowR2SetupModal] = useState6(false);
3367
- const [processProgress, setProcessProgress] = useState6(null);
3368
- const [alertMessage, setAlertMessage] = useState6(null);
3369
- const [showCopied, setShowCopied] = useState6(false);
3370
- const [syncing, setSyncing] = useState6(false);
3440
+ const [showDeleteConfirm, setShowDeleteConfirm] = useState7(false);
3441
+ const [showRenameModal, setShowRenameModal] = useState7(false);
3442
+ const [showProcessConfirm, setShowProcessConfirm] = useState7(false);
3443
+ const [showR2SetupModal, setShowR2SetupModal] = useState7(false);
3444
+ const [processProgress, setProcessProgress] = useState7(null);
3445
+ const [alertMessage, setAlertMessage] = useState7(null);
3446
+ const [showCopied, setShowCopied] = useState7(false);
3447
+ const [syncing, setSyncing] = useState7(false);
3371
3448
  if (!focusedItem) return null;
3372
3449
  const isImage = isImageFile(focusedItem.name);
3373
3450
  const isVideo = isVideoFile(focusedItem.name);
@@ -3668,7 +3745,7 @@ function formatFileSize3(bytes) {
3668
3745
  }
3669
3746
 
3670
3747
  // src/components/StudioSettings.tsx
3671
- import { useState as useState7 } from "react";
3748
+ import { useState as useState8 } from "react";
3672
3749
  import { css as css8 } from "@emotion/react";
3673
3750
  import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs8 } from "@emotion/react/jsx-runtime";
3674
3751
  var btnHeight2 = "36px";
@@ -3908,7 +3985,7 @@ var styles8 = {
3908
3985
  `
3909
3986
  };
3910
3987
  function StudioSettings() {
3911
- const [isOpen, setIsOpen] = useState7(false);
3988
+ const [isOpen, setIsOpen] = useState8(false);
3912
3989
  return /* @__PURE__ */ jsxs8(Fragment4, { children: [
3913
3990
  /* @__PURE__ */ jsx8("button", { css: styles8.btn, onClick: () => setIsOpen(true), "aria-label": "Settings", children: /* @__PURE__ */ jsxs8(
3914
3991
  "svg",
@@ -3936,7 +4013,7 @@ CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_secret_access_key_here
3936
4013
  CLOUDFLARE_R2_BUCKET_NAME=my-images-bucket
3937
4014
  CLOUDFLARE_R2_PUBLIC_URL=https://cdn.yourdomain.com`;
3938
4015
  function SettingsPanel({ onClose }) {
3939
- const [copied, setCopied] = useState7(false);
4016
+ const [copied, setCopied] = useState8(false);
3940
4017
  const handleCopy = () => {
3941
4018
  navigator.clipboard.writeText(envTemplate);
3942
4019
  setCopied(true);
@@ -4206,17 +4283,17 @@ var styles10 = {
4206
4283
  `
4207
4284
  };
4208
4285
  function StudioUI({ onClose, isVisible = true }) {
4209
- const [currentPath, setCurrentPathInternal] = useState8("public");
4210
- const [selectedItems, setSelectedItems] = useState8(/* @__PURE__ */ new Set());
4211
- const [lastSelectedPath, setLastSelectedPath] = useState8(null);
4212
- const [viewMode, setViewMode] = useState8("grid");
4213
- const [focusedItem, setFocusedItem] = useState8(null);
4214
- const [meta, setMeta] = useState8(null);
4215
- const [isLoading, setIsLoading] = useState8(false);
4216
- const [refreshKey, setRefreshKey] = useState8(0);
4217
- const [searchQuery, setSearchQuery] = useState8("");
4218
- const [error, setError] = useState8(null);
4219
- const [isDragging, setIsDragging] = useState8(false);
4286
+ const [currentPath, setCurrentPathInternal] = useState9("public");
4287
+ const [selectedItems, setSelectedItems] = useState9(/* @__PURE__ */ new Set());
4288
+ const [lastSelectedPath, setLastSelectedPath] = useState9(null);
4289
+ const [viewMode, setViewMode] = useState9("grid");
4290
+ const [focusedItem, setFocusedItem] = useState9(null);
4291
+ const [meta, setMeta] = useState9(null);
4292
+ const [isLoading, setIsLoading] = useState9(false);
4293
+ const [refreshKey, setRefreshKey] = useState9(0);
4294
+ const [searchQuery, setSearchQuery] = useState9("");
4295
+ const [error, setError] = useState9(null);
4296
+ const [isDragging, setIsDragging] = useState9(false);
4220
4297
  const triggerRefresh = useCallback3(() => {
4221
4298
  setRefreshKey((k) => k + 1);
4222
4299
  }, []);
@@ -4442,4 +4519,4 @@ export {
4442
4519
  StudioUI,
4443
4520
  StudioUI_default as default
4444
4521
  };
4445
- //# sourceMappingURL=StudioUI-XV7HCEAF.mjs.map
4522
+ //# sourceMappingURL=StudioUI-EER6PAXH.mjs.map