@files-preview-app/preview-file 1.3.12 → 1.3.14

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/react.cjs CHANGED
@@ -202,6 +202,10 @@ var EXTENSION_MIME_MAP = {
202
202
  ".wav": "audio/wav",
203
203
  ".aac": "audio/aac",
204
204
  ".flac": "audio/flac",
205
+ ".m4a": "audio/mp4",
206
+ ".wma": "audio/x-ms-wma",
207
+ ".opus": "audio/opus",
208
+ ".weba": "audio/webm",
205
209
  // Code/Text
206
210
  ".txt": "text/plain",
207
211
  ".log": "text/plain",
@@ -528,6 +532,7 @@ var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
528
532
  var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>`;
529
533
  var ICON_FAST_FORWARD = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 19 22 12 13 5 13 19"></polygon><polygon points="2 19 11 12 2 5 2 19"></polygon></svg>`;
530
534
  var ICON_REWIND = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 19 2 12 11 5 11 19"></polygon><polygon points="22 19 13 12 22 5 22 19"></polygon></svg>`;
535
+ var ICON_SPEED = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>`;
531
536
  var ICON_EXTERNAL_WINDOW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><line x1="3" y1="8" x2="21" y2="8"></line><circle cx="6" cy="5.5" r="0.75" fill="currentColor"></circle><circle cx="8.5" cy="5.5" r="0.75" fill="currentColor"></circle><polyline points="14 13 18 13 18 17"></polyline><line x1="11" y1="20" x2="18" y2="13"></line></svg>`;
532
537
  var ICON_RESET_ZOOM = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><path d="M13 11a3 3 0 1 0-3 3"></path><path d="M10 11v3h3"></path></svg>`;
533
538
  var ICON_MAP = {
@@ -562,7 +567,8 @@ var ICON_MAP = {
562
567
  "openSeparateWindow": ICON_EXTERNAL_WINDOW,
563
568
  "reset-zoom": ICON_RESET_ZOOM,
564
569
  "zoom-reset": ICON_RESET_ZOOM,
565
- "resetZoom": ICON_RESET_ZOOM
570
+ "resetZoom": ICON_RESET_ZOOM,
571
+ "speed": ICON_SPEED
566
572
  };
567
573
  var ToolbarController = class {
568
574
  el;
@@ -2696,13 +2702,42 @@ var MediaPlugin = class {
2696
2702
  }
2697
2703
  });
2698
2704
  }
2705
+ actions.push({
2706
+ id: "open-window",
2707
+ icon: "open-window",
2708
+ label: "Open in Separate Full Window",
2709
+ type: "button",
2710
+ group: "actions",
2711
+ execute: () => {
2712
+ instance.openInSeparateWindow?.();
2713
+ }
2714
+ });
2699
2715
  return actions;
2700
2716
  }
2701
2717
  async render(ctx) {
2702
- const mimeType = ctx.metadata.mimeType || "application/octet-stream";
2703
- const isImage = mimeType.startsWith("image/") || IMAGE_EXTS.includes(ctx.metadata.extension || "");
2704
- const isVideo = mimeType.startsWith("video/") || VIDEO_EXTS.includes(ctx.metadata.extension || "");
2705
- const isAudio = mimeType.startsWith("audio/") || AUDIO_EXTS.includes(ctx.metadata.extension || "");
2718
+ const ext = (ctx.metadata.extension || "").toLowerCase();
2719
+ let mimeType = ctx.metadata.mimeType || "";
2720
+ if (!mimeType || mimeType === "application/octet-stream") {
2721
+ const audioMimes = {
2722
+ ".mp3": "audio/mpeg",
2723
+ ".wav": "audio/wav",
2724
+ ".ogg": "audio/ogg",
2725
+ ".flac": "audio/flac",
2726
+ ".aac": "audio/aac",
2727
+ ".m4a": "audio/mp4",
2728
+ ".wma": "audio/x-ms-wma",
2729
+ ".opus": "audio/opus",
2730
+ ".weba": "audio/webm"
2731
+ };
2732
+ if (audioMimes[ext]) {
2733
+ mimeType = audioMimes[ext];
2734
+ } else {
2735
+ mimeType = "application/octet-stream";
2736
+ }
2737
+ }
2738
+ const isImage = mimeType.startsWith("image/") || IMAGE_EXTS.includes(ext);
2739
+ const isVideo = mimeType.startsWith("video/") || VIDEO_EXTS.includes(ext);
2740
+ const isAudio = mimeType.startsWith("audio/") || AUDIO_EXTS.includes(ext);
2706
2741
  let url = "";
2707
2742
  let naturalW = 800;
2708
2743
  let naturalH = 600;
@@ -2774,10 +2809,79 @@ var MediaPlugin = class {
2774
2809
  video.addEventListener("canplay", onMeta, { once: true });
2775
2810
  }
2776
2811
  } else if (isAudio) {
2812
+ const audioCard = document.createElement("div");
2813
+ audioCard.className = "fp-audio-card";
2814
+ const artWrapper = document.createElement("div");
2815
+ artWrapper.className = "fp-audio-artwork-wrapper";
2816
+ const disc = document.createElement("div");
2817
+ disc.className = "fp-audio-disc";
2818
+ const discCenter = document.createElement("div");
2819
+ discCenter.className = "fp-audio-disc-center";
2820
+ const discHole = document.createElement("div");
2821
+ discHole.className = "fp-audio-disc-hole";
2822
+ discCenter.appendChild(discHole);
2823
+ disc.appendChild(discCenter);
2824
+ artWrapper.appendChild(disc);
2825
+ audioCard.appendChild(artWrapper);
2826
+ const info = document.createElement("div");
2827
+ info.className = "fp-audio-info";
2828
+ const title = document.createElement("div");
2829
+ title.className = "fp-audio-title";
2830
+ title.textContent = ctx.metadata.name || "Audio Track";
2831
+ const badges = document.createElement("div");
2832
+ badges.className = "fp-audio-badges";
2833
+ const extTag = document.createElement("span");
2834
+ extTag.className = "fp-audio-ext-tag";
2835
+ const cleanExt = (ext || ".mp3").replace(".", "").toUpperCase();
2836
+ extTag.textContent = `${cleanExt} AUDIO`;
2837
+ badges.appendChild(extTag);
2838
+ const timeTag = document.createElement("span");
2839
+ timeTag.className = "fp-audio-time-tag";
2840
+ timeTag.textContent = "0:00";
2841
+ badges.appendChild(timeTag);
2842
+ info.appendChild(title);
2843
+ info.appendChild(badges);
2844
+ audioCard.appendChild(info);
2845
+ const waveform = document.createElement("div");
2846
+ waveform.className = "fp-audio-waveform";
2847
+ for (let i = 0; i < 16; i++) {
2848
+ const bar = document.createElement("div");
2849
+ bar.className = "fp-audio-wave-bar";
2850
+ waveform.appendChild(bar);
2851
+ }
2852
+ audioCard.appendChild(waveform);
2853
+ const nativeWrapper = document.createElement("div");
2854
+ nativeWrapper.className = "fp-audio-native-wrapper";
2777
2855
  const audio = document.createElement("audio");
2778
2856
  audio.src = url;
2779
2857
  audio.controls = true;
2780
- element = audio;
2858
+ nativeWrapper.appendChild(audio);
2859
+ audioCard.appendChild(nativeWrapper);
2860
+ const onPlay = () => {
2861
+ disc.classList.add("playing");
2862
+ waveform.classList.add("playing");
2863
+ };
2864
+ const onPause = () => {
2865
+ disc.classList.remove("playing");
2866
+ waveform.classList.remove("playing");
2867
+ };
2868
+ const formatTime = (secs) => {
2869
+ if (!isFinite(secs) || isNaN(secs)) return "0:00";
2870
+ const m = Math.floor(secs / 60);
2871
+ const s = Math.floor(secs % 60);
2872
+ return `${m}:${s < 10 ? "0" : ""}${s}`;
2873
+ };
2874
+ const onTimeUpdate = () => {
2875
+ timeTag.textContent = `${formatTime(audio.currentTime)} / ${formatTime(audio.duration)}`;
2876
+ };
2877
+ const onLoadedMetadata = () => {
2878
+ timeTag.textContent = `0:00 / ${formatTime(audio.duration)}`;
2879
+ };
2880
+ audio.addEventListener("play", onPlay);
2881
+ audio.addEventListener("pause", onPause);
2882
+ audio.addEventListener("timeupdate", onTimeUpdate);
2883
+ audio.addEventListener("loadedmetadata", onLoadedMetadata);
2884
+ element = audioCard;
2781
2885
  mediaElement = audio;
2782
2886
  } else {
2783
2887
  element = document.createElement("div");
@@ -2787,11 +2891,12 @@ var MediaPlugin = class {
2787
2891
  scrollWrapper.className = "fp-media-scroll-wrapper";
2788
2892
  scrollWrapper.style.minWidth = "100%";
2789
2893
  scrollWrapper.style.minHeight = "100%";
2790
- scrollWrapper.style.width = "max-content";
2791
- scrollWrapper.style.height = "max-content";
2894
+ scrollWrapper.style.width = isAudio ? "100%" : "max-content";
2895
+ scrollWrapper.style.height = isAudio ? "100%" : "max-content";
2792
2896
  scrollWrapper.style.display = "flex";
2793
2897
  scrollWrapper.style.flexDirection = "column";
2794
2898
  scrollWrapper.style.alignItems = "center";
2899
+ scrollWrapper.style.justifyContent = isAudio ? "center" : "flex-start";
2795
2900
  scrollWrapper.style.padding = "16px";
2796
2901
  scrollWrapper.style.boxSizing = "border-box";
2797
2902
  const sizer = document.createElement("div");
@@ -2802,6 +2907,11 @@ var MediaPlugin = class {
2802
2907
  sizer.style.justifyContent = "center";
2803
2908
  sizer.style.alignItems = "center";
2804
2909
  sizer.style.margin = "auto 0";
2910
+ if (isAudio) {
2911
+ sizer.style.width = "100%";
2912
+ sizer.style.maxWidth = "520px";
2913
+ sizer.style.margin = "auto";
2914
+ }
2805
2915
  sizer.appendChild(element);
2806
2916
  scrollWrapper.appendChild(sizer);
2807
2917
  ctx.container.style.overflow = "auto";
@@ -2860,7 +2970,9 @@ var MediaPlugin = class {
2860
2970
  element.style.transformOrigin = "center center";
2861
2971
  element.style.flexShrink = "0";
2862
2972
  } else {
2863
- element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2973
+ if (!isAudio) {
2974
+ element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2975
+ }
2864
2976
  }
2865
2977
  };
2866
2978
  updateBaseDimensions();
@@ -2886,6 +2998,10 @@ var MediaPlugin = class {
2886
2998
  ro?.observe(ctx.container);
2887
2999
  const cleanup = () => {
2888
3000
  ro?.disconnect();
3001
+ if (mediaElement) {
3002
+ mediaElement.pause();
3003
+ mediaElement.src = "";
3004
+ }
2889
3005
  if (url) URL.revokeObjectURL(url);
2890
3006
  scrollWrapper.remove();
2891
3007
  ctx.container.innerHTML = "";
@@ -2909,36 +3025,54 @@ var MediaPlugin = class {
2909
3025
  currentZoom = level;
2910
3026
  applyTransform();
2911
3027
  } : void 0,
2912
- fitToPage: isImage || isVideo ? () => {
2913
- isUserZoomed = false;
2914
- fitMode = "page";
2915
- currentZoom = 1;
2916
- rotation = 0;
2917
- ctx.container.scrollTop = 0;
2918
- ctx.container.scrollLeft = 0;
2919
- updateBaseDimensions();
2920
- applyTransform();
2921
- } : void 0,
2922
- fitToWidth: isImage || isVideo ? () => {
2923
- isUserZoomed = false;
2924
- fitMode = "width";
2925
- currentZoom = 1;
2926
- rotation = 0;
2927
- ctx.container.scrollTop = 0;
2928
- ctx.container.scrollLeft = 0;
2929
- updateBaseDimensions();
2930
- applyTransform();
2931
- } : void 0,
2932
- resetZoom: isImage || isVideo ? () => {
2933
- isUserZoomed = false;
2934
- fitMode = ctx?.options?.fitMode || "width";
2935
- currentZoom = 1;
2936
- rotation = 0;
2937
- ctx.container.scrollTop = 0;
2938
- ctx.container.scrollLeft = 0;
2939
- updateBaseDimensions();
2940
- applyTransform();
2941
- } : void 0,
3028
+ fitToPage: () => {
3029
+ if (isImage || isVideo) {
3030
+ isUserZoomed = false;
3031
+ fitMode = "page";
3032
+ currentZoom = 1;
3033
+ rotation = 0;
3034
+ ctx.container.scrollTop = 0;
3035
+ ctx.container.scrollLeft = 0;
3036
+ updateBaseDimensions();
3037
+ applyTransform();
3038
+ } else if (isAudio) {
3039
+ ctx.container.scrollTop = 0;
3040
+ ctx.container.scrollLeft = 0;
3041
+ currentZoom = 1;
3042
+ }
3043
+ },
3044
+ fitToWidth: () => {
3045
+ if (isImage || isVideo) {
3046
+ isUserZoomed = false;
3047
+ fitMode = "width";
3048
+ currentZoom = 1;
3049
+ rotation = 0;
3050
+ ctx.container.scrollTop = 0;
3051
+ ctx.container.scrollLeft = 0;
3052
+ updateBaseDimensions();
3053
+ applyTransform();
3054
+ } else if (isAudio) {
3055
+ ctx.container.scrollTop = 0;
3056
+ ctx.container.scrollLeft = 0;
3057
+ currentZoom = 1;
3058
+ }
3059
+ },
3060
+ resetZoom: () => {
3061
+ if (isImage || isVideo) {
3062
+ isUserZoomed = false;
3063
+ fitMode = ctx?.options?.fitMode || "width";
3064
+ currentZoom = 1;
3065
+ rotation = 0;
3066
+ ctx.container.scrollTop = 0;
3067
+ ctx.container.scrollLeft = 0;
3068
+ updateBaseDimensions();
3069
+ applyTransform();
3070
+ } else if (isAudio) {
3071
+ ctx.container.scrollTop = 0;
3072
+ ctx.container.scrollLeft = 0;
3073
+ currentZoom = 1;
3074
+ }
3075
+ },
2942
3076
  rotateCW: isImage || isVideo ? () => {
2943
3077
  rotation = (rotation + 90) % 360;
2944
3078
  applyTransform();