@sparkstudio/storage-ui 1.0.14 → 1.0.15

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 CHANGED
@@ -478,6 +478,14 @@ var UploadProgressList = ({
478
478
  },
479
479
  children: [
480
480
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "bi bi-file-earmark fs-2" }),
481
+ u.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
482
+ "div",
483
+ {
484
+ className: "position-absolute top-50 start-50 translate-middle",
485
+ style: { pointerEvents: "none" },
486
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "spinner-border spinner-border-sm text-primary" })
487
+ }
488
+ ),
481
489
  u.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger", children: "!" })
482
490
  ]
483
491
  }
@@ -531,9 +539,11 @@ var DesktopFileIcon = ({
531
539
  null
532
540
  );
533
541
  const [isHovered, setIsHovered] = (0, import_react4.useState)(false);
542
+ const [isDeleting, setIsDeleting] = (0, import_react4.useState)(false);
534
543
  const iconRef = (0, import_react4.useRef)(null);
535
544
  const menuRef = (0, import_react4.useRef)(null);
536
545
  const handleDoubleClick = () => {
546
+ if (isDeleting) return;
537
547
  if (onOpen) {
538
548
  onOpen();
539
549
  return;
@@ -550,13 +560,14 @@ var DesktopFileIcon = ({
550
560
  }
551
561
  };
552
562
  const handleContextMenu = (e) => {
563
+ if (isDeleting) return;
553
564
  e.preventDefault();
554
565
  setContextMenuPos({ x: e.clientX, y: e.clientY });
555
566
  };
556
567
  const closeMenu = () => setContextMenuPos(null);
557
568
  const handleDownload = () => {
558
569
  closeMenu();
559
- if (!downloadUrl) return;
570
+ if (!downloadUrl || isDeleting) return;
560
571
  const a = document.createElement("a");
561
572
  a.href = downloadUrl;
562
573
  a.download = name ?? "";
@@ -568,16 +579,22 @@ var DesktopFileIcon = ({
568
579
  };
569
580
  const handleCopyUrl = async () => {
570
581
  closeMenu();
571
- if (!downloadUrl) return;
582
+ if (!downloadUrl || isDeleting) return;
572
583
  try {
573
584
  await navigator.clipboard?.writeText(downloadUrl);
574
585
  } catch (err) {
575
586
  console.error("Failed to copy URL", err);
576
587
  }
577
588
  };
578
- const handleDelete = () => {
589
+ const handleDelete = async () => {
579
590
  closeMenu();
580
- onDelete?.();
591
+ if (!onDelete) return;
592
+ try {
593
+ setIsDeleting(true);
594
+ await Promise.resolve(onDelete());
595
+ } catch (err) {
596
+ console.error("Delete failed", err);
597
+ }
581
598
  };
582
599
  const formattedSize = typeof sizeBytes === "number" ? `${(sizeBytes / 1024).toFixed(1)} KB` : void 0;
583
600
  (0, import_react4.useEffect)(() => {
@@ -602,12 +619,15 @@ var DesktopFileIcon = ({
602
619
  "div",
603
620
  {
604
621
  ref: iconRef,
605
- className: "d-flex flex-column align-items-center rounded-3 p-1 " + (isHovered || contextMenuPos ? "bg-light border" : ""),
622
+ className: "d-flex flex-column align-items-center rounded-3 p-1 " + (isHovered || contextMenuPos ? "bg-light border-primary" : "border-transparent"),
606
623
  style: {
607
624
  width: 96,
608
- cursor: "pointer",
625
+ cursor: isDeleting ? "default" : "pointer",
609
626
  userSelect: "none",
610
- transition: "background-color 0.1s ease, border-color 0.1s ease"
627
+ transition: "background-color 0.1s ease, border-color 0.1s ease, opacity 0.1s ease",
628
+ opacity: isDeleting ? 0.6 : 1,
629
+ borderWidth: 1,
630
+ borderStyle: "solid"
611
631
  },
612
632
  onDoubleClick: handleDoubleClick,
613
633
  onContextMenu: handleContextMenu,
@@ -620,15 +640,18 @@ var DesktopFileIcon = ({
620
640
  onMouseEnter: () => setIsHovered(true),
621
641
  onMouseLeave: () => setIsHovered(false),
622
642
  children: [
623
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
643
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
624
644
  "div",
625
645
  {
626
- className: "bg-white border rounded-3 d-flex align-items-center justify-content-center mb-1 shadow-sm",
646
+ className: "bg-white border rounded-3 d-flex align-items-center justify-content-center mb-1 shadow-sm position-relative",
627
647
  style: {
628
648
  width: 64,
629
649
  height: 64
630
650
  },
631
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "bi bi-file-earmark fs-2" })
651
+ children: [
652
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "bi bi-file-earmark fs-2" }),
653
+ isDeleting && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "position-absolute top-50 start-50 translate-middle", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "spinner-border spinner-border-sm text-danger" }) })
654
+ ]
632
655
  }
633
656
  ),
634
657
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -643,7 +666,7 @@ var DesktopFileIcon = ({
643
666
  ]
644
667
  }
645
668
  ),
646
- contextMenuPos && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
669
+ contextMenuPos && !isDeleting && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
647
670
  "div",
648
671
  {
649
672
  ref: menuRef,
@@ -752,6 +775,7 @@ var UploadContainer = ({
752
775
  className: "w-100",
753
776
  style: { minHeight: "260px", alignItems: "stretch" },
754
777
  children: [
778
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "w-100 mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "d-flex flex-column flex-md-row align-items-start align-items-md-center justify-content-between gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex-grow-1 w-100", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UploadProgressList, { uploads }) }) }) }),
755
779
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
756
780
  "div",
757
781
  {
@@ -761,16 +785,15 @@ var UploadContainer = ({
761
785
  DesktopFileIcon,
762
786
  {
763
787
  name: file.Name,
764
- sizeBytes: typeof file.FileSize === "number" ? file.FileSize : null,
765
- downloadUrl: file.PublicUrl ?? null,
788
+ sizeBytes: file.FileSize,
789
+ downloadUrl: file.PublicUrl,
766
790
  onOpen: () => handleExistingFileOpen(file),
767
- onDelete: onDeleteFile ? () => onDeleteFile(file) : void 0
791
+ onDelete: () => onDeleteFile?.(file)
768
792
  },
769
793
  file.Id
770
794
  ))
771
795
  }
772
- ),
773
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "w-100 mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "d-flex flex-column flex-md-row align-items-start align-items-md-center justify-content-between gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex-grow-1 w-100", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UploadProgressList, { uploads }) }) }) })
796
+ )
774
797
  ]
775
798
  }
776
799
  );
@@ -802,6 +825,7 @@ function UseContainers({ apiBaseUrl, parentId }) {
802
825
  }, [apiBaseUrl, parentId]);
803
826
  return {
804
827
  containers,
828
+ setContainers,
805
829
  loading,
806
830
  error,
807
831
  reload: load
@@ -815,17 +839,18 @@ var ContainerUploadPanel = ({
815
839
  storageApiBaseUrl,
816
840
  parentContainerId
817
841
  }) => {
818
- const { containers, reload, loading } = UseContainers({
842
+ const { containers, setContainers, reload, loading } = UseContainers({
819
843
  apiBaseUrl: containerApiBaseUrl,
820
844
  parentId: parentContainerId
821
845
  });
822
846
  const getPresignedUrl = async (file) => {
823
847
  const sdkDb = new SparkStudioStorageSDK(containerApiBaseUrl);
824
848
  const sdkS3 = new SparkStudioStorageSDK(storageApiBaseUrl);
849
+ const contentType = file.type || "application/octet-stream";
825
850
  const containerDTO = await sdkDb.container.CreateFileContainer(
826
851
  file.name,
827
852
  file.size,
828
- encodeURIComponent(file.type)
853
+ encodeURIComponent(contentType)
829
854
  );
830
855
  async function getPresignedUrlWithRetry(container, attempts = 3) {
831
856
  let lastError;
@@ -850,13 +875,6 @@ var ContainerUploadPanel = ({
850
875
  const handleUploadError = (file, err) => {
851
876
  console.error("Upload failed:", file.name, err);
852
877
  };
853
- const handleOnDeleteFile = async (file) => {
854
- const sdkDb = new SparkStudioStorageSDK(containerApiBaseUrl);
855
- const sdkS3 = new SparkStudioStorageSDK(storageApiBaseUrl);
856
- await sdkDb.container.DeleteContainer(file.Id);
857
- await sdkS3.s3.DeleteS3(file);
858
- await reload();
859
- };
860
878
  const handleExistingFileClick = (file) => {
861
879
  const a = document.createElement("a");
862
880
  a.href = file.PublicUrl ?? "";
@@ -867,6 +885,13 @@ var ContainerUploadPanel = ({
867
885
  a.click();
868
886
  document.body.removeChild(a);
869
887
  };
888
+ const handleDeleteFile = async (file) => {
889
+ const sdkDb = new SparkStudioStorageSDK(containerApiBaseUrl);
890
+ const sdkS3 = new SparkStudioStorageSDK(storageApiBaseUrl);
891
+ await sdkDb.container.DeleteContainer(file.Id);
892
+ await sdkS3.s3.DeleteS3(file);
893
+ setContainers((prev) => prev.filter((c) => c.Id !== file.Id));
894
+ };
870
895
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
871
896
  UploadContainer,
872
897
  {
@@ -877,7 +902,7 @@ var ContainerUploadPanel = ({
877
902
  getPresignedUrl,
878
903
  onUploadComplete: handleUploadComplete,
879
904
  onUploadError: handleUploadError,
880
- onDeleteFile: handleOnDeleteFile
905
+ onDeleteFile: handleDeleteFile
881
906
  }
882
907
  );
883
908
  };
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
+ import React__default from 'react';
2
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  declare enum ContainerType {
@@ -102,7 +103,7 @@ interface ContainerUploadPanelProps {
102
103
  /** Optional parent container – if set, we query children instead of roots. */
103
104
  parentContainerId?: string;
104
105
  }
105
- declare const ContainerUploadPanel: React.FC<ContainerUploadPanelProps>;
106
+ declare const ContainerUploadPanel: React__default.FC<ContainerUploadPanelProps>;
106
107
 
107
108
  interface DesktopFileIconProps {
108
109
  name?: string | null;
@@ -110,10 +111,10 @@ interface DesktopFileIconProps {
110
111
  downloadUrl?: string | null;
111
112
  /** Double-click / open action */
112
113
  onOpen?: () => void;
113
- /** Delete action */
114
- onDelete?: () => void;
114
+ /** Delete action (can be async) */
115
+ onDelete?: () => Promise<void> | void;
115
116
  }
116
- declare const DesktopFileIcon: React.FC<DesktopFileIconProps>;
117
+ declare const DesktopFileIcon: React__default.FC<DesktopFileIconProps>;
117
118
 
118
119
  interface UploadContainerProps {
119
120
  multiple?: boolean;
@@ -129,20 +130,20 @@ interface UploadContainerProps {
129
130
  onUploadComplete?: (file: File, s3Url: string) => void;
130
131
  onUploadError?: (file: File, error: Error) => void;
131
132
  }
132
- declare const UploadContainer: React.FC<UploadContainerProps>;
133
+ declare const UploadContainer: React__default.FC<UploadContainerProps>;
133
134
 
134
135
  interface UploadDropzoneProps {
135
136
  isDragging: boolean;
136
- onDragOver?: (e: React.DragEvent<HTMLDivElement>) => void;
137
- onDragLeave?: (e: React.DragEvent<HTMLDivElement>) => void;
138
- onDrop?: (e: React.DragEvent<HTMLDivElement>) => void;
137
+ onDragOver?: (e: React__default.DragEvent<HTMLDivElement>) => void;
138
+ onDragLeave?: (e: React__default.DragEvent<HTMLDivElement>) => void;
139
+ onDrop?: (e: React__default.DragEvent<HTMLDivElement>) => void;
139
140
  /** Extra className so you can make this the root wrapper */
140
141
  className?: string;
141
- style?: React.CSSProperties;
142
+ style?: React__default.CSSProperties;
142
143
  /** Custom content to render inside the dropzone */
143
- children?: React.ReactNode;
144
+ children?: React__default.ReactNode;
144
145
  }
145
- declare const UploadDropzone: React.FC<UploadDropzoneProps>;
146
+ declare const UploadDropzone: React__default.FC<UploadDropzoneProps>;
146
147
 
147
148
  type UploadStatus = "pending" | "uploading" | "success" | "error";
148
149
  interface UploadState {
@@ -158,7 +159,7 @@ interface UploadState {
158
159
  interface UploadProgressListProps {
159
160
  uploads: UploadState[];
160
161
  }
161
- declare const UploadProgressList: React.FC<UploadProgressListProps>;
162
+ declare const UploadProgressList: React__default.FC<UploadProgressListProps>;
162
163
 
163
164
  /**
164
165
  * Helper: upload a file to a pre-signed S3 URL with progress + retries.
@@ -171,6 +172,7 @@ interface UseContainersOptions {
171
172
  }
172
173
  declare function UseContainers({ apiBaseUrl, parentId }: UseContainersOptions): {
173
174
  containers: ContainerDTO[];
175
+ setContainers: React.Dispatch<React.SetStateAction<ContainerDTO[]>>;
174
176
  loading: boolean;
175
177
  error: Error | null;
176
178
  reload: () => Promise<void>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
+ import React__default from 'react';
2
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  declare enum ContainerType {
@@ -102,7 +103,7 @@ interface ContainerUploadPanelProps {
102
103
  /** Optional parent container – if set, we query children instead of roots. */
103
104
  parentContainerId?: string;
104
105
  }
105
- declare const ContainerUploadPanel: React.FC<ContainerUploadPanelProps>;
106
+ declare const ContainerUploadPanel: React__default.FC<ContainerUploadPanelProps>;
106
107
 
107
108
  interface DesktopFileIconProps {
108
109
  name?: string | null;
@@ -110,10 +111,10 @@ interface DesktopFileIconProps {
110
111
  downloadUrl?: string | null;
111
112
  /** Double-click / open action */
112
113
  onOpen?: () => void;
113
- /** Delete action */
114
- onDelete?: () => void;
114
+ /** Delete action (can be async) */
115
+ onDelete?: () => Promise<void> | void;
115
116
  }
116
- declare const DesktopFileIcon: React.FC<DesktopFileIconProps>;
117
+ declare const DesktopFileIcon: React__default.FC<DesktopFileIconProps>;
117
118
 
118
119
  interface UploadContainerProps {
119
120
  multiple?: boolean;
@@ -129,20 +130,20 @@ interface UploadContainerProps {
129
130
  onUploadComplete?: (file: File, s3Url: string) => void;
130
131
  onUploadError?: (file: File, error: Error) => void;
131
132
  }
132
- declare const UploadContainer: React.FC<UploadContainerProps>;
133
+ declare const UploadContainer: React__default.FC<UploadContainerProps>;
133
134
 
134
135
  interface UploadDropzoneProps {
135
136
  isDragging: boolean;
136
- onDragOver?: (e: React.DragEvent<HTMLDivElement>) => void;
137
- onDragLeave?: (e: React.DragEvent<HTMLDivElement>) => void;
138
- onDrop?: (e: React.DragEvent<HTMLDivElement>) => void;
137
+ onDragOver?: (e: React__default.DragEvent<HTMLDivElement>) => void;
138
+ onDragLeave?: (e: React__default.DragEvent<HTMLDivElement>) => void;
139
+ onDrop?: (e: React__default.DragEvent<HTMLDivElement>) => void;
139
140
  /** Extra className so you can make this the root wrapper */
140
141
  className?: string;
141
- style?: React.CSSProperties;
142
+ style?: React__default.CSSProperties;
142
143
  /** Custom content to render inside the dropzone */
143
- children?: React.ReactNode;
144
+ children?: React__default.ReactNode;
144
145
  }
145
- declare const UploadDropzone: React.FC<UploadDropzoneProps>;
146
+ declare const UploadDropzone: React__default.FC<UploadDropzoneProps>;
146
147
 
147
148
  type UploadStatus = "pending" | "uploading" | "success" | "error";
148
149
  interface UploadState {
@@ -158,7 +159,7 @@ interface UploadState {
158
159
  interface UploadProgressListProps {
159
160
  uploads: UploadState[];
160
161
  }
161
- declare const UploadProgressList: React.FC<UploadProgressListProps>;
162
+ declare const UploadProgressList: React__default.FC<UploadProgressListProps>;
162
163
 
163
164
  /**
164
165
  * Helper: upload a file to a pre-signed S3 URL with progress + retries.
@@ -171,6 +172,7 @@ interface UseContainersOptions {
171
172
  }
172
173
  declare function UseContainers({ apiBaseUrl, parentId }: UseContainersOptions): {
173
174
  containers: ContainerDTO[];
175
+ setContainers: React.Dispatch<React.SetStateAction<ContainerDTO[]>>;
174
176
  loading: boolean;
175
177
  error: Error | null;
176
178
  reload: () => Promise<void>;
package/dist/index.js CHANGED
@@ -437,6 +437,14 @@ var UploadProgressList = ({
437
437
  },
438
438
  children: [
439
439
  /* @__PURE__ */ jsx2("i", { className: "bi bi-file-earmark fs-2" }),
440
+ u.status === "uploading" && /* @__PURE__ */ jsx2(
441
+ "div",
442
+ {
443
+ className: "position-absolute top-50 start-50 translate-middle",
444
+ style: { pointerEvents: "none" },
445
+ children: /* @__PURE__ */ jsx2("div", { className: "spinner-border spinner-border-sm text-primary" })
446
+ }
447
+ ),
440
448
  u.status === "error" && /* @__PURE__ */ jsx2("span", { className: "position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger", children: "!" })
441
449
  ]
442
450
  }
@@ -490,9 +498,11 @@ var DesktopFileIcon = ({
490
498
  null
491
499
  );
492
500
  const [isHovered, setIsHovered] = useState2(false);
501
+ const [isDeleting, setIsDeleting] = useState2(false);
493
502
  const iconRef = useRef(null);
494
503
  const menuRef = useRef(null);
495
504
  const handleDoubleClick = () => {
505
+ if (isDeleting) return;
496
506
  if (onOpen) {
497
507
  onOpen();
498
508
  return;
@@ -509,13 +519,14 @@ var DesktopFileIcon = ({
509
519
  }
510
520
  };
511
521
  const handleContextMenu = (e) => {
522
+ if (isDeleting) return;
512
523
  e.preventDefault();
513
524
  setContextMenuPos({ x: e.clientX, y: e.clientY });
514
525
  };
515
526
  const closeMenu = () => setContextMenuPos(null);
516
527
  const handleDownload = () => {
517
528
  closeMenu();
518
- if (!downloadUrl) return;
529
+ if (!downloadUrl || isDeleting) return;
519
530
  const a = document.createElement("a");
520
531
  a.href = downloadUrl;
521
532
  a.download = name ?? "";
@@ -527,16 +538,22 @@ var DesktopFileIcon = ({
527
538
  };
528
539
  const handleCopyUrl = async () => {
529
540
  closeMenu();
530
- if (!downloadUrl) return;
541
+ if (!downloadUrl || isDeleting) return;
531
542
  try {
532
543
  await navigator.clipboard?.writeText(downloadUrl);
533
544
  } catch (err) {
534
545
  console.error("Failed to copy URL", err);
535
546
  }
536
547
  };
537
- const handleDelete = () => {
548
+ const handleDelete = async () => {
538
549
  closeMenu();
539
- onDelete?.();
550
+ if (!onDelete) return;
551
+ try {
552
+ setIsDeleting(true);
553
+ await Promise.resolve(onDelete());
554
+ } catch (err) {
555
+ console.error("Delete failed", err);
556
+ }
540
557
  };
541
558
  const formattedSize = typeof sizeBytes === "number" ? `${(sizeBytes / 1024).toFixed(1)} KB` : void 0;
542
559
  useEffect(() => {
@@ -561,12 +578,15 @@ var DesktopFileIcon = ({
561
578
  "div",
562
579
  {
563
580
  ref: iconRef,
564
- className: "d-flex flex-column align-items-center rounded-3 p-1 " + (isHovered || contextMenuPos ? "bg-light border" : ""),
581
+ className: "d-flex flex-column align-items-center rounded-3 p-1 " + (isHovered || contextMenuPos ? "bg-light border-primary" : "border-transparent"),
565
582
  style: {
566
583
  width: 96,
567
- cursor: "pointer",
584
+ cursor: isDeleting ? "default" : "pointer",
568
585
  userSelect: "none",
569
- transition: "background-color 0.1s ease, border-color 0.1s ease"
586
+ transition: "background-color 0.1s ease, border-color 0.1s ease, opacity 0.1s ease",
587
+ opacity: isDeleting ? 0.6 : 1,
588
+ borderWidth: 1,
589
+ borderStyle: "solid"
570
590
  },
571
591
  onDoubleClick: handleDoubleClick,
572
592
  onContextMenu: handleContextMenu,
@@ -579,15 +599,18 @@ var DesktopFileIcon = ({
579
599
  onMouseEnter: () => setIsHovered(true),
580
600
  onMouseLeave: () => setIsHovered(false),
581
601
  children: [
582
- /* @__PURE__ */ jsx3(
602
+ /* @__PURE__ */ jsxs2(
583
603
  "div",
584
604
  {
585
- className: "bg-white border rounded-3 d-flex align-items-center justify-content-center mb-1 shadow-sm",
605
+ className: "bg-white border rounded-3 d-flex align-items-center justify-content-center mb-1 shadow-sm position-relative",
586
606
  style: {
587
607
  width: 64,
588
608
  height: 64
589
609
  },
590
- children: /* @__PURE__ */ jsx3("i", { className: "bi bi-file-earmark fs-2" })
610
+ children: [
611
+ /* @__PURE__ */ jsx3("i", { className: "bi bi-file-earmark fs-2" }),
612
+ isDeleting && /* @__PURE__ */ jsx3("div", { className: "position-absolute top-50 start-50 translate-middle", children: /* @__PURE__ */ jsx3("div", { className: "spinner-border spinner-border-sm text-danger" }) })
613
+ ]
591
614
  }
592
615
  ),
593
616
  /* @__PURE__ */ jsx3(
@@ -602,7 +625,7 @@ var DesktopFileIcon = ({
602
625
  ]
603
626
  }
604
627
  ),
605
- contextMenuPos && /* @__PURE__ */ jsxs2(
628
+ contextMenuPos && !isDeleting && /* @__PURE__ */ jsxs2(
606
629
  "div",
607
630
  {
608
631
  ref: menuRef,
@@ -711,6 +734,7 @@ var UploadContainer = ({
711
734
  className: "w-100",
712
735
  style: { minHeight: "260px", alignItems: "stretch" },
713
736
  children: [
737
+ /* @__PURE__ */ jsx4("div", { className: "w-100 mb-3", children: /* @__PURE__ */ jsx4("div", { className: "d-flex flex-column flex-md-row align-items-start align-items-md-center justify-content-between gap-3", children: /* @__PURE__ */ jsx4("div", { className: "flex-grow-1 w-100", children: /* @__PURE__ */ jsx4(UploadProgressList, { uploads }) }) }) }),
714
738
  /* @__PURE__ */ jsx4(
715
739
  "div",
716
740
  {
@@ -720,16 +744,15 @@ var UploadContainer = ({
720
744
  DesktopFileIcon,
721
745
  {
722
746
  name: file.Name,
723
- sizeBytes: typeof file.FileSize === "number" ? file.FileSize : null,
724
- downloadUrl: file.PublicUrl ?? null,
747
+ sizeBytes: file.FileSize,
748
+ downloadUrl: file.PublicUrl,
725
749
  onOpen: () => handleExistingFileOpen(file),
726
- onDelete: onDeleteFile ? () => onDeleteFile(file) : void 0
750
+ onDelete: () => onDeleteFile?.(file)
727
751
  },
728
752
  file.Id
729
753
  ))
730
754
  }
731
- ),
732
- /* @__PURE__ */ jsx4("div", { className: "w-100 mt-3", children: /* @__PURE__ */ jsx4("div", { className: "d-flex flex-column flex-md-row align-items-start align-items-md-center justify-content-between gap-3", children: /* @__PURE__ */ jsx4("div", { className: "flex-grow-1 w-100", children: /* @__PURE__ */ jsx4(UploadProgressList, { uploads }) }) }) })
755
+ )
733
756
  ]
734
757
  }
735
758
  );
@@ -761,6 +784,7 @@ function UseContainers({ apiBaseUrl, parentId }) {
761
784
  }, [apiBaseUrl, parentId]);
762
785
  return {
763
786
  containers,
787
+ setContainers,
764
788
  loading,
765
789
  error,
766
790
  reload: load
@@ -774,17 +798,18 @@ var ContainerUploadPanel = ({
774
798
  storageApiBaseUrl,
775
799
  parentContainerId
776
800
  }) => {
777
- const { containers, reload, loading } = UseContainers({
801
+ const { containers, setContainers, reload, loading } = UseContainers({
778
802
  apiBaseUrl: containerApiBaseUrl,
779
803
  parentId: parentContainerId
780
804
  });
781
805
  const getPresignedUrl = async (file) => {
782
806
  const sdkDb = new SparkStudioStorageSDK(containerApiBaseUrl);
783
807
  const sdkS3 = new SparkStudioStorageSDK(storageApiBaseUrl);
808
+ const contentType = file.type || "application/octet-stream";
784
809
  const containerDTO = await sdkDb.container.CreateFileContainer(
785
810
  file.name,
786
811
  file.size,
787
- encodeURIComponent(file.type)
812
+ encodeURIComponent(contentType)
788
813
  );
789
814
  async function getPresignedUrlWithRetry(container, attempts = 3) {
790
815
  let lastError;
@@ -809,13 +834,6 @@ var ContainerUploadPanel = ({
809
834
  const handleUploadError = (file, err) => {
810
835
  console.error("Upload failed:", file.name, err);
811
836
  };
812
- const handleOnDeleteFile = async (file) => {
813
- const sdkDb = new SparkStudioStorageSDK(containerApiBaseUrl);
814
- const sdkS3 = new SparkStudioStorageSDK(storageApiBaseUrl);
815
- await sdkDb.container.DeleteContainer(file.Id);
816
- await sdkS3.s3.DeleteS3(file);
817
- await reload();
818
- };
819
837
  const handleExistingFileClick = (file) => {
820
838
  const a = document.createElement("a");
821
839
  a.href = file.PublicUrl ?? "";
@@ -826,6 +844,13 @@ var ContainerUploadPanel = ({
826
844
  a.click();
827
845
  document.body.removeChild(a);
828
846
  };
847
+ const handleDeleteFile = async (file) => {
848
+ const sdkDb = new SparkStudioStorageSDK(containerApiBaseUrl);
849
+ const sdkS3 = new SparkStudioStorageSDK(storageApiBaseUrl);
850
+ await sdkDb.container.DeleteContainer(file.Id);
851
+ await sdkS3.s3.DeleteS3(file);
852
+ setContainers((prev) => prev.filter((c) => c.Id !== file.Id));
853
+ };
829
854
  return /* @__PURE__ */ jsx5(
830
855
  UploadContainer,
831
856
  {
@@ -836,7 +861,7 @@ var ContainerUploadPanel = ({
836
861
  getPresignedUrl,
837
862
  onUploadComplete: handleUploadComplete,
838
863
  onUploadError: handleUploadError,
839
- onDeleteFile: handleOnDeleteFile
864
+ onDeleteFile: handleDeleteFile
840
865
  }
841
866
  );
842
867
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sparkstudio/storage-ui",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",