@plugable-io/react 0.0.5 → 0.0.6

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.d.mts CHANGED
@@ -92,8 +92,9 @@ interface FileImageProps {
92
92
  style?: CSSProperties;
93
93
  onLoad?: () => void;
94
94
  onError?: (error: Error) => void;
95
+ onRefetchNeeded?: () => Promise<void>;
95
96
  }
96
- declare function FileImage({ file, width, height, objectFit, borderRadius, alt, className, style, onLoad, onError, }: FileImageProps): react_jsx_runtime.JSX.Element;
97
+ declare function FileImage({ file, width, height, objectFit, borderRadius, alt, className, style, onLoad, onError, onRefetchNeeded, }: FileImageProps): react_jsx_runtime.JSX.Element;
97
98
  declare function clearImageCache(): void;
98
99
 
99
100
  interface FilePreviewProps {
@@ -106,7 +107,7 @@ interface FilePreviewProps {
106
107
  showExtension?: boolean;
107
108
  renderNonImage?: (file: FileObject) => React.ReactNode;
108
109
  }
109
- declare function FilePreview({ file, width, height, className, style, objectFit, showExtension, renderNonImage, }: FilePreviewProps): react_jsx_runtime.JSX.Element;
110
+ declare function FilePreview({ file: initialFile, width, height, className, style, objectFit, showExtension, renderNonImage, }: FilePreviewProps): react_jsx_runtime.JSX.Element;
110
111
 
111
112
  interface UseFilesOptions {
112
113
  metadata?: Record<string, any>;
package/dist/index.d.ts CHANGED
@@ -92,8 +92,9 @@ interface FileImageProps {
92
92
  style?: CSSProperties;
93
93
  onLoad?: () => void;
94
94
  onError?: (error: Error) => void;
95
+ onRefetchNeeded?: () => Promise<void>;
95
96
  }
96
- declare function FileImage({ file, width, height, objectFit, borderRadius, alt, className, style, onLoad, onError, }: FileImageProps): react_jsx_runtime.JSX.Element;
97
+ declare function FileImage({ file, width, height, objectFit, borderRadius, alt, className, style, onLoad, onError, onRefetchNeeded, }: FileImageProps): react_jsx_runtime.JSX.Element;
97
98
  declare function clearImageCache(): void;
98
99
 
99
100
  interface FilePreviewProps {
@@ -106,7 +107,7 @@ interface FilePreviewProps {
106
107
  showExtension?: boolean;
107
108
  renderNonImage?: (file: FileObject) => React.ReactNode;
108
109
  }
109
- declare function FilePreview({ file, width, height, className, style, objectFit, showExtension, renderNonImage, }: FilePreviewProps): react_jsx_runtime.JSX.Element;
110
+ declare function FilePreview({ file: initialFile, width, height, className, style, objectFit, showExtension, renderNonImage, }: FilePreviewProps): react_jsx_runtime.JSX.Element;
110
111
 
111
112
  interface UseFilesOptions {
112
113
  metadata?: Record<string, any>;
package/dist/index.js CHANGED
@@ -579,11 +579,13 @@ function FileImage({
579
579
  className,
580
580
  style,
581
581
  onLoad,
582
- onError
582
+ onError,
583
+ onRefetchNeeded
583
584
  }) {
584
585
  const [imageSrc, setImageSrc] = (0, import_react4.useState)(null);
585
586
  const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
586
587
  const [error, setError] = (0, import_react4.useState)(null);
588
+ const refetchAttemptedRef = (0, import_react4.useRef)(null);
587
589
  (0, import_react4.useEffect)(() => {
588
590
  let isMounted = true;
589
591
  let objectUrl = null;
@@ -606,6 +608,13 @@ function FileImage({
606
608
  }
607
609
  });
608
610
  if (!response.ok) {
611
+ const downloadUrlKey = `${file.id}-${file.download_url}`;
612
+ if (response.status === 403 && onRefetchNeeded && refetchAttemptedRef.current !== downloadUrlKey) {
613
+ refetchAttemptedRef.current = downloadUrlKey;
614
+ imageCache.delete(cacheKey);
615
+ await onRefetchNeeded();
616
+ return;
617
+ }
609
618
  throw new Error(`Failed to fetch image: ${response.statusText}`);
610
619
  }
611
620
  const blob = await response.blob();
@@ -614,6 +623,7 @@ function FileImage({
614
623
  if (isMounted) {
615
624
  setImageSrc(objectUrl);
616
625
  setIsLoading(false);
626
+ refetchAttemptedRef.current = null;
617
627
  }
618
628
  } else {
619
629
  throw new Error("No download URL available for file");
@@ -632,7 +642,7 @@ function FileImage({
632
642
  return () => {
633
643
  isMounted = false;
634
644
  };
635
- }, [file.id, file.checksum, file.download_url, onError]);
645
+ }, [file.id, file.checksum, file.download_url, onError, onRefetchNeeded]);
636
646
  const handleLoad = () => {
637
647
  setIsLoading(false);
638
648
  onLoad?.();
@@ -722,9 +732,10 @@ function clearImageCache() {
722
732
  }
723
733
 
724
734
  // src/components/FilePreview.tsx
735
+ var import_react5 = require("react");
725
736
  var import_jsx_runtime5 = require("react/jsx-runtime");
726
737
  function FilePreview({
727
- file,
738
+ file: initialFile,
728
739
  width = 80,
729
740
  height = 80,
730
741
  className,
@@ -733,6 +744,24 @@ function FilePreview({
733
744
  showExtension = true,
734
745
  renderNonImage
735
746
  }) {
747
+ const { client } = usePlugable();
748
+ const [file, setFile] = (0, import_react5.useState)(initialFile);
749
+ const [isRefetching, setIsRefetching] = (0, import_react5.useState)(false);
750
+ (0, import_react5.useEffect)(() => {
751
+ setFile(initialFile);
752
+ }, [initialFile.id, initialFile.download_url]);
753
+ const handleRefetch = (0, import_react5.useCallback)(async () => {
754
+ if (isRefetching) return;
755
+ try {
756
+ setIsRefetching(true);
757
+ const refreshedFile = await client.get(file.id);
758
+ setFile(refreshedFile);
759
+ } catch (err) {
760
+ console.error("Failed to refetch file:", err);
761
+ } finally {
762
+ setIsRefetching(false);
763
+ }
764
+ }, [file.id, client]);
736
765
  const isImage = file.content_type.startsWith("image/");
737
766
  const containerStyle = {
738
767
  width,
@@ -756,7 +785,8 @@ function FilePreview({
756
785
  objectFit,
757
786
  className,
758
787
  style,
759
- borderRadius: 4
788
+ borderRadius: 4,
789
+ onRefetchNeeded: handleRefetch
760
790
  }
761
791
  );
762
792
  }
package/dist/index.mjs CHANGED
@@ -523,7 +523,7 @@ function FileList({
523
523
  }
524
524
 
525
525
  // src/components/FileImage.tsx
526
- import { useEffect as useEffect2, useState as useState4 } from "react";
526
+ import { useEffect as useEffect2, useState as useState4, useRef as useRef3 } from "react";
527
527
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
528
528
  var imageCache = /* @__PURE__ */ new Map();
529
529
  function FileImage({
@@ -536,11 +536,13 @@ function FileImage({
536
536
  className,
537
537
  style,
538
538
  onLoad,
539
- onError
539
+ onError,
540
+ onRefetchNeeded
540
541
  }) {
541
542
  const [imageSrc, setImageSrc] = useState4(null);
542
543
  const [isLoading, setIsLoading] = useState4(true);
543
544
  const [error, setError] = useState4(null);
545
+ const refetchAttemptedRef = useRef3(null);
544
546
  useEffect2(() => {
545
547
  let isMounted = true;
546
548
  let objectUrl = null;
@@ -563,6 +565,13 @@ function FileImage({
563
565
  }
564
566
  });
565
567
  if (!response.ok) {
568
+ const downloadUrlKey = `${file.id}-${file.download_url}`;
569
+ if (response.status === 403 && onRefetchNeeded && refetchAttemptedRef.current !== downloadUrlKey) {
570
+ refetchAttemptedRef.current = downloadUrlKey;
571
+ imageCache.delete(cacheKey);
572
+ await onRefetchNeeded();
573
+ return;
574
+ }
566
575
  throw new Error(`Failed to fetch image: ${response.statusText}`);
567
576
  }
568
577
  const blob = await response.blob();
@@ -571,6 +580,7 @@ function FileImage({
571
580
  if (isMounted) {
572
581
  setImageSrc(objectUrl);
573
582
  setIsLoading(false);
583
+ refetchAttemptedRef.current = null;
574
584
  }
575
585
  } else {
576
586
  throw new Error("No download URL available for file");
@@ -589,7 +599,7 @@ function FileImage({
589
599
  return () => {
590
600
  isMounted = false;
591
601
  };
592
- }, [file.id, file.checksum, file.download_url, onError]);
602
+ }, [file.id, file.checksum, file.download_url, onError, onRefetchNeeded]);
593
603
  const handleLoad = () => {
594
604
  setIsLoading(false);
595
605
  onLoad?.();
@@ -679,9 +689,10 @@ function clearImageCache() {
679
689
  }
680
690
 
681
691
  // src/components/FilePreview.tsx
692
+ import { useState as useState5, useCallback as useCallback4, useEffect as useEffect3 } from "react";
682
693
  import { jsx as jsx5 } from "react/jsx-runtime";
683
694
  function FilePreview({
684
- file,
695
+ file: initialFile,
685
696
  width = 80,
686
697
  height = 80,
687
698
  className,
@@ -690,6 +701,24 @@ function FilePreview({
690
701
  showExtension = true,
691
702
  renderNonImage
692
703
  }) {
704
+ const { client } = usePlugable();
705
+ const [file, setFile] = useState5(initialFile);
706
+ const [isRefetching, setIsRefetching] = useState5(false);
707
+ useEffect3(() => {
708
+ setFile(initialFile);
709
+ }, [initialFile.id, initialFile.download_url]);
710
+ const handleRefetch = useCallback4(async () => {
711
+ if (isRefetching) return;
712
+ try {
713
+ setIsRefetching(true);
714
+ const refreshedFile = await client.get(file.id);
715
+ setFile(refreshedFile);
716
+ } catch (err) {
717
+ console.error("Failed to refetch file:", err);
718
+ } finally {
719
+ setIsRefetching(false);
720
+ }
721
+ }, [file.id, client]);
693
722
  const isImage = file.content_type.startsWith("image/");
694
723
  const containerStyle = {
695
724
  width,
@@ -713,7 +742,8 @@ function FilePreview({
713
742
  objectFit,
714
743
  className,
715
744
  style,
716
- borderRadius: 4
745
+ borderRadius: 4,
746
+ onRefetchNeeded: handleRefetch
717
747
  }
718
748
  );
719
749
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plugable-io/react",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "React components and hooks for Plugable File Management API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",