@files-preview-app/preview-file 1.3.5 → 1.3.7

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
@@ -610,6 +610,7 @@ var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" str
610
610
  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>`;
611
611
  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>`;
612
612
  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>`;
613
+ 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>`;
613
614
  var ICON_MAP = {
614
615
  "zoom-in": ICON_ZOOM_IN,
615
616
  "zoom-out": ICON_ZOOM_OUT,
@@ -639,7 +640,10 @@ var ICON_MAP = {
639
640
  "open-window": ICON_EXTERNAL_WINDOW,
640
641
  "external-window": ICON_EXTERNAL_WINDOW,
641
642
  "openWindow": ICON_EXTERNAL_WINDOW,
642
- "openSeparateWindow": ICON_EXTERNAL_WINDOW
643
+ "openSeparateWindow": ICON_EXTERNAL_WINDOW,
644
+ "reset-zoom": ICON_RESET_ZOOM,
645
+ "zoom-reset": ICON_RESET_ZOOM,
646
+ "resetZoom": ICON_RESET_ZOOM
643
647
  };
644
648
  var ToolbarController = class {
645
649
  el;
@@ -672,6 +676,10 @@ var ToolbarController = class {
672
676
  this.config.fitToPage = false;
673
677
  this.config.fitWidth = false;
674
678
  }
679
+ if (actionId === "reset-zoom" || actionId === "zoom-reset" || actionId === "resetZoom") {
680
+ this.config.resetZoom = false;
681
+ this.config.zoomReset = false;
682
+ }
675
683
  if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = false;
676
684
  if (actionId === "fullscreen") this.config.fullscreen = false;
677
685
  if (actionId === "download") this.config.download = false;
@@ -696,6 +704,10 @@ var ToolbarController = class {
696
704
  this.config.fitToPage = true;
697
705
  this.config.fitWidth = true;
698
706
  }
707
+ if (actionId === "reset-zoom" || actionId === "zoom-reset" || actionId === "resetZoom") {
708
+ this.config.resetZoom = true;
709
+ this.config.zoomReset = true;
710
+ }
699
711
  if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = true;
700
712
  if (actionId === "fullscreen") this.config.fullscreen = true;
701
713
  if (actionId === "download") this.config.download = true;
@@ -715,6 +727,7 @@ var ToolbarController = class {
715
727
  if (actionId === "zoomIn") return "zoom-in";
716
728
  if (actionId === "zoomOut") return "zoom-out";
717
729
  if (actionId === "fitPage" || actionId === "fitToPage" || actionId === "fitWidth") return "fit-page";
730
+ if (actionId === "resetZoom" || actionId === "zoomReset") return "reset-zoom";
718
731
  if (actionId === "rotateCW") return "rotate-cw";
719
732
  if (actionId === "rotateCCW") return "rotate-ccw";
720
733
  if (actionId === "openWindow" || actionId === "openSeparateWindow") return "open-window";
@@ -757,6 +770,9 @@ var ToolbarController = class {
757
770
  if ((id === "fit-page" || id === "fit-width" || id === "fit-slide") && (c.fitPage === false || c.fitToPage === false || c.fitWidth === false || c["fit-page"] === false || c["fit-width"] === false)) {
758
771
  return false;
759
772
  }
773
+ if ((id === "reset-zoom" || id === "zoom-reset") && (c.resetZoom === false || c.zoomReset === false || c["reset-zoom"] === false || c["zoom-reset"] === false)) {
774
+ return false;
775
+ }
760
776
  if ((id === "rotate-cw" || id === "rotate-ccw" || id === "rotate") && (c.rotate === false || c.rotateCW === false || c.rotateCCW === false || c["rotate-cw"] === false)) {
761
777
  return false;
762
778
  }
@@ -1203,6 +1219,9 @@ var FilePreviewViewer = class _FilePreviewViewer {
1203
1219
  this.activeInstance = instance;
1204
1220
  instance.openInSeparateWindow = () => this.openInSeparateWindow();
1205
1221
  instance.toggleThumbnails = () => this.toggleThumbnails();
1222
+ if (!instance.resetZoom && instance.fitToPage) {
1223
+ instance.resetZoom = () => instance.fitToPage?.();
1224
+ }
1206
1225
  this.hideLoading();
1207
1226
  this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
1208
1227
  const isToolbarVisible = options.showToolbar !== false && options.toolbar !== false;
@@ -1486,6 +1505,16 @@ var FilePreviewViewer = class _FilePreviewViewer {
1486
1505
  fitToPage() {
1487
1506
  this.activeInstance?.fitToPage?.();
1488
1507
  }
1508
+ /**
1509
+ * Reset zoom level to initial/default fit state.
1510
+ */
1511
+ resetZoom() {
1512
+ if (this.activeInstance?.resetZoom) {
1513
+ this.activeInstance.resetZoom();
1514
+ } else if (this.activeInstance?.fitToPage) {
1515
+ this.activeInstance.fitToPage();
1516
+ }
1517
+ }
1489
1518
  /**
1490
1519
  * Zoom in.
1491
1520
  */
@@ -2107,6 +2136,14 @@ var PdfPlugin = class {
2107
2136
  group: "zoom",
2108
2137
  execute: () => instance.fitToPage?.()
2109
2138
  },
2139
+ {
2140
+ id: "reset-zoom",
2141
+ icon: "reset-zoom",
2142
+ label: "Reset Zoom",
2143
+ type: "button",
2144
+ group: "zoom",
2145
+ execute: () => instance.resetZoom?.()
2146
+ },
2110
2147
  {
2111
2148
  id: "fit-width",
2112
2149
  icon: "fit-width",
@@ -2162,16 +2199,22 @@ var PdfPlugin = class {
2162
2199
  container.className = "fp-pdf-container";
2163
2200
  container.style.width = "100%";
2164
2201
  container.style.height = "100%";
2165
- container.style.overflowX = "hidden";
2166
- container.style.overflowY = "auto";
2167
- container.style.display = "flex";
2168
- container.style.flexDirection = "column";
2169
- container.style.alignItems = "center";
2170
- container.style.justifyContent = "flex-start";
2171
- container.style.padding = "16px 8px";
2202
+ container.style.overflow = "auto";
2172
2203
  container.style.backgroundColor = "#0f172a";
2173
2204
  container.style.boxSizing = "border-box";
2174
2205
  container.style.position = "relative";
2206
+ const scrollWrapper = document.createElement("div");
2207
+ scrollWrapper.className = "fp-pdf-scroll-wrapper";
2208
+ scrollWrapper.style.minWidth = "100%";
2209
+ scrollWrapper.style.minHeight = "100%";
2210
+ scrollWrapper.style.width = "max-content";
2211
+ scrollWrapper.style.height = "max-content";
2212
+ scrollWrapper.style.display = "flex";
2213
+ scrollWrapper.style.flexDirection = "column";
2214
+ scrollWrapper.style.alignItems = "center";
2215
+ scrollWrapper.style.justifyContent = "flex-start";
2216
+ scrollWrapper.style.padding = "16px 8px";
2217
+ scrollWrapper.style.boxSizing = "border-box";
2175
2218
  const pageCard = document.createElement("div");
2176
2219
  pageCard.className = "fp-pdf-page-card";
2177
2220
  pageCard.style.boxShadow = "0 10px 35px rgba(0, 0, 0, 0.5)";
@@ -2184,7 +2227,8 @@ var PdfPlugin = class {
2184
2227
  pageCard.style.transition = "box-shadow 0.2s ease";
2185
2228
  let canvas = document.createElement("canvas");
2186
2229
  pageCard.appendChild(canvas);
2187
- container.appendChild(pageCard);
2230
+ scrollWrapper.appendChild(pageCard);
2231
+ container.appendChild(scrollWrapper);
2188
2232
  ctx.container.appendChild(container);
2189
2233
  const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
2190
2234
  const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
@@ -2369,6 +2413,14 @@ var PdfPlugin = class {
2369
2413
  zoomScale = 1;
2370
2414
  renderPage(currentPage);
2371
2415
  },
2416
+ resetZoom: () => {
2417
+ fitMode = "page";
2418
+ zoomScale = 1;
2419
+ rotation = 0;
2420
+ container.scrollTop = 0;
2421
+ container.scrollLeft = 0;
2422
+ renderPage(currentPage);
2423
+ },
2372
2424
  fitToWidth: () => {
2373
2425
  fitMode = "width";
2374
2426
  zoomScale = 1;
@@ -2536,6 +2588,16 @@ var MediaPlugin = class {
2536
2588
  instance.fitToPage?.();
2537
2589
  }
2538
2590
  },
2591
+ {
2592
+ id: "reset-zoom",
2593
+ icon: "reset-zoom",
2594
+ label: "Reset Zoom",
2595
+ type: "button",
2596
+ group: "zoom",
2597
+ execute: () => {
2598
+ instance.resetZoom?.();
2599
+ }
2600
+ },
2539
2601
  {
2540
2602
  id: "rotate-cw",
2541
2603
  icon: "rotate-cw",
@@ -2675,17 +2737,86 @@ var MediaPlugin = class {
2675
2737
  element = document.createElement("div");
2676
2738
  element.textContent = "Unsupported media type";
2677
2739
  }
2678
- ctx.container.style.display = "flex";
2679
- ctx.container.style.alignItems = "center";
2680
- ctx.container.style.justifyContent = "center";
2681
- ctx.container.style.overflow = "hidden";
2682
- ctx.container.appendChild(element);
2740
+ const scrollWrapper = document.createElement("div");
2741
+ scrollWrapper.className = "fp-media-scroll-wrapper";
2742
+ scrollWrapper.style.minWidth = "100%";
2743
+ scrollWrapper.style.minHeight = "100%";
2744
+ scrollWrapper.style.width = "max-content";
2745
+ scrollWrapper.style.height = "max-content";
2746
+ scrollWrapper.style.display = "flex";
2747
+ scrollWrapper.style.justifyContent = "center";
2748
+ scrollWrapper.style.alignItems = "center";
2749
+ scrollWrapper.style.padding = "16px";
2750
+ scrollWrapper.style.boxSizing = "border-box";
2751
+ const sizer = document.createElement("div");
2752
+ sizer.className = "fp-media-sizer";
2753
+ sizer.style.position = "relative";
2754
+ sizer.style.flexShrink = "0";
2755
+ sizer.style.display = "flex";
2756
+ sizer.style.justifyContent = "center";
2757
+ sizer.style.alignItems = "center";
2758
+ sizer.appendChild(element);
2759
+ scrollWrapper.appendChild(sizer);
2760
+ ctx.container.style.overflow = "auto";
2761
+ ctx.container.style.padding = "0";
2762
+ ctx.container.innerHTML = "";
2763
+ ctx.container.appendChild(scrollWrapper);
2764
+ let naturalW = 800;
2765
+ let naturalH = 600;
2766
+ let baseW = 800;
2767
+ let baseH = 600;
2768
+ const updateBaseDimensions = () => {
2769
+ if (!isImage) return;
2770
+ const img = element;
2771
+ naturalW = img.naturalWidth || naturalW;
2772
+ naturalH = img.naturalHeight || naturalH;
2773
+ const availW = Math.max(100, ctx.container.clientWidth - 48);
2774
+ const availH = Math.max(100, ctx.container.clientHeight - 48);
2775
+ const fitRatio = Math.min(1, availW / naturalW, availH / naturalH);
2776
+ baseW = Math.max(1, Math.round(naturalW * fitRatio));
2777
+ baseH = Math.max(1, Math.round(naturalH * fitRatio));
2778
+ };
2683
2779
  const applyTransform = () => {
2684
- element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2780
+ if (isImage) {
2781
+ updateBaseDimensions();
2782
+ const isRotated90 = rotation % 180 !== 0;
2783
+ const boxW = Math.round((isRotated90 ? baseH : baseW) * currentZoom);
2784
+ const boxH = Math.round((isRotated90 ? baseW : baseH) * currentZoom);
2785
+ sizer.style.width = `${boxW}px`;
2786
+ sizer.style.height = `${boxH}px`;
2787
+ element.style.width = `${baseW}px`;
2788
+ element.style.height = `${baseH}px`;
2789
+ element.style.maxWidth = "none";
2790
+ element.style.maxHeight = "none";
2791
+ element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2792
+ element.style.transformOrigin = "center center";
2793
+ element.style.flexShrink = "0";
2794
+ } else {
2795
+ element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2796
+ }
2685
2797
  };
2798
+ if (isImage) {
2799
+ const img = element;
2800
+ if (img.complete && img.naturalWidth > 0) {
2801
+ updateBaseDimensions();
2802
+ applyTransform();
2803
+ } else {
2804
+ img.onload = () => {
2805
+ updateBaseDimensions();
2806
+ applyTransform();
2807
+ };
2808
+ }
2809
+ }
2810
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
2811
+ if (currentZoom === 1) {
2812
+ applyTransform();
2813
+ }
2814
+ }) : null;
2815
+ ro?.observe(ctx.container);
2686
2816
  const cleanup = () => {
2817
+ ro?.disconnect();
2687
2818
  if (url) URL.revokeObjectURL(url);
2688
- element.remove();
2819
+ scrollWrapper.remove();
2689
2820
  ctx.container.innerHTML = "";
2690
2821
  };
2691
2822
  ctx.signal.addEventListener("abort", cleanup);
@@ -2709,6 +2840,13 @@ var MediaPlugin = class {
2709
2840
  rotation = 0;
2710
2841
  applyTransform();
2711
2842
  } : void 0,
2843
+ resetZoom: isImage ? () => {
2844
+ currentZoom = 1;
2845
+ rotation = 0;
2846
+ ctx.container.scrollTop = 0;
2847
+ ctx.container.scrollLeft = 0;
2848
+ applyTransform();
2849
+ } : void 0,
2712
2850
  rotateCW: isImage || isVideo ? () => {
2713
2851
  rotation = (rotation + 90) % 360;
2714
2852
  applyTransform();
@@ -2825,6 +2963,14 @@ var DocxPlugin = class {
2825
2963
  group: "zoom",
2826
2964
  execute: () => instance.fitToPage?.()
2827
2965
  },
2966
+ {
2967
+ id: "reset-zoom",
2968
+ icon: "reset-zoom",
2969
+ label: "Reset Zoom",
2970
+ type: "button",
2971
+ group: "zoom",
2972
+ execute: () => instance.resetZoom?.()
2973
+ },
2828
2974
  {
2829
2975
  id: "rotate-cw",
2830
2976
  icon: "rotate-cw",
@@ -2863,7 +3009,7 @@ var DocxPlugin = class {
2863
3009
  async render(ctx) {
2864
3010
  const wrapper = document.createElement("div");
2865
3011
  wrapper.className = "fp-docx-wrapper";
2866
- wrapper.style.transformOrigin = "top center";
3012
+ wrapper.style.transformOrigin = "center center";
2867
3013
  wrapper.style.transition = "transform 0.2s ease";
2868
3014
  wrapper.style.padding = "0";
2869
3015
  wrapper.style.maxWidth = "none";
@@ -2873,11 +3019,31 @@ var DocxPlugin = class {
2873
3019
  wrapper.style.flexDirection = "column";
2874
3020
  wrapper.style.alignItems = "center";
2875
3021
  wrapper.style.boxSizing = "border-box";
2876
- ctx.container.style.overflowX = "hidden";
2877
- ctx.container.style.overflowY = "auto";
2878
- ctx.container.style.padding = "16px 8px";
3022
+ wrapper.style.flexShrink = "0";
3023
+ const sizer = document.createElement("div");
3024
+ sizer.className = "fp-docx-sizer";
3025
+ sizer.style.position = "relative";
3026
+ sizer.style.flexShrink = "0";
3027
+ sizer.style.display = "flex";
3028
+ sizer.style.justifyContent = "center";
3029
+ sizer.style.alignItems = "center";
3030
+ const scrollWrapper = document.createElement("div");
3031
+ scrollWrapper.className = "fp-docx-scroll-wrapper";
3032
+ scrollWrapper.style.minWidth = "100%";
3033
+ scrollWrapper.style.minHeight = "100%";
3034
+ scrollWrapper.style.width = "max-content";
3035
+ scrollWrapper.style.height = "max-content";
3036
+ scrollWrapper.style.display = "flex";
3037
+ scrollWrapper.style.justifyContent = "center";
3038
+ scrollWrapper.style.alignItems = "flex-start";
3039
+ scrollWrapper.style.padding = "16px 8px";
3040
+ scrollWrapper.style.boxSizing = "border-box";
3041
+ sizer.appendChild(wrapper);
3042
+ scrollWrapper.appendChild(sizer);
3043
+ ctx.container.style.overflow = "auto";
3044
+ ctx.container.style.padding = "0";
2879
3045
  ctx.container.style.backgroundColor = "#f1f5f9";
2880
- ctx.container.appendChild(wrapper);
3046
+ ctx.container.appendChild(scrollWrapper);
2881
3047
  const styleOverride = document.createElement("style");
2882
3048
  styleOverride.textContent = `
2883
3049
  .fp-docx-wrapper .docx-wrapper {
@@ -2916,8 +3082,8 @@ var DocxPlugin = class {
2916
3082
  renderEndnotes: true,
2917
3083
  useBase64URL: true
2918
3084
  });
2919
- if (!ctx.container.contains(wrapper)) {
2920
- ctx.container.appendChild(wrapper);
3085
+ if (!sizer.contains(wrapper)) {
3086
+ sizer.appendChild(wrapper);
2921
3087
  }
2922
3088
  if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
2923
3089
  renderedSuccessfully = true;
@@ -2954,8 +3120,8 @@ var DocxPlugin = class {
2954
3120
  try {
2955
3121
  wrapper.innerHTML = "";
2956
3122
  this.renderXmlFallback(ctx, wrapper, createdBlobUrls);
2957
- if (!ctx.container.contains(wrapper)) {
2958
- ctx.container.appendChild(wrapper);
3123
+ if (!sizer.contains(wrapper)) {
3124
+ sizer.appendChild(wrapper);
2959
3125
  }
2960
3126
  renderedSuccessfully = true;
2961
3127
  } catch (fallbackErr) {
@@ -2970,8 +3136,8 @@ var DocxPlugin = class {
2970
3136
  </p>
2971
3137
  </div>
2972
3138
  `;
2973
- if (!ctx.container.contains(wrapper)) {
2974
- ctx.container.appendChild(wrapper);
3139
+ if (!sizer.contains(wrapper)) {
3140
+ sizer.appendChild(wrapper);
2975
3141
  }
2976
3142
  }
2977
3143
  }
@@ -3074,15 +3240,18 @@ var DocxPlugin = class {
3074
3240
  return Math.max(0.35, Math.min(3, sW));
3075
3241
  };
3076
3242
  const applyTransform = () => {
3077
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
3078
- wrapper.style.transformOrigin = "top center";
3079
3243
  const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
3244
+ const elW = activeEl.offsetWidth || 816;
3080
3245
  const elH = activeEl.offsetHeight || 1056;
3081
- if (scale > 1) {
3082
- wrapper.style.marginBottom = `${Math.round(elH * scale - elH + 32)}px`;
3083
- } else {
3084
- wrapper.style.marginBottom = "32px";
3085
- }
3246
+ const isRotated90 = rotation % 180 !== 0;
3247
+ const boxW = Math.round((isRotated90 ? elH : elW) * scale);
3248
+ const boxH = Math.round((isRotated90 ? elW : elH) * scale);
3249
+ sizer.style.width = `${boxW}px`;
3250
+ sizer.style.height = `${boxH}px`;
3251
+ wrapper.style.width = `${elW}px`;
3252
+ wrapper.style.height = `${elH}px`;
3253
+ wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
3254
+ wrapper.style.transformOrigin = "center center";
3086
3255
  };
3087
3256
  let resizeObserver = null;
3088
3257
  if (typeof ResizeObserver !== "undefined") {
@@ -3107,7 +3276,7 @@ var DocxPlugin = class {
3107
3276
  for (const url of createdBlobUrls) {
3108
3277
  URL.revokeObjectURL(url);
3109
3278
  }
3110
- wrapper.remove();
3279
+ scrollWrapper.remove();
3111
3280
  styleOverride.remove();
3112
3281
  ctx.container.innerHTML = "";
3113
3282
  };
@@ -3141,6 +3310,14 @@ var DocxPlugin = class {
3141
3310
  rotation = 0;
3142
3311
  applyTransform();
3143
3312
  },
3313
+ resetZoom: () => {
3314
+ isUserZoomed = false;
3315
+ scale = calculateFitScale("page");
3316
+ rotation = 0;
3317
+ ctx.container.scrollTop = 0;
3318
+ ctx.container.scrollLeft = 0;
3319
+ applyTransform();
3320
+ },
3144
3321
  rotateCW: () => {
3145
3322
  rotation = (rotation + 90) % 360;
3146
3323
  applyTransform();
@@ -3590,6 +3767,16 @@ var ExcelPlugin = class {
3590
3767
  instance.zoomIn?.();
3591
3768
  }
3592
3769
  },
3770
+ {
3771
+ id: "reset-zoom",
3772
+ icon: "reset-zoom",
3773
+ label: "Reset Zoom",
3774
+ type: "button",
3775
+ group: "zoom",
3776
+ execute: () => {
3777
+ instance.resetZoom?.();
3778
+ }
3779
+ },
3593
3780
  {
3594
3781
  id: "download",
3595
3782
  icon: "download",
@@ -3636,7 +3823,7 @@ var ExcelPlugin = class {
3636
3823
  contentArea.style.flex = "1";
3637
3824
  contentArea.style.overflow = "auto";
3638
3825
  contentArea.style.padding = "16px";
3639
- contentArea.style.transformOrigin = "top left";
3826
+ contentArea.style.boxSizing = "border-box";
3640
3827
  const tabsArea = document.createElement("div");
3641
3828
  tabsArea.className = "fp-excel-tabs";
3642
3829
  tabsArea.style.display = "flex";
@@ -3650,18 +3837,35 @@ var ExcelPlugin = class {
3650
3837
  container.appendChild(tabsArea);
3651
3838
  ctx.container.appendChild(container);
3652
3839
  let scale = 1;
3840
+ let isUserZoomed = false;
3653
3841
  let currentSheetIndex = 1;
3654
3842
  let sheetNames = [];
3655
3843
  let wb = null;
3656
3844
  const applyTransform = () => {
3657
- contentArea.style.transform = `scale(${scale})`;
3658
- contentArea.style.transformOrigin = "top left";
3845
+ const sizer = contentArea.querySelector(".fp-excel-sizer");
3846
+ const table = contentArea.querySelector("table");
3847
+ if (!sizer || !table) return;
3848
+ if (!table._baseWidth && table.offsetWidth > 0) {
3849
+ table._baseWidth = table.offsetWidth;
3850
+ table._baseHeight = table.offsetHeight;
3851
+ }
3852
+ const baseW = table._baseWidth || table.offsetWidth || 800;
3853
+ const baseH = table._baseHeight || table.offsetHeight || 600;
3854
+ const scaledW = Math.round(baseW * scale);
3855
+ const scaledH = Math.round(baseH * scale);
3856
+ sizer.style.width = `${scaledW}px`;
3857
+ sizer.style.height = `${scaledH}px`;
3858
+ table.style.position = "absolute";
3859
+ table.style.top = "0";
3860
+ table.style.left = "0";
3861
+ table.style.transform = `scale(${scale})`;
3862
+ table.style.transformOrigin = "top left";
3659
3863
  };
3660
3864
  const calculateFitScale = () => {
3661
3865
  const table = contentArea.querySelector("table");
3662
3866
  if (!table) return 1;
3663
3867
  const availW = Math.max(280, container.clientWidth - 48);
3664
- const tW = table.offsetWidth || 800;
3868
+ const tW = table._baseWidth || table.offsetWidth || 800;
3665
3869
  return Math.max(0.4, Math.min(1, availW / tW));
3666
3870
  };
3667
3871
  try {
@@ -3681,9 +3885,13 @@ var ExcelPlugin = class {
3681
3885
  contentArea.innerHTML = '<div style="padding: 24px; color: #888;">Empty sheet</div>';
3682
3886
  return;
3683
3887
  }
3888
+ const sizer = document.createElement("div");
3889
+ sizer.className = "fp-excel-sizer";
3890
+ sizer.style.position = "relative";
3684
3891
  const html = XLSX__namespace.utils.sheet_to_html(ws, { id: "fp-sheet-table", editable: false });
3685
- contentArea.innerHTML = html;
3686
- const table = contentArea.querySelector("table");
3892
+ sizer.innerHTML = html;
3893
+ contentArea.appendChild(sizer);
3894
+ const table = sizer.querySelector("table");
3687
3895
  if (table) {
3688
3896
  table.style.borderCollapse = "collapse";
3689
3897
  table.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
@@ -3718,13 +3926,17 @@ var ExcelPlugin = class {
3718
3926
  });
3719
3927
  ctx.emit("page-change", { page: currentSheetIndex, total: sheetNames.length });
3720
3928
  requestAnimationFrame(() => {
3721
- scale = calculateFitScale();
3929
+ if (!isUserZoomed) {
3930
+ scale = calculateFitScale();
3931
+ }
3722
3932
  applyTransform();
3723
3933
  });
3724
3934
  };
3725
3935
  const ro = new ResizeObserver(() => {
3726
- scale = calculateFitScale();
3727
- applyTransform();
3936
+ if (!isUserZoomed) {
3937
+ scale = calculateFitScale();
3938
+ applyTransform();
3939
+ }
3728
3940
  });
3729
3941
  ro.observe(container);
3730
3942
  if (sheetNames.length > 0) {
@@ -3761,20 +3973,31 @@ var ExcelPlugin = class {
3761
3973
  return {
3762
3974
  destroy: cleanup,
3763
3975
  zoomIn: () => {
3976
+ isUserZoomed = true;
3764
3977
  scale += 0.15;
3765
3978
  applyTransform();
3766
3979
  },
3767
3980
  zoomOut: () => {
3981
+ isUserZoomed = true;
3768
3982
  scale = Math.max(0.2, scale - 0.15);
3769
3983
  applyTransform();
3770
3984
  },
3771
3985
  getZoom: () => scale,
3772
3986
  setZoom: (level) => {
3987
+ isUserZoomed = true;
3773
3988
  scale = level;
3774
3989
  applyTransform();
3775
3990
  },
3776
3991
  fitToPage: () => {
3992
+ isUserZoomed = false;
3993
+ scale = calculateFitScale();
3994
+ applyTransform();
3995
+ },
3996
+ resetZoom: () => {
3997
+ isUserZoomed = false;
3777
3998
  scale = calculateFitScale();
3999
+ contentArea.scrollTop = 0;
4000
+ contentArea.scrollLeft = 0;
3778
4001
  applyTransform();
3779
4002
  },
3780
4003
  rotateCW: () => {
@@ -3907,6 +4130,16 @@ var CsvPlugin = class {
3907
4130
  instance.zoomIn?.();
3908
4131
  }
3909
4132
  },
4133
+ {
4134
+ id: "reset-zoom",
4135
+ icon: "reset-zoom",
4136
+ label: "Reset Zoom",
4137
+ type: "button",
4138
+ group: "zoom",
4139
+ execute: () => {
4140
+ instance.resetZoom?.();
4141
+ }
4142
+ },
3910
4143
  {
3911
4144
  id: "download",
3912
4145
  icon: "download",
@@ -3993,21 +4226,41 @@ var CsvPlugin = class {
3993
4226
  container.appendChild(tableWrapper);
3994
4227
  ctx.container.appendChild(container);
3995
4228
  let scale = 1;
4229
+ let isUserZoomed = false;
3996
4230
  const calculateFitScale = () => {
3997
4231
  const availW = Math.max(280, container.clientWidth - 48);
3998
- const tW = table.offsetWidth || 800;
4232
+ const tW = table._baseWidth || table.offsetWidth || 800;
3999
4233
  return Math.max(0.4, Math.min(1, availW / tW));
4000
4234
  };
4001
4235
  const applyScale = () => {
4002
- tableWrapper.style.transform = `scale(${scale})`;
4236
+ if (!table._baseWidth && table.offsetWidth > 0) {
4237
+ table._baseWidth = table.offsetWidth;
4238
+ table._baseHeight = table.offsetHeight;
4239
+ }
4240
+ const baseW = table._baseWidth || table.offsetWidth || 800;
4241
+ const baseH = table._baseHeight || table.offsetHeight || 600;
4242
+ const scaledW = Math.round(baseW * scale);
4243
+ const scaledH = Math.round(baseH * scale);
4244
+ tableWrapper.style.position = "relative";
4245
+ tableWrapper.style.width = `${scaledW}px`;
4246
+ tableWrapper.style.height = `${scaledH}px`;
4247
+ table.style.position = "absolute";
4248
+ table.style.top = "0";
4249
+ table.style.left = "0";
4250
+ table.style.transform = `scale(${scale})`;
4251
+ table.style.transformOrigin = "top left";
4003
4252
  };
4004
4253
  requestAnimationFrame(() => {
4005
- scale = calculateFitScale();
4254
+ if (!isUserZoomed) {
4255
+ scale = calculateFitScale();
4256
+ }
4006
4257
  applyScale();
4007
4258
  });
4008
4259
  const ro = new ResizeObserver(() => {
4009
- scale = calculateFitScale();
4010
- applyScale();
4260
+ if (!isUserZoomed) {
4261
+ scale = calculateFitScale();
4262
+ applyScale();
4263
+ }
4011
4264
  });
4012
4265
  ro.observe(container);
4013
4266
  const cleanup = () => {
@@ -4080,20 +4333,31 @@ var CsvPlugin = class {
4080
4333
  }];
4081
4334
  },
4082
4335
  zoomIn: () => {
4336
+ isUserZoomed = true;
4083
4337
  scale += 0.1;
4084
4338
  applyScale();
4085
4339
  },
4086
4340
  zoomOut: () => {
4341
+ isUserZoomed = true;
4087
4342
  scale = Math.max(0.2, scale - 0.1);
4088
4343
  applyScale();
4089
4344
  },
4090
4345
  getZoom: () => scale,
4091
4346
  setZoom: (level) => {
4347
+ isUserZoomed = true;
4092
4348
  scale = level;
4093
4349
  applyScale();
4094
4350
  },
4095
4351
  fitToPage: () => {
4352
+ isUserZoomed = false;
4353
+ scale = calculateFitScale();
4354
+ applyScale();
4355
+ },
4356
+ resetZoom: () => {
4357
+ isUserZoomed = false;
4096
4358
  scale = calculateFitScale();
4359
+ container.scrollTop = 0;
4360
+ container.scrollLeft = 0;
4097
4361
  applyScale();
4098
4362
  },
4099
4363
  rotateCW: () => {
@@ -4211,6 +4475,16 @@ var CodePlugin = class {
4211
4475
  instance.zoomIn?.();
4212
4476
  }
4213
4477
  },
4478
+ {
4479
+ id: "reset-zoom",
4480
+ icon: "reset-zoom",
4481
+ label: "Reset Zoom",
4482
+ type: "button",
4483
+ group: "zoom",
4484
+ execute: () => {
4485
+ instance.resetZoom?.();
4486
+ }
4487
+ },
4214
4488
  {
4215
4489
  id: "copy",
4216
4490
  icon: "copy",
@@ -4316,15 +4590,27 @@ var CodePlugin = class {
4316
4590
  let isUserZoomed = false;
4317
4591
  const pre = document.createElement("pre");
4318
4592
  const code = document.createElement("code");
4593
+ const sizer = document.createElement("div");
4594
+ const scrollWrapper = document.createElement("div");
4319
4595
  if (isTxt) {
4320
- container.style.overflowX = "hidden";
4321
- container.style.overflowY = "auto";
4596
+ container.style.overflow = "auto";
4322
4597
  container.style.backgroundColor = "#f1f5f9";
4323
- container.style.padding = "16px 8px";
4324
- container.style.boxSizing = "border-box";
4325
- container.style.display = "flex";
4326
- container.style.flexDirection = "column";
4327
- container.style.alignItems = "center";
4598
+ scrollWrapper.className = "fp-code-scroll-wrapper";
4599
+ scrollWrapper.style.minWidth = "100%";
4600
+ scrollWrapper.style.minHeight = "100%";
4601
+ scrollWrapper.style.width = "max-content";
4602
+ scrollWrapper.style.height = "max-content";
4603
+ scrollWrapper.style.display = "flex";
4604
+ scrollWrapper.style.justifyContent = "center";
4605
+ scrollWrapper.style.alignItems = "flex-start";
4606
+ scrollWrapper.style.padding = "16px 8px";
4607
+ scrollWrapper.style.boxSizing = "border-box";
4608
+ sizer.className = "fp-code-sizer";
4609
+ sizer.style.position = "relative";
4610
+ sizer.style.flexShrink = "0";
4611
+ sizer.style.display = "flex";
4612
+ sizer.style.justifyContent = "center";
4613
+ sizer.style.alignItems = "center";
4328
4614
  pre.style.margin = "0 auto";
4329
4615
  pre.style.fontFamily = "Consolas, 'Courier New', monospace";
4330
4616
  pre.style.fontSize = "13px";
@@ -4339,8 +4625,9 @@ var CodePlugin = class {
4339
4625
  pre.style.boxSizing = "border-box";
4340
4626
  pre.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4341
4627
  pre.style.borderRadius = "4px";
4342
- pre.style.transformOrigin = "top center";
4628
+ pre.style.transformOrigin = "center center";
4343
4629
  pre.style.transition = "transform 0.15s ease";
4630
+ pre.style.flexShrink = "0";
4344
4631
  } else {
4345
4632
  container.style.overflow = "auto";
4346
4633
  container.style.backgroundColor = "#1e1e1e";
@@ -4373,7 +4660,13 @@ var CodePlugin = class {
4373
4660
  };
4374
4661
  renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
4375
4662
  pre.appendChild(code);
4376
- container.appendChild(pre);
4663
+ if (isTxt) {
4664
+ sizer.appendChild(pre);
4665
+ scrollWrapper.appendChild(sizer);
4666
+ container.appendChild(scrollWrapper);
4667
+ } else {
4668
+ container.appendChild(pre);
4669
+ }
4377
4670
  const showPage = (pageNum) => {
4378
4671
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
4379
4672
  renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
@@ -4390,10 +4683,16 @@ var CodePlugin = class {
4390
4683
  };
4391
4684
  const updateTransform = () => {
4392
4685
  if (isTxt) {
4686
+ const elW = 816;
4687
+ const baseH = pre.offsetHeight || 1056;
4688
+ const isRotated90 = rotation % 180 !== 0;
4689
+ const boxW = Math.round((isRotated90 ? baseH : elW) * zoomLevel);
4690
+ const boxH = Math.round((isRotated90 ? elW : baseH) * zoomLevel);
4691
+ sizer.style.width = `${boxW}px`;
4692
+ sizer.style.height = `${boxH}px`;
4693
+ pre.style.width = `${elW}px`;
4393
4694
  pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
4394
- const scaledH = 1056 * zoomLevel;
4395
- const extraH = Math.max(0, scaledH - 1056);
4396
- pre.style.marginBottom = `${extraH + 32}px`;
4695
+ pre.style.transformOrigin = "center center";
4397
4696
  } else {
4398
4697
  pre.style.transform = `rotate(${rotation}deg)`;
4399
4698
  pre.style.fontSize = `${fontSize}px`;
@@ -4490,6 +4789,15 @@ var CodePlugin = class {
4490
4789
  zoomLevel = isTxt ? calculateTxtFit() : 1;
4491
4790
  updateTransform();
4492
4791
  },
4792
+ resetZoom: () => {
4793
+ isUserZoomed = false;
4794
+ fontSize = 13;
4795
+ rotation = 0;
4796
+ zoomLevel = isTxt ? calculateTxtFit() : 1;
4797
+ container.scrollTop = 0;
4798
+ container.scrollLeft = 0;
4799
+ updateTransform();
4800
+ },
4493
4801
  rotateCW: () => {
4494
4802
  rotation = (rotation + 90) % 360;
4495
4803
  updateTransform();
@@ -4552,11 +4860,19 @@ var ArchivePlugin = class {
4552
4860
  {
4553
4861
  id: "fit-page",
4554
4862
  icon: "fit-page",
4555
- label: "Reset Zoom",
4863
+ label: "Fit to Page",
4556
4864
  type: "button",
4557
4865
  group: "zoom",
4558
4866
  execute: () => instance.fitToPage?.()
4559
4867
  },
4868
+ {
4869
+ id: "reset-zoom",
4870
+ icon: "reset-zoom",
4871
+ label: "Reset Zoom",
4872
+ type: "button",
4873
+ group: "zoom",
4874
+ execute: () => instance.resetZoom?.()
4875
+ },
4560
4876
  {
4561
4877
  id: "download",
4562
4878
  icon: "download",
@@ -4582,16 +4898,56 @@ var ArchivePlugin = class {
4582
4898
  width: 100%;
4583
4899
  height: 100%;
4584
4900
  overflow: auto;
4585
- padding: 24px;
4586
4901
  box-sizing: border-box;
4587
4902
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
4588
- transform-origin: top left;
4589
- transition: transform 0.2s ease;
4590
4903
  `;
4904
+ const scrollWrapper = document.createElement("div");
4905
+ scrollWrapper.className = "fp-archive-scroll-wrapper";
4906
+ scrollWrapper.style.cssText = `
4907
+ min-width: 100%;
4908
+ min-height: 100%;
4909
+ width: max-content;
4910
+ height: max-content;
4911
+ display: flex;
4912
+ justify-content: center;
4913
+ align-items: flex-start;
4914
+ padding: 24px;
4915
+ box-sizing: border-box;
4916
+ `;
4917
+ const sizer = document.createElement("div");
4918
+ sizer.className = "fp-archive-sizer";
4919
+ sizer.style.cssText = `
4920
+ position: relative;
4921
+ flex-shrink: 0;
4922
+ display: flex;
4923
+ justify-content: center;
4924
+ align-items: flex-start;
4925
+ `;
4926
+ const card = document.createElement("div");
4927
+ card.className = "fp-archive-card";
4928
+ card.style.cssText = `
4929
+ width: 900px;
4930
+ box-sizing: border-box;
4931
+ transform-origin: top center;
4932
+ transition: transform 0.15s ease;
4933
+ flex-shrink: 0;
4934
+ `;
4935
+ sizer.appendChild(card);
4936
+ scrollWrapper.appendChild(sizer);
4937
+ wrapper.appendChild(scrollWrapper);
4591
4938
  ctx.container.innerHTML = "";
4592
4939
  ctx.container.style.overflow = "auto";
4593
4940
  ctx.container.appendChild(wrapper);
4594
4941
  let scale = 1;
4942
+ const applyTransform = () => {
4943
+ const boxW = Math.round(900 * scale);
4944
+ const cardH = card.offsetHeight || 600;
4945
+ const boxH = Math.round(cardH * scale);
4946
+ sizer.style.width = `${boxW}px`;
4947
+ sizer.style.height = `${boxH}px`;
4948
+ card.style.transform = `scale(${scale})`;
4949
+ card.style.transformOrigin = "top center";
4950
+ };
4595
4951
  const entries = await new Promise((resolve, reject) => {
4596
4952
  fflate.unzip(new Uint8Array(ctx.buffer), (err, unzipped) => {
4597
4953
  if (err) {
@@ -4615,7 +4971,7 @@ var ArchivePlugin = class {
4615
4971
  });
4616
4972
  const totalUncompressedSize = entries.reduce((acc, e) => acc + e.size, 0);
4617
4973
  const renderUI = (filteredEntries) => {
4618
- wrapper.innerHTML = `
4974
+ card.innerHTML = `
4619
4975
  <div style="max-width: 900px; margin: 0 auto; background: var(--fp-bg, #ffffff); border: 1px solid var(--fp-border, #e5e7eb); border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); overflow: hidden;">
4620
4976
  <div style="padding: 16px 20px; background: var(--fp-toolbar-bg, #f9fafb); border-bottom: 1px solid var(--fp-border, #e5e7eb); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;">
4621
4977
  <div>
@@ -4645,7 +5001,7 @@ var ArchivePlugin = class {
4645
5001
  </div>
4646
5002
  </div>
4647
5003
  `;
4648
- const tbody = wrapper.querySelector("#fp-archive-body");
5004
+ const tbody = card.querySelector("#fp-archive-body");
4649
5005
  if (filteredEntries.length === 0) {
4650
5006
  tbody.innerHTML = `<tr><td colspan="3" style="padding: 24px; text-align: center; color: #9ca3af;">No matching files found</td></tr>`;
4651
5007
  } else {
@@ -4674,19 +5030,20 @@ var ArchivePlugin = class {
4674
5030
  }
4675
5031
  });
4676
5032
  });
4677
- const searchInput = wrapper.querySelector("#fp-archive-search");
5033
+ const searchInput = card.querySelector("#fp-archive-search");
4678
5034
  if (searchInput) {
4679
5035
  searchInput.addEventListener("input", () => {
4680
5036
  const q = searchInput.value.toLowerCase().trim();
4681
5037
  const filtered = q ? entries.filter((e) => e.path.toLowerCase().includes(q)) : entries;
4682
5038
  renderUI(filtered);
4683
- const newSearch = wrapper.querySelector("#fp-archive-search");
5039
+ const newSearch = card.querySelector("#fp-archive-search");
4684
5040
  if (newSearch) {
4685
5041
  newSearch.value = q;
4686
5042
  newSearch.focus();
4687
5043
  }
4688
5044
  });
4689
5045
  }
5046
+ applyTransform();
4690
5047
  };
4691
5048
  renderUI(entries);
4692
5049
  const cleanup = () => {
@@ -4698,20 +5055,26 @@ var ArchivePlugin = class {
4698
5055
  destroy: cleanup,
4699
5056
  zoomIn: () => {
4700
5057
  scale += 0.1;
4701
- wrapper.style.transform = `scale(${scale})`;
5058
+ applyTransform();
4702
5059
  },
4703
5060
  zoomOut: () => {
4704
5061
  scale = Math.max(0.3, scale - 0.1);
4705
- wrapper.style.transform = `scale(${scale})`;
5062
+ applyTransform();
4706
5063
  },
4707
5064
  getZoom: () => scale,
4708
5065
  setZoom: (level) => {
4709
5066
  scale = level;
4710
- wrapper.style.transform = `scale(${scale})`;
5067
+ applyTransform();
4711
5068
  },
4712
5069
  fitToPage: () => {
4713
5070
  scale = 1;
4714
- wrapper.style.transform = `scale(1)`;
5071
+ applyTransform();
5072
+ },
5073
+ resetZoom: () => {
5074
+ scale = 1;
5075
+ wrapper.scrollTop = 0;
5076
+ wrapper.scrollLeft = 0;
5077
+ applyTransform();
4715
5078
  },
4716
5079
  download: () => {
4717
5080
  downloadFile(ctx.buffer, ctx.metadata.name || "archive.zip", "application/zip");
@@ -4763,6 +5126,14 @@ var MarkdownPlugin = class {
4763
5126
  group: "zoom",
4764
5127
  execute: () => instance.fitToPage?.()
4765
5128
  },
5129
+ {
5130
+ id: "reset-zoom",
5131
+ icon: "reset-zoom",
5132
+ label: "Reset Zoom",
5133
+ type: "button",
5134
+ group: "zoom",
5135
+ execute: () => instance.resetZoom?.()
5136
+ },
4766
5137
  {
4767
5138
  id: "copy",
4768
5139
  icon: "copy",
@@ -4916,6 +5287,12 @@ var MarkdownPlugin = class {
4916
5287
  fontSize = 15;
4917
5288
  wrapper.style.fontSize = "15px";
4918
5289
  },
5290
+ resetZoom: () => {
5291
+ fontSize = 15;
5292
+ wrapper.style.fontSize = "15px";
5293
+ ctx.container.scrollTop = 0;
5294
+ ctx.container.scrollLeft = 0;
5295
+ },
4919
5296
  download: () => {
4920
5297
  downloadFile(ctx.buffer, ctx.metadata.name || "document.md", "text/markdown");
4921
5298
  },
@@ -5009,6 +5386,14 @@ var PptxPlugin = class {
5009
5386
  group: "zoom",
5010
5387
  execute: () => instance.fitToPage?.()
5011
5388
  },
5389
+ {
5390
+ id: "reset-zoom",
5391
+ icon: "reset-zoom",
5392
+ label: "Reset Zoom",
5393
+ type: "button",
5394
+ group: "zoom",
5395
+ execute: () => instance.resetZoom?.()
5396
+ },
5012
5397
  {
5013
5398
  id: "rotate-cw",
5014
5399
  icon: "rotate-cw",
@@ -5048,12 +5433,30 @@ var PptxPlugin = class {
5048
5433
  width: 100%;
5049
5434
  height: 100%;
5050
5435
  overflow: auto;
5436
+ box-sizing: border-box;
5437
+ background: var(--fp-bg-canvas, #525659);
5438
+ `;
5439
+ const scrollWrapper = document.createElement("div");
5440
+ scrollWrapper.className = "fp-pptx-scroll-wrapper";
5441
+ scrollWrapper.style.cssText = `
5442
+ min-width: 100%;
5443
+ min-height: 100%;
5444
+ width: max-content;
5445
+ height: max-content;
5051
5446
  display: flex;
5052
5447
  justify-content: center;
5053
- align-items: flex-start;
5448
+ align-items: center;
5054
5449
  padding: 24px;
5055
5450
  box-sizing: border-box;
5056
- background: var(--fp-bg-canvas, #525659);
5451
+ `;
5452
+ const sizer = document.createElement("div");
5453
+ sizer.className = "fp-pptx-sizer";
5454
+ sizer.style.cssText = `
5455
+ position: relative;
5456
+ flex-shrink: 0;
5457
+ display: flex;
5458
+ justify-content: center;
5459
+ align-items: center;
5057
5460
  `;
5058
5461
  const slideContainer = document.createElement("div");
5059
5462
  slideContainer.className = "fp-slide-container";
@@ -5062,14 +5465,15 @@ var PptxPlugin = class {
5062
5465
  border-radius: 4px;
5063
5466
  overflow: hidden;
5064
5467
  background: #ffffff;
5065
- transform-origin: top center;
5468
+ transform-origin: center center;
5066
5469
  transition: transform 0.2s ease;
5067
- max-width: calc(100% - 32px);
5068
- max-height: calc(100% - 48px);
5470
+ flex-shrink: 0;
5069
5471
  `;
5070
5472
  const canvas = document.createElement("canvas");
5071
5473
  slideContainer.appendChild(canvas);
5072
- wrapper.appendChild(slideContainer);
5474
+ sizer.appendChild(slideContainer);
5475
+ scrollWrapper.appendChild(sizer);
5476
+ wrapper.appendChild(scrollWrapper);
5073
5477
  ctx.container.innerHTML = "";
5074
5478
  ctx.container.style.overflow = "auto";
5075
5479
  ctx.container.appendChild(wrapper);
@@ -5081,7 +5485,17 @@ var PptxPlugin = class {
5081
5485
  return Math.min(1, Math.min(availW / cW, availH / cH));
5082
5486
  };
5083
5487
  const applyTransform = () => {
5488
+ const cW = canvas.offsetWidth || 1280;
5489
+ const cH = canvas.offsetHeight || 720;
5490
+ const isRotated90 = rotation % 180 !== 0;
5491
+ const boxW = Math.round((isRotated90 ? cH : cW) * scale);
5492
+ const boxH = Math.round((isRotated90 ? cW : cH) * scale);
5493
+ sizer.style.width = `${boxW}px`;
5494
+ sizer.style.height = `${boxH}px`;
5495
+ slideContainer.style.width = `${cW}px`;
5496
+ slideContainer.style.height = `${cH}px`;
5084
5497
  slideContainer.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5498
+ slideContainer.style.transformOrigin = "center center";
5085
5499
  };
5086
5500
  const renderCurrentSlide = async () => {
5087
5501
  try {
@@ -5128,6 +5542,13 @@ var PptxPlugin = class {
5128
5542
  rotation = 0;
5129
5543
  applyTransform();
5130
5544
  },
5545
+ resetZoom: () => {
5546
+ scale = calculateFitScale();
5547
+ rotation = 0;
5548
+ wrapper.scrollTop = 0;
5549
+ wrapper.scrollLeft = 0;
5550
+ applyTransform();
5551
+ },
5131
5552
  rotateCW: () => {
5132
5553
  rotation = (rotation + 90) % 360;
5133
5554
  applyTransform();
@@ -5203,6 +5624,14 @@ var ThreeDPlugin = class {
5203
5624
  group: "zoom",
5204
5625
  execute: () => instance.fitToPage?.()
5205
5626
  },
5627
+ {
5628
+ id: "reset-zoom",
5629
+ icon: "reset-zoom",
5630
+ label: "Reset Zoom",
5631
+ type: "button",
5632
+ group: "zoom",
5633
+ execute: () => instance.resetZoom?.()
5634
+ },
5206
5635
  {
5207
5636
  id: "rotate-cw",
5208
5637
  icon: "rotate-cw",
@@ -5339,6 +5768,7 @@ var ThreeDPlugin = class {
5339
5768
  controls.update();
5340
5769
  },
5341
5770
  fitToPage: fitCamera,
5771
+ resetZoom: fitCamera,
5342
5772
  rotateCW: () => {
5343
5773
  isWireframe = !isWireframe;
5344
5774
  materials.forEach((m) => {
@@ -5553,6 +5983,14 @@ var RtfPlugin = class {
5553
5983
  group: "zoom",
5554
5984
  execute: () => instance.fitToPage?.()
5555
5985
  },
5986
+ {
5987
+ id: "reset-zoom",
5988
+ icon: "reset-zoom",
5989
+ label: "Reset Zoom",
5990
+ type: "button",
5991
+ group: "zoom",
5992
+ execute: () => instance.resetZoom?.()
5993
+ },
5556
5994
  {
5557
5995
  id: "rotate-cw",
5558
5996
  icon: "rotate-cw",
@@ -5663,13 +6101,33 @@ var RtfPlugin = class {
5663
6101
  wrapper.style.flexDirection = "column";
5664
6102
  wrapper.style.alignItems = "center";
5665
6103
  wrapper.style.backgroundColor = "transparent";
5666
- wrapper.style.transformOrigin = "top center";
6104
+ wrapper.style.transformOrigin = "center center";
5667
6105
  wrapper.style.transition = "transform 0.15s ease";
5668
- ctx.container.style.overflowX = "hidden";
5669
- ctx.container.style.overflowY = "auto";
5670
- ctx.container.style.padding = "16px 8px";
6106
+ wrapper.style.flexShrink = "0";
6107
+ const sizer = document.createElement("div");
6108
+ sizer.className = "fp-rtf-sizer";
6109
+ sizer.style.position = "relative";
6110
+ sizer.style.flexShrink = "0";
6111
+ sizer.style.display = "flex";
6112
+ sizer.style.justifyContent = "center";
6113
+ sizer.style.alignItems = "center";
6114
+ const scrollWrapper = document.createElement("div");
6115
+ scrollWrapper.className = "fp-rtf-scroll-wrapper";
6116
+ scrollWrapper.style.minWidth = "100%";
6117
+ scrollWrapper.style.minHeight = "100%";
6118
+ scrollWrapper.style.width = "max-content";
6119
+ scrollWrapper.style.height = "max-content";
6120
+ scrollWrapper.style.display = "flex";
6121
+ scrollWrapper.style.justifyContent = "center";
6122
+ scrollWrapper.style.alignItems = "flex-start";
6123
+ scrollWrapper.style.padding = "16px 8px";
6124
+ scrollWrapper.style.boxSizing = "border-box";
6125
+ sizer.appendChild(wrapper);
6126
+ scrollWrapper.appendChild(sizer);
6127
+ ctx.container.style.overflow = "auto";
6128
+ ctx.container.style.padding = "0";
5671
6129
  ctx.container.style.backgroundColor = "#f1f5f9";
5672
- ctx.container.appendChild(wrapper);
6130
+ ctx.container.appendChild(scrollWrapper);
5673
6131
  let scale = 1;
5674
6132
  let rotation = 0;
5675
6133
  let pageElements = [];
@@ -5688,12 +6146,17 @@ var RtfPlugin = class {
5688
6146
  return Math.max(0.4, Math.min(3, sW));
5689
6147
  };
5690
6148
  const applyTransform = () => {
5691
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5692
- wrapper.style.transformOrigin = "top center";
6149
+ const elW = pageWidth;
5693
6150
  const baseH = pageHeight;
5694
- const scaledH = baseH * scale;
5695
- const extraH = Math.max(0, scaledH - baseH);
5696
- wrapper.style.marginBottom = `${extraH + 32}px`;
6151
+ const isRotated90 = rotation % 180 !== 0;
6152
+ const boxW = Math.round((isRotated90 ? baseH : elW) * scale);
6153
+ const boxH = Math.round((isRotated90 ? elW : baseH) * scale);
6154
+ sizer.style.width = `${boxW}px`;
6155
+ sizer.style.height = `${boxH}px`;
6156
+ wrapper.style.width = `${elW}px`;
6157
+ wrapper.style.height = `${baseH}px`;
6158
+ wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
6159
+ wrapper.style.transformOrigin = "center center";
5697
6160
  };
5698
6161
  const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
5699
6162
  if (!isUserZoomed) {
@@ -5964,7 +6427,7 @@ var RtfPlugin = class {
5964
6427
  }
5965
6428
  const cleanup = () => {
5966
6429
  resizeObserver?.disconnect();
5967
- wrapper.remove();
6430
+ scrollWrapper.remove();
5968
6431
  ctx.container.innerHTML = "";
5969
6432
  };
5970
6433
  ctx.signal.addEventListener("abort", cleanup);
@@ -6022,6 +6485,15 @@ var RtfPlugin = class {
6022
6485
  rotation = 0;
6023
6486
  applyTransform();
6024
6487
  },
6488
+ resetZoom: () => {
6489
+ isUserZoomed = false;
6490
+ fitMode = "width";
6491
+ scale = calculateFitScale("width");
6492
+ rotation = 0;
6493
+ ctx.container.scrollTop = 0;
6494
+ ctx.container.scrollLeft = 0;
6495
+ applyTransform();
6496
+ },
6025
6497
  rotateCW: () => {
6026
6498
  rotation = (rotation + 90) % 360;
6027
6499
  applyTransform();
@@ -6089,6 +6561,14 @@ var HtmlPreviewPlugin = class {
6089
6561
  group: "zoom",
6090
6562
  execute: () => instance.fitToPage?.()
6091
6563
  },
6564
+ {
6565
+ id: "reset-zoom",
6566
+ icon: "reset-zoom",
6567
+ label: "Reset Zoom",
6568
+ type: "button",
6569
+ group: "zoom",
6570
+ execute: () => instance.resetZoom?.()
6571
+ },
6092
6572
  {
6093
6573
  id: "copy",
6094
6574
  icon: "copy",
@@ -6122,23 +6602,44 @@ var HtmlPreviewPlugin = class {
6122
6602
  ADD_TAGS: ["style", "link"],
6123
6603
  ADD_ATTR: ["target", "rel"]
6124
6604
  });
6605
+ const sizer = document.createElement("div");
6606
+ sizer.className = "fp-html-sizer";
6607
+ sizer.style.position = "relative";
6125
6608
  const iframe = document.createElement("iframe");
6126
6609
  iframe.className = "fp-html-iframe";
6127
- iframe.style.width = "100%";
6128
- iframe.style.height = "100%";
6129
6610
  iframe.style.border = "none";
6130
6611
  iframe.style.backgroundColor = "#ffffff";
6131
6612
  iframe.style.transformOrigin = "top left";
6132
6613
  iframe.style.transition = "transform 0.2s ease";
6133
6614
  iframe.sandbox.add("allow-same-origin");
6615
+ sizer.appendChild(iframe);
6134
6616
  ctx.container.style.overflow = "auto";
6135
6617
  ctx.container.style.width = "100%";
6136
6618
  ctx.container.style.height = "100%";
6137
- ctx.container.appendChild(iframe);
6619
+ ctx.container.innerHTML = "";
6620
+ ctx.container.appendChild(sizer);
6138
6621
  iframe.srcdoc = sanitized;
6139
6622
  let scale = 1;
6623
+ const applyTransform = () => {
6624
+ const baseW = Math.max(600, ctx.container.clientWidth || 800);
6625
+ const baseH = Math.max(400, ctx.container.clientHeight || 600);
6626
+ const scaledW = Math.round(baseW * scale);
6627
+ const scaledH = Math.round(baseH * scale);
6628
+ sizer.style.width = `${scaledW}px`;
6629
+ sizer.style.height = `${scaledH}px`;
6630
+ iframe.style.position = "absolute";
6631
+ iframe.style.top = "0";
6632
+ iframe.style.left = "0";
6633
+ iframe.style.width = `${baseW}px`;
6634
+ iframe.style.height = `${baseH}px`;
6635
+ iframe.style.transform = `scale(${scale})`;
6636
+ iframe.style.transformOrigin = "top left";
6637
+ };
6638
+ requestAnimationFrame(() => {
6639
+ applyTransform();
6640
+ });
6140
6641
  const cleanup = () => {
6141
- iframe.remove();
6642
+ sizer.remove();
6142
6643
  ctx.container.innerHTML = "";
6143
6644
  };
6144
6645
  ctx.signal.addEventListener("abort", cleanup);
@@ -6146,20 +6647,26 @@ var HtmlPreviewPlugin = class {
6146
6647
  destroy: cleanup,
6147
6648
  zoomIn: () => {
6148
6649
  scale += 0.1;
6149
- iframe.style.transform = `scale(${scale})`;
6650
+ applyTransform();
6150
6651
  },
6151
6652
  zoomOut: () => {
6152
6653
  scale = Math.max(0.2, scale - 0.1);
6153
- iframe.style.transform = `scale(${scale})`;
6654
+ applyTransform();
6154
6655
  },
6155
6656
  getZoom: () => scale,
6156
6657
  setZoom: (level) => {
6157
6658
  scale = level;
6158
- iframe.style.transform = `scale(${scale})`;
6659
+ applyTransform();
6159
6660
  },
6160
6661
  fitToPage: () => {
6161
6662
  scale = 1;
6162
- iframe.style.transform = "scale(1)";
6663
+ applyTransform();
6664
+ },
6665
+ resetZoom: () => {
6666
+ scale = 1;
6667
+ ctx.container.scrollTop = 0;
6668
+ ctx.container.scrollLeft = 0;
6669
+ applyTransform();
6163
6670
  },
6164
6671
  copy: () => {
6165
6672
  navigator.clipboard.writeText(rawHtml);
@@ -6261,6 +6768,14 @@ var OpenDocumentPlugin = class {
6261
6768
  group: "zoom",
6262
6769
  execute: () => instance.fitToPage?.()
6263
6770
  },
6771
+ {
6772
+ id: "reset-zoom",
6773
+ icon: "reset-zoom",
6774
+ label: "Reset Zoom",
6775
+ type: "button",
6776
+ group: "zoom",
6777
+ execute: () => instance.resetZoom?.()
6778
+ },
6264
6779
  {
6265
6780
  id: "rotate-cw",
6266
6781
  icon: "rotate-cw",
@@ -6326,10 +6841,26 @@ var OpenDocumentPlugin = class {
6326
6841
  container.className = "fp-odf-container";
6327
6842
  container.style.width = "100%";
6328
6843
  container.style.height = "100%";
6329
- container.style.overflowX = "hidden";
6330
- container.style.overflowY = "auto";
6331
- container.style.padding = "16px 8px";
6844
+ container.style.overflow = "auto";
6332
6845
  container.style.backgroundColor = "#f1f5f9";
6846
+ const scrollWrapper = document.createElement("div");
6847
+ scrollWrapper.className = "fp-odf-scroll-wrapper";
6848
+ scrollWrapper.style.minWidth = "100%";
6849
+ scrollWrapper.style.minHeight = "100%";
6850
+ scrollWrapper.style.width = "max-content";
6851
+ scrollWrapper.style.height = "max-content";
6852
+ scrollWrapper.style.display = "flex";
6853
+ scrollWrapper.style.justifyContent = "center";
6854
+ scrollWrapper.style.alignItems = "flex-start";
6855
+ scrollWrapper.style.padding = "16px 8px";
6856
+ scrollWrapper.style.boxSizing = "border-box";
6857
+ const sizer = document.createElement("div");
6858
+ sizer.className = "fp-odf-sizer";
6859
+ sizer.style.position = "relative";
6860
+ sizer.style.flexShrink = "0";
6861
+ sizer.style.display = "flex";
6862
+ sizer.style.justifyContent = "center";
6863
+ sizer.style.alignItems = "center";
6333
6864
  const wrapper = document.createElement("div");
6334
6865
  wrapper.className = "fp-odf-wrapper";
6335
6866
  wrapper.style.margin = "0 auto";
@@ -6338,9 +6869,12 @@ var OpenDocumentPlugin = class {
6338
6869
  wrapper.style.backgroundColor = "#ffffff";
6339
6870
  wrapper.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
6340
6871
  wrapper.style.borderRadius = "4px";
6341
- wrapper.style.transformOrigin = "top center";
6872
+ wrapper.style.transformOrigin = "center center";
6342
6873
  wrapper.style.transition = "transform 0.15s ease";
6343
- container.appendChild(wrapper);
6874
+ wrapper.style.flexShrink = "0";
6875
+ sizer.appendChild(wrapper);
6876
+ scrollWrapper.appendChild(sizer);
6877
+ container.appendChild(scrollWrapper);
6344
6878
  ctx.container.appendChild(container);
6345
6879
  let scale = 1;
6346
6880
  let rotation = 0;
@@ -6366,13 +6900,18 @@ var OpenDocumentPlugin = class {
6366
6900
  return Math.max(0.4, Math.min(3, sW));
6367
6901
  };
6368
6902
  const applyTransform = () => {
6369
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
6370
- wrapper.style.transformOrigin = "top center";
6371
6903
  const activeSlide = slides[currentPage - 1];
6904
+ const elW = isPresentation ? 960 : 816;
6372
6905
  const baseH = activeSlide?.offsetHeight || wrapper.offsetHeight || 1056;
6373
- const scaledH = baseH * scale;
6374
- const extraH = Math.max(0, scaledH - baseH);
6375
- wrapper.style.marginBottom = `${extraH + 32}px`;
6906
+ const isRotated90 = rotation % 180 !== 0;
6907
+ const boxW = Math.round((isRotated90 ? baseH : elW) * scale);
6908
+ const boxH = Math.round((isRotated90 ? elW : baseH) * scale);
6909
+ sizer.style.width = `${boxW}px`;
6910
+ sizer.style.height = `${boxH}px`;
6911
+ wrapper.style.width = `${elW}px`;
6912
+ wrapper.style.height = `${baseH}px`;
6913
+ wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
6914
+ wrapper.style.transformOrigin = "center center";
6376
6915
  };
6377
6916
  const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
6378
6917
  if (!isUserZoomed) {
@@ -6528,6 +7067,15 @@ var OpenDocumentPlugin = class {
6528
7067
  rotation = 0;
6529
7068
  applyTransform();
6530
7069
  },
7070
+ resetZoom: () => {
7071
+ isUserZoomed = false;
7072
+ fitMode = "width";
7073
+ scale = calculateFitScale("width");
7074
+ rotation = 0;
7075
+ container.scrollTop = 0;
7076
+ container.scrollLeft = 0;
7077
+ applyTransform();
7078
+ },
6531
7079
  rotateCW: () => {
6532
7080
  rotation = (rotation + 90) % 360;
6533
7081
  applyTransform();
@@ -6871,6 +7419,14 @@ var DocPlugin = class {
6871
7419
  group: "zoom",
6872
7420
  execute: () => instance.fitToPage?.()
6873
7421
  },
7422
+ {
7423
+ id: "reset-zoom",
7424
+ icon: "reset-zoom",
7425
+ label: "Reset Zoom",
7426
+ type: "button",
7427
+ group: "zoom",
7428
+ execute: () => instance.resetZoom?.()
7429
+ },
6874
7430
  {
6875
7431
  id: "rotate-cw",
6876
7432
  icon: "rotate-cw",
@@ -6919,13 +7475,28 @@ var DocPlugin = class {
6919
7475
  container.className = "fp-doc-container";
6920
7476
  container.style.width = "100%";
6921
7477
  container.style.height = "100%";
6922
- container.style.overflowX = "hidden";
6923
- container.style.overflowY = "auto";
6924
- container.style.padding = "16px 8px";
7478
+ container.style.overflow = "auto";
6925
7479
  container.style.backgroundColor = "#f1f5f9";
6926
- container.style.display = "flex";
6927
- container.style.justifyContent = "center";
6928
- container.style.alignItems = "flex-start";
7480
+ const scrollWrapper = document.createElement("div");
7481
+ scrollWrapper.className = "fp-doc-scroll-wrapper";
7482
+ scrollWrapper.style.minWidth = "100%";
7483
+ scrollWrapper.style.minHeight = "100%";
7484
+ scrollWrapper.style.width = "max-content";
7485
+ scrollWrapper.style.height = "max-content";
7486
+ scrollWrapper.style.display = "flex";
7487
+ scrollWrapper.style.justifyContent = "center";
7488
+ scrollWrapper.style.alignItems = "flex-start";
7489
+ scrollWrapper.style.padding = "16px 8px";
7490
+ scrollWrapper.style.boxSizing = "border-box";
7491
+ const sizer = document.createElement("div");
7492
+ sizer.className = "fp-doc-sizer";
7493
+ sizer.style.position = "relative";
7494
+ sizer.style.flexShrink = "0";
7495
+ sizer.style.display = "flex";
7496
+ sizer.style.justifyContent = "center";
7497
+ sizer.style.alignItems = "center";
7498
+ scrollWrapper.appendChild(sizer);
7499
+ container.appendChild(scrollWrapper);
6929
7500
  ctx.container.appendChild(container);
6930
7501
  let scale = 1;
6931
7502
  let extractedRawText = "";
@@ -6973,10 +7544,11 @@ var DocPlugin = class {
6973
7544
  pageCard.style.padding = "72px 56px";
6974
7545
  pageCard.style.boxSizing = "border-box";
6975
7546
  pageCard.style.display = i === 0 ? "block" : "none";
6976
- pageCard.style.transformOrigin = "top center";
7547
+ pageCard.style.transformOrigin = "center center";
6977
7548
  pageCard.style.transition = "transform 0.15s ease";
6978
7549
  pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
6979
7550
  pageCard.style.color = "#1e293b";
7551
+ pageCard.style.flexShrink = "0";
6980
7552
  if (isFallback && i === 0) {
6981
7553
  pageCard.innerHTML = `
6982
7554
  <div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
@@ -6988,18 +7560,23 @@ var DocPlugin = class {
6988
7560
  } else {
6989
7561
  pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
6990
7562
  }
6991
- container.appendChild(pageCard);
7563
+ sizer.appendChild(pageCard);
6992
7564
  pageCards.push(pageCard);
6993
7565
  }
6994
7566
  let rotation = 0;
6995
7567
  const applyTransform = () => {
6996
7568
  const activeCard = pageCards[currentPage - 1];
6997
7569
  if (activeCard) {
6998
- activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
7570
+ const baseW = 816;
6999
7571
  const baseH = activeCard.offsetHeight || 1056;
7000
- const scaledH = baseH * scale;
7001
- const extraH = Math.max(0, scaledH - baseH);
7002
- activeCard.style.marginBottom = `${extraH + 32}px`;
7572
+ const isRotated90 = rotation % 180 !== 0;
7573
+ const boxW = Math.round((isRotated90 ? baseH : baseW) * scale);
7574
+ const boxH = Math.round((isRotated90 ? baseW : baseH) * scale);
7575
+ sizer.style.width = `${boxW}px`;
7576
+ sizer.style.height = `${boxH}px`;
7577
+ activeCard.style.width = `${baseW}px`;
7578
+ activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
7579
+ activeCard.style.transformOrigin = "center center";
7003
7580
  }
7004
7581
  };
7005
7582
  const showPage = (pageNum) => {
@@ -7007,11 +7584,11 @@ var DocPlugin = class {
7007
7584
  pageCards.forEach((card, idx) => {
7008
7585
  if (idx + 1 === currentPage) {
7009
7586
  card.style.display = "block";
7010
- card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
7011
7587
  } else {
7012
7588
  card.style.display = "none";
7013
7589
  }
7014
7590
  });
7591
+ applyTransform();
7015
7592
  container.scrollTop = 0;
7016
7593
  ctx.emit("page-change", { page: currentPage, total: totalPages });
7017
7594
  };
@@ -7077,6 +7654,17 @@ var DocPlugin = class {
7077
7654
  rotation = 0;
7078
7655
  applyTransform();
7079
7656
  },
7657
+ resetZoom: () => {
7658
+ isUserZoomed = false;
7659
+ fitMode = "width";
7660
+ scale = calculateFitScale("width");
7661
+ rotation = 0;
7662
+ container.scrollTop = 0;
7663
+ container.scrollLeft = 0;
7664
+ ctx.container.scrollTop = 0;
7665
+ ctx.container.scrollLeft = 0;
7666
+ applyTransform();
7667
+ },
7080
7668
  rotateCW: () => {
7081
7669
  rotation = (rotation + 90) % 360;
7082
7670
  applyTransform();
@@ -7557,6 +8145,14 @@ var PptPlugin = class {
7557
8145
  group: "zoom",
7558
8146
  execute: () => instance.fitToPage?.()
7559
8147
  },
8148
+ {
8149
+ id: "reset-zoom",
8150
+ icon: "reset-zoom",
8151
+ label: "Reset Zoom",
8152
+ type: "button",
8153
+ group: "zoom",
8154
+ execute: () => instance.resetZoom?.()
8155
+ },
7560
8156
  {
7561
8157
  id: "rotate-cw",
7562
8158
  icon: "rotate-cw",
@@ -7589,17 +8185,30 @@ var PptPlugin = class {
7589
8185
  container.style.width = "100%";
7590
8186
  container.style.height = "100%";
7591
8187
  container.style.overflow = "auto";
7592
- container.style.display = "flex";
7593
- container.style.justifyContent = "center";
7594
- container.style.alignItems = "center";
7595
- container.style.padding = "32px 16px";
7596
8188
  container.style.backgroundColor = "#0f172a";
7597
8189
  container.style.boxSizing = "border-box";
8190
+ const scrollWrapper = document.createElement("div");
8191
+ scrollWrapper.className = "fp-ppt-scroll-wrapper";
8192
+ scrollWrapper.style.minWidth = "100%";
8193
+ scrollWrapper.style.minHeight = "100%";
8194
+ scrollWrapper.style.width = "max-content";
8195
+ scrollWrapper.style.height = "max-content";
8196
+ scrollWrapper.style.display = "flex";
8197
+ scrollWrapper.style.justifyContent = "center";
8198
+ scrollWrapper.style.alignItems = "center";
8199
+ scrollWrapper.style.padding = "32px 16px";
8200
+ scrollWrapper.style.boxSizing = "border-box";
8201
+ const sizer = document.createElement("div");
8202
+ sizer.className = "fp-ppt-sizer";
8203
+ sizer.style.position = "relative";
8204
+ sizer.style.flexShrink = "0";
8205
+ sizer.style.display = "flex";
8206
+ sizer.style.justifyContent = "center";
8207
+ sizer.style.alignItems = "center";
7598
8208
  const slideCard = document.createElement("div");
7599
8209
  slideCard.className = "fp-ppt-slide-card";
7600
8210
  slideCard.style.width = "960px";
7601
- slideCard.style.maxWidth = "calc(100% - 32px)";
7602
- slideCard.style.maxHeight = "calc(100% - 48px)";
8211
+ slideCard.style.height = "540px";
7603
8212
  slideCard.style.aspectRatio = "16 / 9";
7604
8213
  slideCard.style.backgroundColor = "#ffffff";
7605
8214
  slideCard.style.boxShadow = "0 12px 40px rgba(0,0,0,0.35)";
@@ -7609,7 +8218,9 @@ var PptPlugin = class {
7609
8218
  slideCard.style.transition = "transform 0.2s ease";
7610
8219
  slideCard.style.transformOrigin = "center center";
7611
8220
  slideCard.style.flexShrink = "0";
7612
- container.appendChild(slideCard);
8221
+ sizer.appendChild(slideCard);
8222
+ scrollWrapper.appendChild(sizer);
8223
+ container.appendChild(scrollWrapper);
7613
8224
  ctx.container.appendChild(container);
7614
8225
  let scale = 1;
7615
8226
  let rotation = 0;
@@ -7622,7 +8233,17 @@ var PptPlugin = class {
7622
8233
  return Math.min(1, Math.min(availW / 960, availH / 540));
7623
8234
  };
7624
8235
  const applyTransform = () => {
8236
+ const cW = 960;
8237
+ const cH = 540;
8238
+ const isRotated90 = rotation % 180 !== 0;
8239
+ const boxW = Math.round((isRotated90 ? cH : cW) * scale);
8240
+ const boxH = Math.round((isRotated90 ? cW : cH) * scale);
8241
+ sizer.style.width = `${boxW}px`;
8242
+ sizer.style.height = `${boxH}px`;
8243
+ slideCard.style.width = `${cW}px`;
8244
+ slideCard.style.height = `${cH}px`;
7625
8245
  slideCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
8246
+ slideCard.style.transformOrigin = "center center";
7626
8247
  };
7627
8248
  setTimeout(() => {
7628
8249
  scale = calculateFitScale();
@@ -7745,6 +8366,13 @@ var PptPlugin = class {
7745
8366
  rotation = 0;
7746
8367
  applyTransform();
7747
8368
  },
8369
+ resetZoom: () => {
8370
+ scale = calculateFitScale();
8371
+ rotation = 0;
8372
+ container.scrollTop = 0;
8373
+ container.scrollLeft = 0;
8374
+ applyTransform();
8375
+ },
7748
8376
  rotateCW: () => {
7749
8377
  rotation = (rotation + 90) % 360;
7750
8378
  applyTransform();