@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/react.cjs CHANGED
@@ -529,6 +529,7 @@ var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" str
529
529
  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
530
  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>`;
531
531
  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
+ 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>`;
532
533
  var ICON_MAP = {
533
534
  "zoom-in": ICON_ZOOM_IN,
534
535
  "zoom-out": ICON_ZOOM_OUT,
@@ -558,7 +559,10 @@ var ICON_MAP = {
558
559
  "open-window": ICON_EXTERNAL_WINDOW,
559
560
  "external-window": ICON_EXTERNAL_WINDOW,
560
561
  "openWindow": ICON_EXTERNAL_WINDOW,
561
- "openSeparateWindow": ICON_EXTERNAL_WINDOW
562
+ "openSeparateWindow": ICON_EXTERNAL_WINDOW,
563
+ "reset-zoom": ICON_RESET_ZOOM,
564
+ "zoom-reset": ICON_RESET_ZOOM,
565
+ "resetZoom": ICON_RESET_ZOOM
562
566
  };
563
567
  var ToolbarController = class {
564
568
  el;
@@ -591,6 +595,10 @@ var ToolbarController = class {
591
595
  this.config.fitToPage = false;
592
596
  this.config.fitWidth = false;
593
597
  }
598
+ if (actionId === "reset-zoom" || actionId === "zoom-reset" || actionId === "resetZoom") {
599
+ this.config.resetZoom = false;
600
+ this.config.zoomReset = false;
601
+ }
594
602
  if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = false;
595
603
  if (actionId === "fullscreen") this.config.fullscreen = false;
596
604
  if (actionId === "download") this.config.download = false;
@@ -615,6 +623,10 @@ var ToolbarController = class {
615
623
  this.config.fitToPage = true;
616
624
  this.config.fitWidth = true;
617
625
  }
626
+ if (actionId === "reset-zoom" || actionId === "zoom-reset" || actionId === "resetZoom") {
627
+ this.config.resetZoom = true;
628
+ this.config.zoomReset = true;
629
+ }
618
630
  if (actionId === "rotate-cw" || actionId === "rotate" || actionId === "rotateCW") this.config.rotate = true;
619
631
  if (actionId === "fullscreen") this.config.fullscreen = true;
620
632
  if (actionId === "download") this.config.download = true;
@@ -634,6 +646,7 @@ var ToolbarController = class {
634
646
  if (actionId === "zoomIn") return "zoom-in";
635
647
  if (actionId === "zoomOut") return "zoom-out";
636
648
  if (actionId === "fitPage" || actionId === "fitToPage" || actionId === "fitWidth") return "fit-page";
649
+ if (actionId === "resetZoom" || actionId === "zoomReset") return "reset-zoom";
637
650
  if (actionId === "rotateCW") return "rotate-cw";
638
651
  if (actionId === "rotateCCW") return "rotate-ccw";
639
652
  if (actionId === "openWindow" || actionId === "openSeparateWindow") return "open-window";
@@ -676,6 +689,9 @@ var ToolbarController = class {
676
689
  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)) {
677
690
  return false;
678
691
  }
692
+ if ((id === "reset-zoom" || id === "zoom-reset") && (c.resetZoom === false || c.zoomReset === false || c["reset-zoom"] === false || c["zoom-reset"] === false)) {
693
+ return false;
694
+ }
679
695
  if ((id === "rotate-cw" || id === "rotate-ccw" || id === "rotate") && (c.rotate === false || c.rotateCW === false || c.rotateCCW === false || c["rotate-cw"] === false)) {
680
696
  return false;
681
697
  }
@@ -1122,6 +1138,9 @@ var FilePreviewViewer = class _FilePreviewViewer {
1122
1138
  this.activeInstance = instance;
1123
1139
  instance.openInSeparateWindow = () => this.openInSeparateWindow();
1124
1140
  instance.toggleThumbnails = () => this.toggleThumbnails();
1141
+ if (!instance.resetZoom && instance.fitToPage) {
1142
+ instance.resetZoom = () => instance.fitToPage?.();
1143
+ }
1125
1144
  this.hideLoading();
1126
1145
  this.eventEmitter.emit("loaded", { metadata, plugin: matchedPlugin.id });
1127
1146
  const isToolbarVisible = options.showToolbar !== false && options.toolbar !== false;
@@ -1405,6 +1424,16 @@ var FilePreviewViewer = class _FilePreviewViewer {
1405
1424
  fitToPage() {
1406
1425
  this.activeInstance?.fitToPage?.();
1407
1426
  }
1427
+ /**
1428
+ * Reset zoom level to initial/default fit state.
1429
+ */
1430
+ resetZoom() {
1431
+ if (this.activeInstance?.resetZoom) {
1432
+ this.activeInstance.resetZoom();
1433
+ } else if (this.activeInstance?.fitToPage) {
1434
+ this.activeInstance.fitToPage();
1435
+ }
1436
+ }
1408
1437
  /**
1409
1438
  * Zoom in.
1410
1439
  */
@@ -2026,6 +2055,14 @@ var PdfPlugin = class {
2026
2055
  group: "zoom",
2027
2056
  execute: () => instance.fitToPage?.()
2028
2057
  },
2058
+ {
2059
+ id: "reset-zoom",
2060
+ icon: "reset-zoom",
2061
+ label: "Reset Zoom",
2062
+ type: "button",
2063
+ group: "zoom",
2064
+ execute: () => instance.resetZoom?.()
2065
+ },
2029
2066
  {
2030
2067
  id: "fit-width",
2031
2068
  icon: "fit-width",
@@ -2081,16 +2118,22 @@ var PdfPlugin = class {
2081
2118
  container.className = "fp-pdf-container";
2082
2119
  container.style.width = "100%";
2083
2120
  container.style.height = "100%";
2084
- container.style.overflowX = "hidden";
2085
- container.style.overflowY = "auto";
2086
- container.style.display = "flex";
2087
- container.style.flexDirection = "column";
2088
- container.style.alignItems = "center";
2089
- container.style.justifyContent = "flex-start";
2090
- container.style.padding = "16px 8px";
2121
+ container.style.overflow = "auto";
2091
2122
  container.style.backgroundColor = "#0f172a";
2092
2123
  container.style.boxSizing = "border-box";
2093
2124
  container.style.position = "relative";
2125
+ const scrollWrapper = document.createElement("div");
2126
+ scrollWrapper.className = "fp-pdf-scroll-wrapper";
2127
+ scrollWrapper.style.minWidth = "100%";
2128
+ scrollWrapper.style.minHeight = "100%";
2129
+ scrollWrapper.style.width = "max-content";
2130
+ scrollWrapper.style.height = "max-content";
2131
+ scrollWrapper.style.display = "flex";
2132
+ scrollWrapper.style.flexDirection = "column";
2133
+ scrollWrapper.style.alignItems = "center";
2134
+ scrollWrapper.style.justifyContent = "flex-start";
2135
+ scrollWrapper.style.padding = "16px 8px";
2136
+ scrollWrapper.style.boxSizing = "border-box";
2094
2137
  const pageCard = document.createElement("div");
2095
2138
  pageCard.className = "fp-pdf-page-card";
2096
2139
  pageCard.style.boxShadow = "0 10px 35px rgba(0, 0, 0, 0.5)";
@@ -2103,7 +2146,8 @@ var PdfPlugin = class {
2103
2146
  pageCard.style.transition = "box-shadow 0.2s ease";
2104
2147
  let canvas = document.createElement("canvas");
2105
2148
  pageCard.appendChild(canvas);
2106
- container.appendChild(pageCard);
2149
+ scrollWrapper.appendChild(pageCard);
2150
+ container.appendChild(scrollWrapper);
2107
2151
  ctx.container.appendChild(container);
2108
2152
  const standardFontsUrl = typeof window !== "undefined" && window.__PDF_STANDARD_FONTS_URL__ || "./standard_fonts/";
2109
2153
  const cmapsUrl = typeof window !== "undefined" && window.__PDF_CMAPS_URL__ || "./cmaps/";
@@ -2288,6 +2332,14 @@ var PdfPlugin = class {
2288
2332
  zoomScale = 1;
2289
2333
  renderPage(currentPage);
2290
2334
  },
2335
+ resetZoom: () => {
2336
+ fitMode = "page";
2337
+ zoomScale = 1;
2338
+ rotation = 0;
2339
+ container.scrollTop = 0;
2340
+ container.scrollLeft = 0;
2341
+ renderPage(currentPage);
2342
+ },
2291
2343
  fitToWidth: () => {
2292
2344
  fitMode = "width";
2293
2345
  zoomScale = 1;
@@ -2455,6 +2507,16 @@ var MediaPlugin = class {
2455
2507
  instance.fitToPage?.();
2456
2508
  }
2457
2509
  },
2510
+ {
2511
+ id: "reset-zoom",
2512
+ icon: "reset-zoom",
2513
+ label: "Reset Zoom",
2514
+ type: "button",
2515
+ group: "zoom",
2516
+ execute: () => {
2517
+ instance.resetZoom?.();
2518
+ }
2519
+ },
2458
2520
  {
2459
2521
  id: "rotate-cw",
2460
2522
  icon: "rotate-cw",
@@ -2594,17 +2656,86 @@ var MediaPlugin = class {
2594
2656
  element = document.createElement("div");
2595
2657
  element.textContent = "Unsupported media type";
2596
2658
  }
2597
- ctx.container.style.display = "flex";
2598
- ctx.container.style.alignItems = "center";
2599
- ctx.container.style.justifyContent = "center";
2600
- ctx.container.style.overflow = "hidden";
2601
- ctx.container.appendChild(element);
2659
+ const scrollWrapper = document.createElement("div");
2660
+ scrollWrapper.className = "fp-media-scroll-wrapper";
2661
+ scrollWrapper.style.minWidth = "100%";
2662
+ scrollWrapper.style.minHeight = "100%";
2663
+ scrollWrapper.style.width = "max-content";
2664
+ scrollWrapper.style.height = "max-content";
2665
+ scrollWrapper.style.display = "flex";
2666
+ scrollWrapper.style.justifyContent = "center";
2667
+ scrollWrapper.style.alignItems = "center";
2668
+ scrollWrapper.style.padding = "16px";
2669
+ scrollWrapper.style.boxSizing = "border-box";
2670
+ const sizer = document.createElement("div");
2671
+ sizer.className = "fp-media-sizer";
2672
+ sizer.style.position = "relative";
2673
+ sizer.style.flexShrink = "0";
2674
+ sizer.style.display = "flex";
2675
+ sizer.style.justifyContent = "center";
2676
+ sizer.style.alignItems = "center";
2677
+ sizer.appendChild(element);
2678
+ scrollWrapper.appendChild(sizer);
2679
+ ctx.container.style.overflow = "auto";
2680
+ ctx.container.style.padding = "0";
2681
+ ctx.container.innerHTML = "";
2682
+ ctx.container.appendChild(scrollWrapper);
2683
+ let naturalW = 800;
2684
+ let naturalH = 600;
2685
+ let baseW = 800;
2686
+ let baseH = 600;
2687
+ const updateBaseDimensions = () => {
2688
+ if (!isImage) return;
2689
+ const img = element;
2690
+ naturalW = img.naturalWidth || naturalW;
2691
+ naturalH = img.naturalHeight || naturalH;
2692
+ const availW = Math.max(100, ctx.container.clientWidth - 48);
2693
+ const availH = Math.max(100, ctx.container.clientHeight - 48);
2694
+ const fitRatio = Math.min(1, availW / naturalW, availH / naturalH);
2695
+ baseW = Math.max(1, Math.round(naturalW * fitRatio));
2696
+ baseH = Math.max(1, Math.round(naturalH * fitRatio));
2697
+ };
2602
2698
  const applyTransform = () => {
2603
- element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2699
+ if (isImage) {
2700
+ updateBaseDimensions();
2701
+ const isRotated90 = rotation % 180 !== 0;
2702
+ const boxW = Math.round((isRotated90 ? baseH : baseW) * currentZoom);
2703
+ const boxH = Math.round((isRotated90 ? baseW : baseH) * currentZoom);
2704
+ sizer.style.width = `${boxW}px`;
2705
+ sizer.style.height = `${boxH}px`;
2706
+ element.style.width = `${baseW}px`;
2707
+ element.style.height = `${baseH}px`;
2708
+ element.style.maxWidth = "none";
2709
+ element.style.maxHeight = "none";
2710
+ element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2711
+ element.style.transformOrigin = "center center";
2712
+ element.style.flexShrink = "0";
2713
+ } else {
2714
+ element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
2715
+ }
2604
2716
  };
2717
+ if (isImage) {
2718
+ const img = element;
2719
+ if (img.complete && img.naturalWidth > 0) {
2720
+ updateBaseDimensions();
2721
+ applyTransform();
2722
+ } else {
2723
+ img.onload = () => {
2724
+ updateBaseDimensions();
2725
+ applyTransform();
2726
+ };
2727
+ }
2728
+ }
2729
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
2730
+ if (currentZoom === 1) {
2731
+ applyTransform();
2732
+ }
2733
+ }) : null;
2734
+ ro?.observe(ctx.container);
2605
2735
  const cleanup = () => {
2736
+ ro?.disconnect();
2606
2737
  if (url) URL.revokeObjectURL(url);
2607
- element.remove();
2738
+ scrollWrapper.remove();
2608
2739
  ctx.container.innerHTML = "";
2609
2740
  };
2610
2741
  ctx.signal.addEventListener("abort", cleanup);
@@ -2628,6 +2759,13 @@ var MediaPlugin = class {
2628
2759
  rotation = 0;
2629
2760
  applyTransform();
2630
2761
  } : void 0,
2762
+ resetZoom: isImage ? () => {
2763
+ currentZoom = 1;
2764
+ rotation = 0;
2765
+ ctx.container.scrollTop = 0;
2766
+ ctx.container.scrollLeft = 0;
2767
+ applyTransform();
2768
+ } : void 0,
2631
2769
  rotateCW: isImage || isVideo ? () => {
2632
2770
  rotation = (rotation + 90) % 360;
2633
2771
  applyTransform();
@@ -2744,6 +2882,14 @@ var DocxPlugin = class {
2744
2882
  group: "zoom",
2745
2883
  execute: () => instance.fitToPage?.()
2746
2884
  },
2885
+ {
2886
+ id: "reset-zoom",
2887
+ icon: "reset-zoom",
2888
+ label: "Reset Zoom",
2889
+ type: "button",
2890
+ group: "zoom",
2891
+ execute: () => instance.resetZoom?.()
2892
+ },
2747
2893
  {
2748
2894
  id: "rotate-cw",
2749
2895
  icon: "rotate-cw",
@@ -2782,7 +2928,7 @@ var DocxPlugin = class {
2782
2928
  async render(ctx) {
2783
2929
  const wrapper = document.createElement("div");
2784
2930
  wrapper.className = "fp-docx-wrapper";
2785
- wrapper.style.transformOrigin = "top center";
2931
+ wrapper.style.transformOrigin = "center center";
2786
2932
  wrapper.style.transition = "transform 0.2s ease";
2787
2933
  wrapper.style.padding = "0";
2788
2934
  wrapper.style.maxWidth = "none";
@@ -2792,11 +2938,31 @@ var DocxPlugin = class {
2792
2938
  wrapper.style.flexDirection = "column";
2793
2939
  wrapper.style.alignItems = "center";
2794
2940
  wrapper.style.boxSizing = "border-box";
2795
- ctx.container.style.overflowX = "hidden";
2796
- ctx.container.style.overflowY = "auto";
2797
- ctx.container.style.padding = "16px 8px";
2941
+ wrapper.style.flexShrink = "0";
2942
+ const sizer = document.createElement("div");
2943
+ sizer.className = "fp-docx-sizer";
2944
+ sizer.style.position = "relative";
2945
+ sizer.style.flexShrink = "0";
2946
+ sizer.style.display = "flex";
2947
+ sizer.style.justifyContent = "center";
2948
+ sizer.style.alignItems = "center";
2949
+ const scrollWrapper = document.createElement("div");
2950
+ scrollWrapper.className = "fp-docx-scroll-wrapper";
2951
+ scrollWrapper.style.minWidth = "100%";
2952
+ scrollWrapper.style.minHeight = "100%";
2953
+ scrollWrapper.style.width = "max-content";
2954
+ scrollWrapper.style.height = "max-content";
2955
+ scrollWrapper.style.display = "flex";
2956
+ scrollWrapper.style.justifyContent = "center";
2957
+ scrollWrapper.style.alignItems = "flex-start";
2958
+ scrollWrapper.style.padding = "16px 8px";
2959
+ scrollWrapper.style.boxSizing = "border-box";
2960
+ sizer.appendChild(wrapper);
2961
+ scrollWrapper.appendChild(sizer);
2962
+ ctx.container.style.overflow = "auto";
2963
+ ctx.container.style.padding = "0";
2798
2964
  ctx.container.style.backgroundColor = "#f1f5f9";
2799
- ctx.container.appendChild(wrapper);
2965
+ ctx.container.appendChild(scrollWrapper);
2800
2966
  const styleOverride = document.createElement("style");
2801
2967
  styleOverride.textContent = `
2802
2968
  .fp-docx-wrapper .docx-wrapper {
@@ -2835,8 +3001,8 @@ var DocxPlugin = class {
2835
3001
  renderEndnotes: true,
2836
3002
  useBase64URL: true
2837
3003
  });
2838
- if (!ctx.container.contains(wrapper)) {
2839
- ctx.container.appendChild(wrapper);
3004
+ if (!sizer.contains(wrapper)) {
3005
+ sizer.appendChild(wrapper);
2840
3006
  }
2841
3007
  if (wrapper.children.length > 0 && (wrapper.textContent?.trim().length ?? 0) > 0) {
2842
3008
  renderedSuccessfully = true;
@@ -2873,8 +3039,8 @@ var DocxPlugin = class {
2873
3039
  try {
2874
3040
  wrapper.innerHTML = "";
2875
3041
  this.renderXmlFallback(ctx, wrapper, createdBlobUrls);
2876
- if (!ctx.container.contains(wrapper)) {
2877
- ctx.container.appendChild(wrapper);
3042
+ if (!sizer.contains(wrapper)) {
3043
+ sizer.appendChild(wrapper);
2878
3044
  }
2879
3045
  renderedSuccessfully = true;
2880
3046
  } catch (fallbackErr) {
@@ -2889,8 +3055,8 @@ var DocxPlugin = class {
2889
3055
  </p>
2890
3056
  </div>
2891
3057
  `;
2892
- if (!ctx.container.contains(wrapper)) {
2893
- ctx.container.appendChild(wrapper);
3058
+ if (!sizer.contains(wrapper)) {
3059
+ sizer.appendChild(wrapper);
2894
3060
  }
2895
3061
  }
2896
3062
  }
@@ -2993,15 +3159,18 @@ var DocxPlugin = class {
2993
3159
  return Math.max(0.35, Math.min(3, sW));
2994
3160
  };
2995
3161
  const applyTransform = () => {
2996
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
2997
- wrapper.style.transformOrigin = "top center";
2998
3162
  const activeEl = pageElements[currentPage - 1] || wrapper.querySelector("section.docx") || wrapper;
3163
+ const elW = activeEl.offsetWidth || 816;
2999
3164
  const elH = activeEl.offsetHeight || 1056;
3000
- if (scale > 1) {
3001
- wrapper.style.marginBottom = `${Math.round(elH * scale - elH + 32)}px`;
3002
- } else {
3003
- wrapper.style.marginBottom = "32px";
3004
- }
3165
+ const isRotated90 = rotation % 180 !== 0;
3166
+ const boxW = Math.round((isRotated90 ? elH : elW) * scale);
3167
+ const boxH = Math.round((isRotated90 ? elW : elH) * scale);
3168
+ sizer.style.width = `${boxW}px`;
3169
+ sizer.style.height = `${boxH}px`;
3170
+ wrapper.style.width = `${elW}px`;
3171
+ wrapper.style.height = `${elH}px`;
3172
+ wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
3173
+ wrapper.style.transformOrigin = "center center";
3005
3174
  };
3006
3175
  let resizeObserver = null;
3007
3176
  if (typeof ResizeObserver !== "undefined") {
@@ -3026,7 +3195,7 @@ var DocxPlugin = class {
3026
3195
  for (const url of createdBlobUrls) {
3027
3196
  URL.revokeObjectURL(url);
3028
3197
  }
3029
- wrapper.remove();
3198
+ scrollWrapper.remove();
3030
3199
  styleOverride.remove();
3031
3200
  ctx.container.innerHTML = "";
3032
3201
  };
@@ -3060,6 +3229,14 @@ var DocxPlugin = class {
3060
3229
  rotation = 0;
3061
3230
  applyTransform();
3062
3231
  },
3232
+ resetZoom: () => {
3233
+ isUserZoomed = false;
3234
+ scale = calculateFitScale("page");
3235
+ rotation = 0;
3236
+ ctx.container.scrollTop = 0;
3237
+ ctx.container.scrollLeft = 0;
3238
+ applyTransform();
3239
+ },
3063
3240
  rotateCW: () => {
3064
3241
  rotation = (rotation + 90) % 360;
3065
3242
  applyTransform();
@@ -3509,6 +3686,16 @@ var ExcelPlugin = class {
3509
3686
  instance.zoomIn?.();
3510
3687
  }
3511
3688
  },
3689
+ {
3690
+ id: "reset-zoom",
3691
+ icon: "reset-zoom",
3692
+ label: "Reset Zoom",
3693
+ type: "button",
3694
+ group: "zoom",
3695
+ execute: () => {
3696
+ instance.resetZoom?.();
3697
+ }
3698
+ },
3512
3699
  {
3513
3700
  id: "download",
3514
3701
  icon: "download",
@@ -3555,7 +3742,7 @@ var ExcelPlugin = class {
3555
3742
  contentArea.style.flex = "1";
3556
3743
  contentArea.style.overflow = "auto";
3557
3744
  contentArea.style.padding = "16px";
3558
- contentArea.style.transformOrigin = "top left";
3745
+ contentArea.style.boxSizing = "border-box";
3559
3746
  const tabsArea = document.createElement("div");
3560
3747
  tabsArea.className = "fp-excel-tabs";
3561
3748
  tabsArea.style.display = "flex";
@@ -3569,18 +3756,35 @@ var ExcelPlugin = class {
3569
3756
  container.appendChild(tabsArea);
3570
3757
  ctx.container.appendChild(container);
3571
3758
  let scale = 1;
3759
+ let isUserZoomed = false;
3572
3760
  let currentSheetIndex = 1;
3573
3761
  let sheetNames = [];
3574
3762
  let wb = null;
3575
3763
  const applyTransform = () => {
3576
- contentArea.style.transform = `scale(${scale})`;
3577
- contentArea.style.transformOrigin = "top left";
3764
+ const sizer = contentArea.querySelector(".fp-excel-sizer");
3765
+ const table = contentArea.querySelector("table");
3766
+ if (!sizer || !table) return;
3767
+ if (!table._baseWidth && table.offsetWidth > 0) {
3768
+ table._baseWidth = table.offsetWidth;
3769
+ table._baseHeight = table.offsetHeight;
3770
+ }
3771
+ const baseW = table._baseWidth || table.offsetWidth || 800;
3772
+ const baseH = table._baseHeight || table.offsetHeight || 600;
3773
+ const scaledW = Math.round(baseW * scale);
3774
+ const scaledH = Math.round(baseH * scale);
3775
+ sizer.style.width = `${scaledW}px`;
3776
+ sizer.style.height = `${scaledH}px`;
3777
+ table.style.position = "absolute";
3778
+ table.style.top = "0";
3779
+ table.style.left = "0";
3780
+ table.style.transform = `scale(${scale})`;
3781
+ table.style.transformOrigin = "top left";
3578
3782
  };
3579
3783
  const calculateFitScale = () => {
3580
3784
  const table = contentArea.querySelector("table");
3581
3785
  if (!table) return 1;
3582
3786
  const availW = Math.max(280, container.clientWidth - 48);
3583
- const tW = table.offsetWidth || 800;
3787
+ const tW = table._baseWidth || table.offsetWidth || 800;
3584
3788
  return Math.max(0.4, Math.min(1, availW / tW));
3585
3789
  };
3586
3790
  try {
@@ -3600,9 +3804,13 @@ var ExcelPlugin = class {
3600
3804
  contentArea.innerHTML = '<div style="padding: 24px; color: #888;">Empty sheet</div>';
3601
3805
  return;
3602
3806
  }
3807
+ const sizer = document.createElement("div");
3808
+ sizer.className = "fp-excel-sizer";
3809
+ sizer.style.position = "relative";
3603
3810
  const html = XLSX__namespace.utils.sheet_to_html(ws, { id: "fp-sheet-table", editable: false });
3604
- contentArea.innerHTML = html;
3605
- const table = contentArea.querySelector("table");
3811
+ sizer.innerHTML = html;
3812
+ contentArea.appendChild(sizer);
3813
+ const table = sizer.querySelector("table");
3606
3814
  if (table) {
3607
3815
  table.style.borderCollapse = "collapse";
3608
3816
  table.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
@@ -3637,13 +3845,17 @@ var ExcelPlugin = class {
3637
3845
  });
3638
3846
  ctx.emit("page-change", { page: currentSheetIndex, total: sheetNames.length });
3639
3847
  requestAnimationFrame(() => {
3640
- scale = calculateFitScale();
3848
+ if (!isUserZoomed) {
3849
+ scale = calculateFitScale();
3850
+ }
3641
3851
  applyTransform();
3642
3852
  });
3643
3853
  };
3644
3854
  const ro = new ResizeObserver(() => {
3645
- scale = calculateFitScale();
3646
- applyTransform();
3855
+ if (!isUserZoomed) {
3856
+ scale = calculateFitScale();
3857
+ applyTransform();
3858
+ }
3647
3859
  });
3648
3860
  ro.observe(container);
3649
3861
  if (sheetNames.length > 0) {
@@ -3680,20 +3892,31 @@ var ExcelPlugin = class {
3680
3892
  return {
3681
3893
  destroy: cleanup,
3682
3894
  zoomIn: () => {
3895
+ isUserZoomed = true;
3683
3896
  scale += 0.15;
3684
3897
  applyTransform();
3685
3898
  },
3686
3899
  zoomOut: () => {
3900
+ isUserZoomed = true;
3687
3901
  scale = Math.max(0.2, scale - 0.15);
3688
3902
  applyTransform();
3689
3903
  },
3690
3904
  getZoom: () => scale,
3691
3905
  setZoom: (level) => {
3906
+ isUserZoomed = true;
3692
3907
  scale = level;
3693
3908
  applyTransform();
3694
3909
  },
3695
3910
  fitToPage: () => {
3911
+ isUserZoomed = false;
3912
+ scale = calculateFitScale();
3913
+ applyTransform();
3914
+ },
3915
+ resetZoom: () => {
3916
+ isUserZoomed = false;
3696
3917
  scale = calculateFitScale();
3918
+ contentArea.scrollTop = 0;
3919
+ contentArea.scrollLeft = 0;
3697
3920
  applyTransform();
3698
3921
  },
3699
3922
  rotateCW: () => {
@@ -3826,6 +4049,16 @@ var CsvPlugin = class {
3826
4049
  instance.zoomIn?.();
3827
4050
  }
3828
4051
  },
4052
+ {
4053
+ id: "reset-zoom",
4054
+ icon: "reset-zoom",
4055
+ label: "Reset Zoom",
4056
+ type: "button",
4057
+ group: "zoom",
4058
+ execute: () => {
4059
+ instance.resetZoom?.();
4060
+ }
4061
+ },
3829
4062
  {
3830
4063
  id: "download",
3831
4064
  icon: "download",
@@ -3912,21 +4145,41 @@ var CsvPlugin = class {
3912
4145
  container.appendChild(tableWrapper);
3913
4146
  ctx.container.appendChild(container);
3914
4147
  let scale = 1;
4148
+ let isUserZoomed = false;
3915
4149
  const calculateFitScale = () => {
3916
4150
  const availW = Math.max(280, container.clientWidth - 48);
3917
- const tW = table.offsetWidth || 800;
4151
+ const tW = table._baseWidth || table.offsetWidth || 800;
3918
4152
  return Math.max(0.4, Math.min(1, availW / tW));
3919
4153
  };
3920
4154
  const applyScale = () => {
3921
- tableWrapper.style.transform = `scale(${scale})`;
4155
+ if (!table._baseWidth && table.offsetWidth > 0) {
4156
+ table._baseWidth = table.offsetWidth;
4157
+ table._baseHeight = table.offsetHeight;
4158
+ }
4159
+ const baseW = table._baseWidth || table.offsetWidth || 800;
4160
+ const baseH = table._baseHeight || table.offsetHeight || 600;
4161
+ const scaledW = Math.round(baseW * scale);
4162
+ const scaledH = Math.round(baseH * scale);
4163
+ tableWrapper.style.position = "relative";
4164
+ tableWrapper.style.width = `${scaledW}px`;
4165
+ tableWrapper.style.height = `${scaledH}px`;
4166
+ table.style.position = "absolute";
4167
+ table.style.top = "0";
4168
+ table.style.left = "0";
4169
+ table.style.transform = `scale(${scale})`;
4170
+ table.style.transformOrigin = "top left";
3922
4171
  };
3923
4172
  requestAnimationFrame(() => {
3924
- scale = calculateFitScale();
4173
+ if (!isUserZoomed) {
4174
+ scale = calculateFitScale();
4175
+ }
3925
4176
  applyScale();
3926
4177
  });
3927
4178
  const ro = new ResizeObserver(() => {
3928
- scale = calculateFitScale();
3929
- applyScale();
4179
+ if (!isUserZoomed) {
4180
+ scale = calculateFitScale();
4181
+ applyScale();
4182
+ }
3930
4183
  });
3931
4184
  ro.observe(container);
3932
4185
  const cleanup = () => {
@@ -3999,20 +4252,31 @@ var CsvPlugin = class {
3999
4252
  }];
4000
4253
  },
4001
4254
  zoomIn: () => {
4255
+ isUserZoomed = true;
4002
4256
  scale += 0.1;
4003
4257
  applyScale();
4004
4258
  },
4005
4259
  zoomOut: () => {
4260
+ isUserZoomed = true;
4006
4261
  scale = Math.max(0.2, scale - 0.1);
4007
4262
  applyScale();
4008
4263
  },
4009
4264
  getZoom: () => scale,
4010
4265
  setZoom: (level) => {
4266
+ isUserZoomed = true;
4011
4267
  scale = level;
4012
4268
  applyScale();
4013
4269
  },
4014
4270
  fitToPage: () => {
4271
+ isUserZoomed = false;
4272
+ scale = calculateFitScale();
4273
+ applyScale();
4274
+ },
4275
+ resetZoom: () => {
4276
+ isUserZoomed = false;
4015
4277
  scale = calculateFitScale();
4278
+ container.scrollTop = 0;
4279
+ container.scrollLeft = 0;
4016
4280
  applyScale();
4017
4281
  },
4018
4282
  rotateCW: () => {
@@ -4130,6 +4394,16 @@ var CodePlugin = class {
4130
4394
  instance.zoomIn?.();
4131
4395
  }
4132
4396
  },
4397
+ {
4398
+ id: "reset-zoom",
4399
+ icon: "reset-zoom",
4400
+ label: "Reset Zoom",
4401
+ type: "button",
4402
+ group: "zoom",
4403
+ execute: () => {
4404
+ instance.resetZoom?.();
4405
+ }
4406
+ },
4133
4407
  {
4134
4408
  id: "copy",
4135
4409
  icon: "copy",
@@ -4235,15 +4509,27 @@ var CodePlugin = class {
4235
4509
  let isUserZoomed = false;
4236
4510
  const pre = document.createElement("pre");
4237
4511
  const code = document.createElement("code");
4512
+ const sizer = document.createElement("div");
4513
+ const scrollWrapper = document.createElement("div");
4238
4514
  if (isTxt) {
4239
- container.style.overflowX = "hidden";
4240
- container.style.overflowY = "auto";
4515
+ container.style.overflow = "auto";
4241
4516
  container.style.backgroundColor = "#f1f5f9";
4242
- container.style.padding = "16px 8px";
4243
- container.style.boxSizing = "border-box";
4244
- container.style.display = "flex";
4245
- container.style.flexDirection = "column";
4246
- container.style.alignItems = "center";
4517
+ scrollWrapper.className = "fp-code-scroll-wrapper";
4518
+ scrollWrapper.style.minWidth = "100%";
4519
+ scrollWrapper.style.minHeight = "100%";
4520
+ scrollWrapper.style.width = "max-content";
4521
+ scrollWrapper.style.height = "max-content";
4522
+ scrollWrapper.style.display = "flex";
4523
+ scrollWrapper.style.justifyContent = "center";
4524
+ scrollWrapper.style.alignItems = "flex-start";
4525
+ scrollWrapper.style.padding = "16px 8px";
4526
+ scrollWrapper.style.boxSizing = "border-box";
4527
+ sizer.className = "fp-code-sizer";
4528
+ sizer.style.position = "relative";
4529
+ sizer.style.flexShrink = "0";
4530
+ sizer.style.display = "flex";
4531
+ sizer.style.justifyContent = "center";
4532
+ sizer.style.alignItems = "center";
4247
4533
  pre.style.margin = "0 auto";
4248
4534
  pre.style.fontFamily = "Consolas, 'Courier New', monospace";
4249
4535
  pre.style.fontSize = "13px";
@@ -4258,8 +4544,9 @@ var CodePlugin = class {
4258
4544
  pre.style.boxSizing = "border-box";
4259
4545
  pre.style.boxShadow = "0 4px 24px rgba(0, 0, 0, 0.08)";
4260
4546
  pre.style.borderRadius = "4px";
4261
- pre.style.transformOrigin = "top center";
4547
+ pre.style.transformOrigin = "center center";
4262
4548
  pre.style.transition = "transform 0.15s ease";
4549
+ pre.style.flexShrink = "0";
4263
4550
  } else {
4264
4551
  container.style.overflow = "auto";
4265
4552
  container.style.backgroundColor = "#1e1e1e";
@@ -4292,7 +4579,13 @@ var CodePlugin = class {
4292
4579
  };
4293
4580
  renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
4294
4581
  pre.appendChild(code);
4295
- container.appendChild(pre);
4582
+ if (isTxt) {
4583
+ sizer.appendChild(pre);
4584
+ scrollWrapper.appendChild(sizer);
4585
+ container.appendChild(scrollWrapper);
4586
+ } else {
4587
+ container.appendChild(pre);
4588
+ }
4296
4589
  const showPage = (pageNum) => {
4297
4590
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
4298
4591
  renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
@@ -4309,10 +4602,16 @@ var CodePlugin = class {
4309
4602
  };
4310
4603
  const updateTransform = () => {
4311
4604
  if (isTxt) {
4605
+ const elW = 816;
4606
+ const baseH = pre.offsetHeight || 1056;
4607
+ const isRotated90 = rotation % 180 !== 0;
4608
+ const boxW = Math.round((isRotated90 ? baseH : elW) * zoomLevel);
4609
+ const boxH = Math.round((isRotated90 ? elW : baseH) * zoomLevel);
4610
+ sizer.style.width = `${boxW}px`;
4611
+ sizer.style.height = `${boxH}px`;
4612
+ pre.style.width = `${elW}px`;
4312
4613
  pre.style.transform = `scale(${zoomLevel}) rotate(${rotation}deg)`;
4313
- const scaledH = 1056 * zoomLevel;
4314
- const extraH = Math.max(0, scaledH - 1056);
4315
- pre.style.marginBottom = `${extraH + 32}px`;
4614
+ pre.style.transformOrigin = "center center";
4316
4615
  } else {
4317
4616
  pre.style.transform = `rotate(${rotation}deg)`;
4318
4617
  pre.style.fontSize = `${fontSize}px`;
@@ -4409,6 +4708,15 @@ var CodePlugin = class {
4409
4708
  zoomLevel = isTxt ? calculateTxtFit() : 1;
4410
4709
  updateTransform();
4411
4710
  },
4711
+ resetZoom: () => {
4712
+ isUserZoomed = false;
4713
+ fontSize = 13;
4714
+ rotation = 0;
4715
+ zoomLevel = isTxt ? calculateTxtFit() : 1;
4716
+ container.scrollTop = 0;
4717
+ container.scrollLeft = 0;
4718
+ updateTransform();
4719
+ },
4412
4720
  rotateCW: () => {
4413
4721
  rotation = (rotation + 90) % 360;
4414
4722
  updateTransform();
@@ -4471,11 +4779,19 @@ var ArchivePlugin = class {
4471
4779
  {
4472
4780
  id: "fit-page",
4473
4781
  icon: "fit-page",
4474
- label: "Reset Zoom",
4782
+ label: "Fit to Page",
4475
4783
  type: "button",
4476
4784
  group: "zoom",
4477
4785
  execute: () => instance.fitToPage?.()
4478
4786
  },
4787
+ {
4788
+ id: "reset-zoom",
4789
+ icon: "reset-zoom",
4790
+ label: "Reset Zoom",
4791
+ type: "button",
4792
+ group: "zoom",
4793
+ execute: () => instance.resetZoom?.()
4794
+ },
4479
4795
  {
4480
4796
  id: "download",
4481
4797
  icon: "download",
@@ -4501,16 +4817,56 @@ var ArchivePlugin = class {
4501
4817
  width: 100%;
4502
4818
  height: 100%;
4503
4819
  overflow: auto;
4504
- padding: 24px;
4505
4820
  box-sizing: border-box;
4506
4821
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
4507
- transform-origin: top left;
4508
- transition: transform 0.2s ease;
4509
4822
  `;
4823
+ const scrollWrapper = document.createElement("div");
4824
+ scrollWrapper.className = "fp-archive-scroll-wrapper";
4825
+ scrollWrapper.style.cssText = `
4826
+ min-width: 100%;
4827
+ min-height: 100%;
4828
+ width: max-content;
4829
+ height: max-content;
4830
+ display: flex;
4831
+ justify-content: center;
4832
+ align-items: flex-start;
4833
+ padding: 24px;
4834
+ box-sizing: border-box;
4835
+ `;
4836
+ const sizer = document.createElement("div");
4837
+ sizer.className = "fp-archive-sizer";
4838
+ sizer.style.cssText = `
4839
+ position: relative;
4840
+ flex-shrink: 0;
4841
+ display: flex;
4842
+ justify-content: center;
4843
+ align-items: flex-start;
4844
+ `;
4845
+ const card = document.createElement("div");
4846
+ card.className = "fp-archive-card";
4847
+ card.style.cssText = `
4848
+ width: 900px;
4849
+ box-sizing: border-box;
4850
+ transform-origin: top center;
4851
+ transition: transform 0.15s ease;
4852
+ flex-shrink: 0;
4853
+ `;
4854
+ sizer.appendChild(card);
4855
+ scrollWrapper.appendChild(sizer);
4856
+ wrapper.appendChild(scrollWrapper);
4510
4857
  ctx.container.innerHTML = "";
4511
4858
  ctx.container.style.overflow = "auto";
4512
4859
  ctx.container.appendChild(wrapper);
4513
4860
  let scale = 1;
4861
+ const applyTransform = () => {
4862
+ const boxW = Math.round(900 * scale);
4863
+ const cardH = card.offsetHeight || 600;
4864
+ const boxH = Math.round(cardH * scale);
4865
+ sizer.style.width = `${boxW}px`;
4866
+ sizer.style.height = `${boxH}px`;
4867
+ card.style.transform = `scale(${scale})`;
4868
+ card.style.transformOrigin = "top center";
4869
+ };
4514
4870
  const entries = await new Promise((resolve, reject) => {
4515
4871
  fflate.unzip(new Uint8Array(ctx.buffer), (err, unzipped) => {
4516
4872
  if (err) {
@@ -4534,7 +4890,7 @@ var ArchivePlugin = class {
4534
4890
  });
4535
4891
  const totalUncompressedSize = entries.reduce((acc, e) => acc + e.size, 0);
4536
4892
  const renderUI = (filteredEntries) => {
4537
- wrapper.innerHTML = `
4893
+ card.innerHTML = `
4538
4894
  <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;">
4539
4895
  <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;">
4540
4896
  <div>
@@ -4564,7 +4920,7 @@ var ArchivePlugin = class {
4564
4920
  </div>
4565
4921
  </div>
4566
4922
  `;
4567
- const tbody = wrapper.querySelector("#fp-archive-body");
4923
+ const tbody = card.querySelector("#fp-archive-body");
4568
4924
  if (filteredEntries.length === 0) {
4569
4925
  tbody.innerHTML = `<tr><td colspan="3" style="padding: 24px; text-align: center; color: #9ca3af;">No matching files found</td></tr>`;
4570
4926
  } else {
@@ -4593,19 +4949,20 @@ var ArchivePlugin = class {
4593
4949
  }
4594
4950
  });
4595
4951
  });
4596
- const searchInput = wrapper.querySelector("#fp-archive-search");
4952
+ const searchInput = card.querySelector("#fp-archive-search");
4597
4953
  if (searchInput) {
4598
4954
  searchInput.addEventListener("input", () => {
4599
4955
  const q = searchInput.value.toLowerCase().trim();
4600
4956
  const filtered = q ? entries.filter((e) => e.path.toLowerCase().includes(q)) : entries;
4601
4957
  renderUI(filtered);
4602
- const newSearch = wrapper.querySelector("#fp-archive-search");
4958
+ const newSearch = card.querySelector("#fp-archive-search");
4603
4959
  if (newSearch) {
4604
4960
  newSearch.value = q;
4605
4961
  newSearch.focus();
4606
4962
  }
4607
4963
  });
4608
4964
  }
4965
+ applyTransform();
4609
4966
  };
4610
4967
  renderUI(entries);
4611
4968
  const cleanup = () => {
@@ -4617,20 +4974,26 @@ var ArchivePlugin = class {
4617
4974
  destroy: cleanup,
4618
4975
  zoomIn: () => {
4619
4976
  scale += 0.1;
4620
- wrapper.style.transform = `scale(${scale})`;
4977
+ applyTransform();
4621
4978
  },
4622
4979
  zoomOut: () => {
4623
4980
  scale = Math.max(0.3, scale - 0.1);
4624
- wrapper.style.transform = `scale(${scale})`;
4981
+ applyTransform();
4625
4982
  },
4626
4983
  getZoom: () => scale,
4627
4984
  setZoom: (level) => {
4628
4985
  scale = level;
4629
- wrapper.style.transform = `scale(${scale})`;
4986
+ applyTransform();
4630
4987
  },
4631
4988
  fitToPage: () => {
4632
4989
  scale = 1;
4633
- wrapper.style.transform = `scale(1)`;
4990
+ applyTransform();
4991
+ },
4992
+ resetZoom: () => {
4993
+ scale = 1;
4994
+ wrapper.scrollTop = 0;
4995
+ wrapper.scrollLeft = 0;
4996
+ applyTransform();
4634
4997
  },
4635
4998
  download: () => {
4636
4999
  downloadFile(ctx.buffer, ctx.metadata.name || "archive.zip", "application/zip");
@@ -4682,6 +5045,14 @@ var MarkdownPlugin = class {
4682
5045
  group: "zoom",
4683
5046
  execute: () => instance.fitToPage?.()
4684
5047
  },
5048
+ {
5049
+ id: "reset-zoom",
5050
+ icon: "reset-zoom",
5051
+ label: "Reset Zoom",
5052
+ type: "button",
5053
+ group: "zoom",
5054
+ execute: () => instance.resetZoom?.()
5055
+ },
4685
5056
  {
4686
5057
  id: "copy",
4687
5058
  icon: "copy",
@@ -4835,6 +5206,12 @@ var MarkdownPlugin = class {
4835
5206
  fontSize = 15;
4836
5207
  wrapper.style.fontSize = "15px";
4837
5208
  },
5209
+ resetZoom: () => {
5210
+ fontSize = 15;
5211
+ wrapper.style.fontSize = "15px";
5212
+ ctx.container.scrollTop = 0;
5213
+ ctx.container.scrollLeft = 0;
5214
+ },
4838
5215
  download: () => {
4839
5216
  downloadFile(ctx.buffer, ctx.metadata.name || "document.md", "text/markdown");
4840
5217
  },
@@ -4928,6 +5305,14 @@ var PptxPlugin = class {
4928
5305
  group: "zoom",
4929
5306
  execute: () => instance.fitToPage?.()
4930
5307
  },
5308
+ {
5309
+ id: "reset-zoom",
5310
+ icon: "reset-zoom",
5311
+ label: "Reset Zoom",
5312
+ type: "button",
5313
+ group: "zoom",
5314
+ execute: () => instance.resetZoom?.()
5315
+ },
4931
5316
  {
4932
5317
  id: "rotate-cw",
4933
5318
  icon: "rotate-cw",
@@ -4967,12 +5352,30 @@ var PptxPlugin = class {
4967
5352
  width: 100%;
4968
5353
  height: 100%;
4969
5354
  overflow: auto;
5355
+ box-sizing: border-box;
5356
+ background: var(--fp-bg-canvas, #525659);
5357
+ `;
5358
+ const scrollWrapper = document.createElement("div");
5359
+ scrollWrapper.className = "fp-pptx-scroll-wrapper";
5360
+ scrollWrapper.style.cssText = `
5361
+ min-width: 100%;
5362
+ min-height: 100%;
5363
+ width: max-content;
5364
+ height: max-content;
4970
5365
  display: flex;
4971
5366
  justify-content: center;
4972
- align-items: flex-start;
5367
+ align-items: center;
4973
5368
  padding: 24px;
4974
5369
  box-sizing: border-box;
4975
- background: var(--fp-bg-canvas, #525659);
5370
+ `;
5371
+ const sizer = document.createElement("div");
5372
+ sizer.className = "fp-pptx-sizer";
5373
+ sizer.style.cssText = `
5374
+ position: relative;
5375
+ flex-shrink: 0;
5376
+ display: flex;
5377
+ justify-content: center;
5378
+ align-items: center;
4976
5379
  `;
4977
5380
  const slideContainer = document.createElement("div");
4978
5381
  slideContainer.className = "fp-slide-container";
@@ -4981,14 +5384,15 @@ var PptxPlugin = class {
4981
5384
  border-radius: 4px;
4982
5385
  overflow: hidden;
4983
5386
  background: #ffffff;
4984
- transform-origin: top center;
5387
+ transform-origin: center center;
4985
5388
  transition: transform 0.2s ease;
4986
- max-width: calc(100% - 32px);
4987
- max-height: calc(100% - 48px);
5389
+ flex-shrink: 0;
4988
5390
  `;
4989
5391
  const canvas = document.createElement("canvas");
4990
5392
  slideContainer.appendChild(canvas);
4991
- wrapper.appendChild(slideContainer);
5393
+ sizer.appendChild(slideContainer);
5394
+ scrollWrapper.appendChild(sizer);
5395
+ wrapper.appendChild(scrollWrapper);
4992
5396
  ctx.container.innerHTML = "";
4993
5397
  ctx.container.style.overflow = "auto";
4994
5398
  ctx.container.appendChild(wrapper);
@@ -5000,7 +5404,17 @@ var PptxPlugin = class {
5000
5404
  return Math.min(1, Math.min(availW / cW, availH / cH));
5001
5405
  };
5002
5406
  const applyTransform = () => {
5407
+ const cW = canvas.offsetWidth || 1280;
5408
+ const cH = canvas.offsetHeight || 720;
5409
+ const isRotated90 = rotation % 180 !== 0;
5410
+ const boxW = Math.round((isRotated90 ? cH : cW) * scale);
5411
+ const boxH = Math.round((isRotated90 ? cW : cH) * scale);
5412
+ sizer.style.width = `${boxW}px`;
5413
+ sizer.style.height = `${boxH}px`;
5414
+ slideContainer.style.width = `${cW}px`;
5415
+ slideContainer.style.height = `${cH}px`;
5003
5416
  slideContainer.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5417
+ slideContainer.style.transformOrigin = "center center";
5004
5418
  };
5005
5419
  const renderCurrentSlide = async () => {
5006
5420
  try {
@@ -5047,6 +5461,13 @@ var PptxPlugin = class {
5047
5461
  rotation = 0;
5048
5462
  applyTransform();
5049
5463
  },
5464
+ resetZoom: () => {
5465
+ scale = calculateFitScale();
5466
+ rotation = 0;
5467
+ wrapper.scrollTop = 0;
5468
+ wrapper.scrollLeft = 0;
5469
+ applyTransform();
5470
+ },
5050
5471
  rotateCW: () => {
5051
5472
  rotation = (rotation + 90) % 360;
5052
5473
  applyTransform();
@@ -5122,6 +5543,14 @@ var ThreeDPlugin = class {
5122
5543
  group: "zoom",
5123
5544
  execute: () => instance.fitToPage?.()
5124
5545
  },
5546
+ {
5547
+ id: "reset-zoom",
5548
+ icon: "reset-zoom",
5549
+ label: "Reset Zoom",
5550
+ type: "button",
5551
+ group: "zoom",
5552
+ execute: () => instance.resetZoom?.()
5553
+ },
5125
5554
  {
5126
5555
  id: "rotate-cw",
5127
5556
  icon: "rotate-cw",
@@ -5258,6 +5687,7 @@ var ThreeDPlugin = class {
5258
5687
  controls.update();
5259
5688
  },
5260
5689
  fitToPage: fitCamera,
5690
+ resetZoom: fitCamera,
5261
5691
  rotateCW: () => {
5262
5692
  isWireframe = !isWireframe;
5263
5693
  materials.forEach((m) => {
@@ -5472,6 +5902,14 @@ var RtfPlugin = class {
5472
5902
  group: "zoom",
5473
5903
  execute: () => instance.fitToPage?.()
5474
5904
  },
5905
+ {
5906
+ id: "reset-zoom",
5907
+ icon: "reset-zoom",
5908
+ label: "Reset Zoom",
5909
+ type: "button",
5910
+ group: "zoom",
5911
+ execute: () => instance.resetZoom?.()
5912
+ },
5475
5913
  {
5476
5914
  id: "rotate-cw",
5477
5915
  icon: "rotate-cw",
@@ -5582,13 +6020,33 @@ var RtfPlugin = class {
5582
6020
  wrapper.style.flexDirection = "column";
5583
6021
  wrapper.style.alignItems = "center";
5584
6022
  wrapper.style.backgroundColor = "transparent";
5585
- wrapper.style.transformOrigin = "top center";
6023
+ wrapper.style.transformOrigin = "center center";
5586
6024
  wrapper.style.transition = "transform 0.15s ease";
5587
- ctx.container.style.overflowX = "hidden";
5588
- ctx.container.style.overflowY = "auto";
5589
- ctx.container.style.padding = "16px 8px";
6025
+ wrapper.style.flexShrink = "0";
6026
+ const sizer = document.createElement("div");
6027
+ sizer.className = "fp-rtf-sizer";
6028
+ sizer.style.position = "relative";
6029
+ sizer.style.flexShrink = "0";
6030
+ sizer.style.display = "flex";
6031
+ sizer.style.justifyContent = "center";
6032
+ sizer.style.alignItems = "center";
6033
+ const scrollWrapper = document.createElement("div");
6034
+ scrollWrapper.className = "fp-rtf-scroll-wrapper";
6035
+ scrollWrapper.style.minWidth = "100%";
6036
+ scrollWrapper.style.minHeight = "100%";
6037
+ scrollWrapper.style.width = "max-content";
6038
+ scrollWrapper.style.height = "max-content";
6039
+ scrollWrapper.style.display = "flex";
6040
+ scrollWrapper.style.justifyContent = "center";
6041
+ scrollWrapper.style.alignItems = "flex-start";
6042
+ scrollWrapper.style.padding = "16px 8px";
6043
+ scrollWrapper.style.boxSizing = "border-box";
6044
+ sizer.appendChild(wrapper);
6045
+ scrollWrapper.appendChild(sizer);
6046
+ ctx.container.style.overflow = "auto";
6047
+ ctx.container.style.padding = "0";
5590
6048
  ctx.container.style.backgroundColor = "#f1f5f9";
5591
- ctx.container.appendChild(wrapper);
6049
+ ctx.container.appendChild(scrollWrapper);
5592
6050
  let scale = 1;
5593
6051
  let rotation = 0;
5594
6052
  let pageElements = [];
@@ -5607,12 +6065,17 @@ var RtfPlugin = class {
5607
6065
  return Math.max(0.4, Math.min(3, sW));
5608
6066
  };
5609
6067
  const applyTransform = () => {
5610
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
5611
- wrapper.style.transformOrigin = "top center";
6068
+ const elW = pageWidth;
5612
6069
  const baseH = pageHeight;
5613
- const scaledH = baseH * scale;
5614
- const extraH = Math.max(0, scaledH - baseH);
5615
- wrapper.style.marginBottom = `${extraH + 32}px`;
6070
+ const isRotated90 = rotation % 180 !== 0;
6071
+ const boxW = Math.round((isRotated90 ? baseH : elW) * scale);
6072
+ const boxH = Math.round((isRotated90 ? elW : baseH) * scale);
6073
+ sizer.style.width = `${boxW}px`;
6074
+ sizer.style.height = `${boxH}px`;
6075
+ wrapper.style.width = `${elW}px`;
6076
+ wrapper.style.height = `${baseH}px`;
6077
+ wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
6078
+ wrapper.style.transformOrigin = "center center";
5616
6079
  };
5617
6080
  const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
5618
6081
  if (!isUserZoomed) {
@@ -5883,7 +6346,7 @@ var RtfPlugin = class {
5883
6346
  }
5884
6347
  const cleanup = () => {
5885
6348
  resizeObserver?.disconnect();
5886
- wrapper.remove();
6349
+ scrollWrapper.remove();
5887
6350
  ctx.container.innerHTML = "";
5888
6351
  };
5889
6352
  ctx.signal.addEventListener("abort", cleanup);
@@ -5941,6 +6404,15 @@ var RtfPlugin = class {
5941
6404
  rotation = 0;
5942
6405
  applyTransform();
5943
6406
  },
6407
+ resetZoom: () => {
6408
+ isUserZoomed = false;
6409
+ fitMode = "width";
6410
+ scale = calculateFitScale("width");
6411
+ rotation = 0;
6412
+ ctx.container.scrollTop = 0;
6413
+ ctx.container.scrollLeft = 0;
6414
+ applyTransform();
6415
+ },
5944
6416
  rotateCW: () => {
5945
6417
  rotation = (rotation + 90) % 360;
5946
6418
  applyTransform();
@@ -6008,6 +6480,14 @@ var HtmlPreviewPlugin = class {
6008
6480
  group: "zoom",
6009
6481
  execute: () => instance.fitToPage?.()
6010
6482
  },
6483
+ {
6484
+ id: "reset-zoom",
6485
+ icon: "reset-zoom",
6486
+ label: "Reset Zoom",
6487
+ type: "button",
6488
+ group: "zoom",
6489
+ execute: () => instance.resetZoom?.()
6490
+ },
6011
6491
  {
6012
6492
  id: "copy",
6013
6493
  icon: "copy",
@@ -6041,23 +6521,44 @@ var HtmlPreviewPlugin = class {
6041
6521
  ADD_TAGS: ["style", "link"],
6042
6522
  ADD_ATTR: ["target", "rel"]
6043
6523
  });
6524
+ const sizer = document.createElement("div");
6525
+ sizer.className = "fp-html-sizer";
6526
+ sizer.style.position = "relative";
6044
6527
  const iframe = document.createElement("iframe");
6045
6528
  iframe.className = "fp-html-iframe";
6046
- iframe.style.width = "100%";
6047
- iframe.style.height = "100%";
6048
6529
  iframe.style.border = "none";
6049
6530
  iframe.style.backgroundColor = "#ffffff";
6050
6531
  iframe.style.transformOrigin = "top left";
6051
6532
  iframe.style.transition = "transform 0.2s ease";
6052
6533
  iframe.sandbox.add("allow-same-origin");
6534
+ sizer.appendChild(iframe);
6053
6535
  ctx.container.style.overflow = "auto";
6054
6536
  ctx.container.style.width = "100%";
6055
6537
  ctx.container.style.height = "100%";
6056
- ctx.container.appendChild(iframe);
6538
+ ctx.container.innerHTML = "";
6539
+ ctx.container.appendChild(sizer);
6057
6540
  iframe.srcdoc = sanitized;
6058
6541
  let scale = 1;
6542
+ const applyTransform = () => {
6543
+ const baseW = Math.max(600, ctx.container.clientWidth || 800);
6544
+ const baseH = Math.max(400, ctx.container.clientHeight || 600);
6545
+ const scaledW = Math.round(baseW * scale);
6546
+ const scaledH = Math.round(baseH * scale);
6547
+ sizer.style.width = `${scaledW}px`;
6548
+ sizer.style.height = `${scaledH}px`;
6549
+ iframe.style.position = "absolute";
6550
+ iframe.style.top = "0";
6551
+ iframe.style.left = "0";
6552
+ iframe.style.width = `${baseW}px`;
6553
+ iframe.style.height = `${baseH}px`;
6554
+ iframe.style.transform = `scale(${scale})`;
6555
+ iframe.style.transformOrigin = "top left";
6556
+ };
6557
+ requestAnimationFrame(() => {
6558
+ applyTransform();
6559
+ });
6059
6560
  const cleanup = () => {
6060
- iframe.remove();
6561
+ sizer.remove();
6061
6562
  ctx.container.innerHTML = "";
6062
6563
  };
6063
6564
  ctx.signal.addEventListener("abort", cleanup);
@@ -6065,20 +6566,26 @@ var HtmlPreviewPlugin = class {
6065
6566
  destroy: cleanup,
6066
6567
  zoomIn: () => {
6067
6568
  scale += 0.1;
6068
- iframe.style.transform = `scale(${scale})`;
6569
+ applyTransform();
6069
6570
  },
6070
6571
  zoomOut: () => {
6071
6572
  scale = Math.max(0.2, scale - 0.1);
6072
- iframe.style.transform = `scale(${scale})`;
6573
+ applyTransform();
6073
6574
  },
6074
6575
  getZoom: () => scale,
6075
6576
  setZoom: (level) => {
6076
6577
  scale = level;
6077
- iframe.style.transform = `scale(${scale})`;
6578
+ applyTransform();
6078
6579
  },
6079
6580
  fitToPage: () => {
6080
6581
  scale = 1;
6081
- iframe.style.transform = "scale(1)";
6582
+ applyTransform();
6583
+ },
6584
+ resetZoom: () => {
6585
+ scale = 1;
6586
+ ctx.container.scrollTop = 0;
6587
+ ctx.container.scrollLeft = 0;
6588
+ applyTransform();
6082
6589
  },
6083
6590
  copy: () => {
6084
6591
  navigator.clipboard.writeText(rawHtml);
@@ -6180,6 +6687,14 @@ var OpenDocumentPlugin = class {
6180
6687
  group: "zoom",
6181
6688
  execute: () => instance.fitToPage?.()
6182
6689
  },
6690
+ {
6691
+ id: "reset-zoom",
6692
+ icon: "reset-zoom",
6693
+ label: "Reset Zoom",
6694
+ type: "button",
6695
+ group: "zoom",
6696
+ execute: () => instance.resetZoom?.()
6697
+ },
6183
6698
  {
6184
6699
  id: "rotate-cw",
6185
6700
  icon: "rotate-cw",
@@ -6245,10 +6760,26 @@ var OpenDocumentPlugin = class {
6245
6760
  container.className = "fp-odf-container";
6246
6761
  container.style.width = "100%";
6247
6762
  container.style.height = "100%";
6248
- container.style.overflowX = "hidden";
6249
- container.style.overflowY = "auto";
6250
- container.style.padding = "16px 8px";
6763
+ container.style.overflow = "auto";
6251
6764
  container.style.backgroundColor = "#f1f5f9";
6765
+ const scrollWrapper = document.createElement("div");
6766
+ scrollWrapper.className = "fp-odf-scroll-wrapper";
6767
+ scrollWrapper.style.minWidth = "100%";
6768
+ scrollWrapper.style.minHeight = "100%";
6769
+ scrollWrapper.style.width = "max-content";
6770
+ scrollWrapper.style.height = "max-content";
6771
+ scrollWrapper.style.display = "flex";
6772
+ scrollWrapper.style.justifyContent = "center";
6773
+ scrollWrapper.style.alignItems = "flex-start";
6774
+ scrollWrapper.style.padding = "16px 8px";
6775
+ scrollWrapper.style.boxSizing = "border-box";
6776
+ const sizer = document.createElement("div");
6777
+ sizer.className = "fp-odf-sizer";
6778
+ sizer.style.position = "relative";
6779
+ sizer.style.flexShrink = "0";
6780
+ sizer.style.display = "flex";
6781
+ sizer.style.justifyContent = "center";
6782
+ sizer.style.alignItems = "center";
6252
6783
  const wrapper = document.createElement("div");
6253
6784
  wrapper.className = "fp-odf-wrapper";
6254
6785
  wrapper.style.margin = "0 auto";
@@ -6257,9 +6788,12 @@ var OpenDocumentPlugin = class {
6257
6788
  wrapper.style.backgroundColor = "#ffffff";
6258
6789
  wrapper.style.boxShadow = "0 2px 10px rgba(0,0,0,0.08)";
6259
6790
  wrapper.style.borderRadius = "4px";
6260
- wrapper.style.transformOrigin = "top center";
6791
+ wrapper.style.transformOrigin = "center center";
6261
6792
  wrapper.style.transition = "transform 0.15s ease";
6262
- container.appendChild(wrapper);
6793
+ wrapper.style.flexShrink = "0";
6794
+ sizer.appendChild(wrapper);
6795
+ scrollWrapper.appendChild(sizer);
6796
+ container.appendChild(scrollWrapper);
6263
6797
  ctx.container.appendChild(container);
6264
6798
  let scale = 1;
6265
6799
  let rotation = 0;
@@ -6285,13 +6819,18 @@ var OpenDocumentPlugin = class {
6285
6819
  return Math.max(0.4, Math.min(3, sW));
6286
6820
  };
6287
6821
  const applyTransform = () => {
6288
- wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
6289
- wrapper.style.transformOrigin = "top center";
6290
6822
  const activeSlide = slides[currentPage - 1];
6823
+ const elW = isPresentation ? 960 : 816;
6291
6824
  const baseH = activeSlide?.offsetHeight || wrapper.offsetHeight || 1056;
6292
- const scaledH = baseH * scale;
6293
- const extraH = Math.max(0, scaledH - baseH);
6294
- wrapper.style.marginBottom = `${extraH + 32}px`;
6825
+ const isRotated90 = rotation % 180 !== 0;
6826
+ const boxW = Math.round((isRotated90 ? baseH : elW) * scale);
6827
+ const boxH = Math.round((isRotated90 ? elW : baseH) * scale);
6828
+ sizer.style.width = `${boxW}px`;
6829
+ sizer.style.height = `${boxH}px`;
6830
+ wrapper.style.width = `${elW}px`;
6831
+ wrapper.style.height = `${baseH}px`;
6832
+ wrapper.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
6833
+ wrapper.style.transformOrigin = "center center";
6295
6834
  };
6296
6835
  const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
6297
6836
  if (!isUserZoomed) {
@@ -6447,6 +6986,15 @@ var OpenDocumentPlugin = class {
6447
6986
  rotation = 0;
6448
6987
  applyTransform();
6449
6988
  },
6989
+ resetZoom: () => {
6990
+ isUserZoomed = false;
6991
+ fitMode = "width";
6992
+ scale = calculateFitScale("width");
6993
+ rotation = 0;
6994
+ container.scrollTop = 0;
6995
+ container.scrollLeft = 0;
6996
+ applyTransform();
6997
+ },
6450
6998
  rotateCW: () => {
6451
6999
  rotation = (rotation + 90) % 360;
6452
7000
  applyTransform();
@@ -6790,6 +7338,14 @@ var DocPlugin = class {
6790
7338
  group: "zoom",
6791
7339
  execute: () => instance.fitToPage?.()
6792
7340
  },
7341
+ {
7342
+ id: "reset-zoom",
7343
+ icon: "reset-zoom",
7344
+ label: "Reset Zoom",
7345
+ type: "button",
7346
+ group: "zoom",
7347
+ execute: () => instance.resetZoom?.()
7348
+ },
6793
7349
  {
6794
7350
  id: "rotate-cw",
6795
7351
  icon: "rotate-cw",
@@ -6838,13 +7394,28 @@ var DocPlugin = class {
6838
7394
  container.className = "fp-doc-container";
6839
7395
  container.style.width = "100%";
6840
7396
  container.style.height = "100%";
6841
- container.style.overflowX = "hidden";
6842
- container.style.overflowY = "auto";
6843
- container.style.padding = "16px 8px";
7397
+ container.style.overflow = "auto";
6844
7398
  container.style.backgroundColor = "#f1f5f9";
6845
- container.style.display = "flex";
6846
- container.style.justifyContent = "center";
6847
- container.style.alignItems = "flex-start";
7399
+ const scrollWrapper = document.createElement("div");
7400
+ scrollWrapper.className = "fp-doc-scroll-wrapper";
7401
+ scrollWrapper.style.minWidth = "100%";
7402
+ scrollWrapper.style.minHeight = "100%";
7403
+ scrollWrapper.style.width = "max-content";
7404
+ scrollWrapper.style.height = "max-content";
7405
+ scrollWrapper.style.display = "flex";
7406
+ scrollWrapper.style.justifyContent = "center";
7407
+ scrollWrapper.style.alignItems = "flex-start";
7408
+ scrollWrapper.style.padding = "16px 8px";
7409
+ scrollWrapper.style.boxSizing = "border-box";
7410
+ const sizer = document.createElement("div");
7411
+ sizer.className = "fp-doc-sizer";
7412
+ sizer.style.position = "relative";
7413
+ sizer.style.flexShrink = "0";
7414
+ sizer.style.display = "flex";
7415
+ sizer.style.justifyContent = "center";
7416
+ sizer.style.alignItems = "center";
7417
+ scrollWrapper.appendChild(sizer);
7418
+ container.appendChild(scrollWrapper);
6848
7419
  ctx.container.appendChild(container);
6849
7420
  let scale = 1;
6850
7421
  let extractedRawText = "";
@@ -6892,10 +7463,11 @@ var DocPlugin = class {
6892
7463
  pageCard.style.padding = "72px 56px";
6893
7464
  pageCard.style.boxSizing = "border-box";
6894
7465
  pageCard.style.display = i === 0 ? "block" : "none";
6895
- pageCard.style.transformOrigin = "top center";
7466
+ pageCard.style.transformOrigin = "center center";
6896
7467
  pageCard.style.transition = "transform 0.15s ease";
6897
7468
  pageCard.style.fontFamily = 'Calibri, "Segoe UI", Arial, sans-serif';
6898
7469
  pageCard.style.color = "#1e293b";
7470
+ pageCard.style.flexShrink = "0";
6899
7471
  if (isFallback && i === 0) {
6900
7472
  pageCard.innerHTML = `
6901
7473
  <div style="border-bottom: 1px solid #e2e8f0; padding-bottom: 12px; margin-bottom: 24px;">
@@ -6907,18 +7479,23 @@ var DocPlugin = class {
6907
7479
  } else {
6908
7480
  pageCard.innerHTML = this.formatDocToHtml(rawPages[i], ctx.metadata.name || "Document");
6909
7481
  }
6910
- container.appendChild(pageCard);
7482
+ sizer.appendChild(pageCard);
6911
7483
  pageCards.push(pageCard);
6912
7484
  }
6913
7485
  let rotation = 0;
6914
7486
  const applyTransform = () => {
6915
7487
  const activeCard = pageCards[currentPage - 1];
6916
7488
  if (activeCard) {
6917
- activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
7489
+ const baseW = 816;
6918
7490
  const baseH = activeCard.offsetHeight || 1056;
6919
- const scaledH = baseH * scale;
6920
- const extraH = Math.max(0, scaledH - baseH);
6921
- activeCard.style.marginBottom = `${extraH + 32}px`;
7491
+ const isRotated90 = rotation % 180 !== 0;
7492
+ const boxW = Math.round((isRotated90 ? baseH : baseW) * scale);
7493
+ const boxH = Math.round((isRotated90 ? baseW : baseH) * scale);
7494
+ sizer.style.width = `${boxW}px`;
7495
+ sizer.style.height = `${boxH}px`;
7496
+ activeCard.style.width = `${baseW}px`;
7497
+ activeCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
7498
+ activeCard.style.transformOrigin = "center center";
6922
7499
  }
6923
7500
  };
6924
7501
  const showPage = (pageNum) => {
@@ -6926,11 +7503,11 @@ var DocPlugin = class {
6926
7503
  pageCards.forEach((card, idx) => {
6927
7504
  if (idx + 1 === currentPage) {
6928
7505
  card.style.display = "block";
6929
- card.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
6930
7506
  } else {
6931
7507
  card.style.display = "none";
6932
7508
  }
6933
7509
  });
7510
+ applyTransform();
6934
7511
  container.scrollTop = 0;
6935
7512
  ctx.emit("page-change", { page: currentPage, total: totalPages });
6936
7513
  };
@@ -6996,6 +7573,17 @@ var DocPlugin = class {
6996
7573
  rotation = 0;
6997
7574
  applyTransform();
6998
7575
  },
7576
+ resetZoom: () => {
7577
+ isUserZoomed = false;
7578
+ fitMode = "width";
7579
+ scale = calculateFitScale("width");
7580
+ rotation = 0;
7581
+ container.scrollTop = 0;
7582
+ container.scrollLeft = 0;
7583
+ ctx.container.scrollTop = 0;
7584
+ ctx.container.scrollLeft = 0;
7585
+ applyTransform();
7586
+ },
6999
7587
  rotateCW: () => {
7000
7588
  rotation = (rotation + 90) % 360;
7001
7589
  applyTransform();
@@ -7476,6 +8064,14 @@ var PptPlugin = class {
7476
8064
  group: "zoom",
7477
8065
  execute: () => instance.fitToPage?.()
7478
8066
  },
8067
+ {
8068
+ id: "reset-zoom",
8069
+ icon: "reset-zoom",
8070
+ label: "Reset Zoom",
8071
+ type: "button",
8072
+ group: "zoom",
8073
+ execute: () => instance.resetZoom?.()
8074
+ },
7479
8075
  {
7480
8076
  id: "rotate-cw",
7481
8077
  icon: "rotate-cw",
@@ -7508,17 +8104,30 @@ var PptPlugin = class {
7508
8104
  container.style.width = "100%";
7509
8105
  container.style.height = "100%";
7510
8106
  container.style.overflow = "auto";
7511
- container.style.display = "flex";
7512
- container.style.justifyContent = "center";
7513
- container.style.alignItems = "center";
7514
- container.style.padding = "32px 16px";
7515
8107
  container.style.backgroundColor = "#0f172a";
7516
8108
  container.style.boxSizing = "border-box";
8109
+ const scrollWrapper = document.createElement("div");
8110
+ scrollWrapper.className = "fp-ppt-scroll-wrapper";
8111
+ scrollWrapper.style.minWidth = "100%";
8112
+ scrollWrapper.style.minHeight = "100%";
8113
+ scrollWrapper.style.width = "max-content";
8114
+ scrollWrapper.style.height = "max-content";
8115
+ scrollWrapper.style.display = "flex";
8116
+ scrollWrapper.style.justifyContent = "center";
8117
+ scrollWrapper.style.alignItems = "center";
8118
+ scrollWrapper.style.padding = "32px 16px";
8119
+ scrollWrapper.style.boxSizing = "border-box";
8120
+ const sizer = document.createElement("div");
8121
+ sizer.className = "fp-ppt-sizer";
8122
+ sizer.style.position = "relative";
8123
+ sizer.style.flexShrink = "0";
8124
+ sizer.style.display = "flex";
8125
+ sizer.style.justifyContent = "center";
8126
+ sizer.style.alignItems = "center";
7517
8127
  const slideCard = document.createElement("div");
7518
8128
  slideCard.className = "fp-ppt-slide-card";
7519
8129
  slideCard.style.width = "960px";
7520
- slideCard.style.maxWidth = "calc(100% - 32px)";
7521
- slideCard.style.maxHeight = "calc(100% - 48px)";
8130
+ slideCard.style.height = "540px";
7522
8131
  slideCard.style.aspectRatio = "16 / 9";
7523
8132
  slideCard.style.backgroundColor = "#ffffff";
7524
8133
  slideCard.style.boxShadow = "0 12px 40px rgba(0,0,0,0.35)";
@@ -7528,7 +8137,9 @@ var PptPlugin = class {
7528
8137
  slideCard.style.transition = "transform 0.2s ease";
7529
8138
  slideCard.style.transformOrigin = "center center";
7530
8139
  slideCard.style.flexShrink = "0";
7531
- container.appendChild(slideCard);
8140
+ sizer.appendChild(slideCard);
8141
+ scrollWrapper.appendChild(sizer);
8142
+ container.appendChild(scrollWrapper);
7532
8143
  ctx.container.appendChild(container);
7533
8144
  let scale = 1;
7534
8145
  let rotation = 0;
@@ -7541,7 +8152,17 @@ var PptPlugin = class {
7541
8152
  return Math.min(1, Math.min(availW / 960, availH / 540));
7542
8153
  };
7543
8154
  const applyTransform = () => {
8155
+ const cW = 960;
8156
+ const cH = 540;
8157
+ const isRotated90 = rotation % 180 !== 0;
8158
+ const boxW = Math.round((isRotated90 ? cH : cW) * scale);
8159
+ const boxH = Math.round((isRotated90 ? cW : cH) * scale);
8160
+ sizer.style.width = `${boxW}px`;
8161
+ sizer.style.height = `${boxH}px`;
8162
+ slideCard.style.width = `${cW}px`;
8163
+ slideCard.style.height = `${cH}px`;
7544
8164
  slideCard.style.transform = `scale(${scale}) rotate(${rotation}deg)`;
8165
+ slideCard.style.transformOrigin = "center center";
7545
8166
  };
7546
8167
  setTimeout(() => {
7547
8168
  scale = calculateFitScale();
@@ -7664,6 +8285,13 @@ var PptPlugin = class {
7664
8285
  rotation = 0;
7665
8286
  applyTransform();
7666
8287
  },
8288
+ resetZoom: () => {
8289
+ scale = calculateFitScale();
8290
+ rotation = 0;
8291
+ container.scrollTop = 0;
8292
+ container.scrollLeft = 0;
8293
+ applyTransform();
8294
+ },
7667
8295
  rotateCW: () => {
7668
8296
  rotation = (rotation + 90) % 360;
7669
8297
  applyTransform();