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

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.js CHANGED
@@ -169,6 +169,10 @@ var EXTENSION_MIME_MAP = {
169
169
  ".wav": "audio/wav",
170
170
  ".aac": "audio/aac",
171
171
  ".flac": "audio/flac",
172
+ ".m4a": "audio/mp4",
173
+ ".wma": "audio/x-ms-wma",
174
+ ".opus": "audio/opus",
175
+ ".weba": "audio/webm",
172
176
  // Code/Text
173
177
  ".txt": "text/plain",
174
178
  ".log": "text/plain",
@@ -495,6 +499,7 @@ var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
495
499
  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>`;
496
500
  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>`;
497
501
  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>`;
502
+ 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>`;
498
503
  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>`;
499
504
  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>`;
500
505
  var ICON_MAP = {
@@ -529,7 +534,8 @@ var ICON_MAP = {
529
534
  "openSeparateWindow": ICON_EXTERNAL_WINDOW,
530
535
  "reset-zoom": ICON_RESET_ZOOM,
531
536
  "zoom-reset": ICON_RESET_ZOOM,
532
- "resetZoom": ICON_RESET_ZOOM
537
+ "resetZoom": ICON_RESET_ZOOM,
538
+ "speed": ICON_SPEED
533
539
  };
534
540
  var ToolbarController = class {
535
541
  el;
@@ -2663,13 +2669,42 @@ var MediaPlugin = class {
2663
2669
  }
2664
2670
  });
2665
2671
  }
2672
+ actions.push({
2673
+ id: "open-window",
2674
+ icon: "open-window",
2675
+ label: "Open in Separate Full Window",
2676
+ type: "button",
2677
+ group: "actions",
2678
+ execute: () => {
2679
+ instance.openInSeparateWindow?.();
2680
+ }
2681
+ });
2666
2682
  return actions;
2667
2683
  }
2668
2684
  async render(ctx) {
2669
- const mimeType = ctx.metadata.mimeType || "application/octet-stream";
2670
- const isImage = mimeType.startsWith("image/") || IMAGE_EXTS.includes(ctx.metadata.extension || "");
2671
- const isVideo = mimeType.startsWith("video/") || VIDEO_EXTS.includes(ctx.metadata.extension || "");
2672
- const isAudio = mimeType.startsWith("audio/") || AUDIO_EXTS.includes(ctx.metadata.extension || "");
2685
+ const ext = (ctx.metadata.extension || "").toLowerCase();
2686
+ let mimeType = ctx.metadata.mimeType || "";
2687
+ if (!mimeType || mimeType === "application/octet-stream") {
2688
+ const audioMimes = {
2689
+ ".mp3": "audio/mpeg",
2690
+ ".wav": "audio/wav",
2691
+ ".ogg": "audio/ogg",
2692
+ ".flac": "audio/flac",
2693
+ ".aac": "audio/aac",
2694
+ ".m4a": "audio/mp4",
2695
+ ".wma": "audio/x-ms-wma",
2696
+ ".opus": "audio/opus",
2697
+ ".weba": "audio/webm"
2698
+ };
2699
+ if (audioMimes[ext]) {
2700
+ mimeType = audioMimes[ext];
2701
+ } else {
2702
+ mimeType = "application/octet-stream";
2703
+ }
2704
+ }
2705
+ const isImage = mimeType.startsWith("image/") || IMAGE_EXTS.includes(ext);
2706
+ const isVideo = mimeType.startsWith("video/") || VIDEO_EXTS.includes(ext);
2707
+ const isAudio = mimeType.startsWith("audio/") || AUDIO_EXTS.includes(ext);
2673
2708
  let url = "";
2674
2709
  let naturalW = 800;
2675
2710
  let naturalH = 600;
@@ -2741,10 +2776,79 @@ var MediaPlugin = class {
2741
2776
  video.addEventListener("canplay", onMeta, { once: true });
2742
2777
  }
2743
2778
  } else if (isAudio) {
2779
+ const audioCard = document.createElement("div");
2780
+ audioCard.className = "fp-audio-card";
2781
+ const artWrapper = document.createElement("div");
2782
+ artWrapper.className = "fp-audio-artwork-wrapper";
2783
+ const disc = document.createElement("div");
2784
+ disc.className = "fp-audio-disc";
2785
+ const discCenter = document.createElement("div");
2786
+ discCenter.className = "fp-audio-disc-center";
2787
+ const discHole = document.createElement("div");
2788
+ discHole.className = "fp-audio-disc-hole";
2789
+ discCenter.appendChild(discHole);
2790
+ disc.appendChild(discCenter);
2791
+ artWrapper.appendChild(disc);
2792
+ audioCard.appendChild(artWrapper);
2793
+ const info = document.createElement("div");
2794
+ info.className = "fp-audio-info";
2795
+ const title = document.createElement("div");
2796
+ title.className = "fp-audio-title";
2797
+ title.textContent = ctx.metadata.name || "Audio Track";
2798
+ const badges = document.createElement("div");
2799
+ badges.className = "fp-audio-badges";
2800
+ const extTag = document.createElement("span");
2801
+ extTag.className = "fp-audio-ext-tag";
2802
+ const cleanExt = (ext || ".mp3").replace(".", "").toUpperCase();
2803
+ extTag.textContent = `${cleanExt} AUDIO`;
2804
+ badges.appendChild(extTag);
2805
+ const timeTag = document.createElement("span");
2806
+ timeTag.className = "fp-audio-time-tag";
2807
+ timeTag.textContent = "0:00";
2808
+ badges.appendChild(timeTag);
2809
+ info.appendChild(title);
2810
+ info.appendChild(badges);
2811
+ audioCard.appendChild(info);
2812
+ const waveform = document.createElement("div");
2813
+ waveform.className = "fp-audio-waveform";
2814
+ for (let i = 0; i < 16; i++) {
2815
+ const bar = document.createElement("div");
2816
+ bar.className = "fp-audio-wave-bar";
2817
+ waveform.appendChild(bar);
2818
+ }
2819
+ audioCard.appendChild(waveform);
2820
+ const nativeWrapper = document.createElement("div");
2821
+ nativeWrapper.className = "fp-audio-native-wrapper";
2744
2822
  const audio = document.createElement("audio");
2745
2823
  audio.src = url;
2746
2824
  audio.controls = true;
2747
- element = audio;
2825
+ nativeWrapper.appendChild(audio);
2826
+ audioCard.appendChild(nativeWrapper);
2827
+ const onPlay = () => {
2828
+ disc.classList.add("playing");
2829
+ waveform.classList.add("playing");
2830
+ };
2831
+ const onPause = () => {
2832
+ disc.classList.remove("playing");
2833
+ waveform.classList.remove("playing");
2834
+ };
2835
+ const formatTime = (secs) => {
2836
+ if (!isFinite(secs) || isNaN(secs)) return "0:00";
2837
+ const m = Math.floor(secs / 60);
2838
+ const s = Math.floor(secs % 60);
2839
+ return `${m}:${s < 10 ? "0" : ""}${s}`;
2840
+ };
2841
+ const onTimeUpdate = () => {
2842
+ timeTag.textContent = `${formatTime(audio.currentTime)} / ${formatTime(audio.duration)}`;
2843
+ };
2844
+ const onLoadedMetadata = () => {
2845
+ timeTag.textContent = `0:00 / ${formatTime(audio.duration)}`;
2846
+ };
2847
+ audio.addEventListener("play", onPlay);
2848
+ audio.addEventListener("pause", onPause);
2849
+ audio.addEventListener("timeupdate", onTimeUpdate);
2850
+ audio.addEventListener("loadedmetadata", onLoadedMetadata);
2851
+ element = audioCard;
2748
2852
  mediaElement = audio;
2749
2853
  } else {
2750
2854
  element = document.createElement("div");
@@ -2754,11 +2858,12 @@ var MediaPlugin = class {
2754
2858
  scrollWrapper.className = "fp-media-scroll-wrapper";
2755
2859
  scrollWrapper.style.minWidth = "100%";
2756
2860
  scrollWrapper.style.minHeight = "100%";
2757
- scrollWrapper.style.width = "max-content";
2758
- scrollWrapper.style.height = "max-content";
2861
+ scrollWrapper.style.width = isAudio ? "100%" : "max-content";
2862
+ scrollWrapper.style.height = isAudio ? "100%" : "max-content";
2759
2863
  scrollWrapper.style.display = "flex";
2760
2864
  scrollWrapper.style.flexDirection = "column";
2761
2865
  scrollWrapper.style.alignItems = "center";
2866
+ scrollWrapper.style.justifyContent = isAudio ? "center" : "flex-start";
2762
2867
  scrollWrapper.style.padding = "16px";
2763
2868
  scrollWrapper.style.boxSizing = "border-box";
2764
2869
  const sizer = document.createElement("div");
@@ -2769,6 +2874,11 @@ var MediaPlugin = class {
2769
2874
  sizer.style.justifyContent = "center";
2770
2875
  sizer.style.alignItems = "center";
2771
2876
  sizer.style.margin = "auto 0";
2877
+ if (isAudio) {
2878
+ sizer.style.width = "100%";
2879
+ sizer.style.maxWidth = "520px";
2880
+ sizer.style.margin = "auto";
2881
+ }
2772
2882
  sizer.appendChild(element);
2773
2883
  scrollWrapper.appendChild(sizer);
2774
2884
  ctx.container.style.overflow = "auto";
@@ -2827,7 +2937,9 @@ var MediaPlugin = class {
2827
2937
  element.style.transformOrigin = "center center";
2828
2938
  element.style.flexShrink = "0";
2829
2939
  } else {
2830
- element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2940
+ if (!isAudio) {
2941
+ element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2942
+ }
2831
2943
  }
2832
2944
  };
2833
2945
  updateBaseDimensions();
@@ -2853,6 +2965,10 @@ var MediaPlugin = class {
2853
2965
  ro?.observe(ctx.container);
2854
2966
  const cleanup = () => {
2855
2967
  ro?.disconnect();
2968
+ if (mediaElement) {
2969
+ mediaElement.pause();
2970
+ mediaElement.src = "";
2971
+ }
2856
2972
  if (url) URL.revokeObjectURL(url);
2857
2973
  scrollWrapper.remove();
2858
2974
  ctx.container.innerHTML = "";
@@ -2876,36 +2992,54 @@ var MediaPlugin = class {
2876
2992
  currentZoom = level;
2877
2993
  applyTransform();
2878
2994
  } : void 0,
2879
- fitToPage: isImage || isVideo ? () => {
2880
- isUserZoomed = false;
2881
- fitMode = "page";
2882
- currentZoom = 1;
2883
- rotation = 0;
2884
- ctx.container.scrollTop = 0;
2885
- ctx.container.scrollLeft = 0;
2886
- updateBaseDimensions();
2887
- applyTransform();
2888
- } : void 0,
2889
- fitToWidth: isImage || isVideo ? () => {
2890
- isUserZoomed = false;
2891
- fitMode = "width";
2892
- currentZoom = 1;
2893
- rotation = 0;
2894
- ctx.container.scrollTop = 0;
2895
- ctx.container.scrollLeft = 0;
2896
- updateBaseDimensions();
2897
- applyTransform();
2898
- } : void 0,
2899
- resetZoom: isImage || isVideo ? () => {
2900
- isUserZoomed = false;
2901
- fitMode = ctx?.options?.fitMode || "width";
2902
- currentZoom = 1;
2903
- rotation = 0;
2904
- ctx.container.scrollTop = 0;
2905
- ctx.container.scrollLeft = 0;
2906
- updateBaseDimensions();
2907
- applyTransform();
2908
- } : void 0,
2995
+ fitToPage: () => {
2996
+ if (isImage || isVideo) {
2997
+ isUserZoomed = false;
2998
+ fitMode = "page";
2999
+ currentZoom = 1;
3000
+ rotation = 0;
3001
+ ctx.container.scrollTop = 0;
3002
+ ctx.container.scrollLeft = 0;
3003
+ updateBaseDimensions();
3004
+ applyTransform();
3005
+ } else if (isAudio) {
3006
+ ctx.container.scrollTop = 0;
3007
+ ctx.container.scrollLeft = 0;
3008
+ currentZoom = 1;
3009
+ }
3010
+ },
3011
+ fitToWidth: () => {
3012
+ if (isImage || isVideo) {
3013
+ isUserZoomed = false;
3014
+ fitMode = "width";
3015
+ currentZoom = 1;
3016
+ rotation = 0;
3017
+ ctx.container.scrollTop = 0;
3018
+ ctx.container.scrollLeft = 0;
3019
+ updateBaseDimensions();
3020
+ applyTransform();
3021
+ } else if (isAudio) {
3022
+ ctx.container.scrollTop = 0;
3023
+ ctx.container.scrollLeft = 0;
3024
+ currentZoom = 1;
3025
+ }
3026
+ },
3027
+ resetZoom: () => {
3028
+ if (isImage || isVideo) {
3029
+ isUserZoomed = false;
3030
+ fitMode = ctx?.options?.fitMode || "width";
3031
+ currentZoom = 1;
3032
+ rotation = 0;
3033
+ ctx.container.scrollTop = 0;
3034
+ ctx.container.scrollLeft = 0;
3035
+ updateBaseDimensions();
3036
+ applyTransform();
3037
+ } else if (isAudio) {
3038
+ ctx.container.scrollTop = 0;
3039
+ ctx.container.scrollLeft = 0;
3040
+ currentZoom = 1;
3041
+ }
3042
+ },
2909
3043
  rotateCW: isImage || isVideo ? () => {
2910
3044
  rotation = (rotation + 90) % 360;
2911
3045
  applyTransform();