@sparkstudio/storage-ui 1.0.34 → 1.0.35
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.
- package/dist/index.cjs +396 -219
- package/dist/index.d.cts +1 -10
- package/dist/index.d.ts +1 -10
- package/dist/index.js +460 -283
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -234,7 +234,7 @@ var ContainerType = /* @__PURE__ */ ((ContainerType2) => {
|
|
|
234
234
|
})(ContainerType || {});
|
|
235
235
|
|
|
236
236
|
// src/components/ContainerIdGridPanel.tsx
|
|
237
|
-
import { useEffect
|
|
237
|
+
import { useEffect as useEffect3, useMemo, useRef, useState as useState4 } from "react";
|
|
238
238
|
|
|
239
239
|
// src/hooks/UseUploadManager.ts
|
|
240
240
|
import { useState, useCallback } from "react";
|
|
@@ -467,13 +467,20 @@ var UploadProgressList = ({
|
|
|
467
467
|
};
|
|
468
468
|
|
|
469
469
|
// src/components/FileIconGrid.tsx
|
|
470
|
-
import "react";
|
|
470
|
+
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
471
471
|
|
|
472
472
|
// src/components/FileIconCard.tsx
|
|
473
|
-
import {
|
|
474
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
475
|
-
function
|
|
476
|
-
|
|
473
|
+
import { useEffect, useState as useState2 } from "react";
|
|
474
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
475
|
+
function useIsMobile(breakpoint = 640) {
|
|
476
|
+
const getValue = () => typeof window !== "undefined" ? window.innerWidth <= breakpoint : false;
|
|
477
|
+
const [isMobile, setIsMobile] = useState2(getValue);
|
|
478
|
+
useEffect(() => {
|
|
479
|
+
const onResize = () => setIsMobile(getValue());
|
|
480
|
+
window.addEventListener("resize", onResize);
|
|
481
|
+
return () => window.removeEventListener("resize", onResize);
|
|
482
|
+
}, [breakpoint]);
|
|
483
|
+
return isMobile;
|
|
477
484
|
}
|
|
478
485
|
var FileIconCard = (props) => {
|
|
479
486
|
const {
|
|
@@ -483,17 +490,12 @@ var FileIconCard = (props) => {
|
|
|
483
490
|
onSelect,
|
|
484
491
|
onDeleteFile,
|
|
485
492
|
onClickFile,
|
|
486
|
-
icon,
|
|
487
|
-
iconHtml,
|
|
488
493
|
title,
|
|
489
494
|
className
|
|
490
495
|
} = props;
|
|
496
|
+
const isMobile = useIsMobile();
|
|
491
497
|
const [deleting, setDeleting] = useState2(false);
|
|
492
498
|
const [error, setError] = useState2(null);
|
|
493
|
-
const safeIconHtml = useMemo(() => {
|
|
494
|
-
if (!iconHtml) return null;
|
|
495
|
-
return sanitizeIconHtml(iconHtml);
|
|
496
|
-
}, [iconHtml]);
|
|
497
499
|
const canDelete = !!onDeleteFile && !deleteDisabled && !deleting;
|
|
498
500
|
const handleClick = () => {
|
|
499
501
|
onSelect?.(file);
|
|
@@ -535,69 +537,115 @@ var FileIconCard = (props) => {
|
|
|
535
537
|
title: title ?? file.Name ?? "File",
|
|
536
538
|
style: {
|
|
537
539
|
display: "flex",
|
|
538
|
-
|
|
539
|
-
gap:
|
|
540
|
-
padding: 12,
|
|
540
|
+
flexDirection: "column",
|
|
541
|
+
gap: 10,
|
|
542
|
+
padding: isMobile ? 14 : 12,
|
|
541
543
|
border: `1px solid ${borderColor}`,
|
|
542
544
|
boxShadow,
|
|
543
|
-
borderRadius:
|
|
545
|
+
borderRadius: 16,
|
|
544
546
|
userSelect: "none",
|
|
545
547
|
cursor: "pointer",
|
|
546
|
-
background: "white"
|
|
548
|
+
background: "white",
|
|
549
|
+
minWidth: 0,
|
|
550
|
+
width: "100%",
|
|
551
|
+
boxSizing: "border-box"
|
|
547
552
|
},
|
|
548
553
|
children: [
|
|
549
|
-
/* @__PURE__ */
|
|
554
|
+
/* @__PURE__ */ jsxs2(
|
|
550
555
|
"div",
|
|
551
556
|
{
|
|
552
557
|
style: {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
flex: "0 0 auto"
|
|
558
|
+
display: "flex",
|
|
559
|
+
alignItems: "center",
|
|
560
|
+
justifyContent: "space-between",
|
|
561
|
+
gap: 12,
|
|
562
|
+
minWidth: 0,
|
|
563
|
+
width: "100%"
|
|
560
564
|
},
|
|
561
|
-
children:
|
|
565
|
+
children: [
|
|
566
|
+
/* @__PURE__ */ jsxs2(
|
|
567
|
+
"div",
|
|
568
|
+
{
|
|
569
|
+
style: {
|
|
570
|
+
minWidth: 0,
|
|
571
|
+
flex: "1 1 auto",
|
|
572
|
+
overflow: "hidden"
|
|
573
|
+
},
|
|
574
|
+
children: [
|
|
575
|
+
/* @__PURE__ */ jsx2(
|
|
576
|
+
"div",
|
|
577
|
+
{
|
|
578
|
+
style: {
|
|
579
|
+
fontWeight: 700,
|
|
580
|
+
fontSize: isMobile ? 15 : 14,
|
|
581
|
+
lineHeight: 1.2,
|
|
582
|
+
overflow: "hidden",
|
|
583
|
+
textOverflow: "ellipsis",
|
|
584
|
+
whiteSpace: "nowrap"
|
|
585
|
+
},
|
|
586
|
+
children: title ?? file.Name ?? "Untitled"
|
|
587
|
+
}
|
|
588
|
+
),
|
|
589
|
+
/* @__PURE__ */ jsx2(
|
|
590
|
+
"div",
|
|
591
|
+
{
|
|
592
|
+
style: {
|
|
593
|
+
fontSize: 12,
|
|
594
|
+
opacity: 0.7,
|
|
595
|
+
marginTop: 4,
|
|
596
|
+
overflow: "hidden",
|
|
597
|
+
textOverflow: "ellipsis",
|
|
598
|
+
whiteSpace: "nowrap"
|
|
599
|
+
},
|
|
600
|
+
children: typeof file.FileSize === "number" ? formatBytes(file.FileSize) : ""
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
]
|
|
604
|
+
}
|
|
605
|
+
),
|
|
606
|
+
!deleteDisabled ? /* @__PURE__ */ jsxs2(
|
|
607
|
+
"button",
|
|
608
|
+
{
|
|
609
|
+
type: "button",
|
|
610
|
+
onClick: handleDelete,
|
|
611
|
+
disabled: !canDelete,
|
|
612
|
+
"aria-label": deleting ? "Deleting file" : "Delete file",
|
|
613
|
+
title: deleting ? "Deleting..." : "Delete",
|
|
614
|
+
style: {
|
|
615
|
+
flex: "0 0 auto",
|
|
616
|
+
width: isMobile ? 40 : "auto",
|
|
617
|
+
height: isMobile ? 40 : "auto",
|
|
618
|
+
minWidth: isMobile ? 40 : 110,
|
|
619
|
+
border: "1px solid rgba(0,0,0,0.18)",
|
|
620
|
+
background: canDelete ? "white" : "rgba(0,0,0,0.04)",
|
|
621
|
+
borderRadius: 12,
|
|
622
|
+
padding: isMobile ? 0 : "8px 10px",
|
|
623
|
+
cursor: canDelete ? "pointer" : "not-allowed",
|
|
624
|
+
display: "flex",
|
|
625
|
+
alignItems: "center",
|
|
626
|
+
justifyContent: "center",
|
|
627
|
+
gap: 8,
|
|
628
|
+
boxSizing: "border-box"
|
|
629
|
+
},
|
|
630
|
+
children: [
|
|
631
|
+
deleting ? /* @__PURE__ */ jsx2(SmallSpinner, {}) : /* @__PURE__ */ jsx2(TrashIcon, {}),
|
|
632
|
+
!isMobile ? /* @__PURE__ */ jsx2("span", { style: { fontSize: 14, fontWeight: 600 }, children: deleting ? "Deleting\u2026" : "Delete" }) : null
|
|
633
|
+
]
|
|
634
|
+
}
|
|
635
|
+
) : null
|
|
636
|
+
]
|
|
562
637
|
}
|
|
563
638
|
),
|
|
564
|
-
/* @__PURE__ */
|
|
565
|
-
|
|
566
|
-
"div",
|
|
567
|
-
{
|
|
568
|
-
style: {
|
|
569
|
-
fontWeight: 600,
|
|
570
|
-
overflow: "hidden",
|
|
571
|
-
textOverflow: "ellipsis",
|
|
572
|
-
whiteSpace: "nowrap"
|
|
573
|
-
},
|
|
574
|
-
children: title ?? file.Name ?? "Untitled"
|
|
575
|
-
}
|
|
576
|
-
),
|
|
577
|
-
/* @__PURE__ */ jsx2("div", { style: { fontSize: 12, opacity: 0.7 }, children: typeof file.FileSize === "number" ? formatBytes(file.FileSize) : "" }),
|
|
578
|
-
error ? /* @__PURE__ */ jsx2("div", { style: { fontSize: 12, color: "crimson", marginTop: 4 }, children: error }) : null
|
|
579
|
-
] }),
|
|
580
|
-
!deleteDisabled ? /* @__PURE__ */ jsxs2(
|
|
581
|
-
"button",
|
|
639
|
+
error ? /* @__PURE__ */ jsx2(
|
|
640
|
+
"div",
|
|
582
641
|
{
|
|
583
|
-
type: "button",
|
|
584
|
-
onClick: handleDelete,
|
|
585
|
-
disabled: !canDelete,
|
|
586
|
-
"aria-label": "Delete file",
|
|
587
642
|
style: {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
cursor: canDelete ? "pointer" : "not-allowed",
|
|
593
|
-
display: "flex",
|
|
594
|
-
alignItems: "center",
|
|
595
|
-
gap: 8
|
|
643
|
+
fontSize: 12,
|
|
644
|
+
color: "crimson",
|
|
645
|
+
marginTop: -2,
|
|
646
|
+
wordBreak: "break-word"
|
|
596
647
|
},
|
|
597
|
-
children:
|
|
598
|
-
deleting ? /* @__PURE__ */ jsx2(SmallSpinner, {}) : /* @__PURE__ */ jsx2(TrashIcon, {}),
|
|
599
|
-
/* @__PURE__ */ jsx2("span", { style: { fontSize: 13 }, children: deleting ? "Deleting\u2026" : "Delete" })
|
|
600
|
-
]
|
|
648
|
+
children: error
|
|
601
649
|
}
|
|
602
650
|
) : null
|
|
603
651
|
]
|
|
@@ -616,33 +664,33 @@ function formatBytes(bytes) {
|
|
|
616
664
|
return `${v.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
|
|
617
665
|
}
|
|
618
666
|
function SmallSpinner() {
|
|
619
|
-
return /* @__PURE__ */
|
|
620
|
-
"
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
animation: "fileIconSpin 0.8s linear infinite"
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
);
|
|
634
|
-
}
|
|
635
|
-
function DefaultFileIcon() {
|
|
636
|
-
return /* @__PURE__ */ jsxs2("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, children: [
|
|
667
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
668
|
+
/* @__PURE__ */ jsx2("style", { children: `
|
|
669
|
+
@keyframes fileIconSpin {
|
|
670
|
+
from {
|
|
671
|
+
transform: rotate(0deg);
|
|
672
|
+
}
|
|
673
|
+
to {
|
|
674
|
+
transform: rotate(360deg);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
` }),
|
|
637
678
|
/* @__PURE__ */ jsx2(
|
|
638
|
-
"
|
|
679
|
+
"span",
|
|
639
680
|
{
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
681
|
+
"aria-hidden": true,
|
|
682
|
+
style: {
|
|
683
|
+
width: 14,
|
|
684
|
+
height: 14,
|
|
685
|
+
borderRadius: "50%",
|
|
686
|
+
border: "2px solid rgba(0,0,0,0.2)",
|
|
687
|
+
borderTopColor: "rgba(0,0,0,0.7)",
|
|
688
|
+
display: "inline-block",
|
|
689
|
+
boxSizing: "border-box",
|
|
690
|
+
animation: "fileIconSpin 0.8s linear infinite"
|
|
691
|
+
}
|
|
643
692
|
}
|
|
644
|
-
)
|
|
645
|
-
/* @__PURE__ */ jsx2("path", { d: "M14 3v4a1 1 0 0 0 1 1h4", stroke: "currentColor", strokeWidth: "2" })
|
|
693
|
+
)
|
|
646
694
|
] });
|
|
647
695
|
}
|
|
648
696
|
function TrashIcon() {
|
|
@@ -678,25 +726,29 @@ function TrashIcon() {
|
|
|
678
726
|
|
|
679
727
|
// src/components/FileIconGrid.tsx
|
|
680
728
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
729
|
+
function useIsMobile2(breakpoint = 640) {
|
|
730
|
+
const getValue = () => typeof window !== "undefined" ? window.innerWidth <= breakpoint : false;
|
|
731
|
+
const [isMobile, setIsMobile] = useState3(getValue);
|
|
732
|
+
useEffect2(() => {
|
|
733
|
+
const onResize = () => setIsMobile(getValue());
|
|
734
|
+
window.addEventListener("resize", onResize);
|
|
735
|
+
return () => window.removeEventListener("resize", onResize);
|
|
736
|
+
}, [breakpoint]);
|
|
737
|
+
return isMobile;
|
|
738
|
+
}
|
|
681
739
|
function FileIconGrid(props) {
|
|
682
|
-
const {
|
|
683
|
-
|
|
684
|
-
deleteDisabled,
|
|
685
|
-
onDeleted,
|
|
686
|
-
selectedId,
|
|
687
|
-
onSelect,
|
|
688
|
-
icon,
|
|
689
|
-
iconHtml,
|
|
690
|
-
className
|
|
691
|
-
} = props;
|
|
740
|
+
const { files, deleteDisabled, onDeleted, selectedId, onSelect, className } = props;
|
|
741
|
+
const isMobile = useIsMobile2();
|
|
692
742
|
return /* @__PURE__ */ jsx3(
|
|
693
743
|
"div",
|
|
694
744
|
{
|
|
695
745
|
className,
|
|
696
746
|
style: {
|
|
697
747
|
display: "grid",
|
|
698
|
-
gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
|
|
699
|
-
gap: 12
|
|
748
|
+
gridTemplateColumns: isMobile ? "minmax(0, 1fr)" : "repeat(auto-fill, minmax(280px, 1fr))",
|
|
749
|
+
gap: 12,
|
|
750
|
+
width: "100%",
|
|
751
|
+
minWidth: 0
|
|
700
752
|
},
|
|
701
753
|
children: files.map((f) => /* @__PURE__ */ jsx3(
|
|
702
754
|
FileIconCard,
|
|
@@ -705,9 +757,7 @@ function FileIconGrid(props) {
|
|
|
705
757
|
deleteDisabled,
|
|
706
758
|
onDeleteFile: onDeleted,
|
|
707
759
|
onSelect,
|
|
708
|
-
selected: selectedId === f.Id
|
|
709
|
-
icon,
|
|
710
|
-
iconHtml
|
|
760
|
+
selected: selectedId === f.Id
|
|
711
761
|
},
|
|
712
762
|
f.Id
|
|
713
763
|
))
|
|
@@ -717,6 +767,16 @@ function FileIconGrid(props) {
|
|
|
717
767
|
|
|
718
768
|
// src/components/ContainerIdGridPanel.tsx
|
|
719
769
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
770
|
+
function useIsMobile3(breakpoint = 640) {
|
|
771
|
+
const getValue = () => typeof window !== "undefined" ? window.innerWidth <= breakpoint : false;
|
|
772
|
+
const [isMobile, setIsMobile] = useState4(getValue);
|
|
773
|
+
useEffect3(() => {
|
|
774
|
+
const onResize = () => setIsMobile(getValue());
|
|
775
|
+
window.addEventListener("resize", onResize);
|
|
776
|
+
return () => window.removeEventListener("resize", onResize);
|
|
777
|
+
}, [breakpoint]);
|
|
778
|
+
return isMobile;
|
|
779
|
+
}
|
|
720
780
|
function ContainerIdGridPanel(props) {
|
|
721
781
|
const {
|
|
722
782
|
containerApiBaseUrl,
|
|
@@ -727,30 +787,29 @@ function ContainerIdGridPanel(props) {
|
|
|
727
787
|
multiple = true,
|
|
728
788
|
selectedId,
|
|
729
789
|
onSelect,
|
|
730
|
-
icon,
|
|
731
|
-
iconHtml,
|
|
732
790
|
deleteDisabled,
|
|
733
791
|
className,
|
|
734
792
|
onDeleted
|
|
735
793
|
} = props;
|
|
736
|
-
const
|
|
794
|
+
const isMobile = useIsMobile3();
|
|
795
|
+
const sdkDb = useMemo(
|
|
737
796
|
() => new SparkStudioStorageSDK(containerApiBaseUrl),
|
|
738
797
|
[containerApiBaseUrl]
|
|
739
798
|
);
|
|
740
|
-
const sdkS3 =
|
|
799
|
+
const sdkS3 = useMemo(
|
|
741
800
|
() => new SparkStudioStorageSDK(storageApiBaseUrl),
|
|
742
801
|
[storageApiBaseUrl]
|
|
743
802
|
);
|
|
744
|
-
const [loading, setLoading] =
|
|
745
|
-
const [files, setFiles] =
|
|
746
|
-
const [dragOver, setDragOver] =
|
|
747
|
-
const [errMsg, setErrMsg] =
|
|
803
|
+
const [loading, setLoading] = useState4(false);
|
|
804
|
+
const [files, setFiles] = useState4([]);
|
|
805
|
+
const [dragOver, setDragOver] = useState4(false);
|
|
806
|
+
const [errMsg, setErrMsg] = useState4(null);
|
|
748
807
|
const idsRef = useRef(containerIds);
|
|
749
|
-
|
|
808
|
+
useEffect3(() => {
|
|
750
809
|
idsRef.current = containerIds;
|
|
751
810
|
}, [containerIds]);
|
|
752
811
|
const createdByFileRef = useRef(/* @__PURE__ */ new WeakMap());
|
|
753
|
-
|
|
812
|
+
useEffect3(() => {
|
|
754
813
|
let cancelled = false;
|
|
755
814
|
async function loadByIds(ids) {
|
|
756
815
|
setErrMsg(null);
|
|
@@ -773,12 +832,11 @@ function ContainerIdGridPanel(props) {
|
|
|
773
832
|
if (cancelled) return;
|
|
774
833
|
const map = /* @__PURE__ */ new Map();
|
|
775
834
|
for (const r of results) if (r?.Id) map.set(r.Id, r);
|
|
776
|
-
setFiles(
|
|
777
|
-
ids.map((id) => map.get(id)).filter(Boolean)
|
|
778
|
-
);
|
|
835
|
+
setFiles(ids.map((id) => map.get(id)).filter(Boolean));
|
|
779
836
|
} catch (e) {
|
|
780
|
-
if (!cancelled)
|
|
837
|
+
if (!cancelled) {
|
|
781
838
|
setErrMsg(e instanceof Error ? e.message : "Failed to load files");
|
|
839
|
+
}
|
|
782
840
|
} finally {
|
|
783
841
|
if (!cancelled) setLoading(false);
|
|
784
842
|
}
|
|
@@ -865,106 +923,149 @@ function ContainerIdGridPanel(props) {
|
|
|
865
923
|
if (!list || list.length === 0) return;
|
|
866
924
|
startUploadsIfNeeded(list);
|
|
867
925
|
};
|
|
868
|
-
return /* @__PURE__ */ jsxs3(
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
e.preventDefault();
|
|
883
|
-
e.stopPropagation();
|
|
884
|
-
setDragOver(true);
|
|
885
|
-
},
|
|
886
|
-
onDragLeave: (e) => {
|
|
887
|
-
e.preventDefault();
|
|
888
|
-
e.stopPropagation();
|
|
889
|
-
setDragOver(false);
|
|
890
|
-
},
|
|
891
|
-
onDrop,
|
|
892
|
-
style: {
|
|
893
|
-
position: "relative",
|
|
894
|
-
borderRadius: 14,
|
|
895
|
-
border: `2px dashed ${dragOver ? "rgba(13,110,253,0.9)" : "rgba(0,0,0,0.15)"}`,
|
|
896
|
-
background: dragOver ? "rgba(13,110,253,0.06)" : "transparent",
|
|
897
|
-
padding: 12
|
|
898
|
-
},
|
|
899
|
-
children: [
|
|
900
|
-
dragOver ? /* @__PURE__ */ jsx4(
|
|
926
|
+
return /* @__PURE__ */ jsxs3(
|
|
927
|
+
"div",
|
|
928
|
+
{
|
|
929
|
+
className,
|
|
930
|
+
style: {
|
|
931
|
+
display: "grid",
|
|
932
|
+
gap: 12,
|
|
933
|
+
width: "100%",
|
|
934
|
+
minWidth: 0
|
|
935
|
+
},
|
|
936
|
+
children: [
|
|
937
|
+
/* @__PURE__ */ jsxs3("div", { style: { minWidth: 0 }, children: [
|
|
938
|
+
/* @__PURE__ */ jsx4(UploadProgressList, { uploads }),
|
|
939
|
+
errMsg ? /* @__PURE__ */ jsx4(
|
|
901
940
|
"div",
|
|
902
941
|
{
|
|
903
942
|
style: {
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
placeItems: "center",
|
|
909
|
-
pointerEvents: "none",
|
|
910
|
-
background: "rgba(13,110,253,0.10)",
|
|
911
|
-
fontWeight: 800
|
|
943
|
+
fontSize: 12,
|
|
944
|
+
color: "crimson",
|
|
945
|
+
marginTop: 6,
|
|
946
|
+
wordBreak: "break-word"
|
|
912
947
|
},
|
|
913
|
-
children:
|
|
948
|
+
children: errMsg
|
|
914
949
|
}
|
|
915
|
-
) : null
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
950
|
+
) : null
|
|
951
|
+
] }),
|
|
952
|
+
/* @__PURE__ */ jsxs3(
|
|
953
|
+
"div",
|
|
954
|
+
{
|
|
955
|
+
onDragEnter: (e) => {
|
|
956
|
+
e.preventDefault();
|
|
957
|
+
e.stopPropagation();
|
|
958
|
+
setDragOver(true);
|
|
959
|
+
},
|
|
960
|
+
onDragOver: (e) => {
|
|
961
|
+
e.preventDefault();
|
|
962
|
+
e.stopPropagation();
|
|
963
|
+
setDragOver(true);
|
|
964
|
+
},
|
|
965
|
+
onDragLeave: (e) => {
|
|
966
|
+
e.preventDefault();
|
|
967
|
+
e.stopPropagation();
|
|
968
|
+
setDragOver(false);
|
|
969
|
+
},
|
|
970
|
+
onDrop,
|
|
971
|
+
style: {
|
|
972
|
+
position: "relative",
|
|
973
|
+
borderRadius: 14,
|
|
974
|
+
border: `2px dashed ${dragOver ? "rgba(13,110,253,0.9)" : "rgba(0,0,0,0.15)"}`,
|
|
975
|
+
background: dragOver ? "rgba(13,110,253,0.06)" : "transparent",
|
|
976
|
+
padding: isMobile ? 10 : 12,
|
|
977
|
+
width: "100%",
|
|
978
|
+
minWidth: 0,
|
|
979
|
+
overflow: "hidden",
|
|
980
|
+
boxSizing: "border-box"
|
|
981
|
+
},
|
|
982
|
+
children: [
|
|
983
|
+
dragOver ? /* @__PURE__ */ jsx4(
|
|
984
|
+
"div",
|
|
985
|
+
{
|
|
986
|
+
style: {
|
|
987
|
+
position: "absolute",
|
|
988
|
+
inset: 0,
|
|
989
|
+
borderRadius: 14,
|
|
990
|
+
display: "grid",
|
|
991
|
+
placeItems: "center",
|
|
992
|
+
pointerEvents: "none",
|
|
993
|
+
background: "rgba(13,110,253,0.10)",
|
|
994
|
+
fontWeight: 800,
|
|
995
|
+
textAlign: "center",
|
|
996
|
+
padding: 12
|
|
997
|
+
},
|
|
998
|
+
children: "Drop files to upload"
|
|
999
|
+
}
|
|
1000
|
+
) : null,
|
|
1001
|
+
/* @__PURE__ */ jsxs3(
|
|
1002
|
+
"div",
|
|
1003
|
+
{
|
|
1004
|
+
style: {
|
|
1005
|
+
display: "flex",
|
|
1006
|
+
flexDirection: isMobile ? "column" : "row",
|
|
1007
|
+
alignItems: isMobile ? "stretch" : "center",
|
|
1008
|
+
justifyContent: "space-between",
|
|
1009
|
+
gap: 10,
|
|
1010
|
+
marginBottom: 10,
|
|
1011
|
+
minWidth: 0
|
|
1012
|
+
},
|
|
1013
|
+
children: [
|
|
1014
|
+
/* @__PURE__ */ jsx4(
|
|
1015
|
+
"div",
|
|
1016
|
+
{
|
|
1017
|
+
style: {
|
|
1018
|
+
fontWeight: 700,
|
|
1019
|
+
minWidth: 0
|
|
1020
|
+
},
|
|
1021
|
+
children: "Files"
|
|
1022
|
+
}
|
|
1023
|
+
),
|
|
1024
|
+
/* @__PURE__ */ jsx4(
|
|
1025
|
+
"button",
|
|
1026
|
+
{
|
|
1027
|
+
type: "button",
|
|
1028
|
+
onClick: openPicker,
|
|
1029
|
+
style: {
|
|
1030
|
+
border: "1px solid rgba(0,0,0,0.18)",
|
|
1031
|
+
background: "white",
|
|
1032
|
+
borderRadius: 10,
|
|
1033
|
+
padding: isMobile ? "10px 12px" : "8px 10px",
|
|
1034
|
+
cursor: "pointer",
|
|
1035
|
+
fontWeight: 600,
|
|
1036
|
+
width: isMobile ? "100%" : "auto",
|
|
1037
|
+
maxWidth: "100%",
|
|
1038
|
+
boxSizing: "border-box"
|
|
1039
|
+
},
|
|
1040
|
+
children: "Browse\u2026"
|
|
1041
|
+
}
|
|
1042
|
+
)
|
|
1043
|
+
]
|
|
1044
|
+
}
|
|
1045
|
+
),
|
|
1046
|
+
/* @__PURE__ */ jsx4("div", { style: { width: "100%", minWidth: 0, overflow: "hidden" }, children: loading ? /* @__PURE__ */ jsx4(
|
|
1047
|
+
"div",
|
|
1048
|
+
{
|
|
1049
|
+
className: "d-flex justify-content-center align-items-center",
|
|
1050
|
+
style: { minHeight: 120 },
|
|
1051
|
+
children: /* @__PURE__ */ jsx4("div", { className: "spinner-border text-secondary", role: "status" })
|
|
1052
|
+
}
|
|
1053
|
+
) : /* @__PURE__ */ jsx4(
|
|
1054
|
+
FileIconGrid,
|
|
1055
|
+
{
|
|
1056
|
+
files,
|
|
1057
|
+
deleteDisabled,
|
|
1058
|
+
onDeleted: handleDelete,
|
|
1059
|
+
selectedId,
|
|
1060
|
+
onSelect
|
|
1061
|
+
}
|
|
1062
|
+
) })
|
|
1063
|
+
]
|
|
1064
|
+
}
|
|
1065
|
+
)
|
|
1066
|
+
]
|
|
1067
|
+
}
|
|
1068
|
+
);
|
|
968
1069
|
}
|
|
969
1070
|
|
|
970
1071
|
// src/components/ContainerUploadPanel.tsx
|
|
@@ -974,9 +1075,9 @@ import "react";
|
|
|
974
1075
|
import {
|
|
975
1076
|
forwardRef,
|
|
976
1077
|
useImperativeHandle,
|
|
977
|
-
useMemo as
|
|
1078
|
+
useMemo as useMemo2,
|
|
978
1079
|
useRef as useRef3,
|
|
979
|
-
useState as
|
|
1080
|
+
useState as useState6
|
|
980
1081
|
} from "react";
|
|
981
1082
|
|
|
982
1083
|
// src/components/UploadDropzone.tsx
|
|
@@ -1032,8 +1133,8 @@ import {
|
|
|
1032
1133
|
faFileCode
|
|
1033
1134
|
} from "@fortawesome/free-solid-svg-icons";
|
|
1034
1135
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
1035
|
-
import { useEffect as
|
|
1036
|
-
import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1136
|
+
import { useEffect as useEffect4, useRef as useRef2, useState as useState5 } from "react";
|
|
1137
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1037
1138
|
function getFileExtension(name) {
|
|
1038
1139
|
if (!name) return null;
|
|
1039
1140
|
const lastDot = name.lastIndexOf(".");
|
|
@@ -1112,11 +1213,11 @@ var DesktopFileIcon = ({
|
|
|
1112
1213
|
onOpen,
|
|
1113
1214
|
onDelete
|
|
1114
1215
|
}) => {
|
|
1115
|
-
const [contextMenuPos, setContextMenuPos] =
|
|
1216
|
+
const [contextMenuPos, setContextMenuPos] = useState5(
|
|
1116
1217
|
null
|
|
1117
1218
|
);
|
|
1118
|
-
const [isHovered, setIsHovered] =
|
|
1119
|
-
const [isDeleting, setIsDeleting] =
|
|
1219
|
+
const [isHovered, setIsHovered] = useState5(false);
|
|
1220
|
+
const [isDeleting, setIsDeleting] = useState5(false);
|
|
1120
1221
|
const iconRef = useRef2(null);
|
|
1121
1222
|
const menuRef = useRef2(null);
|
|
1122
1223
|
const handleDoubleClick = () => {
|
|
@@ -1176,7 +1277,7 @@ var DesktopFileIcon = ({
|
|
|
1176
1277
|
const formattedSize = typeof sizeBytes === "number" ? `${(sizeBytes / 1024).toFixed(1)} KB` : void 0;
|
|
1177
1278
|
const ext = getFileExtension(name);
|
|
1178
1279
|
const iconToRender = getIconForExtension(ext);
|
|
1179
|
-
|
|
1280
|
+
useEffect4(() => {
|
|
1180
1281
|
if (!contextMenuPos) return;
|
|
1181
1282
|
const handleGlobalClick = (e) => {
|
|
1182
1283
|
const target = e.target;
|
|
@@ -1193,7 +1294,7 @@ var DesktopFileIcon = ({
|
|
|
1193
1294
|
document.removeEventListener("mousedown", handleGlobalClick);
|
|
1194
1295
|
};
|
|
1195
1296
|
}, [contextMenuPos]);
|
|
1196
|
-
return /* @__PURE__ */ jsxs4(
|
|
1297
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1197
1298
|
/* @__PURE__ */ jsxs4(
|
|
1198
1299
|
"div",
|
|
1199
1300
|
{
|
|
@@ -1284,7 +1385,7 @@ var DesktopFileIcon = ({
|
|
|
1284
1385
|
};
|
|
1285
1386
|
|
|
1286
1387
|
// src/components/UploadContainer.tsx
|
|
1287
|
-
import { Fragment as
|
|
1388
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1288
1389
|
function filesToFileList(files) {
|
|
1289
1390
|
const dt = new DataTransfer();
|
|
1290
1391
|
for (const f of files) dt.items.add(f);
|
|
@@ -1304,8 +1405,8 @@ var UploadContainer = forwardRef(
|
|
|
1304
1405
|
onUploadComplete,
|
|
1305
1406
|
onUploadError
|
|
1306
1407
|
}, ref) => {
|
|
1307
|
-
const [isDragging, setIsDragging] =
|
|
1308
|
-
const inputId =
|
|
1408
|
+
const [isDragging, setIsDragging] = useState6(false);
|
|
1409
|
+
const inputId = useMemo2(() => `filePicker_${crypto.randomUUID()}`, []);
|
|
1309
1410
|
const inputRef = useRef3(null);
|
|
1310
1411
|
const { uploads, startUploadsIfNeeded } = UseUploadManager({
|
|
1311
1412
|
autoUpload,
|
|
@@ -1356,7 +1457,7 @@ var UploadContainer = forwardRef(
|
|
|
1356
1457
|
a.click();
|
|
1357
1458
|
document.body.removeChild(a);
|
|
1358
1459
|
};
|
|
1359
|
-
return /* @__PURE__ */ jsxs5(
|
|
1460
|
+
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1360
1461
|
/* @__PURE__ */ jsxs5("div", { className: "w-100", children: [
|
|
1361
1462
|
/* @__PURE__ */ jsx7(
|
|
1362
1463
|
"input",
|
|
@@ -1438,11 +1539,11 @@ var UploadContainer = forwardRef(
|
|
|
1438
1539
|
UploadContainer.displayName = "UploadContainer";
|
|
1439
1540
|
|
|
1440
1541
|
// src/hooks/UseContainers.ts
|
|
1441
|
-
import { useEffect as
|
|
1542
|
+
import { useEffect as useEffect5, useState as useState7 } from "react";
|
|
1442
1543
|
function UseContainers({ apiBaseUrl, parentId }) {
|
|
1443
|
-
const [containers, setContainers] =
|
|
1444
|
-
const [loading, setLoading] =
|
|
1445
|
-
const [error, setError] =
|
|
1544
|
+
const [containers, setContainers] = useState7([]);
|
|
1545
|
+
const [loading, setLoading] = useState7(false);
|
|
1546
|
+
const [error, setError] = useState7(null);
|
|
1446
1547
|
const load = async () => {
|
|
1447
1548
|
setLoading(true);
|
|
1448
1549
|
setError(null);
|
|
@@ -1458,7 +1559,7 @@ function UseContainers({ apiBaseUrl, parentId }) {
|
|
|
1458
1559
|
setLoading(false);
|
|
1459
1560
|
}
|
|
1460
1561
|
};
|
|
1461
|
-
|
|
1562
|
+
useEffect5(() => {
|
|
1462
1563
|
void load();
|
|
1463
1564
|
}, [apiBaseUrl, parentId]);
|
|
1464
1565
|
return {
|
|
@@ -1548,7 +1649,7 @@ var ContainerUploadPanel = ({
|
|
|
1548
1649
|
};
|
|
1549
1650
|
|
|
1550
1651
|
// src/components/FileGridUploadPanel.tsx
|
|
1551
|
-
import { useMemo as
|
|
1652
|
+
import { useMemo as useMemo3, useState as useState8 } from "react";
|
|
1552
1653
|
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1553
1654
|
function FileGridUploadPanel(props) {
|
|
1554
1655
|
const {
|
|
@@ -1559,18 +1660,16 @@ function FileGridUploadPanel(props) {
|
|
|
1559
1660
|
multiple = true,
|
|
1560
1661
|
selectedId,
|
|
1561
1662
|
onSelect,
|
|
1562
|
-
icon,
|
|
1563
|
-
iconHtml,
|
|
1564
1663
|
deleteDisabled
|
|
1565
1664
|
} = props;
|
|
1566
1665
|
const { containers, setContainers, reload, loading } = UseContainers({
|
|
1567
1666
|
apiBaseUrl: containerApiBaseUrl,
|
|
1568
1667
|
parentId: parentContainerId
|
|
1569
1668
|
});
|
|
1570
|
-
const [isDragging, setIsDragging] =
|
|
1571
|
-
const [error, setError] =
|
|
1572
|
-
const sdkDb =
|
|
1573
|
-
const sdkS3 =
|
|
1669
|
+
const [isDragging, setIsDragging] = useState8(false);
|
|
1670
|
+
const [error, setError] = useState8(null);
|
|
1671
|
+
const sdkDb = useMemo3(() => new SparkStudioStorageSDK(containerApiBaseUrl), [containerApiBaseUrl]);
|
|
1672
|
+
const sdkS3 = useMemo3(() => new SparkStudioStorageSDK(storageApiBaseUrl), [storageApiBaseUrl]);
|
|
1574
1673
|
const getPresignedUrl = async (file) => {
|
|
1575
1674
|
const contentType = file.type || "application/octet-stream";
|
|
1576
1675
|
const containerDTO = await sdkDb.container.CreateFileContainer(
|
|
@@ -1699,9 +1798,7 @@ function FileGridUploadPanel(props) {
|
|
|
1699
1798
|
deleteDisabled,
|
|
1700
1799
|
onDeleted: handleDeleteFile,
|
|
1701
1800
|
selectedId,
|
|
1702
|
-
onSelect
|
|
1703
|
-
icon,
|
|
1704
|
-
iconHtml
|
|
1801
|
+
onSelect
|
|
1705
1802
|
}
|
|
1706
1803
|
)
|
|
1707
1804
|
]
|
|
@@ -1711,7 +1808,7 @@ function FileGridUploadPanel(props) {
|
|
|
1711
1808
|
}
|
|
1712
1809
|
|
|
1713
1810
|
// src/components/SingleFileProcessUploader.tsx
|
|
1714
|
-
import { useCallback as useCallback2, useRef as useRef4, useState as
|
|
1811
|
+
import { useCallback as useCallback2, useRef as useRef4, useState as useState9 } from "react";
|
|
1715
1812
|
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1716
1813
|
var SingleFileProcessUploader = ({
|
|
1717
1814
|
getPresignedUrl,
|
|
@@ -1721,10 +1818,10 @@ var SingleFileProcessUploader = ({
|
|
|
1721
1818
|
disabled,
|
|
1722
1819
|
uploadOnDrop = false
|
|
1723
1820
|
}) => {
|
|
1724
|
-
const [selectedFile, setSelectedFile] =
|
|
1725
|
-
const [isDragging, setIsDragging] =
|
|
1726
|
-
const [progress, setProgress] =
|
|
1727
|
-
const [status, setStatus] =
|
|
1821
|
+
const [selectedFile, setSelectedFile] = useState9(null);
|
|
1822
|
+
const [isDragging, setIsDragging] = useState9(false);
|
|
1823
|
+
const [progress, setProgress] = useState9(null);
|
|
1824
|
+
const [status, setStatus] = useState9("idle");
|
|
1728
1825
|
const fileInputRef = useRef4(null);
|
|
1729
1826
|
function getErrorMessage(err) {
|
|
1730
1827
|
if (err instanceof Error) return err.message;
|
|
@@ -1891,8 +1988,8 @@ var SingleFileProcessUploader = ({
|
|
|
1891
1988
|
};
|
|
1892
1989
|
|
|
1893
1990
|
// src/components/SingleImageUploadEditor.tsx
|
|
1894
|
-
import { useEffect as
|
|
1895
|
-
import { Fragment as
|
|
1991
|
+
import { useEffect as useEffect6, useMemo as useMemo4, useRef as useRef5, useState as useState10 } from "react";
|
|
1992
|
+
import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1896
1993
|
function SingleImageUploadEditor(props) {
|
|
1897
1994
|
const {
|
|
1898
1995
|
containerApiBaseUrl,
|
|
@@ -1902,21 +1999,21 @@ function SingleImageUploadEditor(props) {
|
|
|
1902
1999
|
height = 280,
|
|
1903
2000
|
disabled = false
|
|
1904
2001
|
} = props;
|
|
1905
|
-
const [isDragging, setIsDragging] =
|
|
1906
|
-
const [error, setError] =
|
|
2002
|
+
const [isDragging, setIsDragging] = useState10(false);
|
|
2003
|
+
const [error, setError] = useState10(null);
|
|
1907
2004
|
const pendingContainerRef = useRef5(null);
|
|
1908
|
-
const [isDeleting, setIsDeleting] =
|
|
1909
|
-
const [isLoadingImage, setIsLoadingImage] =
|
|
1910
|
-
const [
|
|
1911
|
-
const
|
|
2005
|
+
const [isDeleting, setIsDeleting] = useState10(false);
|
|
2006
|
+
const [isLoadingImage, setIsLoadingImage] = useState10(false);
|
|
2007
|
+
const [isPickingFile, setIsPickingFile] = useState10(false);
|
|
2008
|
+
const [currentImage, setCurrentImage] = useState10(null);
|
|
2009
|
+
const sdkDb = useMemo4(
|
|
1912
2010
|
() => new SparkStudioStorageSDK(containerApiBaseUrl),
|
|
1913
2011
|
[containerApiBaseUrl]
|
|
1914
2012
|
);
|
|
1915
|
-
const sdkS3 =
|
|
2013
|
+
const sdkS3 = useMemo4(
|
|
1916
2014
|
() => new SparkStudioStorageSDK(storageApiBaseUrl),
|
|
1917
2015
|
[storageApiBaseUrl]
|
|
1918
2016
|
);
|
|
1919
|
-
const busy = disabled || isDeleting || isLoadingImage;
|
|
1920
2017
|
function logError(context, err) {
|
|
1921
2018
|
console.error(`[SingleImageUploadEditor] ${context}`, err);
|
|
1922
2019
|
}
|
|
@@ -1925,7 +2022,13 @@ function SingleImageUploadEditor(props) {
|
|
|
1925
2022
|
setError(null);
|
|
1926
2023
|
pendingContainerRef.current = null;
|
|
1927
2024
|
}
|
|
1928
|
-
|
|
2025
|
+
function getErrorMessage(err, fallback) {
|
|
2026
|
+
return err instanceof Error ? err.message : fallback;
|
|
2027
|
+
}
|
|
2028
|
+
function isImageFile(file) {
|
|
2029
|
+
return file.type.startsWith("image/");
|
|
2030
|
+
}
|
|
2031
|
+
useEffect6(() => {
|
|
1929
2032
|
let cancelled = false;
|
|
1930
2033
|
async function loadImage() {
|
|
1931
2034
|
if (!value) {
|
|
@@ -1957,12 +2060,6 @@ function SingleImageUploadEditor(props) {
|
|
|
1957
2060
|
cancelled = true;
|
|
1958
2061
|
};
|
|
1959
2062
|
}, [value, sdkDb]);
|
|
1960
|
-
function getErrorMessage(err, fallback) {
|
|
1961
|
-
return err instanceof Error ? err.message : fallback;
|
|
1962
|
-
}
|
|
1963
|
-
function isImageFile(file) {
|
|
1964
|
-
return file.type.startsWith("image/");
|
|
1965
|
-
}
|
|
1966
2063
|
async function createContainerForFile(file) {
|
|
1967
2064
|
const contentType = file.type || "application/octet-stream";
|
|
1968
2065
|
return sdkDb.container.CreateFileContainer(
|
|
@@ -2003,6 +2100,7 @@ function SingleImageUploadEditor(props) {
|
|
|
2003
2100
|
onChange?.(uploaded.Id);
|
|
2004
2101
|
}
|
|
2005
2102
|
pendingContainerRef.current = null;
|
|
2103
|
+
setIsPickingFile(false);
|
|
2006
2104
|
},
|
|
2007
2105
|
onUploadError: async (_file, err) => {
|
|
2008
2106
|
const pending = pendingContainerRef.current;
|
|
@@ -2010,10 +2108,14 @@ function SingleImageUploadEditor(props) {
|
|
|
2010
2108
|
try {
|
|
2011
2109
|
await sdkDb.container.DeleteContainer(pending.Id);
|
|
2012
2110
|
} catch (cleanupErr) {
|
|
2013
|
-
logError(
|
|
2111
|
+
logError(
|
|
2112
|
+
"Failed to cleanup pending container after upload error",
|
|
2113
|
+
cleanupErr
|
|
2114
|
+
);
|
|
2014
2115
|
}
|
|
2015
2116
|
}
|
|
2016
2117
|
pendingContainerRef.current = null;
|
|
2118
|
+
setIsPickingFile(false);
|
|
2017
2119
|
logError("Upload failed", err);
|
|
2018
2120
|
setCurrentImage(null);
|
|
2019
2121
|
setError(getErrorMessage(err, "Upload failed"));
|
|
@@ -2021,7 +2123,10 @@ function SingleImageUploadEditor(props) {
|
|
|
2021
2123
|
});
|
|
2022
2124
|
const visibleUploads = uploads.filter((u) => u.status !== "success");
|
|
2023
2125
|
const activeUpload = visibleUploads[0];
|
|
2126
|
+
const isUploading = !!activeUpload;
|
|
2024
2127
|
const showBottomProgress = !!activeUpload;
|
|
2128
|
+
const busy = disabled || isDeleting || isLoadingImage || isPickingFile || isUploading;
|
|
2129
|
+
const busyText = isUploading ? "Uploading..." : isDeleting ? "Removing..." : isLoadingImage ? "Loading..." : isPickingFile ? "Preparing..." : "";
|
|
2025
2130
|
async function replaceWithFile(file) {
|
|
2026
2131
|
if (busy) {
|
|
2027
2132
|
return;
|
|
@@ -2032,12 +2137,15 @@ function SingleImageUploadEditor(props) {
|
|
|
2032
2137
|
}
|
|
2033
2138
|
try {
|
|
2034
2139
|
setError(null);
|
|
2140
|
+
setIsPickingFile(true);
|
|
2035
2141
|
if (value) {
|
|
2036
2142
|
setIsDeleting(true);
|
|
2037
2143
|
try {
|
|
2038
2144
|
await deleteContainerFile(value);
|
|
2039
2145
|
} catch (err) {
|
|
2040
2146
|
logError(`Failed to delete existing container '${String(value)}'`, err);
|
|
2147
|
+
} finally {
|
|
2148
|
+
setIsDeleting(false);
|
|
2041
2149
|
}
|
|
2042
2150
|
setCurrentImage(null);
|
|
2043
2151
|
onChange?.(null);
|
|
@@ -2049,7 +2157,7 @@ function SingleImageUploadEditor(props) {
|
|
|
2049
2157
|
logError("Failed to replace image", err);
|
|
2050
2158
|
resetState();
|
|
2051
2159
|
setError(getErrorMessage(err, "Failed to replace image."));
|
|
2052
|
-
|
|
2160
|
+
setIsPickingFile(false);
|
|
2053
2161
|
setIsDeleting(false);
|
|
2054
2162
|
}
|
|
2055
2163
|
}
|
|
@@ -2091,6 +2199,29 @@ function SingleImageUploadEditor(props) {
|
|
|
2091
2199
|
setIsDeleting(false);
|
|
2092
2200
|
}
|
|
2093
2201
|
}
|
|
2202
|
+
function SpinnerLabel(props2) {
|
|
2203
|
+
return /* @__PURE__ */ jsxs8(
|
|
2204
|
+
"span",
|
|
2205
|
+
{
|
|
2206
|
+
style: {
|
|
2207
|
+
display: "inline-flex",
|
|
2208
|
+
alignItems: "center",
|
|
2209
|
+
gap: 8
|
|
2210
|
+
},
|
|
2211
|
+
children: [
|
|
2212
|
+
/* @__PURE__ */ jsx11(
|
|
2213
|
+
"span",
|
|
2214
|
+
{
|
|
2215
|
+
className: "spinner-border spinner-border-sm",
|
|
2216
|
+
role: "status",
|
|
2217
|
+
"aria-hidden": "true"
|
|
2218
|
+
}
|
|
2219
|
+
),
|
|
2220
|
+
/* @__PURE__ */ jsx11("span", { children: props2.text })
|
|
2221
|
+
]
|
|
2222
|
+
}
|
|
2223
|
+
);
|
|
2224
|
+
}
|
|
2094
2225
|
return /* @__PURE__ */ jsxs8("div", { style: { display: "grid", gap: 8 }, children: [
|
|
2095
2226
|
error ? /* @__PURE__ */ jsx11("div", { style: { fontSize: 12, color: "crimson" }, children: error }) : null,
|
|
2096
2227
|
/* @__PURE__ */ jsxs8(
|
|
@@ -2155,7 +2286,7 @@ function SingleImageUploadEditor(props) {
|
|
|
2155
2286
|
children: "Drop image to replace"
|
|
2156
2287
|
}
|
|
2157
2288
|
) : null,
|
|
2158
|
-
currentImage ? /* @__PURE__ */ jsxs8(
|
|
2289
|
+
currentImage ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
2159
2290
|
/* @__PURE__ */ jsx11(
|
|
2160
2291
|
"div",
|
|
2161
2292
|
{
|
|
@@ -2176,7 +2307,9 @@ function SingleImageUploadEditor(props) {
|
|
|
2176
2307
|
width: "100%",
|
|
2177
2308
|
height,
|
|
2178
2309
|
objectFit: "contain",
|
|
2179
|
-
background: "rgba(0,0,0,0.02)"
|
|
2310
|
+
background: "rgba(0,0,0,0.02)",
|
|
2311
|
+
opacity: busy ? 0.45 : 1,
|
|
2312
|
+
transition: "opacity 120ms ease"
|
|
2180
2313
|
}
|
|
2181
2314
|
}
|
|
2182
2315
|
)
|
|
@@ -2207,9 +2340,10 @@ function SingleImageUploadEditor(props) {
|
|
|
2207
2340
|
padding: "8px 10px",
|
|
2208
2341
|
cursor: busy ? "not-allowed" : "pointer",
|
|
2209
2342
|
fontWeight: 600,
|
|
2210
|
-
boxShadow: "0 2px 8px rgba(0,0,0,0.08)"
|
|
2343
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.08)",
|
|
2344
|
+
minWidth: 110
|
|
2211
2345
|
},
|
|
2212
|
-
children: "Browse\u2026"
|
|
2346
|
+
children: isUploading || isPickingFile ? /* @__PURE__ */ jsx11(SpinnerLabel, { text: "Uploading..." }) : "Browse\u2026"
|
|
2213
2347
|
}
|
|
2214
2348
|
),
|
|
2215
2349
|
/* @__PURE__ */ jsx11(
|
|
@@ -2226,9 +2360,10 @@ function SingleImageUploadEditor(props) {
|
|
|
2226
2360
|
padding: "8px 10px",
|
|
2227
2361
|
cursor: busy ? "not-allowed" : "pointer",
|
|
2228
2362
|
fontWeight: 600,
|
|
2229
|
-
boxShadow: "0 2px 8px rgba(0,0,0,0.08)"
|
|
2363
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.08)",
|
|
2364
|
+
minWidth: 110
|
|
2230
2365
|
},
|
|
2231
|
-
children: "Remove"
|
|
2366
|
+
children: isDeleting ? /* @__PURE__ */ jsx11(SpinnerLabel, { text: "Removing..." }) : "Remove"
|
|
2232
2367
|
}
|
|
2233
2368
|
)
|
|
2234
2369
|
]
|
|
@@ -2268,17 +2403,59 @@ function SingleImageUploadEditor(props) {
|
|
|
2268
2403
|
borderRadius: 10,
|
|
2269
2404
|
padding: "10px 16px",
|
|
2270
2405
|
cursor: busy ? "not-allowed" : "pointer",
|
|
2271
|
-
fontWeight: 600
|
|
2406
|
+
fontWeight: 600,
|
|
2407
|
+
minWidth: 140
|
|
2272
2408
|
},
|
|
2273
|
-
children: "Browse\u2026"
|
|
2409
|
+
children: isUploading || isPickingFile ? /* @__PURE__ */ jsx11(SpinnerLabel, { text: "Uploading..." }) : isLoadingImage ? /* @__PURE__ */ jsx11(SpinnerLabel, { text: "Loading..." }) : "Browse\u2026"
|
|
2274
2410
|
}
|
|
2275
2411
|
),
|
|
2276
|
-
/* @__PURE__ */ jsx11("div", { style: { fontSize: 13, opacity: 0.7 }, children: "Drag and drop an image here" })
|
|
2412
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 13, opacity: 0.7 }, children: busyText || "Drag and drop an image here" })
|
|
2277
2413
|
]
|
|
2278
2414
|
}
|
|
2279
2415
|
)
|
|
2280
2416
|
}
|
|
2281
2417
|
),
|
|
2418
|
+
busy ? /* @__PURE__ */ jsx11(
|
|
2419
|
+
"div",
|
|
2420
|
+
{
|
|
2421
|
+
style: {
|
|
2422
|
+
position: "absolute",
|
|
2423
|
+
inset: 0,
|
|
2424
|
+
display: "grid",
|
|
2425
|
+
placeItems: "center",
|
|
2426
|
+
background: "rgba(255,255,255,0.55)",
|
|
2427
|
+
backdropFilter: "blur(1px)",
|
|
2428
|
+
zIndex: 5
|
|
2429
|
+
},
|
|
2430
|
+
children: /* @__PURE__ */ jsxs8(
|
|
2431
|
+
"div",
|
|
2432
|
+
{
|
|
2433
|
+
style: {
|
|
2434
|
+
display: "inline-flex",
|
|
2435
|
+
alignItems: "center",
|
|
2436
|
+
gap: 10,
|
|
2437
|
+
background: "white",
|
|
2438
|
+
border: "1px solid rgba(0,0,0,0.08)",
|
|
2439
|
+
borderRadius: 12,
|
|
2440
|
+
padding: "10px 14px",
|
|
2441
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
|
|
2442
|
+
fontWeight: 600
|
|
2443
|
+
},
|
|
2444
|
+
children: [
|
|
2445
|
+
/* @__PURE__ */ jsx11(
|
|
2446
|
+
"span",
|
|
2447
|
+
{
|
|
2448
|
+
className: "spinner-border spinner-border-sm",
|
|
2449
|
+
role: "status",
|
|
2450
|
+
"aria-hidden": "true"
|
|
2451
|
+
}
|
|
2452
|
+
),
|
|
2453
|
+
/* @__PURE__ */ jsx11("span", { children: busyText || "Working..." })
|
|
2454
|
+
]
|
|
2455
|
+
}
|
|
2456
|
+
)
|
|
2457
|
+
}
|
|
2458
|
+
) : null,
|
|
2282
2459
|
showBottomProgress ? /* @__PURE__ */ jsx11(
|
|
2283
2460
|
"div",
|
|
2284
2461
|
{
|
|
@@ -2289,7 +2466,7 @@ function SingleImageUploadEditor(props) {
|
|
|
2289
2466
|
bottom: 0,
|
|
2290
2467
|
height: 4,
|
|
2291
2468
|
background: "rgba(0,0,0,0.08)",
|
|
2292
|
-
zIndex:
|
|
2469
|
+
zIndex: 6
|
|
2293
2470
|
},
|
|
2294
2471
|
title: activeUpload.file.name,
|
|
2295
2472
|
children: /* @__PURE__ */ jsx11(
|
|
@@ -2316,17 +2493,17 @@ function SingleImageUploadEditor(props) {
|
|
|
2316
2493
|
}
|
|
2317
2494
|
|
|
2318
2495
|
// src/components/SingleImageView.tsx
|
|
2319
|
-
import { useEffect as
|
|
2496
|
+
import { useEffect as useEffect7, useMemo as useMemo5, useState as useState11 } from "react";
|
|
2320
2497
|
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2321
2498
|
function SingleImageView(props) {
|
|
2322
2499
|
const { containerApiBaseUrl, value, height = 280, onLoaded } = props;
|
|
2323
|
-
const [imageUrl, setImageUrl] =
|
|
2324
|
-
const [loading, setLoading] =
|
|
2325
|
-
const sdk =
|
|
2500
|
+
const [imageUrl, setImageUrl] = useState11(null);
|
|
2501
|
+
const [loading, setLoading] = useState11(false);
|
|
2502
|
+
const sdk = useMemo5(
|
|
2326
2503
|
() => new SparkStudioStorageSDK(containerApiBaseUrl),
|
|
2327
2504
|
[containerApiBaseUrl]
|
|
2328
2505
|
);
|
|
2329
|
-
|
|
2506
|
+
useEffect7(() => {
|
|
2330
2507
|
let cancelled = false;
|
|
2331
2508
|
async function load() {
|
|
2332
2509
|
if (!value) {
|
|
@@ -2401,14 +2578,14 @@ function SingleImageView(props) {
|
|
|
2401
2578
|
}
|
|
2402
2579
|
|
|
2403
2580
|
// src/views/HomeView.tsx
|
|
2404
|
-
import { useEffect as
|
|
2581
|
+
import { useEffect as useEffect8, useState as useState12 } from "react";
|
|
2405
2582
|
import {
|
|
2406
2583
|
AppSettings,
|
|
2407
2584
|
AuthenticatorProvider,
|
|
2408
2585
|
UserInfoCard,
|
|
2409
2586
|
useUser
|
|
2410
2587
|
} from "@sparkstudio/authentication-ui";
|
|
2411
|
-
import { Fragment as
|
|
2588
|
+
import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2412
2589
|
var CONTAINER_API = "https://lf9zyufpuk.execute-api.us-east-2.amazonaws.com/Prod";
|
|
2413
2590
|
var STORAGE_API = "https://iq0gmcn0pd.execute-api.us-east-2.amazonaws.com/Prod";
|
|
2414
2591
|
function HomeView() {
|
|
@@ -2424,10 +2601,10 @@ function HomeView() {
|
|
|
2424
2601
|
}
|
|
2425
2602
|
function HomeContent() {
|
|
2426
2603
|
const { user } = useUser();
|
|
2427
|
-
const [ids, setIds] =
|
|
2428
|
-
const [selectedId, setSelectedId] =
|
|
2429
|
-
const [selectedFile, setSelectedFile] =
|
|
2430
|
-
|
|
2604
|
+
const [ids, setIds] = useState12([]);
|
|
2605
|
+
const [selectedId, setSelectedId] = useState12(void 0);
|
|
2606
|
+
const [selectedFile, setSelectedFile] = useState12(null);
|
|
2607
|
+
useEffect8(() => {
|
|
2431
2608
|
if (selectedId && !ids.includes(selectedId)) {
|
|
2432
2609
|
setSelectedId(void 0);
|
|
2433
2610
|
setSelectedFile(null);
|
|
@@ -2440,9 +2617,9 @@ function HomeContent() {
|
|
|
2440
2617
|
new TemporaryFileDTO({ Name: file.name, ContentType: contentType })
|
|
2441
2618
|
);
|
|
2442
2619
|
}
|
|
2443
|
-
return /* @__PURE__ */ jsxs10(
|
|
2620
|
+
return /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
2444
2621
|
/* @__PURE__ */ jsx13(UserInfoCard, {}),
|
|
2445
|
-
user ? /* @__PURE__ */ jsxs10(
|
|
2622
|
+
user ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
2446
2623
|
/* @__PURE__ */ jsx13(
|
|
2447
2624
|
SingleFileProcessUploader,
|
|
2448
2625
|
{
|